mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
style: apply prettier 3.9.1 formatting
Mechanical reflow from the prettier 3.9.1 bump; no behaviour change.
This commit is contained in:
1 parent
6329540ade
commit
0f2b548138
90 files changed
+123
-406
No files matched your search
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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}) ─────────────────
|
||||
//
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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`). */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`. */
|
||||
|
||||
@@ -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[]) : [];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user