mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
feat(sources): add Nightscout, Polar and Oura as measurement sources
Introduce the schema foundation the glucose and wearable integrations build on: the NIGHTSCOUT, POLAR and OURA measurement sources, encrypted credential columns for each (Nightscout carries a base URL, an API token and a private-host opt-in flag; Polar and Oura carry OAuth tokens), and their integration keys. The recovery source ladder now ranks WHOOP, then Oura, then Polar over the computed proxy. Additive migration only — new enum values and nullable columns, no backfill. Nightscout is glucose-only and stays off the wearable priority ladders.
This commit is contained in:
commit
4884f019b7
7 files changed
+517
-24
No files matched your search
@@ -1634,6 +1634,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
- in: query
|
||||
name: groupBy
|
||||
schema:
|
||||
@@ -2080,6 +2083,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
externalId:
|
||||
type: string
|
||||
maxLength: 128
|
||||
@@ -3083,6 +3089,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
activeEnergy:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3096,6 +3105,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
walkingRunningDistance:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3109,6 +3121,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
flightsClimbed:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3122,6 +3137,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
sleep:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3135,6 +3153,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
weight:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3148,6 +3169,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bloodPressure:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3161,6 +3185,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
pulse:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3174,6 +3201,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyFat:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3187,6 +3217,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3200,6 +3233,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
spo2:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3213,6 +3249,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
hrv:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3226,6 +3265,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
restingHeartRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3239,6 +3281,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
vo2Max:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3252,6 +3297,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
skinTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3265,6 +3313,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
respiratoryRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3278,6 +3329,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
recovery:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3291,6 +3345,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
metricPriority:
|
||||
type: object
|
||||
properties:
|
||||
@@ -3307,6 +3364,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
activeEnergy:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3320,6 +3380,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
walkingRunningDistance:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3333,6 +3396,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
flightsClimbed:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3346,6 +3412,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
sleep:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3359,6 +3428,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
weight:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3372,6 +3444,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bloodPressure:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3385,6 +3460,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
pulse:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3398,6 +3476,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyFat:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3411,6 +3492,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3424,6 +3508,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
spo2:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3437,6 +3524,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
hrv:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3450,6 +3540,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
restingHeartRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3463,6 +3556,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
vo2Max:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3476,6 +3572,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
skinTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3489,6 +3588,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
respiratoryRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3502,6 +3604,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
recovery:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -3515,6 +3620,9 @@ paths:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
deviceTypePriority:
|
||||
type: object
|
||||
properties:
|
||||
@@ -8157,6 +8265,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
notes:
|
||||
anyOf:
|
||||
- type: string
|
||||
@@ -8583,6 +8694,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
notes:
|
||||
anyOf:
|
||||
- type: string
|
||||
@@ -8797,6 +8911,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
- type: "null"
|
||||
start:
|
||||
type: string
|
||||
@@ -8914,6 +9031,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
- type: "null"
|
||||
start:
|
||||
type: string
|
||||
@@ -9120,6 +9240,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
externalId:
|
||||
anyOf:
|
||||
- type: string
|
||||
@@ -9225,6 +9348,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
externalId:
|
||||
anyOf:
|
||||
- type: string
|
||||
@@ -11176,6 +11302,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
activeEnergy:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11189,6 +11318,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
walkingRunningDistance:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11202,6 +11334,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
flightsClimbed:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11215,6 +11350,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
sleep:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11228,6 +11366,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
weight:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11241,6 +11382,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bloodPressure:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11254,6 +11398,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
pulse:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11267,6 +11414,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyFat:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11280,6 +11430,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11293,6 +11446,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
spo2:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11306,6 +11462,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
hrv:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11319,6 +11478,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
restingHeartRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11332,6 +11494,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
vo2Max:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11345,6 +11510,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
skinTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11358,6 +11526,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
respiratoryRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11371,6 +11542,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
recovery:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11384,6 +11558,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
metricPriority:
|
||||
type: object
|
||||
properties:
|
||||
@@ -11400,6 +11577,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
activeEnergy:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11413,6 +11593,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
walkingRunningDistance:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11426,6 +11609,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
flightsClimbed:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11439,6 +11625,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
sleep:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11452,6 +11641,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
weight:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11465,6 +11657,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bloodPressure:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11478,6 +11673,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
pulse:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11491,6 +11689,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyFat:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11504,6 +11705,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11517,6 +11721,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
spo2:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11530,6 +11737,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
hrv:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11543,6 +11753,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
restingHeartRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11556,6 +11769,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
vo2Max:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11569,6 +11785,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
skinTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11582,6 +11801,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
respiratoryRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11595,6 +11817,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
recovery:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11608,6 +11833,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
additionalProperties: false
|
||||
deviceTypePriority:
|
||||
type: object
|
||||
@@ -11670,6 +11898,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
activeEnergy:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11683,6 +11914,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
walkingRunningDistance:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11696,6 +11930,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
flightsClimbed:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11709,6 +11946,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
sleep:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11722,6 +11962,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
weight:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11735,6 +11978,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bloodPressure:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11748,6 +11994,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
pulse:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11761,6 +12010,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyFat:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11774,6 +12026,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11787,6 +12042,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
spo2:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11800,6 +12058,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
hrv:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11813,6 +12074,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
restingHeartRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11826,6 +12090,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
vo2Max:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11839,6 +12106,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
skinTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11852,6 +12122,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
respiratoryRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11865,6 +12138,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
recovery:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11878,6 +12154,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
metricPriority:
|
||||
type: object
|
||||
properties:
|
||||
@@ -11894,6 +12173,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
activeEnergy:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11907,6 +12189,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
walkingRunningDistance:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11920,6 +12205,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
flightsClimbed:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11933,6 +12221,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
sleep:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11946,6 +12237,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
weight:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11959,6 +12253,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bloodPressure:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11972,6 +12269,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
pulse:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11985,6 +12285,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyFat:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -11998,6 +12301,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
bodyTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -12011,6 +12317,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
spo2:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -12024,6 +12333,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
hrv:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -12037,6 +12349,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
restingHeartRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -12050,6 +12365,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
vo2Max:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -12063,6 +12381,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
skinTemperature:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -12076,6 +12397,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
respiratoryRate:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -12089,6 +12413,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
recovery:
|
||||
maxItems: 8
|
||||
type: array
|
||||
@@ -12102,6 +12429,9 @@ components:
|
||||
- COMPUTED
|
||||
- WHOOP
|
||||
- FITBIT
|
||||
- NIGHTSCOUT
|
||||
- POLAR
|
||||
- OURA
|
||||
additionalProperties: false
|
||||
deviceTypePriority:
|
||||
type: object
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
-- v1.17.0 — schema foundation for three new measurement sources: Nightscout
|
||||
-- glucose (F1) and Polar + Oura OAuth wearables (F4).
|
||||
--
|
||||
-- Purely-additive: three enum-extensions on `measurement_source` plus eight
|
||||
-- new nullable columns on `users` (encrypted credentials + one boolean flag).
|
||||
-- No backfill, no existing row touched, no new tables. The feature waves add
|
||||
-- their own connection / oauth-state tables later; this step only unblocks
|
||||
-- them from colliding on the enum + the credential surface.
|
||||
--
|
||||
-- 1. `measurement_source` += `NIGHTSCOUT`, `POLAR`, `OURA` for the
|
||||
-- server-side native ingest of each source.
|
||||
-- 2. `users` += Nightscout base URL + token (encrypted) + an
|
||||
-- `allow_private_host` opt-in boolean (default false) that lets a
|
||||
-- self-hoster point HealthLog at a private/LAN Nightscout instance past
|
||||
-- the public-host SSRF floor.
|
||||
-- 3. `users` += Polar OAuth credentials (access / refresh token + user id),
|
||||
-- encrypted, mirroring the WHOOP credential columns.
|
||||
-- 4. `users` += Oura OAuth credentials (access / refresh token), encrypted,
|
||||
-- mirroring the WHOOP credential columns.
|
||||
--
|
||||
-- Idempotent guards (`IF NOT EXISTS`) make reruns safe. Forward-only.
|
||||
--
|
||||
-- Reversibility: Postgres cannot remove an enum value, so the three sources
|
||||
-- stay; with no rows carrying them they are inert. The columns drop with
|
||||
-- `DROP COLUMN IF EXISTS`.
|
||||
|
||||
-- ── 1. measurement_source — append the three server-owned sources ──────
|
||||
ALTER TYPE "measurement_source" ADD VALUE IF NOT EXISTS 'NIGHTSCOUT';
|
||||
ALTER TYPE "measurement_source" ADD VALUE IF NOT EXISTS 'POLAR';
|
||||
ALTER TYPE "measurement_source" ADD VALUE IF NOT EXISTS 'OURA';
|
||||
|
||||
-- ── 2. users — Nightscout credentials + private-host opt-in ────────────
|
||||
ALTER TABLE "users"
|
||||
ADD COLUMN IF NOT EXISTS "nightscout_url_encrypted" TEXT;
|
||||
ALTER TABLE "users"
|
||||
ADD COLUMN IF NOT EXISTS "nightscout_token_encrypted" TEXT;
|
||||
ALTER TABLE "users"
|
||||
ADD COLUMN IF NOT EXISTS "nightscout_allow_private_host" BOOLEAN NOT NULL DEFAULT false;
|
||||
|
||||
-- ── 3. users — Polar OAuth credentials (encrypted at app level) ────────
|
||||
ALTER TABLE "users"
|
||||
ADD COLUMN IF NOT EXISTS "polar_access_token_encrypted" TEXT;
|
||||
ALTER TABLE "users"
|
||||
ADD COLUMN IF NOT EXISTS "polar_refresh_token_encrypted" TEXT;
|
||||
ALTER TABLE "users"
|
||||
ADD COLUMN IF NOT EXISTS "polar_user_id_encrypted" TEXT;
|
||||
|
||||
-- ── 4. users — Oura OAuth credentials (encrypted at app level) ─────────
|
||||
ALTER TABLE "users"
|
||||
ADD COLUMN IF NOT EXISTS "oura_access_token_encrypted" TEXT;
|
||||
ALTER TABLE "users"
|
||||
ADD COLUMN IF NOT EXISTS "oura_refresh_token_encrypted" TEXT;
|
||||
@@ -109,6 +109,32 @@ model User {
|
||||
fitbitClientIdEncrypted String? @map("fitbit_client_id_encrypted")
|
||||
fitbitClientSecretEncrypted String? @map("fitbit_client_secret_encrypted")
|
||||
|
||||
// v1.17.0 — Nightscout glucose integration (F1, per-user, encrypted at app
|
||||
// level). A self-hoster points HealthLog at their own Nightscout instance:
|
||||
// the base URL + the API token / secret are stored encrypted. By default
|
||||
// the base URL must resolve to a public host (the SSRF floor); a self-hoster
|
||||
// running Nightscout on a private/LAN network can flip
|
||||
// `nightscoutAllowPrivateHost` to opt that instance past the public-host
|
||||
// requirement explicitly.
|
||||
nightscoutUrlEncrypted String? @map("nightscout_url_encrypted")
|
||||
nightscoutTokenEncrypted String? @map("nightscout_token_encrypted")
|
||||
nightscoutAllowPrivateHost Boolean @default(false) @map("nightscout_allow_private_host")
|
||||
|
||||
// v1.17.0 — Polar OAuth credentials (F4, per-user, encrypted at app level).
|
||||
// Mirrors the WHOOP credential columns: the per-app authorized-user cap on
|
||||
// Polar AccessLink makes a single shared app unworkable for a multi-operator
|
||||
// product, so each self-hoster registers their own Polar app and the OAuth
|
||||
// tokens are stored encrypted.
|
||||
polarAccessTokenEncrypted String? @map("polar_access_token_encrypted")
|
||||
polarRefreshTokenEncrypted String? @map("polar_refresh_token_encrypted")
|
||||
polarUserIdEncrypted String? @map("polar_user_id_encrypted")
|
||||
|
||||
// v1.17.0 — Oura OAuth credentials (F4, per-user, encrypted at app level).
|
||||
// Mirrors the WHOOP credential columns; OAuth access/refresh tokens stored
|
||||
// encrypted.
|
||||
ouraAccessTokenEncrypted String? @map("oura_access_token_encrypted")
|
||||
ouraRefreshTokenEncrypted String? @map("oura_refresh_token_encrypted")
|
||||
|
||||
// moodLog integration (per-user, encrypted)
|
||||
moodLogUrlEncrypted String? @map("mood_log_url_encrypted")
|
||||
moodLogApiKeyEncrypted String? @map("mood_log_api_key_encrypted")
|
||||
@@ -790,6 +816,19 @@ enum MeasurementSource {
|
||||
// (no client write path); rejected on batch + single POST like WITHINGS/WHOOP.
|
||||
// iOS DTO mirrors this exact spelling so /api/sync/changes decodes the rows.
|
||||
FITBIT
|
||||
// v1.17.0 — Nightscout glucose integration (F1). Server-owned (no client
|
||||
// write path); glucose rows ingest from the user's Nightscout instance.
|
||||
// Rejected on batch + single POST like WITHINGS/WHOOP/FITBIT. iOS DTO
|
||||
// mirrors this exact spelling so /api/sync/changes decodes the rows.
|
||||
NIGHTSCOUT
|
||||
// v1.17.0 — Polar OAuth integration (F4). Server-owned (no client write
|
||||
// path); rejected on batch + single POST like WITHINGS/WHOOP/FITBIT. iOS
|
||||
// DTO mirrors this exact spelling so /api/sync/changes decodes the rows.
|
||||
POLAR
|
||||
// v1.17.0 — Oura OAuth integration (F4). Server-owned (no client write
|
||||
// path); rejected on batch + single POST like WITHINGS/WHOOP/FITBIT. iOS
|
||||
// DTO mirrors this exact spelling so /api/sync/changes decodes the rows.
|
||||
OURA
|
||||
|
||||
@@map("measurement_source")
|
||||
}
|
||||
|
||||
@@ -39,7 +39,15 @@ import { auditLog } from "@/lib/auth/audit";
|
||||
import { getEvent } from "@/lib/logging/context";
|
||||
import { dispatchNotification } from "@/lib/notifications/dispatcher";
|
||||
|
||||
export type IntegrationKey = "withings" | "whoop" | "fitbit" | "moodlog";
|
||||
export type IntegrationKey =
|
||||
| "withings"
|
||||
| "whoop"
|
||||
| "fitbit"
|
||||
// v1.17.0 — Nightscout glucose (F1) + Polar / Oura OAuth (F4).
|
||||
| "nightscout"
|
||||
| "polar"
|
||||
| "oura"
|
||||
| "moodlog";
|
||||
|
||||
/**
|
||||
* Failure kinds carried into `recordSyncFailure`.
|
||||
@@ -774,6 +782,22 @@ export interface AlertInput {
|
||||
* kind is a one-row table edit instead of two more arms in two
|
||||
* different ternary stacks (the style-guide forbids nested ternaries).
|
||||
*/
|
||||
/**
|
||||
* Display label per `IntegrationKey`. A one-row table edit replaces the
|
||||
* nested-ternary chain the admin-alert formatter used to carry — adding
|
||||
* a new integration is a single line here instead of another arm in a
|
||||
* ternary stack (the style-guide forbids nested ternaries).
|
||||
*/
|
||||
const INTEGRATION_LABELS: Record<IntegrationKey, string> = {
|
||||
withings: "Withings",
|
||||
whoop: "WHOOP",
|
||||
fitbit: "Fitbit",
|
||||
nightscout: "Nightscout",
|
||||
polar: "Polar",
|
||||
oura: "Oura",
|
||||
moodlog: "moodLog",
|
||||
};
|
||||
|
||||
const FAILURE_KIND_COPY: Record<
|
||||
FailureKind,
|
||||
{ reason: string; action: string }
|
||||
@@ -819,14 +843,7 @@ export function formatAdminAlertPayload(input: AlertInput): {
|
||||
message: string;
|
||||
metadata: Record<string, unknown>;
|
||||
} {
|
||||
const integrationLabel =
|
||||
input.integration === "withings"
|
||||
? "Withings"
|
||||
: input.integration === "whoop"
|
||||
? "WHOOP"
|
||||
: input.integration === "fitbit"
|
||||
? "Fitbit"
|
||||
: "moodLog";
|
||||
const integrationLabel = INTEGRATION_LABELS[input.integration];
|
||||
const subjectLabel = input.subjectLabel ?? input.userId;
|
||||
const { reason: reasonLabel, action: actionLabel } =
|
||||
FAILURE_KIND_COPY[input.kind];
|
||||
|
||||
@@ -217,11 +217,35 @@ describe("DEFAULT_SOURCE_PRIORITY", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("ranks WHOOP native recovery above the COMPUTED proxy (v1.11)", () => {
|
||||
// v1.11.0 — native-vs-derived: the device-native Recovery outranks
|
||||
it("ranks device-native recovery above the COMPUTED proxy (v1.11/v1.17)", () => {
|
||||
// v1.11.0 — native-vs-derived: a device-native Recovery outranks
|
||||
// HealthLog's COMPUTED proxy when both exist, with the proxy as the
|
||||
// fallback for users without a strap.
|
||||
expect(DEFAULT_SOURCE_PRIORITY.recovery).toEqual(["WHOOP", "COMPUTED"]);
|
||||
// fallback for users without a wearable. v1.17.0 — Oura readiness and
|
||||
// Polar nightly recovery slot between WHOOP and the proxy.
|
||||
expect(DEFAULT_SOURCE_PRIORITY.recovery).toEqual([
|
||||
"WHOOP",
|
||||
"OURA",
|
||||
"POLAR",
|
||||
"COMPUTED",
|
||||
]);
|
||||
// The COMPUTED proxy stays the last resort regardless of how many
|
||||
// native wearables precede it.
|
||||
expect(DEFAULT_SOURCE_PRIORITY.recovery.at(-1)).toBe("COMPUTED");
|
||||
});
|
||||
|
||||
it("slots Polar + Oura below the established wearables (v1.17)", () => {
|
||||
// v1.17.0 — Polar / Oura are worn wearables in the same overnight class
|
||||
// as WHOOP/Fitbit; they rank below the established straps but above the
|
||||
// iPhone-relayed HealthKit summary and the Withings nightly summary on
|
||||
// the recovery-input ladders.
|
||||
for (const key of ["sleep", "hrv", "restingHeartRate"] as const) {
|
||||
const ladder = DEFAULT_SOURCE_PRIORITY[key];
|
||||
expect(ladder).toContain("OURA");
|
||||
expect(ladder).toContain("POLAR");
|
||||
expect(ladder.indexOf("OURA")).toBeLessThan(ladder.indexOf("APPLE_HEALTH"));
|
||||
expect(ladder.indexOf("POLAR")).toBeLessThan(ladder.indexOf("APPLE_HEALTH"));
|
||||
expect(ladder.indexOf("WHOOP")).toBeLessThan(ladder.indexOf("OURA"));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -143,6 +143,18 @@ export const measurementSourceEnum = z.enum([
|
||||
// (no client write path), exactly like WHOOP. Part of this enum so the
|
||||
// read/response shapes (and the iOS decoder) can decode the rows it surfaces.
|
||||
"FITBIT",
|
||||
// v1.17.0 — Nightscout glucose integration (F1). Server-owned (no client
|
||||
// write path), exactly like WHOOP/FITBIT. Part of this enum so the
|
||||
// read/response shapes (and the iOS decoder) can decode the rows it surfaces.
|
||||
"NIGHTSCOUT",
|
||||
// v1.17.0 — Polar OAuth integration (F4). Server-owned (no client write
|
||||
// path), exactly like WHOOP/FITBIT. Part of this enum so the read/response
|
||||
// shapes (and the iOS decoder) can decode the rows it surfaces.
|
||||
"POLAR",
|
||||
// v1.17.0 — Oura OAuth integration (F4). Server-owned (no client write
|
||||
// path), exactly like WHOOP/FITBIT. Part of this enum so the read/response
|
||||
// shapes (and the iOS decoder) can decode the rows it surfaces.
|
||||
"OURA",
|
||||
]);
|
||||
|
||||
/**
|
||||
|
||||
@@ -226,27 +226,46 @@ export const DEFAULT_SOURCE_PRIORITY: Required<MetricPriority> = {
|
||||
// the iPhone-relayed HealthKit summary or the Withings nightly summary.
|
||||
// v1.12.0 — Fitbit is a wrist wearable in the same class as WHOOP but with
|
||||
// a lower-fidelity nightly estimate, so it ranks just below it.
|
||||
sleep: ["WHOOP", "FITBIT", "APPLE_HEALTH", "WITHINGS"],
|
||||
hrv: ["WHOOP", "FITBIT", "APPLE_HEALTH", "WITHINGS"],
|
||||
restingHeartRate: ["WHOOP", "FITBIT", "APPLE_HEALTH", "WITHINGS"],
|
||||
// v1.17.0 — Polar + Oura are worn wearables in the same overnight-sampling
|
||||
// class as WHOOP/Fitbit; they rank below the established straps but above
|
||||
// the iPhone-relayed HealthKit summary and the Withings nightly summary.
|
||||
sleep: ["WHOOP", "FITBIT", "OURA", "POLAR", "APPLE_HEALTH", "WITHINGS"],
|
||||
hrv: ["WHOOP", "FITBIT", "OURA", "POLAR", "APPLE_HEALTH", "WITHINGS"],
|
||||
restingHeartRate: [
|
||||
"WHOOP",
|
||||
"FITBIT",
|
||||
"OURA",
|
||||
"POLAR",
|
||||
"APPLE_HEALTH",
|
||||
"WITHINGS",
|
||||
],
|
||||
// A real scale beats a strap's body-measurement estimate for weight.
|
||||
weight: ["WITHINGS", "APPLE_HEALTH", "MANUAL", "WHOOP", "FITBIT"],
|
||||
bloodPressure: ["WITHINGS", "APPLE_HEALTH", "MANUAL"],
|
||||
pulse: ["WITHINGS", "APPLE_HEALTH", "MANUAL", "FITBIT"],
|
||||
pulse: ["WITHINGS", "APPLE_HEALTH", "MANUAL", "FITBIT", "POLAR", "OURA"],
|
||||
bodyFat: ["WITHINGS", "APPLE_HEALTH", "MANUAL", "FITBIT"],
|
||||
bodyTemperature: ["WITHINGS", "APPLE_HEALTH", "MANUAL", "FITBIT"],
|
||||
// Withings ScanWatch pulse-ox is the primary SpO2 sensor; WHOOP second,
|
||||
// Fitbit third.
|
||||
spo2: ["WITHINGS", "WHOOP", "FITBIT", "APPLE_HEALTH", "MANUAL"],
|
||||
// Fitbit third, Oura's ring fourth.
|
||||
spo2: ["WITHINGS", "WHOOP", "FITBIT", "OURA", "APPLE_HEALTH", "MANUAL"],
|
||||
vo2Max: ["WITHINGS", "APPLE_HEALTH", "FITBIT", "MANUAL"],
|
||||
// v1.11.0 — new WHOOP-overlapping keys. ScanWatch dermal reading is the
|
||||
// primary skin-temperature sensor; WHOOP's strap is second, Fitbit third.
|
||||
skinTemperature: ["WITHINGS", "WHOOP", "FITBIT", "APPLE_HEALTH"],
|
||||
respiratoryRate: ["WHOOP", "FITBIT", "APPLE_HEALTH", "WITHINGS"],
|
||||
// primary skin-temperature sensor; WHOOP's strap is second, Fitbit third,
|
||||
// Oura's ring fourth.
|
||||
skinTemperature: ["WITHINGS", "WHOOP", "FITBIT", "OURA", "APPLE_HEALTH"],
|
||||
respiratoryRate: [
|
||||
"WHOOP",
|
||||
"FITBIT",
|
||||
"OURA",
|
||||
"POLAR",
|
||||
"APPLE_HEALTH",
|
||||
"WITHINGS",
|
||||
],
|
||||
// v1.11.0 — native-vs-derived recovery. WHOOP's device-native Recovery
|
||||
// outranks HealthLog's COMPUTED proxy when both exist; the proxy is the
|
||||
// fallback for users without a strap.
|
||||
recovery: ["WHOOP", "COMPUTED"],
|
||||
// fallback for users without a strap. v1.17.0 — Oura readiness + Polar
|
||||
// nightly recovery slot below WHOOP and above the computed proxy.
|
||||
recovery: ["WHOOP", "OURA", "POLAR", "COMPUTED"],
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user