@nativesquare/soma 0.2.0 → 0.4.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.
Files changed (105) hide show
  1. package/dist/client/index.d.ts +167 -0
  2. package/dist/client/index.d.ts.map +1 -1
  3. package/dist/client/index.js +150 -0
  4. package/dist/client/index.js.map +1 -1
  5. package/dist/component/_generated/api.d.ts +2 -0
  6. package/dist/component/_generated/api.d.ts.map +1 -1
  7. package/dist/component/_generated/api.js.map +1 -1
  8. package/dist/component/_generated/component.d.ts +56 -0
  9. package/dist/component/_generated/component.d.ts.map +1 -1
  10. package/dist/component/garmin.d.ts +110 -0
  11. package/dist/component/garmin.d.ts.map +1 -0
  12. package/dist/component/garmin.js +454 -0
  13. package/dist/component/garmin.js.map +1 -0
  14. package/dist/component/public.d.ts +761 -761
  15. package/dist/component/schema.d.ts +390 -388
  16. package/dist/component/schema.d.ts.map +1 -1
  17. package/dist/component/schema.js +3 -2
  18. package/dist/component/schema.js.map +1 -1
  19. package/dist/component/strava.d.ts +5 -4
  20. package/dist/component/strava.d.ts.map +1 -1
  21. package/dist/component/strava.js +18 -1
  22. package/dist/component/strava.js.map +1 -1
  23. package/dist/component/validators/activity.d.ts +42 -42
  24. package/dist/component/validators/body.d.ts +47 -47
  25. package/dist/component/validators/daily.d.ts +17 -17
  26. package/dist/component/validators/plannedWorkout.d.ts +5 -5
  27. package/dist/component/validators/samples.d.ts +2 -2
  28. package/dist/component/validators/shared.d.ts +17 -17
  29. package/dist/component/validators/sleep.d.ts +17 -17
  30. package/dist/garmin/activity.d.ts +101 -0
  31. package/dist/garmin/activity.d.ts.map +1 -0
  32. package/dist/garmin/activity.js +207 -0
  33. package/dist/garmin/activity.js.map +1 -0
  34. package/dist/garmin/auth.d.ts +65 -0
  35. package/dist/garmin/auth.d.ts.map +1 -0
  36. package/dist/garmin/auth.js +155 -0
  37. package/dist/garmin/auth.js.map +1 -0
  38. package/dist/garmin/body.d.ts +26 -0
  39. package/dist/garmin/body.d.ts.map +1 -0
  40. package/dist/garmin/body.js +44 -0
  41. package/dist/garmin/body.js.map +1 -0
  42. package/dist/garmin/client.d.ts +99 -0
  43. package/dist/garmin/client.d.ts.map +1 -0
  44. package/dist/garmin/client.js +153 -0
  45. package/dist/garmin/client.js.map +1 -0
  46. package/dist/garmin/daily.d.ts +74 -0
  47. package/dist/garmin/daily.d.ts.map +1 -0
  48. package/dist/garmin/daily.js +143 -0
  49. package/dist/garmin/daily.js.map +1 -0
  50. package/dist/garmin/index.d.ts +20 -0
  51. package/dist/garmin/index.d.ts.map +1 -0
  52. package/dist/garmin/index.js +21 -0
  53. package/dist/garmin/index.js.map +1 -0
  54. package/dist/garmin/maps/activity-type.d.ts +7 -0
  55. package/dist/garmin/maps/activity-type.d.ts.map +1 -0
  56. package/dist/garmin/maps/activity-type.js +98 -0
  57. package/dist/garmin/maps/activity-type.js.map +1 -0
  58. package/dist/garmin/maps/sleep-level.d.ts +6 -0
  59. package/dist/garmin/maps/sleep-level.d.ts.map +1 -0
  60. package/dist/garmin/maps/sleep-level.js +21 -0
  61. package/dist/garmin/maps/sleep-level.js.map +1 -0
  62. package/dist/garmin/menstruation.d.ts +23 -0
  63. package/dist/garmin/menstruation.d.ts.map +1 -0
  64. package/dist/garmin/menstruation.js +34 -0
  65. package/dist/garmin/menstruation.js.map +1 -0
  66. package/dist/garmin/sleep.d.ts +62 -0
  67. package/dist/garmin/sleep.d.ts.map +1 -0
  68. package/dist/garmin/sleep.js +125 -0
  69. package/dist/garmin/sleep.js.map +1 -0
  70. package/dist/garmin/sync.d.ts +39 -0
  71. package/dist/garmin/sync.d.ts.map +1 -0
  72. package/dist/garmin/sync.js +175 -0
  73. package/dist/garmin/sync.js.map +1 -0
  74. package/dist/garmin/types.d.ts +212 -0
  75. package/dist/garmin/types.d.ts.map +1 -0
  76. package/dist/garmin/types.js +8 -0
  77. package/dist/garmin/types.js.map +1 -0
  78. package/dist/validators.d.ts +6617 -0
  79. package/dist/validators.d.ts.map +1 -0
  80. package/dist/validators.js +78 -0
  81. package/dist/validators.js.map +1 -0
  82. package/package.json +9 -1
  83. package/src/client/index.ts +194 -1
  84. package/src/component/_generated/api.ts +2 -0
  85. package/src/component/_generated/component.ts +62 -0
  86. package/src/component/garmin.ts +534 -0
  87. package/src/component/schema.ts +3 -2
  88. package/src/component/strava.ts +23 -1
  89. package/src/garmin/activity.test.ts +178 -0
  90. package/src/garmin/activity.ts +272 -0
  91. package/src/garmin/auth.test.ts +128 -0
  92. package/src/garmin/auth.ts +249 -0
  93. package/src/garmin/body.ts +59 -0
  94. package/src/garmin/client.ts +254 -0
  95. package/src/garmin/daily.ts +211 -0
  96. package/src/garmin/index.ts +76 -0
  97. package/src/garmin/maps/activity-type.test.ts +78 -0
  98. package/src/garmin/maps/activity-type.ts +116 -0
  99. package/src/garmin/maps/sleep-level.ts +22 -0
  100. package/src/garmin/menstruation.ts +42 -0
  101. package/src/garmin/sleep.test.ts +110 -0
  102. package/src/garmin/sleep.ts +170 -0
  103. package/src/garmin/sync.ts +223 -0
  104. package/src/garmin/types.ts +338 -0
  105. package/src/validators.ts +89 -0
@@ -141,9 +141,9 @@ export declare const metSample: import("convex/values").VObject<{
141
141
  level: import("convex/values").VFloat64<number | undefined, "optional">;
142
142
  }, "required", "timestamp" | "level">;
143
143
  export declare const tssSample: import("convex/values").VObject<{
144
- method?: string | undefined;
145
144
  planned?: number | undefined;
146
145
  actual?: number | undefined;
146
+ method?: string | undefined;
147
147
  intensity_factor_planned?: number | undefined;
148
148
  intensity_factor_actual?: number | undefined;
149
149
  normalized_power_watts?: number | undefined;
@@ -154,7 +154,7 @@ export declare const tssSample: import("convex/values").VObject<{
154
154
  intensity_factor_planned: import("convex/values").VFloat64<number | undefined, "optional">;
155
155
  intensity_factor_actual: import("convex/values").VFloat64<number | undefined, "optional">;
156
156
  normalized_power_watts: import("convex/values").VFloat64<number | undefined, "optional">;
157
- }, "required", "method" | "planned" | "actual" | "intensity_factor_planned" | "intensity_factor_actual" | "normalized_power_watts">;
157
+ }, "required", "planned" | "actual" | "method" | "intensity_factor_planned" | "intensity_factor_actual" | "normalized_power_watts">;
158
158
  export declare const lapSample: import("convex/values").VObject<{
159
159
  calories?: number | undefined;
160
160
  distance_meters?: number | undefined;
@@ -84,22 +84,6 @@ export declare const deviceData: import("convex/values").VObject<{
84
84
  software_version: import("convex/values").VString<string | undefined, "optional">;
85
85
  }, "required", "name" | "manufacturer" | "serial_number" | "software_version" | "hardware_version" | "last_upload_date" | "activation_timestamp" | "data_provided" | "other_devices" | "sensor_state">;
86
86
  export declare const heartRateData: import("convex/values").VObject<{
87
- summary?: {
88
- avg_hr_bpm?: number | undefined;
89
- avg_hrv_rmssd?: number | undefined;
90
- avg_hrv_sdnn?: number | undefined;
91
- hr_zone_data?: {
92
- zone?: number | undefined;
93
- start_percentage?: number | undefined;
94
- end_percentage?: number | undefined;
95
- name?: string | undefined;
96
- duration_seconds?: number | undefined;
97
- }[] | undefined;
98
- max_hr_bpm?: number | undefined;
99
- min_hr_bpm?: number | undefined;
100
- resting_hr_bpm?: number | undefined;
101
- user_max_hr_bpm?: number | undefined;
102
- } | undefined;
103
87
  detailed?: {
104
88
  hr_samples?: {
105
89
  timestamp?: string | undefined;
@@ -116,6 +100,22 @@ export declare const heartRateData: import("convex/values").VObject<{
116
100
  hrv_sdnn?: number | undefined;
117
101
  }[] | undefined;
118
102
  } | undefined;
103
+ summary?: {
104
+ avg_hr_bpm?: number | undefined;
105
+ avg_hrv_rmssd?: number | undefined;
106
+ avg_hrv_sdnn?: number | undefined;
107
+ hr_zone_data?: {
108
+ zone?: number | undefined;
109
+ start_percentage?: number | undefined;
110
+ end_percentage?: number | undefined;
111
+ name?: string | undefined;
112
+ duration_seconds?: number | undefined;
113
+ }[] | undefined;
114
+ max_hr_bpm?: number | undefined;
115
+ min_hr_bpm?: number | undefined;
116
+ resting_hr_bpm?: number | undefined;
117
+ user_max_hr_bpm?: number | undefined;
118
+ } | undefined;
119
119
  }, {
120
120
  detailed: import("convex/values").VObject<{
121
121
  hr_samples?: {
@@ -213,7 +213,7 @@ export declare const heartRateData: import("convex/values").VObject<{
213
213
  resting_hr_bpm: import("convex/values").VFloat64<number | undefined, "optional">;
214
214
  user_max_hr_bpm: import("convex/values").VFloat64<number | undefined, "optional">;
215
215
  }, "optional", "avg_hr_bpm" | "avg_hrv_rmssd" | "avg_hrv_sdnn" | "hr_zone_data" | "max_hr_bpm" | "min_hr_bpm" | "resting_hr_bpm" | "user_max_hr_bpm">;
216
- }, "required", "summary" | "detailed" | "summary.avg_hr_bpm" | "summary.avg_hrv_rmssd" | "summary.avg_hrv_sdnn" | "summary.hr_zone_data" | "summary.max_hr_bpm" | "summary.min_hr_bpm" | "summary.resting_hr_bpm" | "summary.user_max_hr_bpm" | "detailed.hr_samples" | "detailed.hrv_samples_rmssd" | "detailed.hrv_samples_sdnn">;
216
+ }, "required", "detailed" | "summary" | "detailed.hr_samples" | "detailed.hrv_samples_rmssd" | "detailed.hrv_samples_sdnn" | "summary.avg_hr_bpm" | "summary.avg_hrv_rmssd" | "summary.avg_hrv_sdnn" | "summary.hr_zone_data" | "summary.max_hr_bpm" | "summary.min_hr_bpm" | "summary.resting_hr_bpm" | "summary.user_max_hr_bpm">;
217
217
  export declare const oxygenData: import("convex/values").VObject<{
218
218
  vo2max_ml_per_min_per_kg?: number | undefined;
219
219
  avg_saturation_percentage?: number | undefined;
@@ -80,22 +80,6 @@ export declare const sleepValidator: {
80
80
  software_version: import("convex/values").VString<string | undefined, "optional">;
81
81
  }, "optional", "name" | "manufacturer" | "serial_number" | "software_version" | "hardware_version" | "last_upload_date" | "activation_timestamp" | "data_provided" | "other_devices" | "sensor_state">;
82
82
  heart_rate_data: import("convex/values").VObject<{
83
- summary?: {
84
- avg_hr_bpm?: number | undefined;
85
- avg_hrv_rmssd?: number | undefined;
86
- avg_hrv_sdnn?: number | undefined;
87
- hr_zone_data?: {
88
- zone?: number | undefined;
89
- start_percentage?: number | undefined;
90
- end_percentage?: number | undefined;
91
- name?: string | undefined;
92
- duration_seconds?: number | undefined;
93
- }[] | undefined;
94
- max_hr_bpm?: number | undefined;
95
- min_hr_bpm?: number | undefined;
96
- resting_hr_bpm?: number | undefined;
97
- user_max_hr_bpm?: number | undefined;
98
- } | undefined;
99
83
  detailed?: {
100
84
  hr_samples?: {
101
85
  timestamp?: string | undefined;
@@ -112,6 +96,22 @@ export declare const sleepValidator: {
112
96
  hrv_sdnn?: number | undefined;
113
97
  }[] | undefined;
114
98
  } | undefined;
99
+ summary?: {
100
+ avg_hr_bpm?: number | undefined;
101
+ avg_hrv_rmssd?: number | undefined;
102
+ avg_hrv_sdnn?: number | undefined;
103
+ hr_zone_data?: {
104
+ zone?: number | undefined;
105
+ start_percentage?: number | undefined;
106
+ end_percentage?: number | undefined;
107
+ name?: string | undefined;
108
+ duration_seconds?: number | undefined;
109
+ }[] | undefined;
110
+ max_hr_bpm?: number | undefined;
111
+ min_hr_bpm?: number | undefined;
112
+ resting_hr_bpm?: number | undefined;
113
+ user_max_hr_bpm?: number | undefined;
114
+ } | undefined;
115
115
  } | undefined, {
116
116
  detailed: import("convex/values").VObject<{
117
117
  hr_samples?: {
@@ -209,7 +209,7 @@ export declare const sleepValidator: {
209
209
  resting_hr_bpm: import("convex/values").VFloat64<number | undefined, "optional">;
210
210
  user_max_hr_bpm: import("convex/values").VFloat64<number | undefined, "optional">;
211
211
  }, "optional", "avg_hr_bpm" | "avg_hrv_rmssd" | "avg_hrv_sdnn" | "hr_zone_data" | "max_hr_bpm" | "min_hr_bpm" | "resting_hr_bpm" | "user_max_hr_bpm">;
212
- }, "optional", "summary" | "detailed" | "summary.avg_hr_bpm" | "summary.avg_hrv_rmssd" | "summary.avg_hrv_sdnn" | "summary.hr_zone_data" | "summary.max_hr_bpm" | "summary.min_hr_bpm" | "summary.resting_hr_bpm" | "summary.user_max_hr_bpm" | "detailed.hr_samples" | "detailed.hrv_samples_rmssd" | "detailed.hrv_samples_sdnn">;
212
+ }, "optional", "detailed" | "summary" | "detailed.hr_samples" | "detailed.hrv_samples_rmssd" | "detailed.hrv_samples_sdnn" | "summary.avg_hr_bpm" | "summary.avg_hrv_rmssd" | "summary.avg_hrv_sdnn" | "summary.hr_zone_data" | "summary.max_hr_bpm" | "summary.min_hr_bpm" | "summary.resting_hr_bpm" | "summary.user_max_hr_bpm">;
213
213
  metadata: import("convex/values").VObject<{
214
214
  summary_id?: string | undefined;
215
215
  timestamp_localization?: number | undefined;
@@ -0,0 +1,101 @@
1
+ import type { GarminActivity } from "./types.js";
2
+ export type ActivityData = ReturnType<typeof transformActivity>;
3
+ /**
4
+ * Transform a Garmin activity into a Soma Activity document shape.
5
+ *
6
+ * The returned object is ready to be spread into an `ingestActivity` call
7
+ * alongside `connectionId` and `userId`.
8
+ *
9
+ * @param activity - The Garmin activity from the Health API
10
+ * @returns Soma Activity fields (without connectionId/userId)
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const data = transformActivity(garminActivity);
15
+ * await soma.ingestActivity(ctx, { connectionId, userId, ...data });
16
+ * ```
17
+ */
18
+ export declare function transformActivity(activity: GarminActivity): {
19
+ metadata: {
20
+ summary_id: string;
21
+ start_time: string;
22
+ end_time: string;
23
+ type: number;
24
+ upload_type: number;
25
+ name: string | undefined;
26
+ };
27
+ active_durations_data: {
28
+ activity_seconds: number;
29
+ };
30
+ calories_data: {
31
+ net_activity_calories: number | undefined;
32
+ BMR_calories: number | undefined;
33
+ total_burned_calories: number | undefined;
34
+ } | undefined;
35
+ device_data: {
36
+ name: string;
37
+ } | undefined;
38
+ distance_data: {
39
+ summary: {
40
+ distance_meters: number | undefined;
41
+ steps: number | undefined;
42
+ elevation: {
43
+ gain_actual_meters: number;
44
+ loss_actual_meters: number | undefined;
45
+ } | undefined;
46
+ };
47
+ } | undefined;
48
+ heart_rate_data: {
49
+ summary: {
50
+ avg_hr_bpm: number | undefined;
51
+ max_hr_bpm: number | undefined;
52
+ } | undefined;
53
+ detailed: {
54
+ hr_samples: {
55
+ timestamp: string;
56
+ bpm: number;
57
+ }[];
58
+ } | undefined;
59
+ } | undefined;
60
+ movement_data: {
61
+ avg_speed_meters_per_second: number | undefined;
62
+ max_speed_meters_per_second: number | undefined;
63
+ avg_pace_minutes_per_kilometer: number | undefined;
64
+ max_pace_minutes_per_kilometer: number | undefined;
65
+ avg_cadence_rpm: number | undefined;
66
+ max_cadence_rpm: number | undefined;
67
+ speed_samples: {
68
+ timestamp: string;
69
+ speed_meters_per_second: number;
70
+ }[] | undefined;
71
+ cadence_samples: {
72
+ timestamp: string;
73
+ cadence_rpm: number;
74
+ }[] | undefined;
75
+ } | undefined;
76
+ position_data: {
77
+ start_pos_lat_lng_deg: number[] | undefined;
78
+ position_samples: {
79
+ timestamp: string;
80
+ coords_lat_lng_deg: number[];
81
+ }[] | undefined;
82
+ } | undefined;
83
+ power_data: {
84
+ avg_watts: number | undefined;
85
+ max_watts: number | undefined;
86
+ power_samples: {
87
+ timestamp: string;
88
+ watts: number;
89
+ }[] | undefined;
90
+ } | undefined;
91
+ lap_data: {
92
+ laps: {
93
+ start_time: string;
94
+ end_time: string;
95
+ distance_meters: number | undefined;
96
+ avg_hr_bpm: number | undefined;
97
+ avg_speed_meters_per_second: number | undefined;
98
+ }[];
99
+ } | undefined;
100
+ };
101
+ //# sourceMappingURL=activity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../src/garmin/activity.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEhE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsCzD"}
@@ -0,0 +1,207 @@
1
+ // ─── Activity Transformer ────────────────────────────────────────────────────
2
+ // Transforms a Garmin activity into the Soma Activity schema shape.
3
+ import { mapActivityType } from "./maps/activity-type.js";
4
+ /**
5
+ * Transform a Garmin activity into a Soma Activity document shape.
6
+ *
7
+ * The returned object is ready to be spread into an `ingestActivity` call
8
+ * alongside `connectionId` and `userId`.
9
+ *
10
+ * @param activity - The Garmin activity from the Health API
11
+ * @returns Soma Activity fields (without connectionId/userId)
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const data = transformActivity(garminActivity);
16
+ * await soma.ingestActivity(ctx, { connectionId, userId, ...data });
17
+ * ```
18
+ */
19
+ export function transformActivity(activity) {
20
+ const startMs = activity.startTimeInSeconds * 1000;
21
+ const endMs = startMs + activity.durationInSeconds * 1000;
22
+ const startDate = new Date(startMs).toISOString();
23
+ const endDate = new Date(endMs).toISOString();
24
+ return {
25
+ metadata: {
26
+ summary_id: activity.summaryId ?? String(activity.activityId),
27
+ start_time: startDate,
28
+ end_time: endDate,
29
+ type: mapActivityType(activity.activityType),
30
+ upload_type: activity.manual ? 2 : 1,
31
+ name: activity.activityName,
32
+ },
33
+ active_durations_data: {
34
+ activity_seconds: activity.durationInSeconds,
35
+ },
36
+ calories_data: buildCaloriesData(activity),
37
+ device_data: activity.deviceName
38
+ ? { name: activity.deviceName }
39
+ : undefined,
40
+ distance_data: buildDistanceData(activity),
41
+ heart_rate_data: buildHeartRateData(activity),
42
+ movement_data: buildMovementData(activity),
43
+ position_data: buildPositionData(activity),
44
+ power_data: buildPowerData(activity),
45
+ lap_data: buildLapData(activity),
46
+ };
47
+ }
48
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
49
+ function buildCaloriesData(activity) {
50
+ if (activity.activeKilocalories == null &&
51
+ activity.bmrKilocalories == null) {
52
+ return undefined;
53
+ }
54
+ const total = (activity.activeKilocalories ?? 0) + (activity.bmrKilocalories ?? 0);
55
+ return {
56
+ net_activity_calories: activity.activeKilocalories,
57
+ BMR_calories: activity.bmrKilocalories,
58
+ total_burned_calories: total || undefined,
59
+ };
60
+ }
61
+ function buildDistanceData(activity) {
62
+ if (activity.distanceInMeters == null && activity.elevationGainInMeters == null) {
63
+ return undefined;
64
+ }
65
+ return {
66
+ summary: {
67
+ distance_meters: activity.distanceInMeters,
68
+ steps: activity.steps,
69
+ elevation: activity.elevationGainInMeters != null
70
+ ? {
71
+ gain_actual_meters: activity.elevationGainInMeters,
72
+ loss_actual_meters: activity.elevationLossInMeters,
73
+ }
74
+ : undefined,
75
+ },
76
+ };
77
+ }
78
+ function buildHeartRateData(activity) {
79
+ const hasHrSummary = activity.averageHeartRateInBeatsPerMinute != null ||
80
+ activity.maxHeartRateInBeatsPerMinute != null;
81
+ const hasSamples = activity.samples && activity.samples.length > 0;
82
+ if (!hasHrSummary && !hasSamples)
83
+ return undefined;
84
+ const hrSamples = hasSamples
85
+ ? activity.samples
86
+ .filter((s) => s.heartRate != null && s.startTimeInSeconds != null)
87
+ .map((s) => ({
88
+ timestamp: new Date(s.startTimeInSeconds * 1000).toISOString(),
89
+ bpm: s.heartRate,
90
+ }))
91
+ : undefined;
92
+ return {
93
+ summary: hasHrSummary
94
+ ? {
95
+ avg_hr_bpm: activity.averageHeartRateInBeatsPerMinute,
96
+ max_hr_bpm: activity.maxHeartRateInBeatsPerMinute,
97
+ }
98
+ : undefined,
99
+ detailed: hrSamples && hrSamples.length > 0
100
+ ? { hr_samples: hrSamples }
101
+ : undefined,
102
+ };
103
+ }
104
+ function buildMovementData(activity) {
105
+ const avgCadence = activity.averageRunCadenceInStepsPerMinute ??
106
+ activity.averageBikeCadenceInRoundsPerMinute;
107
+ const maxCadence = activity.maxRunCadenceInStepsPerMinute ??
108
+ activity.maxBikeCadenceInRoundsPerMinute;
109
+ const hasMovement = activity.averageSpeedInMetersPerSecond != null ||
110
+ activity.maxSpeedInMetersPerSecond != null ||
111
+ avgCadence != null;
112
+ const hasSamples = activity.samples && activity.samples.length > 0;
113
+ if (!hasMovement && !hasSamples)
114
+ return undefined;
115
+ const speedSamples = hasSamples
116
+ ? activity.samples
117
+ .filter((s) => s.speedMetersPerSecond != null && s.startTimeInSeconds != null)
118
+ .map((s) => ({
119
+ timestamp: new Date(s.startTimeInSeconds * 1000).toISOString(),
120
+ speed_meters_per_second: s.speedMetersPerSecond,
121
+ }))
122
+ : undefined;
123
+ const cadenceSamples = hasSamples
124
+ ? activity.samples
125
+ .filter((s) => (s.runCadenceInStepsPerMinute != null ||
126
+ s.bikeCadenceInRPM != null) &&
127
+ s.startTimeInSeconds != null)
128
+ .map((s) => ({
129
+ timestamp: new Date(s.startTimeInSeconds * 1000).toISOString(),
130
+ cadence_rpm: s.runCadenceInStepsPerMinute ?? s.bikeCadenceInRPM ?? 0,
131
+ }))
132
+ : undefined;
133
+ return {
134
+ avg_speed_meters_per_second: activity.averageSpeedInMetersPerSecond,
135
+ max_speed_meters_per_second: activity.maxSpeedInMetersPerSecond,
136
+ avg_pace_minutes_per_kilometer: activity.averagePaceInMinutesPerKilometer,
137
+ max_pace_minutes_per_kilometer: activity.maxPaceInMinutesPerKilometer,
138
+ avg_cadence_rpm: avgCadence,
139
+ max_cadence_rpm: maxCadence,
140
+ speed_samples: speedSamples && speedSamples.length > 0 ? speedSamples : undefined,
141
+ cadence_samples: cadenceSamples && cadenceSamples.length > 0
142
+ ? cadenceSamples
143
+ : undefined,
144
+ };
145
+ }
146
+ function buildPositionData(activity) {
147
+ const hasStartPos = activity.startingLatitudeInDegree != null &&
148
+ activity.startingLongitudeInDegree != null;
149
+ const hasSamples = activity.samples && activity.samples.length > 0;
150
+ if (!hasStartPos && !hasSamples)
151
+ return undefined;
152
+ const positionSamples = hasSamples
153
+ ? activity.samples
154
+ .filter((s) => s.latitudeInDegree != null &&
155
+ s.longitudeInDegree != null &&
156
+ s.startTimeInSeconds != null)
157
+ .map((s) => ({
158
+ timestamp: new Date(s.startTimeInSeconds * 1000).toISOString(),
159
+ coords_lat_lng_deg: [s.latitudeInDegree, s.longitudeInDegree],
160
+ }))
161
+ : undefined;
162
+ return {
163
+ start_pos_lat_lng_deg: hasStartPos
164
+ ? [
165
+ activity.startingLatitudeInDegree,
166
+ activity.startingLongitudeInDegree,
167
+ ]
168
+ : undefined,
169
+ position_samples: positionSamples && positionSamples.length > 0
170
+ ? positionSamples
171
+ : undefined,
172
+ };
173
+ }
174
+ function buildPowerData(activity) {
175
+ const hasPowerSummary = activity.averagePowerInWatts != null ||
176
+ activity.maxPowerInWatts != null;
177
+ const hasSamples = activity.samples && activity.samples.length > 0;
178
+ if (!hasPowerSummary && !hasSamples)
179
+ return undefined;
180
+ const powerSamples = hasSamples
181
+ ? activity.samples
182
+ .filter((s) => s.powerInWatts != null && s.startTimeInSeconds != null)
183
+ .map((s) => ({
184
+ timestamp: new Date(s.startTimeInSeconds * 1000).toISOString(),
185
+ watts: s.powerInWatts,
186
+ }))
187
+ : undefined;
188
+ return {
189
+ avg_watts: activity.averagePowerInWatts,
190
+ max_watts: activity.maxPowerInWatts,
191
+ power_samples: powerSamples && powerSamples.length > 0 ? powerSamples : undefined,
192
+ };
193
+ }
194
+ function buildLapData(activity) {
195
+ if (!activity.laps || activity.laps.length === 0)
196
+ return undefined;
197
+ return {
198
+ laps: activity.laps.map((lap) => ({
199
+ start_time: new Date(lap.startTimeInSeconds * 1000).toISOString(),
200
+ end_time: new Date((lap.startTimeInSeconds + lap.timerDurationInSeconds) * 1000).toISOString(),
201
+ distance_meters: lap.totalDistanceInMeters,
202
+ avg_hr_bpm: lap.heartRate,
203
+ avg_speed_meters_per_second: lap.maxSpeed,
204
+ })),
205
+ };
206
+ }
207
+ //# sourceMappingURL=activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.js","sourceRoot":"","sources":["../../src/garmin/activity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import type { GarminOAuthRequestTokenResponse, GarminOAuthAccessTokenResponse } from "./types.js";
2
+ /**
3
+ * Generate a random nonce for OAuth 1.0a requests.
4
+ */
5
+ export declare function generateNonce(): string;
6
+ /**
7
+ * Get the current Unix timestamp in seconds.
8
+ */
9
+ export declare function getTimestamp(): string;
10
+ /**
11
+ * Percent-encode a string per RFC 3986 (used by OAuth 1.0a).
12
+ * Unlike encodeURIComponent, this also encodes `!`, `*`, `'`, `(`, `)`.
13
+ */
14
+ export declare function percentEncode(str: string): string;
15
+ /**
16
+ * Build the OAuth 1.0a signature base string and compute the HMAC-SHA1 signature.
17
+ *
18
+ * @param method - HTTP method (e.g., "POST", "GET")
19
+ * @param url - The base URL (without query string)
20
+ * @param params - All OAuth + request parameters sorted alphabetically
21
+ * @param consumerSecret - The application's consumer secret
22
+ * @param tokenSecret - The token secret (empty string for request token step)
23
+ */
24
+ export declare function buildOAuthSignature(method: string, url: string, params: Record<string, string>, consumerSecret: string, tokenSecret?: string): Promise<string>;
25
+ /**
26
+ * Build the `Authorization: OAuth ...` header value from OAuth parameters.
27
+ */
28
+ export declare function buildOAuthHeader(params: Record<string, string>): string;
29
+ export interface GetRequestTokenOptions {
30
+ consumerKey: string;
31
+ consumerSecret: string;
32
+ callbackUrl?: string;
33
+ }
34
+ /**
35
+ * Obtain an unauthorized request token from Garmin.
36
+ *
37
+ * This is Step 1 of the OAuth 1.0a three-legged flow:
38
+ * 1. Your server calls this function to get a temporary request token
39
+ * 2. Redirect the user to the returned `authUrl`
40
+ * 3. After the user authorizes, exchange the verifier for an access token
41
+ *
42
+ * @returns The request token, token secret, and the authorization URL
43
+ */
44
+ export declare function getRequestToken(opts: GetRequestTokenOptions): Promise<GarminOAuthRequestTokenResponse & {
45
+ authUrl: string;
46
+ }>;
47
+ export interface GetAccessTokenOptions {
48
+ consumerKey: string;
49
+ consumerSecret: string;
50
+ /** The request token from Step 1. */
51
+ token: string;
52
+ /** The request token secret from Step 1. */
53
+ tokenSecret: string;
54
+ /** The verifier from the OAuth callback (Step 2). */
55
+ verifier: string;
56
+ }
57
+ /**
58
+ * Exchange a request token + verifier for a permanent access token.
59
+ *
60
+ * This is Step 3 of the OAuth 1.0a three-legged flow.
61
+ * The returned access token and secret are permanent — Garmin tokens
62
+ * do not expire and there is no refresh flow.
63
+ */
64
+ export declare function getAccessToken(opts: GetAccessTokenOptions): Promise<GarminOAuthAccessTokenResponse>;
65
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/garmin/auth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,+BAA+B,EAC/B,8BAA8B,EAC/B,MAAM,YAAY,CAAC;AAOpB;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAItC;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,cAAc,EAAE,MAAM,EACtB,WAAW,GAAE,MAAW,GACvB,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAKvE;AAID,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,+BAA+B,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA2DhE;AAID,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,8BAA8B,CAAC,CAkDzC"}