@nativesquare/soma 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.d.ts +283 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +328 -0
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts +2 -0
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +77 -0
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/garmin.d.ts +164 -0
- package/dist/component/garmin.d.ts.map +1 -0
- package/dist/component/garmin.js +609 -0
- package/dist/component/garmin.js.map +1 -0
- package/dist/component/public.d.ts +761 -761
- package/dist/component/schema.d.ts +405 -388
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +14 -2
- package/dist/component/schema.js.map +1 -1
- package/dist/component/strava.d.ts +5 -4
- package/dist/component/strava.d.ts.map +1 -1
- package/dist/component/strava.js +18 -1
- package/dist/component/strava.js.map +1 -1
- package/dist/component/validators/activity.d.ts +42 -42
- package/dist/component/validators/body.d.ts +47 -47
- package/dist/component/validators/daily.d.ts +17 -17
- package/dist/component/validators/plannedWorkout.d.ts +5 -5
- package/dist/component/validators/samples.d.ts +2 -2
- package/dist/component/validators/shared.d.ts +17 -17
- package/dist/component/validators/sleep.d.ts +17 -17
- package/dist/garmin/activity.d.ts +101 -0
- package/dist/garmin/activity.d.ts.map +1 -0
- package/dist/garmin/activity.js +207 -0
- package/dist/garmin/activity.js.map +1 -0
- package/dist/garmin/auth.d.ts +65 -0
- package/dist/garmin/auth.d.ts.map +1 -0
- package/dist/garmin/auth.js +155 -0
- package/dist/garmin/auth.js.map +1 -0
- package/dist/garmin/body.d.ts +26 -0
- package/dist/garmin/body.d.ts.map +1 -0
- package/dist/garmin/body.js +44 -0
- package/dist/garmin/body.js.map +1 -0
- package/dist/garmin/client.d.ts +99 -0
- package/dist/garmin/client.d.ts.map +1 -0
- package/dist/garmin/client.js +153 -0
- package/dist/garmin/client.js.map +1 -0
- package/dist/garmin/daily.d.ts +74 -0
- package/dist/garmin/daily.d.ts.map +1 -0
- package/dist/garmin/daily.js +143 -0
- package/dist/garmin/daily.js.map +1 -0
- package/dist/garmin/index.d.ts +20 -0
- package/dist/garmin/index.d.ts.map +1 -0
- package/dist/garmin/index.js +21 -0
- package/dist/garmin/index.js.map +1 -0
- package/dist/garmin/maps/activity-type.d.ts +7 -0
- package/dist/garmin/maps/activity-type.d.ts.map +1 -0
- package/dist/garmin/maps/activity-type.js +98 -0
- package/dist/garmin/maps/activity-type.js.map +1 -0
- package/dist/garmin/maps/sleep-level.d.ts +6 -0
- package/dist/garmin/maps/sleep-level.d.ts.map +1 -0
- package/dist/garmin/maps/sleep-level.js +21 -0
- package/dist/garmin/maps/sleep-level.js.map +1 -0
- package/dist/garmin/menstruation.d.ts +23 -0
- package/dist/garmin/menstruation.d.ts.map +1 -0
- package/dist/garmin/menstruation.js +34 -0
- package/dist/garmin/menstruation.js.map +1 -0
- package/dist/garmin/sleep.d.ts +62 -0
- package/dist/garmin/sleep.d.ts.map +1 -0
- package/dist/garmin/sleep.js +125 -0
- package/dist/garmin/sleep.js.map +1 -0
- package/dist/garmin/sync.d.ts +39 -0
- package/dist/garmin/sync.d.ts.map +1 -0
- package/dist/garmin/sync.js +175 -0
- package/dist/garmin/sync.js.map +1 -0
- package/dist/garmin/types.d.ts +212 -0
- package/dist/garmin/types.d.ts.map +1 -0
- package/dist/garmin/types.js +8 -0
- package/dist/garmin/types.js.map +1 -0
- package/dist/validators.d.ts +331 -331
- package/package.json +5 -1
- package/src/client/index.ts +446 -1
- package/src/component/_generated/api.ts +2 -0
- package/src/component/_generated/component.ts +89 -0
- package/src/component/garmin.ts +711 -0
- package/src/component/schema.ts +15 -2
- package/src/component/strava.ts +23 -1
- package/src/garmin/activity.test.ts +178 -0
- package/src/garmin/activity.ts +272 -0
- package/src/garmin/auth.test.ts +128 -0
- package/src/garmin/auth.ts +249 -0
- package/src/garmin/body.ts +59 -0
- package/src/garmin/client.ts +254 -0
- package/src/garmin/daily.ts +211 -0
- package/src/garmin/index.ts +76 -0
- package/src/garmin/maps/activity-type.test.ts +78 -0
- package/src/garmin/maps/activity-type.ts +116 -0
- package/src/garmin/maps/sleep-level.ts +22 -0
- package/src/garmin/menstruation.ts +42 -0
- package/src/garmin/sleep.test.ts +110 -0
- package/src/garmin/sleep.ts +170 -0
- package/src/garmin/sync.ts +223 -0
- package/src/garmin/types.ts +338 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// ─── Daily Transformer ───────────────────────────────────────────────────────
|
|
2
|
+
// Transforms a Garmin daily wellness summary into the Soma Daily schema shape.
|
|
3
|
+
/**
|
|
4
|
+
* Transform a Garmin daily summary into a Soma Daily document shape.
|
|
5
|
+
*
|
|
6
|
+
* @param daily - The Garmin daily summary from the Health API
|
|
7
|
+
* @returns Soma Daily fields (without connectionId/userId)
|
|
8
|
+
*/
|
|
9
|
+
export function transformDaily(daily) {
|
|
10
|
+
const startMs = daily.startTimeInSeconds * 1000;
|
|
11
|
+
const endMs = startMs + daily.durationInSeconds * 1000;
|
|
12
|
+
return {
|
|
13
|
+
metadata: {
|
|
14
|
+
start_time: new Date(startMs).toISOString(),
|
|
15
|
+
end_time: new Date(endMs).toISOString(),
|
|
16
|
+
upload_type: 1, // Automatic
|
|
17
|
+
},
|
|
18
|
+
active_durations_data: buildActiveDurationsData(daily),
|
|
19
|
+
calories_data: buildCaloriesData(daily),
|
|
20
|
+
distance_data: buildDistanceData(daily),
|
|
21
|
+
heart_rate_data: buildHeartRateData(daily),
|
|
22
|
+
oxygen_data: buildOxygenData(daily),
|
|
23
|
+
stress_data: buildStressData(daily),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
27
|
+
function buildActiveDurationsData(daily) {
|
|
28
|
+
if (daily.activeTimeInSeconds == null &&
|
|
29
|
+
daily.moderateIntensityDurationInSeconds == null &&
|
|
30
|
+
daily.vigorousIntensityDurationInSeconds == null) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
activity_seconds: daily.activeTimeInSeconds,
|
|
35
|
+
moderate_intensity_seconds: daily.moderateIntensityDurationInSeconds,
|
|
36
|
+
vigorous_intensity_seconds: daily.vigorousIntensityDurationInSeconds,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function buildCaloriesData(daily) {
|
|
40
|
+
if (daily.activeKilocalories == null && daily.bmrKilocalories == null) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
const total = (daily.activeKilocalories ?? 0) + (daily.bmrKilocalories ?? 0);
|
|
44
|
+
return {
|
|
45
|
+
net_activity_calories: daily.activeKilocalories,
|
|
46
|
+
BMR_calories: daily.bmrKilocalories,
|
|
47
|
+
total_burned_calories: total || undefined,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function buildDistanceData(daily) {
|
|
51
|
+
if (daily.distanceInMeters == null &&
|
|
52
|
+
daily.steps == null &&
|
|
53
|
+
daily.floorsClimbed == null) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
distance_meters: daily.distanceInMeters,
|
|
58
|
+
steps: daily.steps,
|
|
59
|
+
floors_climbed: daily.floorsClimbed,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function buildHeartRateData(daily) {
|
|
63
|
+
const hasSummary = daily.averageHeartRateInBeatsPerMinute != null ||
|
|
64
|
+
daily.maxHeartRateInBeatsPerMinute != null ||
|
|
65
|
+
daily.restingHeartRateInBeatsPerMinute != null;
|
|
66
|
+
const hasSamples = daily.timeOffsetHeartRateSamples != null &&
|
|
67
|
+
Object.keys(daily.timeOffsetHeartRateSamples).length > 0;
|
|
68
|
+
if (!hasSummary && !hasSamples)
|
|
69
|
+
return undefined;
|
|
70
|
+
const hrSamples = hasSamples
|
|
71
|
+
? buildTimeOffsetSamples(daily.startTimeInSeconds, daily.timeOffsetHeartRateSamples, (bpm) => ({ bpm }))
|
|
72
|
+
: undefined;
|
|
73
|
+
return {
|
|
74
|
+
summary: hasSummary
|
|
75
|
+
? {
|
|
76
|
+
avg_hr_bpm: daily.averageHeartRateInBeatsPerMinute,
|
|
77
|
+
max_hr_bpm: daily.maxHeartRateInBeatsPerMinute,
|
|
78
|
+
min_hr_bpm: daily.minHeartRateInBeatsPerMinute,
|
|
79
|
+
resting_hr_bpm: daily.restingHeartRateInBeatsPerMinute,
|
|
80
|
+
}
|
|
81
|
+
: undefined,
|
|
82
|
+
detailed: hrSamples && hrSamples.length > 0
|
|
83
|
+
? { hr_samples: hrSamples }
|
|
84
|
+
: undefined,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function buildOxygenData(daily) {
|
|
88
|
+
if (daily.averageSpo2Value == null && daily.timeOffsetSpo2Values == null) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
const samples = daily.timeOffsetSpo2Values != null
|
|
92
|
+
? buildTimeOffsetSamples(daily.startTimeInSeconds, daily.timeOffsetSpo2Values, (pct) => ({ percentage: pct }))
|
|
93
|
+
: undefined;
|
|
94
|
+
return {
|
|
95
|
+
avg_saturation_percentage: daily.averageSpo2Value,
|
|
96
|
+
saturation_samples: samples && samples.length > 0 ? samples : undefined,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function buildStressData(daily) {
|
|
100
|
+
const hasStress = daily.averageStressLevel != null ||
|
|
101
|
+
daily.maxStressLevel != null ||
|
|
102
|
+
daily.stressDurationInSeconds != null;
|
|
103
|
+
const hasStressSamples = daily.timeOffsetStressLevelValues != null &&
|
|
104
|
+
Object.keys(daily.timeOffsetStressLevelValues).length > 0;
|
|
105
|
+
const hasBodyBatterySamples = daily.timeOffsetBodyBatteryValues != null &&
|
|
106
|
+
Object.keys(daily.timeOffsetBodyBatteryValues).length > 0;
|
|
107
|
+
if (!hasStress && !hasStressSamples && !hasBodyBatterySamples) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
const stressSamples = hasStressSamples
|
|
111
|
+
? buildTimeOffsetSamples(daily.startTimeInSeconds, daily.timeOffsetStressLevelValues, (level) => ({ level }))
|
|
112
|
+
: undefined;
|
|
113
|
+
const bodyBatterySamples = hasBodyBatterySamples
|
|
114
|
+
? buildTimeOffsetSamples(daily.startTimeInSeconds, daily.timeOffsetBodyBatteryValues, (level) => ({ level }))
|
|
115
|
+
: undefined;
|
|
116
|
+
return {
|
|
117
|
+
avg_stress_level: daily.averageStressLevel,
|
|
118
|
+
max_stress_level: daily.maxStressLevel,
|
|
119
|
+
stress_duration_seconds: daily.stressDurationInSeconds,
|
|
120
|
+
rest_stress_duration_seconds: daily.restStressDurationInSeconds,
|
|
121
|
+
activity_stress_duration_seconds: daily.activityStressDurationInSeconds,
|
|
122
|
+
low_stress_duration_seconds: daily.lowStressDurationInSeconds,
|
|
123
|
+
medium_stress_duration_seconds: daily.mediumStressDurationInSeconds,
|
|
124
|
+
high_stress_duration_seconds: daily.highStressDurationInSeconds,
|
|
125
|
+
samples: stressSamples && stressSamples.length > 0 ? stressSamples : undefined,
|
|
126
|
+
body_battery_samples: bodyBatterySamples && bodyBatterySamples.length > 0
|
|
127
|
+
? bodyBatterySamples
|
|
128
|
+
: undefined,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Convert Garmin offset-keyed time-series data into timestamped samples.
|
|
133
|
+
*
|
|
134
|
+
* Garmin sends time-series as `{ [offsetSeconds]: value }` maps.
|
|
135
|
+
* This converts to `{ timestamp: ISO-8601, ...fields }[]`.
|
|
136
|
+
*/
|
|
137
|
+
function buildTimeOffsetSamples(startTimeInSeconds, offsets, mapValue) {
|
|
138
|
+
return Object.entries(offsets).map(([offset, value]) => ({
|
|
139
|
+
timestamp: new Date((startTimeInSeconds + parseInt(offset, 10)) * 1000).toISOString(),
|
|
140
|
+
...mapValue(value),
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=daily.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daily.js","sourceRoot":"","sources":["../../src/garmin/daily.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { transformActivity } from "./activity.js";
|
|
2
|
+
export type { ActivityData } from "./activity.js";
|
|
3
|
+
export { transformDaily } from "./daily.js";
|
|
4
|
+
export type { DailyData } from "./daily.js";
|
|
5
|
+
export { transformSleep } from "./sleep.js";
|
|
6
|
+
export type { SleepData } from "./sleep.js";
|
|
7
|
+
export { transformBody } from "./body.js";
|
|
8
|
+
export type { BodyData } from "./body.js";
|
|
9
|
+
export { transformMenstruation } from "./menstruation.js";
|
|
10
|
+
export type { MenstruationData } from "./menstruation.js";
|
|
11
|
+
export { mapActivityType } from "./maps/activity-type.js";
|
|
12
|
+
export { mapSleepLevel } from "./maps/sleep-level.js";
|
|
13
|
+
export { GarminClient, GarminApiError } from "./client.js";
|
|
14
|
+
export type { GarminClientOptions, TimeRangeParams } from "./client.js";
|
|
15
|
+
export { getRequestToken, getAccessToken, buildOAuthSignature, buildOAuthHeader, percentEncode, generateNonce, getTimestamp, } from "./auth.js";
|
|
16
|
+
export type { GetRequestTokenOptions, GetAccessTokenOptions, } from "./auth.js";
|
|
17
|
+
export { syncAll, syncActivities, syncDailies, syncSleep, syncBody, syncMenstruation, } from "./sync.js";
|
|
18
|
+
export type { SyncOptions, SyncResult, SyncAllResult, } from "./sync.js";
|
|
19
|
+
export type { GarminActivity, GarminActivityLap, GarminActivitySample, GarminDailySummary, GarminSleep, GarminSleepLevel, GarminBodyComposition, GarminMenstrualCycleData, GarminUserProfile, GarminActivityType, GarminOAuthRequestTokenResponse, GarminOAuthAccessTokenResponse, GarminWebhookPayload, } from "./types.js";
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/garmin/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC3D,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGxE,OAAO,EACL,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,YAAY,GACb,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,OAAO,EACP,cAAc,EACd,WAAW,EACX,SAAS,EACT,QAAQ,EACR,gBAAgB,GACjB,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,WAAW,EACX,UAAU,EACV,aAAa,GACd,MAAM,WAAW,CAAC;AAGnB,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,kBAAkB,EAClB,+BAA+B,EAC/B,8BAA8B,EAC9B,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// ─── @nativesquare/soma/garmin ───────────────────────────────────────────────
|
|
2
|
+
// Garmin Health API → Soma schema transformers, API client, OAuth helpers, and sync.
|
|
3
|
+
//
|
|
4
|
+
// Uses the Web Crypto API for OAuth 1.0a HMAC-SHA1 signing.
|
|
5
|
+
// Compatible with both the Convex V8 runtime and Node.js environments.
|
|
6
|
+
// ── Transformers ─────────────────────────────────────────────────────────────
|
|
7
|
+
export { transformActivity } from "./activity.js";
|
|
8
|
+
export { transformDaily } from "./daily.js";
|
|
9
|
+
export { transformSleep } from "./sleep.js";
|
|
10
|
+
export { transformBody } from "./body.js";
|
|
11
|
+
export { transformMenstruation } from "./menstruation.js";
|
|
12
|
+
// ── Enum Maps ────────────────────────────────────────────────────────────────
|
|
13
|
+
export { mapActivityType } from "./maps/activity-type.js";
|
|
14
|
+
export { mapSleepLevel } from "./maps/sleep-level.js";
|
|
15
|
+
// ── API Client ───────────────────────────────────────────────────────────────
|
|
16
|
+
export { GarminClient, GarminApiError } from "./client.js";
|
|
17
|
+
// ── OAuth Helpers ────────────────────────────────────────────────────────────
|
|
18
|
+
export { getRequestToken, getAccessToken, buildOAuthSignature, buildOAuthHeader, percentEncode, generateNonce, getTimestamp, } from "./auth.js";
|
|
19
|
+
// ── Sync Helpers ─────────────────────────────────────────────────────────────
|
|
20
|
+
export { syncAll, syncActivities, syncDailies, syncSleep, syncBody, syncMenstruation, } from "./sync.js";
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/garmin/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,qFAAqF;AACrF,EAAE;AACF,4DAA4D;AAC5D,uEAAuE;AAEvE,gFAAgF;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,gFAAgF;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,gFAAgF;AAChF,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG3D,gFAAgF;AAChF,OAAO,EACL,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,YAAY,GACb,MAAM,WAAW,CAAC;AAMnB,gFAAgF;AAChF,OAAO,EACL,OAAO,EACP,cAAc,EACd,WAAW,EACX,SAAS,EACT,QAAQ,EACR,gBAAgB,GACjB,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { GarminActivityType } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Map a Garmin activity type string to the Terra ActivityType enum.
|
|
4
|
+
* Returns Terra "Other" (108) for unknown types.
|
|
5
|
+
*/
|
|
6
|
+
export declare function mapActivityType(activityType: GarminActivityType): number;
|
|
7
|
+
//# sourceMappingURL=activity-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity-type.d.ts","sourceRoot":"","sources":["../../../src/garmin/maps/activity-type.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAsGtD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,kBAAkB,GAAG,MAAM,CAExE"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// ─── Garmin ActivityType → Terra ActivityType ─────────────────────────────────
|
|
2
|
+
// Maps Garmin activity type strings to Terra's ActivityType numeric enum
|
|
3
|
+
// used by the Soma schema.
|
|
4
|
+
//
|
|
5
|
+
// Garmin values: Garmin Health API activity type strings
|
|
6
|
+
// Terra values: https://docs.tryterra.co/reference/health-and-fitness-api/data-models#activitytype
|
|
7
|
+
const activityTypeMap = {
|
|
8
|
+
// ── Running ─────────────────────────────────────────────────────────────
|
|
9
|
+
// Terra Running = 8
|
|
10
|
+
RUNNING: 8,
|
|
11
|
+
INDOOR_RUNNING: 8,
|
|
12
|
+
TRAIL_RUNNING: 8,
|
|
13
|
+
TREADMILL_RUNNING: 8,
|
|
14
|
+
// ── Cycling ─────────────────────────────────────────────────────────────
|
|
15
|
+
// Terra Biking = 1
|
|
16
|
+
CYCLING: 1,
|
|
17
|
+
INDOOR_CYCLING: 1,
|
|
18
|
+
MOUNTAIN_BIKING: 1,
|
|
19
|
+
GRAVEL_CYCLING: 1,
|
|
20
|
+
VIRTUAL_RIDE: 1,
|
|
21
|
+
// ── Walking ─────────────────────────────────────────────────────────────
|
|
22
|
+
// Terra Walking = 7
|
|
23
|
+
WALKING: 7,
|
|
24
|
+
// ── Hiking ──────────────────────────────────────────────────────────────
|
|
25
|
+
// Terra Hiking = 35
|
|
26
|
+
HIKING: 35,
|
|
27
|
+
// ── Swimming ────────────────────────────────────────────────────────────
|
|
28
|
+
// Terra Swimming = 82
|
|
29
|
+
SWIMMING: 82,
|
|
30
|
+
OPEN_WATER_SWIMMING: 82,
|
|
31
|
+
LAP_SWIMMING: 82,
|
|
32
|
+
POOL_SWIMMING: 82,
|
|
33
|
+
// ── Gym / Fitness ───────────────────────────────────────────────────────
|
|
34
|
+
STRENGTH_TRAINING: 80, // Terra Strength Training
|
|
35
|
+
YOGA: 100, // Terra Yoga
|
|
36
|
+
PILATES: 49, // Terra Pilates
|
|
37
|
+
CARDIO: 108, // Terra Other
|
|
38
|
+
ELLIPTICAL: 25, // Terra Elliptical
|
|
39
|
+
STAIR_CLIMBING: 78, // Terra Stair Climbing Machine
|
|
40
|
+
CROSSFIT: 113, // Terra Crossfit
|
|
41
|
+
HIIT: 114, // Terra HIIT
|
|
42
|
+
FITNESS_EQUIPMENT: 108, // Terra Other
|
|
43
|
+
BREATHWORK: 108, // Terra Other
|
|
44
|
+
// ── Snow Sports ─────────────────────────────────────────────────────────
|
|
45
|
+
CROSS_COUNTRY_SKIING: 67, // Terra Cross Country Skiing
|
|
46
|
+
ALPINE_SKIING: 66, // Terra Alpine Skiing
|
|
47
|
+
SNOWBOARDING: 73, // Terra Snowboarding
|
|
48
|
+
SNOWSHOEING: 74, // Terra Snowshoeing
|
|
49
|
+
// ── Water Sports ────────────────────────────────────────────────────────
|
|
50
|
+
ROWING: 53, // Terra Rowing
|
|
51
|
+
INDOOR_ROWING: 53, // Terra Rowing
|
|
52
|
+
KAYAKING: 40, // Terra Kayaking
|
|
53
|
+
CANOEING: 22, // Terra Canoeing
|
|
54
|
+
SAILING: 59, // Terra Sailing
|
|
55
|
+
SURFING: 81, // Terra Surfing
|
|
56
|
+
KITESURFING: 41, // Terra Kitesurfing
|
|
57
|
+
WINDSURFING: 99, // Terra Windsurfing
|
|
58
|
+
PADDLEBOARDING: 129, // Terra Paddling
|
|
59
|
+
// ── Skating ─────────────────────────────────────────────────────────────
|
|
60
|
+
SKATING: 62, // Terra Skating
|
|
61
|
+
INLINE_SKATING: 62, // Terra Skating
|
|
62
|
+
// ── Racket Sports ───────────────────────────────────────────────────────
|
|
63
|
+
TENNIS: 87, // Terra Tennis
|
|
64
|
+
TABLE_TENNIS: 85, // Terra Table Tennis
|
|
65
|
+
BADMINTON: 10, // Terra Badminton
|
|
66
|
+
RACQUETBALL: 51, // Terra Racquetball
|
|
67
|
+
SQUASH: 76, // Terra Squash
|
|
68
|
+
// ── Climbing ────────────────────────────────────────────────────────────
|
|
69
|
+
ROCK_CLIMBING: 52, // Terra Rock Climbing
|
|
70
|
+
BOULDERING: 52, // Terra Rock Climbing
|
|
71
|
+
// ── Team Sports ─────────────────────────────────────────────────────────
|
|
72
|
+
SOCCER: 29, // Terra English Football
|
|
73
|
+
BASKETBALL: 11, // Terra Basketball
|
|
74
|
+
VOLLEYBALL: 94, // Terra Volleyball
|
|
75
|
+
CRICKET: 23, // Terra Cricket
|
|
76
|
+
RUGBY: 57, // Terra Rugby
|
|
77
|
+
// ── Combat Sports ───────────────────────────────────────────────────────
|
|
78
|
+
BOXING: 16, // Terra Boxing
|
|
79
|
+
MARTIAL_ARTS: 44, // Terra Martial Arts
|
|
80
|
+
// ── Golf ────────────────────────────────────────────────────────────────
|
|
81
|
+
GOLF: 32, // Terra Golf
|
|
82
|
+
// ── Accessibility ───────────────────────────────────────────────────────
|
|
83
|
+
HANDCYCLING: 14, // Terra Handbiking
|
|
84
|
+
WHEELCHAIR_PUSH_WALKING: 98, // Terra Wheelchair
|
|
85
|
+
WHEELCHAIR_PUSH_RUNNING: 98, // Terra Wheelchair
|
|
86
|
+
// ── Other ───────────────────────────────────────────────────────────────
|
|
87
|
+
OTHER: 108, // Terra Other
|
|
88
|
+
MULTI_SPORT: 108, // Terra Other
|
|
89
|
+
FLOOR_CLIMBING: 78, // Terra Stair Climbing Machine
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Map a Garmin activity type string to the Terra ActivityType enum.
|
|
93
|
+
* Returns Terra "Other" (108) for unknown types.
|
|
94
|
+
*/
|
|
95
|
+
export function mapActivityType(activityType) {
|
|
96
|
+
return activityTypeMap[activityType] ?? 108;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=activity-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity-type.js","sourceRoot":"","sources":["../../../src/garmin/maps/activity-type.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep-level.d.ts","sourceRoot":"","sources":["../../../src/garmin/maps/sleep-level.ts"],"names":[],"mappings":"AAeA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// ─── Garmin Sleep Stage → Terra SleepLevel ────────────────────────────────────
|
|
2
|
+
// Maps Garmin sleep stage names to Terra's SleepLevel numeric enum.
|
|
3
|
+
//
|
|
4
|
+
// Garmin provides sleep levels as named map keys in sleepLevelsMap:
|
|
5
|
+
// { deep: [...], light: [...], rem: [...], awake: [...] }
|
|
6
|
+
//
|
|
7
|
+
// Terra SleepLevel: 0=Unknown, 1=Awake, 2=Sleeping, 3=OutOfBed, 4=Light, 5=Deep, 6=REM
|
|
8
|
+
const sleepLevelMap = {
|
|
9
|
+
deep: 5, // Deep → Terra Deep
|
|
10
|
+
light: 4, // Light → Terra Light
|
|
11
|
+
rem: 6, // REM → Terra REM
|
|
12
|
+
awake: 1, // Awake → Terra Awake
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Map a Garmin sleep stage name to the Terra SleepLevel enum.
|
|
16
|
+
* Returns 0 (Unknown) for unrecognized stages.
|
|
17
|
+
*/
|
|
18
|
+
export function mapSleepLevel(stage) {
|
|
19
|
+
return sleepLevelMap[stage] ?? 0;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=sleep-level.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep-level.js","sourceRoot":"","sources":["../../../src/garmin/maps/sleep-level.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,oEAAoE;AACpE,EAAE;AACF,oEAAoE;AACpE,4DAA4D;AAC5D,EAAE;AACF,uFAAuF;AAEvF,MAAM,aAAa,GAA2B;IAC5C,IAAI,EAAE,CAAC,EAAI,oBAAoB;IAC/B,KAAK,EAAE,CAAC,EAAG,sBAAsB;IACjC,GAAG,EAAE,CAAC,EAAK,kBAAkB;IAC7B,KAAK,EAAE,CAAC,EAAG,sBAAsB;CAClC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { GarminMenstrualCycleData } from "./types.js";
|
|
2
|
+
export type MenstruationData = ReturnType<typeof transformMenstruation>;
|
|
3
|
+
/**
|
|
4
|
+
* Transform a Garmin menstrual cycle record into a Soma Menstruation document shape.
|
|
5
|
+
*
|
|
6
|
+
* @param data - The Garmin menstrual cycle data from the Health API
|
|
7
|
+
* @returns Soma Menstruation fields (without connectionId/userId)
|
|
8
|
+
*/
|
|
9
|
+
export declare function transformMenstruation(data: GarminMenstrualCycleData): {
|
|
10
|
+
metadata: {
|
|
11
|
+
start_time: string;
|
|
12
|
+
end_time: string;
|
|
13
|
+
};
|
|
14
|
+
menstruation_data: {
|
|
15
|
+
day_in_cycle: number | undefined;
|
|
16
|
+
current_phase: string | undefined;
|
|
17
|
+
length_of_current_phase_days: number | undefined;
|
|
18
|
+
period_length_days: number | undefined;
|
|
19
|
+
predicted_cycle_length_days: number | undefined;
|
|
20
|
+
is_predicted_cycle: string | undefined;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=menstruation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menstruation.d.ts","sourceRoot":"","sources":["../../src/garmin/menstruation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAExE;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,wBAAwB;;;;;;;;;;;;;EA4BnE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// ─── Menstruation Transformer ────────────────────────────────────────────────
|
|
2
|
+
// Transforms Garmin menstrual cycle data into the Soma Menstruation schema shape.
|
|
3
|
+
/**
|
|
4
|
+
* Transform a Garmin menstrual cycle record into a Soma Menstruation document shape.
|
|
5
|
+
*
|
|
6
|
+
* @param data - The Garmin menstrual cycle data from the Health API
|
|
7
|
+
* @returns Soma Menstruation fields (without connectionId/userId)
|
|
8
|
+
*/
|
|
9
|
+
export function transformMenstruation(data) {
|
|
10
|
+
const dateStr = data.calendarDate;
|
|
11
|
+
const startTime = data.startTimeInSeconds
|
|
12
|
+
? new Date(data.startTimeInSeconds * 1000).toISOString()
|
|
13
|
+
: `${dateStr}T00:00:00.000Z`;
|
|
14
|
+
const endTime = data.startTimeInSeconds
|
|
15
|
+
? new Date((data.startTimeInSeconds + 86400) * 1000).toISOString()
|
|
16
|
+
: `${dateStr}T23:59:59.999Z`;
|
|
17
|
+
return {
|
|
18
|
+
metadata: {
|
|
19
|
+
start_time: startTime,
|
|
20
|
+
end_time: endTime,
|
|
21
|
+
},
|
|
22
|
+
menstruation_data: {
|
|
23
|
+
day_in_cycle: data.dayInCycle,
|
|
24
|
+
current_phase: data.currentPhase?.toLowerCase(),
|
|
25
|
+
length_of_current_phase_days: data.lengthOfCurrentPhase,
|
|
26
|
+
period_length_days: data.periodLength,
|
|
27
|
+
predicted_cycle_length_days: data.predictedCycleLength,
|
|
28
|
+
is_predicted_cycle: data.isPredictedCycle != null
|
|
29
|
+
? String(data.isPredictedCycle)
|
|
30
|
+
: undefined,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=menstruation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menstruation.js","sourceRoot":"","sources":["../../src/garmin/menstruation.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,kFAAkF;AAMlF;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAA8B;IAClE,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC;IAClC,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB;QACvC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;QACxD,CAAC,CAAC,GAAG,OAAO,gBAAgB,CAAC;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB;QACrC,CAAC,CAAC,IAAI,IAAI,CACN,CAAC,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC,GAAG,IAAI,CACzC,CAAC,WAAW,EAAE;QACjB,CAAC,CAAC,GAAG,OAAO,gBAAgB,CAAC;IAE/B,OAAO;QACL,QAAQ,EAAE;YACR,UAAU,EAAE,SAAS;YACrB,QAAQ,EAAE,OAAO;SAClB;QAED,iBAAiB,EAAE;YACjB,YAAY,EAAE,IAAI,CAAC,UAAU;YAC7B,aAAa,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,EAAE;YAC/C,4BAA4B,EAAE,IAAI,CAAC,oBAAoB;YACvD,kBAAkB,EAAE,IAAI,CAAC,YAAY;YACrC,2BAA2B,EAAE,IAAI,CAAC,oBAAoB;YACtD,kBAAkB,EAAE,IAAI,CAAC,gBAAgB,IAAI,IAAI;gBAC/C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC;gBAC/B,CAAC,CAAC,SAAS;SACd;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { GarminSleep } from "./types.js";
|
|
2
|
+
export type SleepData = ReturnType<typeof transformSleep>;
|
|
3
|
+
/**
|
|
4
|
+
* Transform a Garmin sleep session into a Soma Sleep document shape.
|
|
5
|
+
*
|
|
6
|
+
* @param sleep - The Garmin sleep data from the Health API
|
|
7
|
+
* @returns Soma Sleep fields (without connectionId/userId)
|
|
8
|
+
*/
|
|
9
|
+
export declare function transformSleep(sleep: GarminSleep): {
|
|
10
|
+
metadata: {
|
|
11
|
+
summary_id: string;
|
|
12
|
+
start_time: string;
|
|
13
|
+
end_time: string;
|
|
14
|
+
upload_type: number;
|
|
15
|
+
};
|
|
16
|
+
sleep_durations_data: {
|
|
17
|
+
asleep: {
|
|
18
|
+
duration_asleep_state_seconds: number | undefined;
|
|
19
|
+
duration_deep_sleep_state_seconds: number | undefined;
|
|
20
|
+
duration_light_sleep_state_seconds: number | undefined;
|
|
21
|
+
duration_REM_sleep_state_seconds: number | undefined;
|
|
22
|
+
};
|
|
23
|
+
awake: {
|
|
24
|
+
duration_awake_state_seconds: number | undefined;
|
|
25
|
+
};
|
|
26
|
+
other: {
|
|
27
|
+
duration_in_bed_seconds: number;
|
|
28
|
+
duration_unmeasurable_sleep_seconds: number | undefined;
|
|
29
|
+
};
|
|
30
|
+
hypnogram_samples: {
|
|
31
|
+
timestamp: string;
|
|
32
|
+
level: number;
|
|
33
|
+
}[] | undefined;
|
|
34
|
+
};
|
|
35
|
+
heart_rate_data: {
|
|
36
|
+
detailed: {
|
|
37
|
+
hr_samples: {
|
|
38
|
+
timestamp: string;
|
|
39
|
+
bpm: number;
|
|
40
|
+
}[];
|
|
41
|
+
};
|
|
42
|
+
} | undefined;
|
|
43
|
+
respiration_data: {
|
|
44
|
+
breaths_data: {
|
|
45
|
+
avg_breaths_per_min: number | undefined;
|
|
46
|
+
min_breaths_per_min: number | undefined;
|
|
47
|
+
max_breaths_per_min: number | undefined;
|
|
48
|
+
samples: {
|
|
49
|
+
timestamp: string;
|
|
50
|
+
breaths_per_min: number;
|
|
51
|
+
}[] | undefined;
|
|
52
|
+
} | undefined;
|
|
53
|
+
oxygen_saturation_data: {
|
|
54
|
+
avg_saturation_percentage: number | undefined;
|
|
55
|
+
samples: {
|
|
56
|
+
timestamp: string;
|
|
57
|
+
percentage: number;
|
|
58
|
+
}[];
|
|
59
|
+
} | undefined;
|
|
60
|
+
} | undefined;
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=sleep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../../src/garmin/sleep.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,YAAY,CAAC;AAGhE,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAE1D;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW;;;;;;;;;;;;;;;;;;;;;;uBAyDb,MAAM;mBAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA/BxD"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// ─── Sleep Transformer ───────────────────────────────────────────────────────
|
|
2
|
+
// Transforms a Garmin sleep session into the Soma Sleep schema shape.
|
|
3
|
+
import { mapSleepLevel } from "./maps/sleep-level.js";
|
|
4
|
+
/**
|
|
5
|
+
* Transform a Garmin sleep session into a Soma Sleep document shape.
|
|
6
|
+
*
|
|
7
|
+
* @param sleep - The Garmin sleep data from the Health API
|
|
8
|
+
* @returns Soma Sleep fields (without connectionId/userId)
|
|
9
|
+
*/
|
|
10
|
+
export function transformSleep(sleep) {
|
|
11
|
+
const startMs = sleep.startTimeInSeconds * 1000;
|
|
12
|
+
const endMs = startMs + sleep.durationInSeconds * 1000;
|
|
13
|
+
const uploadTypeMap = {
|
|
14
|
+
ENHANCED_FINAL: 2, // Automatic
|
|
15
|
+
ENHANCED_TENTATIVE: 4, // Indeterminate
|
|
16
|
+
AUTO_FINAL: 2, // Automatic
|
|
17
|
+
AUTO_TENTATIVE: 4, // Indeterminate
|
|
18
|
+
MANUAL: 1, // Manual
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
metadata: {
|
|
22
|
+
summary_id: sleep.summaryId,
|
|
23
|
+
start_time: new Date(startMs).toISOString(),
|
|
24
|
+
end_time: new Date(endMs).toISOString(),
|
|
25
|
+
upload_type: uploadTypeMap[sleep.validation] ?? 0,
|
|
26
|
+
},
|
|
27
|
+
sleep_durations_data: buildSleepDurationsData(sleep),
|
|
28
|
+
heart_rate_data: buildHeartRateData(sleep),
|
|
29
|
+
respiration_data: buildRespirationData(sleep),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
33
|
+
function buildSleepDurationsData(sleep) {
|
|
34
|
+
const totalAsleep = (sleep.deepSleepDurationInSeconds ?? 0) +
|
|
35
|
+
(sleep.lightSleepDurationInSeconds ?? 0) +
|
|
36
|
+
(sleep.remSleepInSeconds ?? 0);
|
|
37
|
+
return {
|
|
38
|
+
asleep: {
|
|
39
|
+
duration_asleep_state_seconds: totalAsleep || undefined,
|
|
40
|
+
duration_deep_sleep_state_seconds: sleep.deepSleepDurationInSeconds,
|
|
41
|
+
duration_light_sleep_state_seconds: sleep.lightSleepDurationInSeconds,
|
|
42
|
+
duration_REM_sleep_state_seconds: sleep.remSleepInSeconds,
|
|
43
|
+
},
|
|
44
|
+
awake: {
|
|
45
|
+
duration_awake_state_seconds: sleep.awakeDurationInSeconds,
|
|
46
|
+
},
|
|
47
|
+
other: {
|
|
48
|
+
duration_in_bed_seconds: sleep.durationInSeconds,
|
|
49
|
+
duration_unmeasurable_sleep_seconds: sleep.unmeasurableSleepInSeconds,
|
|
50
|
+
},
|
|
51
|
+
hypnogram_samples: buildHypnogramSamples(sleep),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function buildHypnogramSamples(sleep) {
|
|
55
|
+
if (!sleep.sleepLevelsMap)
|
|
56
|
+
return undefined;
|
|
57
|
+
const samples = [];
|
|
58
|
+
for (const [stage, levels] of Object.entries(sleep.sleepLevelsMap)) {
|
|
59
|
+
if (!levels)
|
|
60
|
+
continue;
|
|
61
|
+
const terraLevel = mapSleepLevel(stage);
|
|
62
|
+
for (const level of levels) {
|
|
63
|
+
samples.push({
|
|
64
|
+
timestamp: new Date(level.startTimeInSeconds * 1000).toISOString(),
|
|
65
|
+
level: terraLevel,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
samples.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
70
|
+
return samples.length > 0 ? samples : undefined;
|
|
71
|
+
}
|
|
72
|
+
function buildHeartRateData(sleep) {
|
|
73
|
+
if (!sleep.timeOffsetHeartRateSamples ||
|
|
74
|
+
Object.keys(sleep.timeOffsetHeartRateSamples).length === 0) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
const hrSamples = Object.entries(sleep.timeOffsetHeartRateSamples).map(([offset, bpm]) => ({
|
|
78
|
+
timestamp: new Date((sleep.startTimeInSeconds + parseInt(offset, 10)) * 1000).toISOString(),
|
|
79
|
+
bpm,
|
|
80
|
+
}));
|
|
81
|
+
return {
|
|
82
|
+
detailed: { hr_samples: hrSamples },
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function buildRespirationData(sleep) {
|
|
86
|
+
const hasBreathSummary = sleep.averageRespirationInBreathsPerMinute != null;
|
|
87
|
+
const hasBreathSamples = sleep.timeOffsetSleepRespiration != null &&
|
|
88
|
+
Object.keys(sleep.timeOffsetSleepRespiration).length > 0;
|
|
89
|
+
const hasSpO2Samples = sleep.timeOffsetSpo2Values != null &&
|
|
90
|
+
Object.keys(sleep.timeOffsetSpo2Values).length > 0;
|
|
91
|
+
if (!hasBreathSummary && !hasBreathSamples && !hasSpO2Samples) {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
const breathSamples = hasBreathSamples
|
|
95
|
+
? Object.entries(sleep.timeOffsetSleepRespiration).map(([offset, rate]) => ({
|
|
96
|
+
timestamp: new Date((sleep.startTimeInSeconds + parseInt(offset, 10)) * 1000).toISOString(),
|
|
97
|
+
breaths_per_min: rate,
|
|
98
|
+
}))
|
|
99
|
+
: undefined;
|
|
100
|
+
const spo2Samples = hasSpO2Samples
|
|
101
|
+
? Object.entries(sleep.timeOffsetSpo2Values).map(([offset, pct]) => ({
|
|
102
|
+
timestamp: new Date((sleep.startTimeInSeconds + parseInt(offset, 10)) * 1000).toISOString(),
|
|
103
|
+
percentage: pct,
|
|
104
|
+
}))
|
|
105
|
+
: undefined;
|
|
106
|
+
return {
|
|
107
|
+
breaths_data: hasBreathSummary || (breathSamples && breathSamples.length > 0)
|
|
108
|
+
? {
|
|
109
|
+
avg_breaths_per_min: sleep.averageRespirationInBreathsPerMinute,
|
|
110
|
+
min_breaths_per_min: sleep.lowestRespirationInBreathsPerMinute,
|
|
111
|
+
max_breaths_per_min: sleep.highestRespirationInBreathsPerMinute,
|
|
112
|
+
samples: breathSamples && breathSamples.length > 0
|
|
113
|
+
? breathSamples
|
|
114
|
+
: undefined,
|
|
115
|
+
}
|
|
116
|
+
: undefined,
|
|
117
|
+
oxygen_saturation_data: spo2Samples && spo2Samples.length > 0
|
|
118
|
+
? {
|
|
119
|
+
avg_saturation_percentage: sleep.averageSpo2Value,
|
|
120
|
+
samples: spo2Samples,
|
|
121
|
+
}
|
|
122
|
+
: undefined,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=sleep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep.js","sourceRoot":"","sources":["../../src/garmin/sleep.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,sEAAsE;AAGtE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAItD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAkB;IAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAChD,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAEvD,MAAM,aAAa,GAA2B;QAC5C,cAAc,EAAE,CAAC,EAAO,YAAY;QACpC,kBAAkB,EAAE,CAAC,EAAG,gBAAgB;QACxC,UAAU,EAAE,CAAC,EAAW,YAAY;QACpC,cAAc,EAAE,CAAC,EAAO,gBAAgB;QACxC,MAAM,EAAE,CAAC,EAAe,SAAS;KAClC,CAAC;IAEF,OAAO;QACL,QAAQ,EAAE;YACR,UAAU,EAAE,KAAK,CAAC,SAAS;YAC3B,UAAU,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE;YAC3C,QAAQ,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE;YACvC,WAAW,EAAE,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;SAClD;QAED,oBAAoB,EAAE,uBAAuB,CAAC,KAAK,CAAC;QAEpD,eAAe,EAAE,kBAAkB,CAAC,KAAK,CAAC;QAE1C,gBAAgB,EAAE,oBAAoB,CAAC,KAAK,CAAC;KAC9C,CAAC;AACJ,CAAC;AAED,iFAAiF;AAEjF,SAAS,uBAAuB,CAAC,KAAkB;IACjD,MAAM,WAAW,GACf,CAAC,KAAK,CAAC,0BAA0B,IAAI,CAAC,CAAC;QACvC,CAAC,KAAK,CAAC,2BAA2B,IAAI,CAAC,CAAC;QACxC,CAAC,KAAK,CAAC,iBAAiB,IAAI,CAAC,CAAC,CAAC;IAEjC,OAAO;QACL,MAAM,EAAE;YACN,6BAA6B,EAAE,WAAW,IAAI,SAAS;YACvD,iCAAiC,EAAE,KAAK,CAAC,0BAA0B;YACnE,kCAAkC,EAAE,KAAK,CAAC,2BAA2B;YACrE,gCAAgC,EAAE,KAAK,CAAC,iBAAiB;SAC1D;QACD,KAAK,EAAE;YACL,4BAA4B,EAAE,KAAK,CAAC,sBAAsB;SAC3D;QACD,KAAK,EAAE;YACL,uBAAuB,EAAE,KAAK,CAAC,iBAAiB;YAChD,mCAAmC,EAAE,KAAK,CAAC,0BAA0B;SACtE;QACD,iBAAiB,EAAE,qBAAqB,CAAC,KAAK,CAAC;KAChD,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAkB;IAC/C,IAAI,CAAC,KAAK,CAAC,cAAc;QAAE,OAAO,SAAS,CAAC;IAE5C,MAAM,OAAO,GAAgD,EAAE,CAAC;IAEhE,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;QACnE,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QAExC,KAAK,MAAM,KAAK,IAAI,MAA4B,EAAE,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC;gBACX,SAAS,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;gBAClE,KAAK,EAAE,UAAU;aAClB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,CAAC,IAAI,CACV,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAC5E,CAAC;IAEF,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAkB;IAC5C,IACE,CAAC,KAAK,CAAC,0BAA0B;QACjC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,MAAM,KAAK,CAAC,EAC1D,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,GAAG,CACpE,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QAClB,SAAS,EAAE,IAAI,IAAI,CACjB,CAAC,KAAK,CAAC,kBAAkB,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CACzD,CAAC,WAAW,EAAE;QACf,GAAG;KACJ,CAAC,CACH,CAAC;IAEF,OAAO;QACL,QAAQ,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE;KACpC,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAkB;IAC9C,MAAM,gBAAgB,GACpB,KAAK,CAAC,oCAAoC,IAAI,IAAI,CAAC;IACrD,MAAM,gBAAgB,GACpB,KAAK,CAAC,0BAA0B,IAAI,IAAI;QACxC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3D,MAAM,cAAc,GAClB,KAAK,CAAC,oBAAoB,IAAI,IAAI;QAClC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAErD,IAAI,CAAC,gBAAgB,IAAI,CAAC,gBAAgB,IAAI,CAAC,cAAc,EAAE,CAAC;QAC9D,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,aAAa,GAAG,gBAAgB;QACpC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,0BAA2B,CAAC,CAAC,GAAG,CACnD,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YACnB,SAAS,EAAE,IAAI,IAAI,CACjB,CAAC,KAAK,CAAC,kBAAkB,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CACzD,CAAC,WAAW,EAAE;YACf,eAAe,EAAE,IAAI;SACtB,CAAC,CACH;QACH,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,WAAW,GAAG,cAAc;QAChC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,oBAAqB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;YAClE,SAAS,EAAE,IAAI,IAAI,CACjB,CAAC,KAAK,CAAC,kBAAkB,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CACzD,CAAC,WAAW,EAAE;YACf,UAAU,EAAE,GAAG;SAChB,CAAC,CAAC;QACL,CAAC,CAAC,SAAS,CAAC;IAEd,OAAO;QACL,YAAY,EACV,gBAAgB,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;YAC7D,CAAC,CAAC;gBACE,mBAAmB,EAAE,KAAK,CAAC,oCAAoC;gBAC/D,mBAAmB,EAAE,KAAK,CAAC,mCAAmC;gBAC9D,mBAAmB,EAAE,KAAK,CAAC,oCAAoC;gBAC/D,OAAO,EACL,aAAa,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC;oBACvC,CAAC,CAAC,aAAa;oBACf,CAAC,CAAC,SAAS;aAChB;YACH,CAAC,CAAC,SAAS;QACf,sBAAsB,EACpB,WAAW,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;YACnC,CAAC,CAAC;gBACE,yBAAyB,EAAE,KAAK,CAAC,gBAAgB;gBACjD,OAAO,EAAE,WAAW;aACrB;YACH,CAAC,CAAC,SAAS;KAChB,CAAC;AACJ,CAAC"}
|