style: apply prettier 3.9.1 formatting

Mechanical reflow from the prettier 3.9.1 bump; no behaviour change.
This commit is contained in:
Marc-André Bombeck committed 2026-06-28 19:26:16 +02:00
1 parent 6329540ade
commit 0f2b548138
90 files changed
+123 -406

No files matched your search

+2 -6
View File
@@ -36,12 +36,8 @@ arrays:
```json
{
"measurements": [
/* … */
],
"moodEntries": [
/* … */
]
"measurements": [/* … */],
"moodEntries": [/* … */]
}
```
+1 -4
View File
@@ -123,10 +123,7 @@ export const POST = apiHandler(async (request: NextRequest) => {
* legacy / unmapped code. Secret-free by construction.
*/
type TestFailureCode =
| "credentials"
| "rate_limited"
| "server_error"
| "unreachable";
"credentials" | "rate_limited" | "server_error" | "unreachable";
/**
* Map an upstream provider failure to a human-readable, secret-free
+1 -4
View File
@@ -53,10 +53,7 @@ const bodySchema = z.object({
});
export type CheckUserBranch =
| "not_found"
| "passkey_only"
| "email_fallback"
| "exists";
"not_found" | "passkey_only" | "email_fallback" | "exists";
export const POST = apiHandler(async (request: NextRequest) => {
// v1.4.43 W13 M-4 — tighter shared bucket on trust-chain misconfig.
@@ -175,8 +175,7 @@ describe("GET /api/dashboard/summary", () => {
// The previous shape emitted "Gewicht" / "kg" / "Schritte" verbatim,
// which injected DE into an English iOS UI.
const weightCard = body.data.metrics.find((m) => m.id === "weight") as
| { titleKey: string; unitKey: string }
| undefined;
{ titleKey: string; unitKey: string } | undefined;
expect(weightCard?.titleKey).toBe("dashboard.metric.title.weight");
expect(weightCard?.unitKey).toBe("dashboard.metric.unit.weight");
expect(
+4 -3
View File
@@ -226,9 +226,10 @@ async function buildComparisonSnapshotForUser(
orderBy: { measuredAt: "asc" },
select: { measuredAt: true, value: true },
});
dataPoints = measurements.map(
(m): DataPoint => ({ date: m.measuredAt, value: m.value }),
);
dataPoints = measurements.map((m): DataPoint => ({
date: m.measuredAt,
value: m.value,
}));
}
const summary = summarize(dataPoints);
const baselineAvg =
+1 -2
View File
@@ -542,8 +542,7 @@ async function postBatch(request: NextRequest): Promise<Response> {
unit: p.row.unit as string,
measuredAt: p.row.measuredAt as Date,
externalSourceVersion: p.row.externalSourceVersion as
| string
| null,
string | null,
deviceType: p.row.deviceType as Prepared["row"]["deviceType"],
sleepStage: p.row.sleepStage as Prepared["row"]["sleepStage"],
},
+2 -4
View File
@@ -205,8 +205,7 @@ export default function DashboardPage() {
bpInTargetCount90: snap.extras?.bpInTargetCount90 ?? null,
bpInTargetSpanDays90: snap.extras?.bpInTargetSpanDays90 ?? null,
glucoseByContext: snap.extras?.glucoseByContext as
| Record<string, DataSummary>
| undefined,
Record<string, DataSummary> | undefined,
};
}
// v1.4.39.3 — the merge moved to `mergeSlimAndThickAnalytics` so
@@ -235,8 +234,7 @@ export default function DashboardPage() {
bpInTargetCount90: merged.bpInTargetCount90,
bpInTargetSpanDays90: merged.bpInTargetSpanDays90,
glucoseByContext: merged.glucoseByContext as
| Record<string, DataSummary>
| undefined,
Record<string, DataSummary> | undefined,
};
}, [
snapshotEnabled,
+1 -5
View File
@@ -279,11 +279,7 @@ export function useAuthActionLabels(): Record<string, string> {
* mirroring the convention established by `useAuthActionLabels`.
*/
export type AuthProvider =
| "password"
| "passkey"
| "api_token"
| "withings"
| "unknown";
"password" | "passkey" | "api_token" | "withings" | "unknown";
export function providerForAction(action: string): AuthProvider {
if (
+3 -6
View File
@@ -494,8 +494,7 @@ export function resolveVerticalMarkerPositions(
export function resolveAnnotationPositions(
annotations:
| Array<{ date: string; label: string; color: string }>
| undefined,
Array<{ date: string; label: string; color: string }> | undefined,
chartData: Array<{ timestamp: number }> | undefined,
): ResolvedAnnotation[] {
if (!annotations || !chartData || chartData.length === 0) return [];
@@ -2021,8 +2020,7 @@ export function HealthChart({
// current ↔ compare values come from the SAME
// payload object.
const hoverPoint = payload[0]?.payload as
| ChartDataPoint
| undefined;
ChartDataPoint | undefined;
for (const item of payload) {
if (typeof item.value !== "number") continue;
const dataKey = String(item.dataKey ?? "");
@@ -2047,8 +2045,7 @@ export function HealthChart({
const compareValue =
effectiveCompareBaseline !== "none" && hoverPoint
? (hoverPoint[`${dataKey}_compare`] as
| number
| undefined)
number | undefined)
: undefined;
if (
effectiveCompareBaseline !== "none" &&
+1 -2
View File
@@ -840,8 +840,7 @@ export function MoodChart({
const dateLabel = ts ? tzFmt.date(new Date(ts)) : "";
const rows: RichTooltipRow[] = [];
const hoverPoint = payload[0]?.payload as
| ChartDataPoint
| undefined;
ChartDataPoint | undefined;
for (const item of payload) {
if (typeof item.value !== "number") continue;
const dataKey = String(item.dataKey ?? "");
@@ -19,14 +19,7 @@ import { cn } from "@/lib/utils";
*/
export type CyclePhaseCrosstabDisplay =
| "hours"
| "steps"
| "bpm"
| "ms"
| "kg"
| "celsius"
| "glucose"
| "mood";
"hours" | "steps" | "bpm" | "ms" | "kg" | "celsius" | "glucose" | "mood";
export type CyclePhaseCrosstabConfidence = "low" | "medium" | "high";
+2 -9
View File
@@ -10,17 +10,10 @@ export type CyclePhase = "MENSTRUAL" | "FOLLICULAR" | "OVULATORY" | "LUTEAL";
export type FlowLevel = "NONE" | "SPOTTING" | "LIGHT" | "MEDIUM" | "HEAVY";
export type OvulationTest =
| "NEGATIVE"
| "POSITIVE_LH_SURGE"
| "ESTROGEN_SURGE"
| "INDETERMINATE";
"NEGATIVE" | "POSITIVE_LH_SURGE" | "ESTROGEN_SURGE" | "INDETERMINATE";
export type CervicalMucus =
| "DRY"
| "STICKY"
| "CREAMY"
| "WATERY"
| "EGG_WHITE";
"DRY" | "STICKY" | "CREAMY" | "WATERY" | "EGG_WHITE";
export type CycleGoal =
| "GENERAL_HEALTH"
@@ -27,10 +27,7 @@ import { MedicationIntakeQuickAdd } from "@/components/dashboard/medication-inta
import { useTranslations } from "@/lib/i18n/context";
export type QuickEntryDialog =
| "measurement"
| "mood"
| "medicationIntake"
| null;
"measurement" | "mood" | "medicationIntake" | null;
/**
* v1.11.3 F3 — guard the quick-entry sheets against an accidental
+1 -4
View File
@@ -13,10 +13,7 @@ export type IllnessType =
| "OTHER";
export type IllnessLifecycle =
| "ACUTE"
| "CHRONIC_ONGOING"
| "RECURRING"
| "FLARE";
"ACUTE" | "CHRONIC_ONGOING" | "RECURRING" | "FLARE";
export interface IllnessSymptomSelection {
key: string;
@@ -36,11 +36,7 @@
/** Lifecycle of one answered question's adopt offer. */
export type GuidedAdoption =
| "pending"
| "adopted"
| "duplicate"
| "declined"
| "failed";
"pending" | "adopted" | "duplicate" | "declined" | "failed";
export interface GuidedOutcome {
/** Index of the question in the session snapshot (progress label). */
@@ -1046,8 +1046,7 @@ interface ChatBubbleProps {
* bubble falls back to that so the card survives reload.
*/
suggestedAction?:
| import("@/lib/ai/coach/suggest-action").CoachSuggestedAction
| null;
import("@/lib/ai/coach/suggest-action").CoachSuggestedAction | null;
providerType?: string | null;
inProgress?: boolean;
errorCode?: string | null;
@@ -72,8 +72,7 @@ export function GlucoseClinicalPanel() {
if (!clinical) return null;
const byContext = query.data?.glucoseByContext as
| Record<string, DataSummary>
| undefined;
Record<string, DataSummary> | undefined;
const formatGlucoseValue = (mgdl: number): string => {
const v = convertGlucose(mgdl, glucoseUnit);
@@ -47,11 +47,7 @@ export type HealthScoreBand = "green" | "yellow" | "red";
* client doesn't pull a heavy analytics import for one string union).
*/
export type HealthScoreComponentSource =
| "manual"
| "withings"
| "appleHealth"
| "mixed"
| "none";
"manual" | "withings" | "appleHealth" | "mixed" | "none";
export interface HealthScoreCardComponent {
value: number | null;
+1 -5
View File
@@ -23,11 +23,7 @@ import type { DailyBriefing as DailyBriefingPayload } from "@/lib/ai/schema";
* `insights.derived.composite.READINESS.component.{key}` labels.
*/
export type ReadinessContributorKey =
| "rhr"
| "hrv"
| "sleep"
| "respiratory"
| "mood";
"rhr" | "hrv" | "sleep" | "respiratory" | "mood";
/**
* Insights redesign hero strip.
@@ -86,12 +86,7 @@ export interface InsightsTabStripProps {
* mounts / no regenerate) falls back to the prior unconditional success.
*/
regenerateOutcome?:
| "fresh"
| "empty"
| "rate-limited"
| "timeout"
| "no-provider"
| null;
"fresh" | "empty" | "rate-limited" | "timeout" | "no-provider" | null;
/**
* v1.4.27 F19 — analytics + event-driven availability inputs the
* gating helper reads. When omitted the strip falls back to its
@@ -21,13 +21,7 @@ import type { MoodInfluenceConfidence } from "./mood-tag-influence";
*/
export type MoodFactorCrosstabDisplay =
| "hours"
| "score"
| "steps"
| "bpm"
| "ms"
| "kg"
| "mmHg";
"hours" | "score" | "steps" | "bpm" | "ms" | "kg" | "mmHg";
export type MoodFactorCrosstabMode = "sameDay" | "nextDay";
export interface MoodFactorMetricCrosstabRow {
@@ -18,10 +18,7 @@ import { useTranslations } from "@/lib/i18n/context";
*/
export type MoodStabilityBand =
| "verySteady"
| "steady"
| "variable"
| "veryVariable";
"verySteady" | "steady" | "variable" | "veryVariable";
export interface MoodStabilityData {
score: number;
@@ -118,8 +118,7 @@ export function MoodTimeOfDayChart({
labelStyle={{ color: "var(--dracula-fg)" }}
formatter={(_value, _name, item) => {
const payload = item?.payload as
| { avgScore: number | null; count: number }
| undefined;
{ avgScore: number | null; count: number } | undefined;
if (!payload || payload.avgScore == null) {
return [t("insights.mood.weekdayNoData"), ""];
}
@@ -125,8 +125,7 @@ export function MoodWeekdayChart({ weekday }: { weekday: MoodWeekdayRow[] }) {
labelStyle={{ color: "var(--dracula-fg)" }}
formatter={(_value, _name, item) => {
const payload = item?.payload as
| { avgScore: number | null; count: number }
| undefined;
{ avgScore: number | null; count: number } | undefined;
if (!payload || payload.avgScore == null) {
return [t("insights.mood.weekdayNoData"), ""];
}
@@ -217,8 +217,7 @@ function RationaleCard({
}: {
rationale: InsightRecommendationRationale;
metricSource:
| { type: string; timeRange: string; summary: string }
| undefined;
{ type: string; timeRange: string; summary: string } | undefined;
referenceId: string | undefined;
confidence: number | undefined;
locale: Locale;
@@ -147,11 +147,7 @@ export function nextAdvisorPollInterval(
* means only the transient 503 surface (provider chain unavailable).
*/
export type AdvisorFetchOutcome =
| "fresh"
| "empty"
| "rate-limited"
| "timeout"
| "no-provider";
"fresh" | "empty" | "rate-limited" | "timeout" | "no-provider";
interface AdvisorFetchResult {
payload: InsightAdvisorPayload | null;
+1 -2
View File
@@ -188,8 +188,7 @@ export function LabBiomarkerChart({
content={(props) => {
const active = props.active ?? false;
const payload = props.payload as
| ReadonlyArray<{ payload?: ChartPoint }>
| undefined;
ReadonlyArray<{ payload?: ChartPoint }> | undefined;
const point = payload?.[0]?.payload;
if (!active || !point) {
return <RichChartTooltip active={false} rows={[]} />;
@@ -133,8 +133,7 @@ describe("runRecordIntake — shared C1 failure toast + C2 Undo", () => {
const [message, opts] = vi.mocked(toast.success).mock.calls[0];
expect(message).toBe("medications.intakeToastTaken:Mounjaro");
const action = opts?.action as
| { label: string; onClick: (e: never) => void }
| undefined;
{ label: string; onClick: (e: never) => void } | undefined;
expect(action?.label).toBe("medications.intakeUndo");
// Firing the action calls undoIntake with the just-created event id.
@@ -98,10 +98,7 @@ export interface TableMedication {
}
export type MedicationTableSortColumn =
| "name"
| "nextDue"
| "compliance"
| "stock";
"name" | "nextDue" | "compliance" | "stock";
export interface MedicationTableSort {
column: MedicationTableSortColumn;
@@ -144,9 +144,7 @@ export function ScheduleTimesEditor({
...(s.scheduleType
? {
scheduleType: s.scheduleType as
| "SCHEDULED"
| "PRN"
| "CYCLIC",
"SCHEDULED" | "PRN" | "CYCLIC",
}
: {}),
...(typeof s.cyclicOnWeeks === "number"
@@ -107,9 +107,7 @@ export function GraceRow({
...(s.scheduleType
? {
scheduleType: s.scheduleType as
| "SCHEDULED"
| "PRN"
| "CYCLIC",
"SCHEDULED" | "PRN" | "CYCLIC",
}
: {}),
...(typeof s.cyclicOnWeeks === "number"
+1 -5
View File
@@ -25,11 +25,7 @@ import type { LucideIcon } from "lucide-react";
import { cn } from "@/lib/utils";
export type SettingsInfoTileTone =
| "info"
| "warning"
| "success"
| "primary"
| "neutral";
"info" | "warning" | "success" | "primary" | "neutral";
const TONE_SURFACE: Record<SettingsInfoTileTone, string> = {
info: "border-info/40 bg-info/10",
@@ -47,8 +47,7 @@ export function resolveInitialTimezone(
* provided error text (which has no key) rides `text` verbatim.
*/
export type StatusMessage =
| { key: string; params?: Record<string, string | number> }
| { text: string };
{ key: string; params?: Record<string, string | number> } | { text: string };
export function statusText(
msg: StatusMessage,
@@ -45,11 +45,7 @@ import { cn } from "@/lib/utils";
* - disconnected → user clicked Disconnect; "Not connected" copy.
*/
export type IntegrationPillState =
| "connected"
| "warning"
| "error"
| "parked"
| "disconnected";
"connected" | "warning" | "error" | "parked" | "disconnected";
interface IntegrationStatusPillProps {
state: IntegrationPillState;
@@ -52,8 +52,7 @@ const WITHINGS_OAUTH_ERROR_KEYS: Record<string, string> = {
};
type WithingsOauthOutcome =
| { kind: "connected" }
| { kind: "error"; reason: string };
{ kind: "connected" } | { kind: "error"; reason: string };
/**
* The OAuth providers whose callbacks redirect back to the settings page with a
@@ -23,12 +23,7 @@ import { useTranslations } from "@/lib/i18n/context";
export const INTEGRATION_DOCS_BASE = "https://docs.healthlog.dev/integrations";
export type IntegrationDocsProvider =
| "whoop"
| "withings"
| "fitbit"
| "polar"
| "oura"
| "nightscout";
"whoop" | "withings" | "fitbit" | "polar" | "oura" | "nightscout";
export function integrationDocsHref(provider: IntegrationDocsProvider): string {
return `${INTEGRATION_DOCS_BASE}/${provider}`;
@@ -19,18 +19,9 @@ import { queryKeys } from "@/lib/query-keys";
// IntegrationStatusPill now owns state + last-sync presentation, and
// the actionable error message is shown inline above the action row.
export type IntegrationKey =
| "withings"
| "whoop"
| "fitbit"
| "moodlog"
| "polar"
| "oura";
"withings" | "whoop" | "fitbit" | "moodlog" | "polar" | "oura";
export type IntegrationState =
| "connected"
| "error_transient"
| "error_reauth"
| "disconnected"
| "parked";
"connected" | "error_transient" | "error_reauth" | "disconnected" | "parked";
export interface IntegrationStatusViewModel {
integration: IntegrationKey;
@@ -41,10 +41,7 @@ import { apiGet, apiPost } from "@/lib/api/api-fetch";
type ChannelType = "TELEGRAM" | "NTFY" | "WEB_PUSH" | "APNS";
type ChannelState =
| "active"
| "auto_disabled"
| "manually_disabled"
| "sending_paused";
"active" | "auto_disabled" | "manually_disabled" | "sending_paused";
interface ChannelStatus {
id: string;
+1 -2
View File
@@ -43,8 +43,7 @@ export type SuggestionSuppressReason =
| "duplicate";
export type SuggestionDecision =
| { surface: true }
| { surface: false; reason: SuggestionSuppressReason };
{ surface: true } | { surface: false; reason: SuggestionSuppressReason };
/**
* Pure pref-level decision (no DB). Applies opt-out, the explicit stop
+2 -4
View File
@@ -337,8 +337,7 @@ async function getMedicationCompliance(
const compliance = pickSection(snapshot.sections, "compliance");
// GLP-1 context rides the `weeklyContext` block.
const weeklyContext = pickSection(snapshot.sections, "weeklyContext") as
| { glp1?: unknown }
| undefined;
{ glp1?: unknown } | undefined;
const glp1 = weeklyContext?.glp1;
if (compliance === undefined && glp1 === undefined) {
return { present: false, reason: "no_data" };
@@ -377,8 +376,7 @@ async function getLabs(
scopeFor([], fallbackWindow, fallbackWindow, sharedScope),
);
const labs = pickSection(snapshot.sections, "labs") as
| { recent?: Array<{ name?: string; analyte?: string }> }
| undefined;
{ recent?: Array<{ name?: string; analyte?: string }> } | undefined;
if (labs === undefined) return { present: false, reason: "no_data" };
const analyte = parsed.data.analyte?.trim().toLowerCase();
+1 -2
View File
@@ -202,8 +202,7 @@ export async function requestDeviceCode(): Promise<DeviceCodeStart> {
}
export type DevicePollResult =
| { status: "pending" }
| { status: "connected"; creds: CodexCreds };
{ status: "pending" } | { status: "connected"; creds: CodexCreds };
/**
* One poll attempt against the device-auth token endpoint. Returns
+1 -5
View File
@@ -31,11 +31,7 @@
export type MedicalReferenceOrg = "AHA" | "ESH" | "ESC" | "WHO" | "DGE" | "ADA";
export type MedicalReferenceMetric =
| "bp"
| "weight"
| "pulse"
| "mood"
| "medication";
"bp" | "weight" | "pulse" | "mood" | "medication";
export interface MedicalReference {
/** Stable slug — used as `recommendation.referenceId`. */
+11 -19
View File
@@ -103,11 +103,7 @@ export type InsightResult = z.infer<typeof insightResultSchema>;
// ─── Provider Types ────────────────────────────────────────
export type ProviderType =
| "codex"
| "admin-key"
| "anthropic"
| "local"
| "none";
"codex" | "admin-key" | "anthropic" | "local" | "none";
export interface AIProvider {
type: ProviderType;
@@ -368,20 +364,16 @@ export function singleUserTurn(p: {
? p.user
: [
{ type: "text", text: p.user },
...images.map(
(img): AiImagePart => ({
type: "image",
mediaType: img.mediaType,
dataBase64: img.dataBase64,
}),
),
...documents.map(
(doc): AiDocPart => ({
type: "document",
mediaType: doc.mediaType,
dataBase64: doc.dataBase64,
}),
),
...images.map((img): AiImagePart => ({
type: "image",
mediaType: img.mediaType,
dataBase64: img.dataBase64,
})),
...documents.map((doc): AiDocPart => ({
type: "document",
mediaType: doc.mediaType,
dataBase64: doc.dataBase64,
})),
];
return {
system: p.system,
+1 -5
View File
@@ -77,11 +77,7 @@ export interface IntakeEvent {
}
export type IntakeTimingClass =
| "early"
| "on_time"
| "late"
| "very_late"
| "missed";
"early" | "on_time" | "late" | "very_late" | "missed";
export interface ComplianceResult {
totalExpected: number;
+8 -9
View File
@@ -54,8 +54,7 @@ export interface AnalyticsThickLike extends AnalyticsSlimLike {
export interface MergedDashboardAnalytics {
summaries: Record<string, DataSummary>;
lastSeenByType?:
| Record<string, { lastSeenAt: string; daysAgo: number } | null>
| undefined;
Record<string, { lastSeenAt: string; daysAgo: number } | null> | undefined;
bpInTargetPct: number | null;
bpInTargetPct7d: number | null;
bpInTargetPct30d: number | null;
@@ -98,13 +97,13 @@ export function mergeSlimAndThickAnalytics(
const slimFreshnessHasContent = hasContent(slim?.lastSeenByType ?? null);
const lastSeenByType:
| Record<string, { lastSeenAt: string; daysAgo: number } | null>
| undefined = slimFreshnessHasContent
? (slim!.lastSeenByType as Record<
string,
{ lastSeenAt: string; daysAgo: number } | null
>)
: (thick?.lastSeenByType ?? undefined);
Record<string, { lastSeenAt: string; daysAgo: number } | null> | undefined =
slimFreshnessHasContent
? (slim!.lastSeenByType as Record<
string,
{ lastSeenAt: string; daysAgo: number } | null
>)
: (thick?.lastSeenByType ?? undefined);
return {
summaries,
+2 -4
View File
@@ -212,8 +212,7 @@ export function pickCanonicalSourceRows<T extends SourcePickerRow>(
>();
for (const row of pickedRows) {
const typeKey = (row.type ?? "__default__") as
| MeasurementType
| "__default__";
MeasurementType | "__default__";
const set = presentByType.get(typeKey) ?? new Set<DeviceType>();
set.add(normalizeDeviceType(row.deviceType));
presentByType.set(typeKey, set);
@@ -248,8 +247,7 @@ export function pickCanonicalSourceRows<T extends SourcePickerRow>(
for (const row of pickedRows) {
const typeKey = (row.type ?? "__default__") as
| MeasurementType
| "__default__";
MeasurementType | "__default__";
const winner = winningDeviceTypeByRowType.get(typeKey);
if (winner === "__fallback__") {
// Per-type fallback: keep every row of this type.
+1 -3
View File
@@ -88,9 +88,7 @@ vi.mock("@/lib/db", () => ({
let count = 0;
for (const row of dbState.apiTokens) {
const tokenHashFilter = where.tokenHash as
| string
| { in: string[] }
| undefined;
string | { in: string[] } | undefined;
const matches =
!tokenHashFilter ||
(typeof tokenHashFilter === "string"
+1 -7
View File
@@ -79,13 +79,7 @@ const authenticationResponseSchema = z
.loose();
type Transport =
| "ble"
| "cable"
| "hybrid"
| "internal"
| "nfc"
| "smart-card"
| "usb";
"ble" | "cable" | "hybrid" | "internal" | "nfc" | "smart-card" | "usb";
const CHALLENGE_TTL_MS = 5 * 60 * 1000;
+1 -7
View File
@@ -73,13 +73,7 @@ const registrationResponseSchema = z
.loose();
type Transport =
| "ble"
| "cable"
| "hybrid"
| "internal"
| "nfc"
| "smart-card"
| "usb";
"ble" | "cable" | "hybrid" | "internal" | "nfc" | "smart-card" | "usb";
// The relying-party config (`rpName` / `getRpId` / `getExpectedOrigin`) is
// shared with the second-factor security-key path via `@/lib/auth/webauthn-rp`
+1 -4
View File
@@ -83,10 +83,7 @@ export async function issueAccessAndRefresh(
}
export type RotationFailureReason =
| "not_found"
| "expired"
| "already_used"
| "revoked";
"not_found" | "expired" | "already_used" | "revoked";
export type RotationResult =
| { ok: true; bundle: IssuedRefreshBundle }
+1 -2
View File
@@ -29,8 +29,7 @@ import type { ConsentReceipt } from "@/lib/consent/receipts";
/** Outcome of an idempotent web-grant call. */
export type WebConsentGrantResult =
| { minted: true; receipt: ConsentReceipt }
| { minted: false };
{ minted: true; receipt: ConsentReceipt } | { minted: false };
/**
* Ensure the web user has an active `ai_full` consent receipt, minting one
+1 -8
View File
@@ -70,14 +70,7 @@ export const PHASE_ORDINAL: Record<CyclePhase, number> = {
/** Display-unit hint the client formatter branches on. */
export type PhaseCrosstabDisplay =
| "hours"
| "steps"
| "bpm"
| "ms"
| "kg"
| "celsius"
| "glucose"
| "mood";
"hours" | "steps" | "bpm" | "ms" | "kg" | "celsius" | "glucose" | "mood";
/**
* Synthetic non-MeasurementType channel key for the MOOD outcome. Mood lives in
+3 -13
View File
@@ -22,17 +22,10 @@
export type FlowLevel = "NONE" | "SPOTTING" | "LIGHT" | "MEDIUM" | "HEAVY";
export type OvulationTest =
| "NEGATIVE"
| "POSITIVE_LH_SURGE"
| "ESTROGEN_SURGE"
| "INDETERMINATE";
"NEGATIVE" | "POSITIVE_LH_SURGE" | "ESTROGEN_SURGE" | "INDETERMINATE";
export type CervicalMucus =
| "DRY"
| "STICKY"
| "CREAMY"
| "WATERY"
| "EGG_WHITE";
"DRY" | "STICKY" | "CREAMY" | "WATERY" | "EGG_WHITE";
/**
* Which symptothermal SECONDARY sign pairs with the temperature primary sign
@@ -53,10 +46,7 @@ export type CervixOpening = "CLOSED" | "OPEN";
export type CyclePhase = "MENSTRUAL" | "FOLLICULAR" | "OVULATORY" | "LUTEAL";
export type PredictionMethod =
| "CALENDAR"
| "SYMPTOTHERMAL"
| "TEMPERATURE_TREND"
| "BLENDED";
"CALENDAR" | "SYMPTOTHERMAL" | "TEMPERATURE_TREND" | "BLENDED";
export type CycleTrackingGoal =
| "GENERAL_HEALTH"
+1 -6
View File
@@ -478,12 +478,7 @@ export interface FitbitMappedMeasurement {
/** HealthLog `SleepStage` values a Fitbit sleep stage maps onto. */
export type FitbitSleepStage =
| "IN_BED"
| "AWAKE"
| "ASLEEP"
| "REM"
| "CORE"
| "DEEP";
"IN_BED" | "AWAKE" | "ASLEEP" | "REM" | "CORE" | "DEEP";
// ── Weight + body fat (/body/log/{weight,fat}) ─────────────────
//
+1 -6
View File
@@ -53,12 +53,7 @@ export type AchievementMetricKey =
* leaked to the DOM)
*/
export type AchievementCategory =
| "medication"
| "vitals"
| "mood"
| "security"
| "engagement"
| "hidden";
"medication" | "vitals" | "mood" | "security" | "engagement" | "hidden";
export interface AchievementDefinition {
id: string;
+1 -2
View File
@@ -12,8 +12,7 @@
* returns the decoded UTF-8 text on success.
*/
export type CappedReadResult =
| { ok: true; text: string }
| { ok: false; reason: "too_large" };
{ ok: true; text: string } | { ok: false; reason: "too_large" };
export async function readBodyCapped(
source: { headers: Headers; body: ReadableStream<Uint8Array> | null },
+1 -3
View File
@@ -60,9 +60,7 @@ function getIdempotencyKey(request: Request | NextRequest): string | null {
* - `null` — no live row; the caller may claim + run.
*/
type CacheLookup =
| { kind: "replay"; response: NextResponse }
| { kind: "pending" }
| null;
{ kind: "replay"; response: NextResponse } | { kind: "pending" } | null;
/**
* Look up the state of a (userId, key, method, path) tuple. Distinguishes
+1 -2
View File
@@ -29,8 +29,7 @@ export function isIllnessEnabled(userId: string): Promise<boolean> {
* verbatim — mirrors `CycleGateResult`.
*/
export type IllnessGateResult =
| { enabled: true }
| { enabled: false; response: Response };
{ enabled: true } | { enabled: false; response: Response };
/**
* Enforce the gate for an `/api/illness/*` route. Returns a 403
+4 -3
View File
@@ -409,9 +409,10 @@ export async function buildComparisonSnapshotForUser(
orderBy: { measuredAt: "asc" },
select: { measuredAt: true, value: true },
});
dataPoints = measurements.map(
(m): DataPoint => ({ date: m.measuredAt, value: m.value }),
);
dataPoints = measurements.map((m): DataPoint => ({
date: m.measuredAt,
value: m.value,
}));
}
const summary = summarize(dataPoints);
const baselineAvg =
+1 -5
View File
@@ -83,11 +83,7 @@ const DEFAULTS: Required<ChronotypeOptions> = {
* surface.
*/
export type ChronotypeBand =
| "extreme_early"
| "early"
| "intermediate"
| "late"
| "extreme_late";
"extreme_early" | "early" | "intermediate" | "late" | "extreme_late";
/**
* Band a corrected mid-sleep (MSFsc, minutes-of-day) into the MCTQ chronotype
+1 -6
View File
@@ -112,12 +112,7 @@ export interface ChronotypeDto {
msfMinutes: number | null;
msfScMinutes: number | null;
band:
| "extreme_early"
| "early"
| "intermediate"
| "late"
| "extreme_late"
| null;
"extreme_early" | "early" | "intermediate" | "late" | "extreme_late" | null;
socialJetlagMinutes: number | null;
freeNightsCounted: number;
workNightsCounted: number;
+1 -6
View File
@@ -28,12 +28,7 @@ export type DerivedConfidenceBand = "high" | "medium" | "low" | "draft";
* = no data backed the value.
*/
export type DerivedProvenanceSource =
| "DAY"
| "WEEK"
| "MONTH"
| "YEAR"
| "live"
| "none";
"DAY" | "WEEK" | "MONTH" | "YEAR" | "live" | "none";
/**
* Where a derived value's inputs came from. Lets every surface show the
+1 -7
View File
@@ -281,13 +281,7 @@ export interface AggregatedFeatures {
export interface SignalOfDay {
/** Briefing `sourceMetric` discriminator the UI pins an icon + route on. */
metric:
| "bp"
| "weight"
| "pulse"
| "mood"
| "sleep"
| "resting_hr"
| "glucose";
"bp" | "weight" | "pulse" | "mood" | "sleep" | "resting_hr" | "glucose";
/** Natural-language label (no enum leak into prose). */
label: string;
/** Unit string when the metric carries one. */
+1 -4
View File
@@ -1677,10 +1677,7 @@ export const STABILITY_MIN_DAYS = 7;
export const STABILITY_SD_FULL_SCALE = 1.5;
export type StabilityBand =
| "verySteady"
| "steady"
| "variable"
| "veryVariable";
"verySteady" | "steady" | "variable" | "veryVariable";
export interface MoodStability {
/** 0..100; higher = steadier (lower day-to-day variance). */
@@ -171,8 +171,7 @@ export interface PeriodNarrativeInsufficient {
}
export type PeriodNarrativeResult =
| PeriodNarrativeContext
| PeriodNarrativeInsufficient;
PeriodNarrativeContext | PeriodNarrativeInsufficient;
// ── pure helpers ──────────────────────────────────────────────────────────
@@ -25,10 +25,7 @@
/** Outcome buckets shared across the HTTP-status-driven integrations. */
export type IntegrationClassification =
| "success"
| "transient"
| "reauth_required"
| "persistent";
"success" | "transient" | "reauth_required" | "persistent";
export interface ClassifiedHttpResponse {
classification: IntegrationClassification;
+1 -5
View File
@@ -108,11 +108,7 @@ export function toFailureKind(
* trail.
*/
export type IntegrationState =
| "connected"
| "error_transient"
| "error_reauth"
| "disconnected"
| "parked";
"connected" | "error_transient" | "error_reauth" | "disconnected" | "parked";
/**
* The ladder at which a streak of failures escalates from "user-visible
+1 -5
View File
@@ -124,11 +124,7 @@ export function resolvePlanMetric(metric: string): ResolvedMetric | null {
}
export type ExperimentVerdict =
| "improved"
| "worsened"
| "no_change"
| "changed"
| "insufficient";
"improved" | "worsened" | "no_change" | "changed" | "insufficient";
export interface ExperimentOutcomeInput {
label: string;
+1 -3
View File
@@ -76,9 +76,7 @@ export const FERTILE_SOON_LEAD_DAYS = 2;
export const PERIOD_CONFIRM_GRACE_DAYS = 3;
export type CycleReminderEvent =
| "CYCLE_PERIOD_SOON"
| "CYCLE_PERIOD_CONFIRM"
| "CYCLE_FERTILE_SOON";
"CYCLE_PERIOD_SOON" | "CYCLE_PERIOD_CONFIRM" | "CYCLE_FERTILE_SOON";
export interface CycleReminderSummary {
candidatesScanned: number;
+1 -5
View File
@@ -183,11 +183,7 @@ export interface ForceWarmResult {
* card warm below.
*/
comprehensive:
| GenerateOutcome["status"]
| "timeout"
| "fresh"
| "backoff"
| "capped";
GenerateOutcome["status"] | "timeout" | "fresh" | "backoff" | "capped";
/** Count of specialised per-status assessments written warm. */
assessmentsWarmed: number;
/** Count of generic per-HealthKit-metric assessments written warm. */
+1 -4
View File
@@ -18,10 +18,7 @@ export const OCR_MAX_BYTES = 12 * 1024 * 1024;
/** The MIME types the extract route accepts (no HEIC in v1). */
export type OcrUploadMime =
| "image/jpeg"
| "image/png"
| "image/webp"
| "application/pdf";
"image/jpeg" | "image/png" | "image/webp" | "application/pdf";
/** Thrown by `readBoundedBody` when the stream exceeds the byte cap. */
export class BodyTooLargeError extends Error {
+1 -4
View File
@@ -53,10 +53,7 @@ export interface ResolvedClient {
* `SafeFetchError.kind` + message + cause) for the `/authorize` annotation.
*/
export type ClientResolutionReason =
| "unknown_client"
| "invalid_metadata"
| "ssrf_blocked"
| "fetch_failed";
"unknown_client" | "invalid_metadata" | "ssrf_blocked" | "fetch_failed";
export type ClientResolution =
| { ok: true; client: ResolvedClient }
+1 -2
View File
@@ -140,8 +140,7 @@ function plainMetricText(rid: string, result: unknown): string {
};
if (!r?.present) return `No recent ${rid} data is on file.`;
const section = (r.data?.section ?? r.data) as
| Record<string, unknown>
| undefined;
Record<string, unknown> | undefined;
const agg = section?.aggregate as Record<string, unknown> | undefined;
const parts: string[] = [];
const mean = num(agg?.mean);
@@ -49,8 +49,7 @@ function buildPagingFindMany(allRows: PerSampleRow[]) {
const or = (and[1] as { OR?: Array<Record<string, unknown>> }).OR;
const gt = or?.[0]?.measuredAt as { gt?: Date } | undefined;
const tie = or?.[1] as
| { measuredAt?: Date; id?: { gt?: string } }
| undefined;
{ measuredAt?: Date; id?: { gt?: string } } | undefined;
afterTime = gt?.gt ? gt.gt.getTime() : null;
afterId = tie?.id?.gt ?? null;
}
+1 -5
View File
@@ -38,11 +38,7 @@ import type {
* in the pipeline once we observe the production sample volume.
*/
export type AppleHealthAggregation =
| "sum"
| "mean"
| "latest"
| "max"
| "median";
"sum" | "mean" | "latest" | "max" | "median";
export interface AppleHealthMapping {
/** HealthKit identifier (e.g. `HKQuantityTypeIdentifierBodyMass`). */
+1 -2
View File
@@ -128,8 +128,7 @@ export function bucketRowsByDay(
/** Outcome of writing a single per-day bucket. */
export type DayWriteOutcome =
| { kind: "written"; sourceRowsRemoved: number }
| { kind: "skipped-conflict" };
{ kind: "written"; sourceRowsRemoved: number } | { kind: "skipped-conflict" };
/**
* Context a per-day write strategy receives. The strategy owns its own
@@ -69,12 +69,7 @@ const SLEEP_STAGE_NAME_TO_CODEPOINT: Record<string, number> = {
/** Phase the worker is currently in. */
export type ImportJobPhase =
| "queued"
| "unpacking"
| "parsing"
| "upserting"
| "done"
| "failed";
"queued" | "unpacking" | "parsing" | "upserting" | "done" | "failed";
/**
* Live snapshot the worker writes to `ImportJob.progress` every
+1 -5
View File
@@ -33,11 +33,7 @@
* UI looks up by id, not by brand name.
*/
export type Glp1DrugId =
| "tirzepatide"
| "semaglutide"
| "liraglutide"
| "dulaglutide"
| "exenatide";
"tirzepatide" | "semaglutide" | "liraglutide" | "dulaglutide" | "exenatide";
/**
* Route enum — most agonists are subcutaneous; Rybelsus is oral
@@ -67,12 +67,7 @@ export interface HistoryIntake {
}
export type DoseHistoryStatus =
| "taken_on_time"
| "taken_late"
| "skipped"
| "missed"
| "upcoming"
| "ad_hoc";
"taken_on_time" | "taken_late" | "skipped" | "missed" | "upcoming" | "ad_hoc";
/**
* v1.15.20 — the due-context an ad-hoc row carries: the nearest scheduled
+1 -5
View File
@@ -135,11 +135,7 @@ export type SideEffectSeverity = 1 | 2 | 3 | 4 | 5;
/** Locale-agnostic semantic labels for the severity ladder. */
export type SideEffectSeverityLabel =
| "mild"
| "moderate"
| "significant"
| "severe"
| "verySevere";
"mild" | "moderate" | "significant" | "severe" | "verySevere";
/**
* Maps a 1-5 severity integer to its locale-agnostic semantic label.
+1 -2
View File
@@ -240,8 +240,7 @@ export async function resolveModuleMap(
* return verbatim — mirrors `CycleGateResult`.
*/
export type ModuleGateResult =
| { enabled: true }
| { enabled: false; response: Response };
{ enabled: true } | { enabled: false; response: Response };
/**
* Enforce the gate for a module-scoped route. Returns a 403
+1 -7
View File
@@ -22,13 +22,7 @@
*/
export type MoodTagIconGroup =
| "emotions"
| "activities"
| "health"
| "food"
| "weather"
| "places"
| "misc";
"emotions" | "activities" | "health" | "food" | "weather" | "places" | "misc";
export interface MoodTagIconCatalogEntry {
/** Lucide icon name — the value stored on `mood_tags.icon` / `mood_tag_categories.icon`. */
+1 -3
View File
@@ -267,9 +267,7 @@ async function fetchCollection<T>(
// 204 No Content — a window with no records. Polar returns an empty body.
if (res.status === 204) return [];
const json = (await res.json().catch(() => null)) as
| CollectionResult<T>
| Record<string, T[]>
| null;
CollectionResult<T> | Record<string, T[]> | null;
if (!json) return [];
const list = (json as Record<string, unknown>)[recordsKey];
return Array.isArray(list) ? (list as T[]) : [];
+1 -4
View File
@@ -458,10 +458,7 @@ export function referenceLabel(metric: ReferenceMetric): string {
* (device-derived / baseline-only signals).
*/
export type ReferencePlacement =
| "within"
| "slightly-outside"
| "outside"
| "insufficient";
"within" | "slightly-outside" | "outside" | "insufficient";
/**
* Place a value against a metric's population bands. Returns
+1 -5
View File
@@ -28,11 +28,7 @@
/** The sync domains the feed serves. */
export type SyncDomain =
| "measurements"
| "mood"
| "intakes"
| "cycleDays"
| "cycles";
"measurements" | "mood" | "intakes" | "cycleDays" | "cycles";
export const SYNC_DOMAINS: readonly SyncDomain[] = [
"measurements",
+1 -4
View File
@@ -43,10 +43,7 @@ import type { TrafficRange } from "@/lib/analytics/value-bands";
import { thresholdMetricForContext } from "@/lib/glucose";
export type GlucoseContextKey =
| "FASTING"
| "POSTPRANDIAL"
| "RANDOM"
| "BEDTIME";
"FASTING" | "POSTPRANDIAL" | "RANDOM" | "BEDTIME";
/**
* ADA glycemic GOAL bands for people living with diabetes (mg/dL).
+1 -4
View File
@@ -136,10 +136,7 @@ export function isNearUtc(tz: string, now: Date = new Date()): boolean {
}
export type FormatInUserTzShape =
| "iso-with-offset"
| "wall-clock"
| "datetime"
| "date";
"iso-with-offset" | "wall-clock" | "datetime" | "date";
/**
* Format an instant in the user's timezone.
+1 -3
View File
@@ -164,9 +164,7 @@ export interface MedicationStatementFactData {
}
export type FactData =
| ConditionFactData
| ObservationFactData
| MedicationStatementFactData;
ConditionFactData | ObservationFactData | MedicationStatementFactData;
/** The staged-fact DTO the routes return + the review UI consumes. */
export interface ExtractedFactDto {
+1 -4
View File
@@ -53,10 +53,7 @@
/** Outcome buckets for a Withings response. */
export type WithingsClassification =
| "success"
| "transient"
| "reauth_required"
| "persistent";
"success" | "transient" | "reauth_required" | "persistent";
export interface ClassifiedResponse {
classification: WithingsClassification;
@@ -165,8 +165,7 @@ describe("GET /api/analytics — chunked per-type reads (Sr-H1)", () => {
// which writes the row-count slot under `slim_summaries` rather than
// the old `bp_aggregate.row_count`.
const analytics = httpEvent!.meta!.analytics as
| { slim_summaries?: { row_count?: number } }
| undefined;
{ slim_summaries?: { row_count?: number } } | undefined;
expect(analytics?.slim_summaries?.row_count).toBe(ROW_COUNT);
});
});