/** * Query keys — insights tree: comprehensive payloads, status assessments, * derived metrics, correlations, layout, and AI settings. * Part of the centralized factory; aggregated in `./index.ts`. */ export const insightsKeys = { insightsRoot: () => ["insights"] as const, insightsComprehensive: () => ["insights", "comprehensive"] as const, insightsTargets: () => ["insights", "targets"] as const, /** * Shared cache key for the rich `/api/insights/generate` advisor * payload. Every surface that subscribes under this key shares the * same cache so a regenerate on one surface refreshes the others * without a second LLM round-trip. */ insightsAdvisor: () => ["insights", "advisor"] as const, /** * v1.11.0 — period-narrative summary (`/api/insights/narrative?period=…`). * Keyed by period + locale so the week and month summaries cache * independently and a locale switch fetches the matching prose. */ insightsNarrative: (period: string, locale: string) => ["insights", "narrative", period, locale] as const, insightsBpStatus: (locale: string) => ["insights", "blood-pressure-status", locale] as const, insightsWeightStatus: (locale: string) => ["insights", "weight-status", locale] as const, insightsPulseStatus: (locale: string) => ["insights", "pulse-status", locale] as const, insightsBmiStatus: (locale: string) => ["insights", "bmi-status", locale] as const, insightsMoodStatus: (locale: string) => ["insights", "mood-status", locale] as const, insightsMedicationComplianceStatus: (locale: string) => ["insights", "medication-compliance-status", locale] as const, /** * v1.8.7.1 — per-metric insight assessment for the HealthKit metric * sub-pages. One generic route (`/api/insights/metric-status?metric=…`) * backs every HealthKit metric, so the key is parameterised by the * metric id alongside the locale rather than minting a bespoke factory * entry per metric. The seven bespoke `*-status` routes above keep * their own keys; this one covers the ~29 generic HealthKit pages. */ insightsMetricStatus: (metric: string, locale: string) => ["insights", "metric-status", metric, locale] as const, /** * Per-biomarker assessment for the lab-marker detail page. One generic * route (`/api/insights/biomarker-assessment?biomarkerId=…`) backs every * marker, so the key is parameterised by the marker id alongside the * locale. Same read-only + stale-while-revalidate contract as * `insightsMetricStatus`; the `["insights"]` prefix keeps it in the * standard invalidation fan-out. */ insightsBiomarkerAssessment: (biomarkerId: string, locale: string) => ["insights", "biomarker-assessment", biomarkerId, locale] as const, /** * v1.8.7.1 — mutationKey for the on-demand full-warm POST * (`/api/insights/pregenerate`). Lives in the factory so the bare-array * ESLint rule stays satisfied; the warm enqueues every assessment * generation on the worker, so there is no read cache to invalidate * here — the existing status queries pick up the warmed text via their * own stale-while-revalidate. */ insightsPregenerate: () => ["insights", "pregenerate"] as const, /** * v1.10.0 — categorical events (WX-B). The device-flagged event * awareness timeline (`/api/insights/rhythm-events`). No locale segment * — the payload is verdicts + timestamps; the surface localises its own * prose. The `["insights"]` prefix keeps it in the standard insights * invalidation fan-out (an Apple Health batch write that lands an event * row busts it via the prefix). */ insightsRhythmEvents: () => ["insights", "rhythm-events"] as const, /** * v1.10.0 — derived-wellness metrics. One generic route * (`/api/insights/derived?metric=…[&type=…]`) backs the vitals * dashboard tiles, the composite score-anatomy view, and the home * wellness strip — all through the one `useDerivedMetric` hook. * * One generic route backs every derived metric (sleep score, readiness, * coincident-deviation, vitals baseline, …); the optional sub-type is the * chosen vital for `VITALS_BASELINE`. The fourth tuple slot is always * present (`null` when no sub-type) so the cache never poisons between a * 3-element and a 4-element shape for the same metric prefix. Pure compute * over the rollup tier — a measurement write keeps it fresh by construction * (next read sees new buckets), so the `["insights"]` prefix carries the * invalidation fan-out. */ insightsDerived: (metric: string, type?: string | null) => ["insights", "derived", metric, type ?? null] as const, /** * v1.10.0 — batched derived-metric read (`/api/insights/derived/batch`). * One request resolves the whole dashboard grid server-side instead of N * concurrent single-metric reads sharing the Prisma pool. Keyed by the * sorted token list so the same grid always hits one cache entry; sits * under the `["insights", "derived"]` prefix so a measurement-write * invalidation fan-out reaches it exactly like the single-metric reads. */ insightsDerivedBatch: (tokens: readonly string[]) => ["insights", "derived", "batch", [...tokens].sort().join(",")] as const, /** * v1.10.0 — FDR-controlled correlation discovery * (`/api/insights/correlations`). Read-only descriptive surface; the * `["insights"]` prefix keeps it in the existing invalidation fan-out. */ insightsCorrelations: () => ["insights", "correlations"] as const, /** * v1.4.41 W-FRONTEND-FACTORY — Settings → AI surfaces (provider chain, * insights settings, user provider preference) and the targets editor * all read these endpoints; centralising the keys keeps invalidation * symmetrical with the user-thresholds + auth surfaces. */ insightsSettings: () => ["insights", "settings"] as const, insightsProviderChain: () => ["insights", "provider-chain"] as const, insightsGlp1Timeline: (limit: number | string) => ["insights", "glp1-timeline", limit] as const, /** * v1.5.5 — per-user insights tile layout (mirrors * `dashboardWidgets`). The Settings UI + the iOS client + the * `/insights` shell all read this key; the PUT mutation invalidates * it on save so every consumer paints the new layout in lockstep. */ insightsLayout: () => ["user", "insightsLayout"] as const, /** * v1.11.4 item J — bounded 30-day daily-aggregate read backing the * Insights Trends-row deterministic caption (`trend-descriptor.ts`). * Keyed by the comma-joined measurement type set so each card's slot * caches its own small window (≤ 30 rollup rows). Distinct from * `chartData(...)` so the caption never re-keys when the chart's * internal value-mode / scale / range state changes; it only needs the * raw 30-day series to derive direction + magnitude. Shares the * `["trend-series"]` invalidation prefix so a measurement write * refreshes the caption in lockstep with the chart. */ insightsTrendSeries: (types: string) => ["trend-series", types] as const, /** * v1.21.2 (A1) — per-metric "Coach read" strip * (`/api/insights/coach-read?metric=`). One generic route * backs every metric sub-page, so the key is parameterised by the * MeasurementType. Pure compute over the baseline + correlation engines — * the `["insights"]` prefix keeps it in the standard invalidation fan-out * (a measurement write busts it so the placement refreshes). */ insightsCoachRead: (metric: string) => ["insights", "coach-read", metric] as const, /** * v1.25 — baseline-drift read (`/api/insights/health-status`). Combines the * personal-band deviations + the dated changepoint shifts into one awareness * card. Pure compute over the rollup tier; the `["insights"]` prefix keeps it * in the standard invalidation fan-out (a measurement write busts it). */ insightsHealthStatus: () => ["insights", "health-status"] as const, /** * v1.25 — breathing-disturbance screening read * (`/api/insights/breathing-screening`). Last ~30 nights of the per-night * index + device-flagged events. The `["insights"]` prefix carries the * invalidation fan-out from an Apple Health sleep batch write. */ insightsBreathingScreening: () => ["insights", "breathing-screening"] as const, /** * v1.25 — "what changed since your last panel" read * (`/api/insights/labs-changes`). The two most-recent numeric lab panels' * shared-analyte deltas. The `["insights"]` prefix keeps it in the standard * invalidation fan-out. */ insightsLabsChanges: () => ["insights", "labs-changes"] as const, };