@nativesquare/soma 0.8.0 → 0.9.1

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 (530) hide show
  1. package/dist/client/index.d.ts +7 -128
  2. package/dist/client/index.d.ts.map +1 -1
  3. package/dist/client/index.js +31 -112
  4. package/dist/client/index.js.map +1 -1
  5. package/dist/component/_generated/api.d.ts +98 -4
  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 +136 -261
  9. package/dist/component/_generated/component.d.ts.map +1 -1
  10. package/dist/{garmin → component/garmin}/auth.d.ts +8 -1
  11. package/dist/component/garmin/auth.d.ts.map +1 -0
  12. package/dist/component/garmin/auth.js.map +1 -0
  13. package/dist/component/garmin/client.d.ts +15 -0
  14. package/dist/component/garmin/client.d.ts.map +1 -0
  15. package/dist/component/garmin/client.js +32 -0
  16. package/dist/component/garmin/client.js.map +1 -0
  17. package/dist/component/garmin/private.d.ts +543 -0
  18. package/dist/component/garmin/private.d.ts.map +1 -0
  19. package/dist/component/garmin/private.js +1461 -0
  20. package/dist/component/garmin/private.js.map +1 -0
  21. package/dist/component/garmin/public.d.ts +149 -0
  22. package/dist/component/garmin/public.d.ts.map +1 -0
  23. package/dist/component/garmin/public.js +823 -0
  24. package/dist/component/garmin/public.js.map +1 -0
  25. package/dist/component/garmin/schemas/activity.d.ts +94 -0
  26. package/dist/component/garmin/schemas/activity.d.ts.map +1 -0
  27. package/dist/component/garmin/schemas/activity.js +29 -0
  28. package/dist/component/garmin/schemas/activity.js.map +1 -0
  29. package/dist/component/garmin/schemas/activityDetails.d.ts +146 -0
  30. package/dist/component/garmin/schemas/activityDetails.d.ts.map +1 -0
  31. package/dist/component/garmin/schemas/activityDetails.js +30 -0
  32. package/dist/component/garmin/schemas/activityDetails.js.map +1 -0
  33. package/dist/component/garmin/schemas/bloodPressure.d.ts +38 -0
  34. package/dist/component/garmin/schemas/bloodPressure.d.ts.map +1 -0
  35. package/dist/component/garmin/schemas/bloodPressure.js +27 -0
  36. package/dist/component/garmin/schemas/bloodPressure.js.map +1 -0
  37. package/dist/component/garmin/schemas/bodyCompositions.d.ts +42 -0
  38. package/dist/component/garmin/schemas/bodyCompositions.d.ts.map +1 -0
  39. package/dist/component/garmin/schemas/bodyCompositions.js +27 -0
  40. package/dist/component/garmin/schemas/bodyCompositions.js.map +1 -0
  41. package/dist/component/garmin/schemas/dailies.d.ts +98 -0
  42. package/dist/component/garmin/schemas/dailies.d.ts.map +1 -0
  43. package/dist/component/garmin/schemas/dailies.js +27 -0
  44. package/dist/component/garmin/schemas/dailies.js.map +1 -0
  45. package/dist/component/garmin/schemas/epochs.d.ts +54 -0
  46. package/dist/component/garmin/schemas/epochs.d.ts.map +1 -0
  47. package/dist/component/garmin/schemas/epochs.js +27 -0
  48. package/dist/component/garmin/schemas/epochs.js.map +1 -0
  49. package/dist/component/garmin/schemas/healthSnapshot.d.ts +48 -0
  50. package/dist/component/garmin/schemas/healthSnapshot.d.ts.map +1 -0
  51. package/dist/component/garmin/schemas/healthSnapshot.js +27 -0
  52. package/dist/component/garmin/schemas/healthSnapshot.js.map +1 -0
  53. package/dist/component/garmin/schemas/hrvSummary.d.ts +40 -0
  54. package/dist/component/garmin/schemas/hrvSummary.d.ts.map +1 -0
  55. package/dist/component/garmin/schemas/hrvSummary.js +27 -0
  56. package/dist/component/garmin/schemas/hrvSummary.js.map +1 -0
  57. package/dist/component/garmin/schemas/manuallyUpdatedActivities.d.ts +94 -0
  58. package/dist/component/garmin/schemas/manuallyUpdatedActivities.d.ts.map +1 -0
  59. package/dist/component/garmin/schemas/manuallyUpdatedActivities.js +29 -0
  60. package/dist/component/garmin/schemas/manuallyUpdatedActivities.js.map +1 -0
  61. package/dist/component/garmin/schemas/menstrualCycleTracking.d.ts +100 -0
  62. package/dist/component/garmin/schemas/menstrualCycleTracking.d.ts.map +1 -0
  63. package/dist/component/garmin/schemas/menstrualCycleTracking.js +28 -0
  64. package/dist/component/garmin/schemas/menstrualCycleTracking.js.map +1 -0
  65. package/dist/component/garmin/schemas/moveIQ.d.ts +40 -0
  66. package/dist/component/garmin/schemas/moveIQ.d.ts.map +1 -0
  67. package/dist/component/garmin/schemas/moveIQ.js +27 -0
  68. package/dist/component/garmin/schemas/moveIQ.js.map +1 -0
  69. package/dist/component/garmin/schemas/pulseOx.d.ts +38 -0
  70. package/dist/component/garmin/schemas/pulseOx.d.ts.map +1 -0
  71. package/dist/component/garmin/schemas/pulseOx.js +28 -0
  72. package/dist/component/garmin/schemas/pulseOx.js.map +1 -0
  73. package/dist/component/garmin/schemas/respiration.d.ts +34 -0
  74. package/dist/component/garmin/schemas/respiration.d.ts.map +1 -0
  75. package/dist/component/garmin/schemas/respiration.js +28 -0
  76. package/dist/component/garmin/schemas/respiration.js.map +1 -0
  77. package/dist/component/garmin/schemas/skinTemperature.d.ts +36 -0
  78. package/dist/component/garmin/schemas/skinTemperature.d.ts.map +1 -0
  79. package/dist/component/garmin/schemas/skinTemperature.js +28 -0
  80. package/dist/component/garmin/schemas/skinTemperature.js.map +1 -0
  81. package/dist/component/garmin/schemas/sleeps.d.ts +88 -0
  82. package/dist/component/garmin/schemas/sleeps.d.ts.map +1 -0
  83. package/dist/component/garmin/schemas/sleeps.js +27 -0
  84. package/dist/component/garmin/schemas/sleeps.js.map +1 -0
  85. package/dist/component/garmin/schemas/stress.d.ts +70 -0
  86. package/dist/component/garmin/schemas/stress.d.ts.map +1 -0
  87. package/dist/component/garmin/schemas/stress.js +30 -0
  88. package/dist/component/garmin/schemas/stress.js.map +1 -0
  89. package/dist/component/garmin/schemas/userMetrics.d.ts +36 -0
  90. package/dist/component/garmin/schemas/userMetrics.d.ts.map +1 -0
  91. package/dist/component/garmin/schemas/userMetrics.js +28 -0
  92. package/dist/component/garmin/schemas/userMetrics.js.map +1 -0
  93. package/dist/component/garmin/transform/activity.d.ts +13 -0
  94. package/dist/component/garmin/transform/activity.d.ts.map +1 -0
  95. package/dist/component/garmin/transform/activity.js +111 -0
  96. package/dist/component/garmin/transform/activity.js.map +1 -0
  97. package/dist/component/garmin/transform/activityDetails.d.ts +13 -0
  98. package/dist/component/garmin/transform/activityDetails.d.ts.map +1 -0
  99. package/dist/component/garmin/transform/activityDetails.js +173 -0
  100. package/dist/component/garmin/transform/activityDetails.js.map +1 -0
  101. package/dist/component/garmin/transform/bloodPressure.d.ts +12 -0
  102. package/dist/component/garmin/transform/bloodPressure.d.ts.map +1 -0
  103. package/dist/{garmin → component/garmin/transform}/bloodPressure.js +7 -8
  104. package/dist/component/garmin/transform/bloodPressure.js.map +1 -0
  105. package/dist/component/garmin/transform/bodyCompositions.d.ts +12 -0
  106. package/dist/component/garmin/transform/bodyCompositions.d.ts.map +1 -0
  107. package/dist/component/garmin/transform/bodyCompositions.js +42 -0
  108. package/dist/component/garmin/transform/bodyCompositions.js.map +1 -0
  109. package/dist/component/garmin/transform/dailies.d.ts +12 -0
  110. package/dist/component/garmin/transform/dailies.d.ts.map +1 -0
  111. package/dist/{garmin/daily.js → component/garmin/transform/dailies.js} +38 -49
  112. package/dist/component/garmin/transform/dailies.js.map +1 -0
  113. package/dist/component/garmin/transform/epochs.d.ts +13 -0
  114. package/dist/component/garmin/transform/epochs.d.ts.map +1 -0
  115. package/dist/component/garmin/transform/epochs.js +76 -0
  116. package/dist/component/garmin/transform/epochs.js.map +1 -0
  117. package/dist/component/garmin/transform/healthSnapshot.d.ts +12 -0
  118. package/dist/component/garmin/transform/healthSnapshot.d.ts.map +1 -0
  119. package/dist/component/garmin/transform/healthSnapshot.js +111 -0
  120. package/dist/component/garmin/transform/healthSnapshot.js.map +1 -0
  121. package/dist/component/garmin/transform/hrvSummary.d.ts +12 -0
  122. package/dist/component/garmin/transform/hrvSummary.d.ts.map +1 -0
  123. package/dist/{garmin/hrv.js → component/garmin/transform/hrvSummary.js} +16 -16
  124. package/dist/component/garmin/transform/hrvSummary.js.map +1 -0
  125. package/dist/component/garmin/transform/manuallyUpdatedActivities.d.ts +11 -0
  126. package/dist/component/garmin/transform/manuallyUpdatedActivities.d.ts.map +1 -0
  127. package/dist/component/garmin/transform/manuallyUpdatedActivities.js +20 -0
  128. package/dist/component/garmin/transform/manuallyUpdatedActivities.js.map +1 -0
  129. package/dist/{garmin/maps/activity-type.d.ts → component/garmin/transform/maps/activityType.d.ts} +1 -1
  130. package/dist/component/garmin/transform/maps/activityType.d.ts.map +1 -0
  131. package/dist/{garmin/maps/activity-type.js → component/garmin/transform/maps/activityType.js} +1 -1
  132. package/dist/component/garmin/transform/maps/activityType.js.map +1 -0
  133. package/dist/{garmin/maps/sleep-level.d.ts → component/garmin/transform/maps/sleepLevel.d.ts} +1 -1
  134. package/dist/component/garmin/transform/maps/sleepLevel.d.ts.map +1 -0
  135. package/dist/{garmin/maps/sleep-level.js → component/garmin/transform/maps/sleepLevel.js} +1 -1
  136. package/dist/component/garmin/transform/maps/sleepLevel.js.map +1 -0
  137. package/dist/component/garmin/transform/menstrualCycleTracking.d.ts +10 -0
  138. package/dist/component/garmin/transform/menstrualCycleTracking.d.ts.map +1 -0
  139. package/dist/{garmin/menstruation.js → component/garmin/transform/menstrualCycleTracking.js} +17 -12
  140. package/dist/component/garmin/transform/menstrualCycleTracking.js.map +1 -0
  141. package/dist/component/garmin/transform/moveIQ.d.ts +14 -0
  142. package/dist/component/garmin/transform/moveIQ.d.ts.map +1 -0
  143. package/dist/component/garmin/transform/moveIQ.js +41 -0
  144. package/dist/component/garmin/transform/moveIQ.js.map +1 -0
  145. package/dist/{garmin → component/garmin/transform}/plannedWorkout.d.ts +3 -4
  146. package/dist/component/garmin/transform/plannedWorkout.d.ts.map +1 -0
  147. package/dist/{garmin → component/garmin/transform}/plannedWorkout.js +61 -70
  148. package/dist/component/garmin/transform/plannedWorkout.js.map +1 -0
  149. package/dist/component/garmin/transform/pulseOx.d.ts +12 -0
  150. package/dist/component/garmin/transform/pulseOx.d.ts.map +1 -0
  151. package/dist/component/garmin/transform/pulseOx.js +46 -0
  152. package/dist/component/garmin/transform/pulseOx.js.map +1 -0
  153. package/dist/component/garmin/transform/respiration.d.ts +12 -0
  154. package/dist/component/garmin/transform/respiration.d.ts.map +1 -0
  155. package/dist/component/garmin/transform/respiration.js +54 -0
  156. package/dist/component/garmin/transform/respiration.js.map +1 -0
  157. package/dist/component/garmin/transform/skinTemperature.d.ts +12 -0
  158. package/dist/component/garmin/transform/skinTemperature.d.ts.map +1 -0
  159. package/dist/{garmin/skinTemp.js → component/garmin/transform/skinTemperature.js} +13 -10
  160. package/dist/component/garmin/transform/skinTemperature.js.map +1 -0
  161. package/dist/{garmin/sleep.d.ts → component/garmin/transform/sleeps.d.ts} +13 -20
  162. package/dist/component/garmin/transform/sleeps.d.ts.map +1 -0
  163. package/dist/{garmin/sleep.js → component/garmin/transform/sleeps.js} +39 -50
  164. package/dist/component/garmin/transform/sleeps.js.map +1 -0
  165. package/dist/component/garmin/transform/stress.d.ts +12 -0
  166. package/dist/component/garmin/transform/stress.d.ts.map +1 -0
  167. package/dist/component/garmin/transform/stress.js +56 -0
  168. package/dist/component/garmin/transform/stress.js.map +1 -0
  169. package/dist/component/garmin/transform/userMetrics.d.ts +12 -0
  170. package/dist/component/garmin/transform/userMetrics.d.ts.map +1 -0
  171. package/dist/{garmin → component/garmin/transform}/userMetrics.js +19 -12
  172. package/dist/component/garmin/transform/userMetrics.js.map +1 -0
  173. package/dist/component/garmin/types/trainingApiWorkouts/client/client.gen.d.ts +3 -0
  174. package/dist/component/garmin/types/trainingApiWorkouts/client/client.gen.d.ts.map +1 -0
  175. package/dist/component/garmin/types/trainingApiWorkouts/client/client.gen.js +236 -0
  176. package/dist/component/garmin/types/trainingApiWorkouts/client/client.gen.js.map +1 -0
  177. package/dist/component/garmin/types/trainingApiWorkouts/client/index.d.ts +9 -0
  178. package/dist/component/garmin/types/trainingApiWorkouts/client/index.d.ts.map +1 -0
  179. package/dist/component/garmin/types/trainingApiWorkouts/client/index.js +7 -0
  180. package/dist/component/garmin/types/trainingApiWorkouts/client/index.js.map +1 -0
  181. package/dist/component/garmin/types/trainingApiWorkouts/client/types.gen.d.ts +118 -0
  182. package/dist/component/garmin/types/trainingApiWorkouts/client/types.gen.d.ts.map +1 -0
  183. package/dist/component/garmin/types/trainingApiWorkouts/client/types.gen.js +3 -0
  184. package/dist/component/garmin/types/trainingApiWorkouts/client/types.gen.js.map +1 -0
  185. package/dist/component/garmin/types/trainingApiWorkouts/client/utils.gen.d.ts +34 -0
  186. package/dist/component/garmin/types/trainingApiWorkouts/client/utils.gen.d.ts.map +1 -0
  187. package/dist/component/garmin/types/trainingApiWorkouts/client/utils.gen.js +229 -0
  188. package/dist/component/garmin/types/trainingApiWorkouts/client/utils.gen.js.map +1 -0
  189. package/dist/component/garmin/types/trainingApiWorkouts/client.gen.d.ts +13 -0
  190. package/dist/component/garmin/types/trainingApiWorkouts/client.gen.d.ts.map +1 -0
  191. package/dist/component/garmin/types/trainingApiWorkouts/client.gen.js +4 -0
  192. package/dist/component/garmin/types/trainingApiWorkouts/client.gen.js.map +1 -0
  193. package/dist/component/garmin/types/trainingApiWorkouts/core/auth.gen.d.ts +19 -0
  194. package/dist/component/garmin/types/trainingApiWorkouts/core/auth.gen.d.ts.map +1 -0
  195. package/dist/component/garmin/types/trainingApiWorkouts/core/auth.gen.js +15 -0
  196. package/dist/component/garmin/types/trainingApiWorkouts/core/auth.gen.js.map +1 -0
  197. package/dist/component/garmin/types/trainingApiWorkouts/core/bodySerializer.gen.d.ts +26 -0
  198. package/dist/component/garmin/types/trainingApiWorkouts/core/bodySerializer.gen.d.ts.map +1 -0
  199. package/dist/component/garmin/types/trainingApiWorkouts/core/bodySerializer.gen.js +58 -0
  200. package/dist/component/garmin/types/trainingApiWorkouts/core/bodySerializer.gen.js.map +1 -0
  201. package/dist/component/garmin/types/trainingApiWorkouts/core/params.gen.d.ts +44 -0
  202. package/dist/component/garmin/types/trainingApiWorkouts/core/params.gen.d.ts.map +1 -0
  203. package/dist/component/garmin/types/trainingApiWorkouts/core/params.gen.js +101 -0
  204. package/dist/component/garmin/types/trainingApiWorkouts/core/params.gen.js.map +1 -0
  205. package/dist/component/garmin/types/trainingApiWorkouts/core/pathSerializer.gen.d.ts +34 -0
  206. package/dist/component/garmin/types/trainingApiWorkouts/core/pathSerializer.gen.d.ts.map +1 -0
  207. package/dist/component/garmin/types/trainingApiWorkouts/core/pathSerializer.gen.js +107 -0
  208. package/dist/component/garmin/types/trainingApiWorkouts/core/pathSerializer.gen.js.map +1 -0
  209. package/dist/component/garmin/types/trainingApiWorkouts/core/queryKeySerializer.gen.d.ts +19 -0
  210. package/dist/component/garmin/types/trainingApiWorkouts/core/queryKeySerializer.gen.d.ts.map +1 -0
  211. package/dist/component/garmin/types/trainingApiWorkouts/core/queryKeySerializer.gen.js +93 -0
  212. package/dist/component/garmin/types/trainingApiWorkouts/core/queryKeySerializer.gen.js.map +1 -0
  213. package/dist/component/garmin/types/trainingApiWorkouts/core/serverSentEvents.gen.d.ts +72 -0
  214. package/dist/component/garmin/types/trainingApiWorkouts/core/serverSentEvents.gen.d.ts.map +1 -0
  215. package/dist/component/garmin/types/trainingApiWorkouts/core/serverSentEvents.gen.js +134 -0
  216. package/dist/component/garmin/types/trainingApiWorkouts/core/serverSentEvents.gen.js.map +1 -0
  217. package/dist/component/garmin/types/trainingApiWorkouts/core/types.gen.d.ts +79 -0
  218. package/dist/component/garmin/types/trainingApiWorkouts/core/types.gen.d.ts.map +1 -0
  219. package/dist/component/garmin/types/trainingApiWorkouts/core/types.gen.js +3 -0
  220. package/dist/component/garmin/types/trainingApiWorkouts/core/types.gen.js.map +1 -0
  221. package/dist/component/garmin/types/trainingApiWorkouts/core/utils.gen.d.ts +20 -0
  222. package/dist/component/garmin/types/trainingApiWorkouts/core/utils.gen.d.ts.map +1 -0
  223. package/dist/component/garmin/types/trainingApiWorkouts/core/utils.gen.js +88 -0
  224. package/dist/component/garmin/types/trainingApiWorkouts/core/utils.gen.js.map +1 -0
  225. package/dist/component/garmin/types/trainingApiWorkouts/index.d.ts +3 -0
  226. package/dist/component/garmin/types/trainingApiWorkouts/index.d.ts.map +1 -0
  227. package/dist/component/garmin/types/trainingApiWorkouts/index.js +3 -0
  228. package/dist/component/garmin/types/trainingApiWorkouts/index.js.map +1 -0
  229. package/dist/component/garmin/types/trainingApiWorkouts/sdk.gen.d.ts +68 -0
  230. package/dist/component/garmin/types/trainingApiWorkouts/sdk.gen.d.ts.map +1 -0
  231. package/dist/component/garmin/types/trainingApiWorkouts/sdk.gen.js +97 -0
  232. package/dist/component/garmin/types/trainingApiWorkouts/sdk.gen.js.map +1 -0
  233. package/dist/component/garmin/types/trainingApiWorkouts/types.gen.d.ts +330 -0
  234. package/dist/component/garmin/types/trainingApiWorkouts/types.gen.d.ts.map +1 -0
  235. package/dist/component/garmin/types/trainingApiWorkouts/types.gen.js +3 -0
  236. package/dist/component/garmin/types/trainingApiWorkouts/types.gen.js.map +1 -0
  237. package/dist/component/garmin/types/trainingApiWorkouts/zod.gen.d.ts +2463 -0
  238. package/dist/component/garmin/types/trainingApiWorkouts/zod.gen.d.ts.map +1 -0
  239. package/dist/component/garmin/types/trainingApiWorkouts/zod.gen.js +388 -0
  240. package/dist/component/garmin/types/trainingApiWorkouts/zod.gen.js.map +1 -0
  241. package/dist/component/garmin/types/wellnessApi/client/client.gen.d.ts +3 -0
  242. package/dist/component/garmin/types/wellnessApi/client/client.gen.d.ts.map +1 -0
  243. package/dist/component/garmin/types/wellnessApi/client/client.gen.js +236 -0
  244. package/dist/component/garmin/types/wellnessApi/client/client.gen.js.map +1 -0
  245. package/dist/component/garmin/types/wellnessApi/client/index.d.ts +9 -0
  246. package/dist/component/garmin/types/wellnessApi/client/index.d.ts.map +1 -0
  247. package/dist/component/garmin/types/wellnessApi/client/index.js +7 -0
  248. package/dist/component/garmin/types/wellnessApi/client/index.js.map +1 -0
  249. package/dist/component/garmin/types/wellnessApi/client/types.gen.d.ts +118 -0
  250. package/dist/component/garmin/types/wellnessApi/client/types.gen.d.ts.map +1 -0
  251. package/dist/component/garmin/types/wellnessApi/client/types.gen.js +3 -0
  252. package/dist/component/garmin/types/wellnessApi/client/types.gen.js.map +1 -0
  253. package/dist/component/garmin/types/wellnessApi/client/utils.gen.d.ts +34 -0
  254. package/dist/component/garmin/types/wellnessApi/client/utils.gen.d.ts.map +1 -0
  255. package/dist/component/garmin/types/wellnessApi/client/utils.gen.js +229 -0
  256. package/dist/component/garmin/types/wellnessApi/client/utils.gen.js.map +1 -0
  257. package/dist/component/garmin/types/wellnessApi/client.gen.d.ts +13 -0
  258. package/dist/component/garmin/types/wellnessApi/client.gen.d.ts.map +1 -0
  259. package/dist/component/garmin/types/wellnessApi/client.gen.js +4 -0
  260. package/dist/component/garmin/types/wellnessApi/client.gen.js.map +1 -0
  261. package/dist/component/garmin/types/wellnessApi/core/auth.gen.d.ts +19 -0
  262. package/dist/component/garmin/types/wellnessApi/core/auth.gen.d.ts.map +1 -0
  263. package/dist/component/garmin/types/wellnessApi/core/auth.gen.js +15 -0
  264. package/dist/component/garmin/types/wellnessApi/core/auth.gen.js.map +1 -0
  265. package/dist/component/garmin/types/wellnessApi/core/bodySerializer.gen.d.ts +26 -0
  266. package/dist/component/garmin/types/wellnessApi/core/bodySerializer.gen.d.ts.map +1 -0
  267. package/dist/component/garmin/types/wellnessApi/core/bodySerializer.gen.js +58 -0
  268. package/dist/component/garmin/types/wellnessApi/core/bodySerializer.gen.js.map +1 -0
  269. package/dist/component/garmin/types/wellnessApi/core/params.gen.d.ts +44 -0
  270. package/dist/component/garmin/types/wellnessApi/core/params.gen.d.ts.map +1 -0
  271. package/dist/component/garmin/types/wellnessApi/core/params.gen.js +101 -0
  272. package/dist/component/garmin/types/wellnessApi/core/params.gen.js.map +1 -0
  273. package/dist/component/garmin/types/wellnessApi/core/pathSerializer.gen.d.ts +34 -0
  274. package/dist/component/garmin/types/wellnessApi/core/pathSerializer.gen.d.ts.map +1 -0
  275. package/dist/component/garmin/types/wellnessApi/core/pathSerializer.gen.js +107 -0
  276. package/dist/component/garmin/types/wellnessApi/core/pathSerializer.gen.js.map +1 -0
  277. package/dist/component/garmin/types/wellnessApi/core/queryKeySerializer.gen.d.ts +19 -0
  278. package/dist/component/garmin/types/wellnessApi/core/queryKeySerializer.gen.d.ts.map +1 -0
  279. package/dist/component/garmin/types/wellnessApi/core/queryKeySerializer.gen.js +93 -0
  280. package/dist/component/garmin/types/wellnessApi/core/queryKeySerializer.gen.js.map +1 -0
  281. package/dist/component/garmin/types/wellnessApi/core/serverSentEvents.gen.d.ts +72 -0
  282. package/dist/component/garmin/types/wellnessApi/core/serverSentEvents.gen.d.ts.map +1 -0
  283. package/dist/component/garmin/types/wellnessApi/core/serverSentEvents.gen.js +134 -0
  284. package/dist/component/garmin/types/wellnessApi/core/serverSentEvents.gen.js.map +1 -0
  285. package/dist/component/garmin/types/wellnessApi/core/types.gen.d.ts +79 -0
  286. package/dist/component/garmin/types/wellnessApi/core/types.gen.d.ts.map +1 -0
  287. package/dist/component/garmin/types/wellnessApi/core/types.gen.js +3 -0
  288. package/dist/component/garmin/types/wellnessApi/core/types.gen.js.map +1 -0
  289. package/dist/component/garmin/types/wellnessApi/core/utils.gen.d.ts +20 -0
  290. package/dist/component/garmin/types/wellnessApi/core/utils.gen.d.ts.map +1 -0
  291. package/dist/component/garmin/types/wellnessApi/core/utils.gen.js +88 -0
  292. package/dist/component/garmin/types/wellnessApi/core/utils.gen.js.map +1 -0
  293. package/dist/component/garmin/types/wellnessApi/index.d.ts +3 -0
  294. package/dist/component/garmin/types/wellnessApi/index.d.ts.map +1 -0
  295. package/dist/component/garmin/types/wellnessApi/index.js +3 -0
  296. package/dist/component/garmin/types/wellnessApi/index.js.map +1 -0
  297. package/dist/component/garmin/types/wellnessApi/sdk.gen.d.ts +166 -0
  298. package/dist/component/garmin/types/wellnessApi/sdk.gen.d.ts.map +1 -0
  299. package/dist/component/garmin/types/wellnessApi/sdk.gen.js +153 -0
  300. package/dist/component/garmin/types/wellnessApi/sdk.gen.js.map +1 -0
  301. package/dist/component/garmin/types/wellnessApi/types.gen.d.ts +2733 -0
  302. package/dist/component/garmin/types/wellnessApi/types.gen.d.ts.map +1 -0
  303. package/dist/component/garmin/types/wellnessApi/types.gen.js +3 -0
  304. package/dist/component/garmin/types/wellnessApi/types.gen.js.map +1 -0
  305. package/dist/component/garmin/types/wellnessApi/zod.gen.d.ts +1319 -0
  306. package/dist/component/garmin/types/wellnessApi/zod.gen.d.ts.map +1 -0
  307. package/dist/component/garmin/types/wellnessApi/zod.gen.js +784 -0
  308. package/dist/component/garmin/types/wellnessApi/zod.gen.js.map +1 -0
  309. package/dist/component/garmin/utils.d.ts +16 -0
  310. package/dist/component/garmin/utils.d.ts.map +1 -0
  311. package/dist/component/garmin/utils.js +17 -0
  312. package/dist/component/garmin/utils.js.map +1 -0
  313. package/dist/component/garmin/webhooks.d.ts +128 -0
  314. package/dist/component/garmin/webhooks.d.ts.map +1 -0
  315. package/dist/component/garmin/webhooks.js +531 -0
  316. package/dist/component/garmin/webhooks.js.map +1 -0
  317. package/dist/component/private.d.ts +4 -4
  318. package/dist/component/public.d.ts +333 -333
  319. package/dist/component/schema.d.ts +133 -133
  320. package/dist/component/strava/private.d.ts +30 -0
  321. package/dist/component/strava/private.d.ts.map +1 -0
  322. package/dist/component/strava/private.js +71 -0
  323. package/dist/component/strava/private.js.map +1 -0
  324. package/dist/component/{strava.d.ts → strava/public.d.ts} +3 -31
  325. package/dist/component/strava/public.d.ts.map +1 -0
  326. package/dist/component/{strava.js → strava/public.js} +22 -101
  327. package/dist/component/strava/public.js.map +1 -0
  328. package/dist/component/validators/activity.d.ts +6 -0
  329. package/dist/component/validators/activity.d.ts.map +1 -1
  330. package/dist/component/validators/activity.js.map +1 -1
  331. package/dist/component/validators/body.d.ts +20 -14
  332. package/dist/component/validators/body.d.ts.map +1 -1
  333. package/dist/component/validators/body.js.map +1 -1
  334. package/dist/component/validators/daily.d.ts +6 -0
  335. package/dist/component/validators/daily.d.ts.map +1 -1
  336. package/dist/component/validators/daily.js.map +1 -1
  337. package/dist/component/validators/enums.d.ts +1 -1
  338. package/dist/component/validators/menstruation.d.ts +5 -0
  339. package/dist/component/validators/menstruation.d.ts.map +1 -1
  340. package/dist/component/validators/menstruation.js.map +1 -1
  341. package/dist/component/validators/plannedWorkout.d.ts +6 -0
  342. package/dist/component/validators/plannedWorkout.d.ts.map +1 -1
  343. package/dist/component/validators/plannedWorkout.js.map +1 -1
  344. package/dist/validators.d.ts +31 -28
  345. package/dist/validators.d.ts.map +1 -1
  346. package/dist/validators.js +2 -2
  347. package/dist/validators.js.map +1 -1
  348. package/package.json +4 -7
  349. package/src/client/index.ts +41 -172
  350. package/src/component/_generated/api.ts +98 -4
  351. package/src/component/_generated/component.ts +252 -284
  352. package/src/{garmin → component/garmin}/auth.ts +8 -1
  353. package/src/component/garmin/client.ts +39 -0
  354. package/src/component/garmin/private.ts +1798 -0
  355. package/src/component/garmin/public.ts +938 -0
  356. package/src/component/garmin/schemas/activity.ts +40 -0
  357. package/src/component/garmin/schemas/activityDetails.ts +45 -0
  358. package/src/component/garmin/schemas/bloodPressure.ts +38 -0
  359. package/src/component/garmin/schemas/bodyCompositions.ts +38 -0
  360. package/src/component/garmin/schemas/dailies.ts +38 -0
  361. package/src/component/garmin/schemas/epochs.ts +38 -0
  362. package/src/component/garmin/schemas/healthSnapshot.ts +38 -0
  363. package/src/component/garmin/schemas/hrvSummary.ts +38 -0
  364. package/src/component/garmin/schemas/manuallyUpdatedActivities.ts +49 -0
  365. package/src/component/garmin/schemas/menstrualCycleTracking.ts +39 -0
  366. package/src/component/garmin/schemas/moveIQ.ts +38 -0
  367. package/src/component/garmin/schemas/pulseOx.ts +39 -0
  368. package/src/component/garmin/schemas/respiration.ts +39 -0
  369. package/src/component/garmin/schemas/skinTemperature.ts +39 -0
  370. package/src/component/garmin/schemas/sleeps.ts +38 -0
  371. package/src/component/garmin/schemas/stress.ts +43 -0
  372. package/src/component/garmin/schemas/userMetrics.ts +39 -0
  373. package/src/component/garmin/transform/activity.ts +143 -0
  374. package/src/component/garmin/transform/activityDetails.ts +236 -0
  375. package/src/{garmin → component/garmin/transform}/bloodPressure.ts +39 -41
  376. package/src/component/garmin/transform/bodyCompositions.ts +51 -0
  377. package/src/component/garmin/transform/dailies.ts +179 -0
  378. package/src/component/garmin/transform/epochs.ts +94 -0
  379. package/src/component/garmin/transform/healthSnapshot.ts +152 -0
  380. package/src/component/garmin/transform/hrvSummary.ts +56 -0
  381. package/src/component/garmin/transform/manuallyUpdatedActivities.ts +27 -0
  382. package/src/{garmin/maps/activity-type.ts → component/garmin/transform/maps/activityType.ts} +116 -116
  383. package/src/{garmin/maps/sleep-level.ts → component/garmin/transform/maps/sleepLevel.ts} +22 -22
  384. package/src/component/garmin/transform/menstrualCycleTracking.ts +48 -0
  385. package/src/component/garmin/transform/moveIQ.ts +48 -0
  386. package/src/{garmin → component/garmin/transform}/plannedWorkout.ts +328 -333
  387. package/src/component/garmin/transform/pulseOx.ts +64 -0
  388. package/src/component/garmin/transform/respiration.ts +73 -0
  389. package/src/component/garmin/transform/skinTemperature.ts +44 -0
  390. package/src/component/garmin/transform/sleeps.ts +159 -0
  391. package/src/component/garmin/transform/stress.ts +78 -0
  392. package/src/component/garmin/transform/userMetrics.ts +56 -0
  393. package/src/component/garmin/types/specs/training-api-workouts.json +699 -0
  394. package/src/component/garmin/types/trainingApiWorkouts/client/client.gen.ts +290 -0
  395. package/src/component/garmin/types/trainingApiWorkouts/client/index.ts +25 -0
  396. package/src/component/garmin/types/trainingApiWorkouts/client/types.gen.ts +214 -0
  397. package/src/component/garmin/types/trainingApiWorkouts/client/utils.gen.ts +316 -0
  398. package/src/component/garmin/types/trainingApiWorkouts/client.gen.ts +16 -0
  399. package/src/component/garmin/types/trainingApiWorkouts/core/auth.gen.ts +41 -0
  400. package/src/component/garmin/types/trainingApiWorkouts/core/bodySerializer.gen.ts +82 -0
  401. package/src/component/garmin/types/trainingApiWorkouts/core/params.gen.ts +169 -0
  402. package/src/component/garmin/types/trainingApiWorkouts/core/pathSerializer.gen.ts +171 -0
  403. package/src/component/garmin/types/trainingApiWorkouts/core/queryKeySerializer.gen.ts +117 -0
  404. package/src/component/garmin/types/trainingApiWorkouts/core/serverSentEvents.gen.ts +243 -0
  405. package/src/component/garmin/types/trainingApiWorkouts/core/types.gen.ts +104 -0
  406. package/src/component/garmin/types/trainingApiWorkouts/core/utils.gen.ts +140 -0
  407. package/src/component/garmin/types/trainingApiWorkouts/index.ts +4 -0
  408. package/src/component/garmin/types/trainingApiWorkouts/sdk.gen.ts +126 -0
  409. package/src/component/garmin/types/trainingApiWorkouts/types.gen.ts +387 -0
  410. package/src/component/garmin/types/trainingApiWorkouts/zod.gen.ts +423 -0
  411. package/src/component/garmin/types/wellnessApi/client/client.gen.ts +290 -0
  412. package/src/component/garmin/types/wellnessApi/client/index.ts +25 -0
  413. package/src/component/garmin/types/wellnessApi/client/types.gen.ts +214 -0
  414. package/src/component/garmin/types/wellnessApi/client/utils.gen.ts +316 -0
  415. package/src/component/garmin/types/wellnessApi/client.gen.ts +16 -0
  416. package/src/component/garmin/types/wellnessApi/core/auth.gen.ts +41 -0
  417. package/src/component/garmin/types/wellnessApi/core/bodySerializer.gen.ts +82 -0
  418. package/src/component/garmin/types/wellnessApi/core/params.gen.ts +169 -0
  419. package/src/component/garmin/types/wellnessApi/core/pathSerializer.gen.ts +171 -0
  420. package/src/component/garmin/types/wellnessApi/core/queryKeySerializer.gen.ts +117 -0
  421. package/src/component/garmin/types/wellnessApi/core/serverSentEvents.gen.ts +243 -0
  422. package/src/component/garmin/types/wellnessApi/core/types.gen.ts +104 -0
  423. package/src/component/garmin/types/wellnessApi/core/utils.gen.ts +140 -0
  424. package/src/component/garmin/types/wellnessApi/index.ts +4 -0
  425. package/src/component/garmin/types/wellnessApi/sdk.gen.ts +207 -0
  426. package/src/component/garmin/types/wellnessApi/types.gen.ts +2942 -0
  427. package/src/component/garmin/types/wellnessApi/zod.gen.ts +878 -0
  428. package/src/component/garmin/utils.ts +25 -0
  429. package/src/component/garmin/webhooks.ts +852 -0
  430. package/src/component/strava/private.ts +89 -0
  431. package/src/component/{strava.ts → strava/public.ts} +341 -404
  432. package/src/component/validators/activity.ts +5 -0
  433. package/src/component/validators/body.ts +5 -0
  434. package/src/component/validators/daily.ts +5 -0
  435. package/src/component/validators/menstruation.ts +5 -1
  436. package/src/component/validators/plannedWorkout.ts +5 -0
  437. package/src/validators.ts +12 -2
  438. package/dist/component/garmin.d.ts +0 -366
  439. package/dist/component/garmin.d.ts.map +0 -1
  440. package/dist/component/garmin.js +0 -1481
  441. package/dist/component/garmin.js.map +0 -1
  442. package/dist/component/strava.d.ts.map +0 -1
  443. package/dist/component/strava.js.map +0 -1
  444. package/dist/garmin/activity.d.ts +0 -92
  445. package/dist/garmin/activity.d.ts.map +0 -1
  446. package/dist/garmin/activity.js +0 -201
  447. package/dist/garmin/activity.js.map +0 -1
  448. package/dist/garmin/auth.d.ts.map +0 -1
  449. package/dist/garmin/auth.js.map +0 -1
  450. package/dist/garmin/bloodPressure.d.ts +0 -28
  451. package/dist/garmin/bloodPressure.d.ts.map +0 -1
  452. package/dist/garmin/bloodPressure.js.map +0 -1
  453. package/dist/garmin/body.d.ts +0 -26
  454. package/dist/garmin/body.d.ts.map +0 -1
  455. package/dist/garmin/body.js +0 -44
  456. package/dist/garmin/body.js.map +0 -1
  457. package/dist/garmin/client.d.ts +0 -246
  458. package/dist/garmin/client.d.ts.map +0 -1
  459. package/dist/garmin/client.js +0 -566
  460. package/dist/garmin/client.js.map +0 -1
  461. package/dist/garmin/daily.d.ts +0 -74
  462. package/dist/garmin/daily.d.ts.map +0 -1
  463. package/dist/garmin/daily.js.map +0 -1
  464. package/dist/garmin/hrv.d.ts +0 -30
  465. package/dist/garmin/hrv.d.ts.map +0 -1
  466. package/dist/garmin/hrv.js.map +0 -1
  467. package/dist/garmin/index.d.ts +0 -34
  468. package/dist/garmin/index.d.ts.map +0 -1
  469. package/dist/garmin/index.js +0 -28
  470. package/dist/garmin/index.js.map +0 -1
  471. package/dist/garmin/maps/activity-type.d.ts.map +0 -1
  472. package/dist/garmin/maps/activity-type.js.map +0 -1
  473. package/dist/garmin/maps/sleep-level.d.ts.map +0 -1
  474. package/dist/garmin/maps/sleep-level.js.map +0 -1
  475. package/dist/garmin/menstruation.d.ts +0 -25
  476. package/dist/garmin/menstruation.d.ts.map +0 -1
  477. package/dist/garmin/menstruation.js.map +0 -1
  478. package/dist/garmin/plannedWorkout.d.ts.map +0 -1
  479. package/dist/garmin/plannedWorkout.js.map +0 -1
  480. package/dist/garmin/pulseOx.d.ts +0 -24
  481. package/dist/garmin/pulseOx.d.ts.map +0 -1
  482. package/dist/garmin/pulseOx.js +0 -33
  483. package/dist/garmin/pulseOx.js.map +0 -1
  484. package/dist/garmin/respiration.d.ts +0 -29
  485. package/dist/garmin/respiration.d.ts.map +0 -1
  486. package/dist/garmin/respiration.js +0 -42
  487. package/dist/garmin/respiration.js.map +0 -1
  488. package/dist/garmin/skinTemp.d.ts +0 -27
  489. package/dist/garmin/skinTemp.d.ts.map +0 -1
  490. package/dist/garmin/skinTemp.js.map +0 -1
  491. package/dist/garmin/sleep.d.ts.map +0 -1
  492. package/dist/garmin/sleep.js.map +0 -1
  493. package/dist/garmin/stressDetails.d.ts +0 -30
  494. package/dist/garmin/stressDetails.d.ts.map +0 -1
  495. package/dist/garmin/stressDetails.js +0 -49
  496. package/dist/garmin/stressDetails.js.map +0 -1
  497. package/dist/garmin/sync.d.ts +0 -53
  498. package/dist/garmin/sync.d.ts.map +0 -1
  499. package/dist/garmin/sync.js +0 -457
  500. package/dist/garmin/sync.js.map +0 -1
  501. package/dist/garmin/types.d.ts +0 -175
  502. package/dist/garmin/types.d.ts.map +0 -1
  503. package/dist/garmin/types.js +0 -10
  504. package/dist/garmin/types.js.map +0 -1
  505. package/dist/garmin/userMetrics.d.ts +0 -23
  506. package/dist/garmin/userMetrics.d.ts.map +0 -1
  507. package/dist/garmin/userMetrics.js.map +0 -1
  508. package/src/component/garmin.ts +0 -1722
  509. package/src/garmin/activity.test.ts +0 -170
  510. package/src/garmin/activity.ts +0 -265
  511. package/src/garmin/auth.test.ts +0 -103
  512. package/src/garmin/body.ts +0 -59
  513. package/src/garmin/client.ts +0 -886
  514. package/src/garmin/daily.ts +0 -215
  515. package/src/garmin/hrv.ts +0 -57
  516. package/src/garmin/index.ts +0 -145
  517. package/src/garmin/maps/activity-type.test.ts +0 -78
  518. package/src/garmin/menstruation.ts +0 -44
  519. package/src/garmin/pulseOx.ts +0 -45
  520. package/src/garmin/respiration.ts +0 -55
  521. package/src/garmin/skinTemp.ts +0 -42
  522. package/src/garmin/sleep.test.ts +0 -109
  523. package/src/garmin/sleep.ts +0 -176
  524. package/src/garmin/stressDetails.ts +0 -71
  525. package/src/garmin/sync.ts +0 -566
  526. package/src/garmin/types.ts +0 -268
  527. package/src/garmin/userMetrics.ts +0 -50
  528. package/src/garmin/wellness-api.d.ts +0 -5637
  529. /package/dist/{garmin → component/garmin}/auth.js +0 -0
  530. /package/src/{garmin/spec → component/garmin/types/specs}/wellness-api.json +0 -0
@@ -0,0 +1,823 @@
1
+ // ─── Garmin Public Actions ───────────────────────────────────────────────────
2
+ // Public actions that handle the full Garmin OAuth 2.0 PKCE + sync lifecycle.
3
+ // The host app calls these through the Soma class, which threads the
4
+ // credentials automatically from env vars or constructor config.
5
+ import { v } from "convex/values";
6
+ import { action } from "../_generated/server";
7
+ import { generateCodeVerifier, generateCodeChallenge, generateState, buildAuthUrl, exchangeCode, refreshToken, } from "./auth.js";
8
+ import { createWellnessClient, createTrainingClient, } from "./client.js";
9
+ import { timeRangeQuery } from "./utils.js";
10
+ import { createWorkoutV2 as sdkCreateWorkoutV2, createWorkoutSchedule as sdkCreateWorkoutSchedule, } from "./types/trainingApiWorkouts/sdk.gen";
11
+ import { userId as sdkUserId, dereg as sdkDereg, getActivities, getDailies, getSleeps, getBodyComps, getMct, getBloodPressures, getSkinTemp, getUserMetrics, getHrv, getStressDetails, getPulseox, getRespiration, } from "./types/wellnessApi/sdk.gen";
12
+ import { transformActivity } from "./transform/activity.js";
13
+ import { transformDailies } from "./transform/dailies.js";
14
+ import { transformSleeps } from "./transform/sleeps.js";
15
+ import { transformBodyComposition } from "./transform/bodyCompositions.js";
16
+ import { transformMenstrualCycleTracking } from "./transform/menstrualCycleTracking.js";
17
+ import { transformBloodPressure } from "./transform/bloodPressure.js";
18
+ import { transformSkinTemperature } from "./transform/skinTemperature.js";
19
+ import { transformUserMetrics } from "./transform/userMetrics.js";
20
+ import { transformHRVSummary } from "./transform/hrvSummary.js";
21
+ import { transformStress } from "./transform/stress.js";
22
+ import { transformPulseOx } from "./transform/pulseOx.js";
23
+ import { transformRespiration } from "./transform/respiration.js";
24
+ import { transformPlannedWorkoutToGarmin } from "./transform/plannedWorkout.js";
25
+ import { api, internal } from "../_generated/api";
26
+ // Default sync window: last 30 days
27
+ const DEFAULT_SYNC_DAYS = 30;
28
+ // Refresh buffer: refresh tokens 10 minutes before expiry
29
+ const REFRESH_BUFFER_SECONDS = 600;
30
+ // ─── Public Actions ──────────────────────────────────────────────────────────
31
+ /**
32
+ * Generate a Garmin OAuth 2.0 authorization URL with PKCE.
33
+ *
34
+ * If `userId` is provided, the PKCE code verifier and state are stored in the
35
+ * component's `pendingOAuth` table so that `completeGarminOAuth` can look
36
+ * them up automatically when the callback fires. This is the recommended
37
+ * flow when using `registerRoutes`.
38
+ *
39
+ * If `userId` is omitted, the host app must store the returned `codeVerifier`
40
+ * itself and pass it to `connectGarmin` manually.
41
+ */
42
+ export const getGarminAuthUrl = action({
43
+ args: {
44
+ clientId: v.string(),
45
+ redirectUri: v.optional(v.string()),
46
+ userId: v.optional(v.string()),
47
+ },
48
+ handler: async (ctx, args) => {
49
+ const codeVerifier = generateCodeVerifier();
50
+ const codeChallenge = await generateCodeChallenge(codeVerifier);
51
+ const state = generateState();
52
+ const authUrl = buildAuthUrl({
53
+ clientId: args.clientId,
54
+ codeChallenge,
55
+ redirectUri: args.redirectUri,
56
+ state,
57
+ });
58
+ if (args.userId) {
59
+ await ctx.runMutation(internal.garmin.private.storePendingOAuth, {
60
+ provider: "GARMIN",
61
+ state,
62
+ codeVerifier,
63
+ userId: args.userId,
64
+ });
65
+ }
66
+ return { authUrl, state, codeVerifier };
67
+ },
68
+ });
69
+ /**
70
+ * Exchange an authorization code for tokens + initial sync.
71
+ *
72
+ * Used in the manual flow where the host app stores the code verifier
73
+ * and handles the callback itself.
74
+ */
75
+ export const connectGarmin = action({
76
+ args: {
77
+ userId: v.string(),
78
+ clientId: v.string(),
79
+ clientSecret: v.string(),
80
+ code: v.string(),
81
+ codeVerifier: v.string(),
82
+ redirectUri: v.optional(v.string()),
83
+ },
84
+ handler: async (ctx, args) => {
85
+ const tokenResult = await exchangeCode({
86
+ clientId: args.clientId,
87
+ clientSecret: args.clientSecret,
88
+ code: args.code,
89
+ codeVerifier: args.codeVerifier,
90
+ redirectUri: args.redirectUri,
91
+ });
92
+ const connectionId = await ctx.runMutation(api.public.connect, {
93
+ userId: args.userId,
94
+ provider: "GARMIN",
95
+ });
96
+ const expiresAt = Math.floor(Date.now() / 1000) + tokenResult.expires_in;
97
+ const _stored = await ctx.runMutation(internal.garmin.private.storeTokens, {
98
+ connectionId,
99
+ accessToken: tokenResult.access_token,
100
+ refreshToken: tokenResult.refresh_token,
101
+ expiresAt,
102
+ });
103
+ // Best-effort: resolve Garmin user ID for webhook mapping
104
+ const wellnessClient = createWellnessClient(tokenResult.access_token);
105
+ const { data: userIdData } = await sdkUserId({ client: wellnessClient });
106
+ const garminUserId = userIdData?.userId ?? null;
107
+ if (garminUserId) {
108
+ const _updated = await ctx.runMutation(api.public.updateConnection, {
109
+ connectionId,
110
+ providerUserId: garminUserId,
111
+ });
112
+ }
113
+ const now = Math.floor(Date.now() / 1000);
114
+ const thirtyDaysAgo = now - DEFAULT_SYNC_DAYS * 86400;
115
+ const timeRange = {
116
+ uploadStartTimeInSeconds: thirtyDaysAgo,
117
+ uploadEndTimeInSeconds: now,
118
+ };
119
+ const result = await ctx.runAction(api.garmin.public.syncAllTypes, {
120
+ accessToken: tokenResult.access_token,
121
+ connectionId,
122
+ userId: args.userId,
123
+ uploadStartTimeInSeconds: timeRange.uploadStartTimeInSeconds,
124
+ uploadEndTimeInSeconds: timeRange.uploadEndTimeInSeconds,
125
+ });
126
+ const _updated = await ctx.runMutation(api.public.updateConnection, {
127
+ connectionId,
128
+ lastDataUpdate: new Date().toISOString(),
129
+ });
130
+ return {
131
+ connectionId,
132
+ synced: result.synced,
133
+ errors: result.errors,
134
+ };
135
+ },
136
+ });
137
+ /**
138
+ * Complete a Garmin OAuth 2.0 flow using stored pending state.
139
+ *
140
+ * Used by `registerRoutes` — the callback handler calls this with the
141
+ * `code` and `state` from the redirect. The action looks up the pending
142
+ * state (codeVerifier, userId) stored during `getGarminAuthUrl`,
143
+ * exchanges for tokens, creates the connection, syncs data, and
144
+ * cleans up the pending entry.
145
+ */
146
+ export const completeGarminOAuth = action({
147
+ args: {
148
+ code: v.string(),
149
+ state: v.string(),
150
+ clientId: v.string(),
151
+ clientSecret: v.string(),
152
+ redirectUri: v.optional(v.string()),
153
+ },
154
+ handler: async (ctx, args) => {
155
+ const pending = await ctx.runQuery(internal.garmin.private.getPendingOAuth, {
156
+ state: args.state,
157
+ });
158
+ if (!pending) {
159
+ throw new Error("No pending Garmin OAuth state found for this state parameter. " +
160
+ "The authorization may have expired or was already used.");
161
+ }
162
+ const tokenResult = await exchangeCode({
163
+ clientId: args.clientId,
164
+ clientSecret: args.clientSecret,
165
+ code: args.code,
166
+ codeVerifier: pending.codeVerifier,
167
+ redirectUri: args.redirectUri,
168
+ });
169
+ const _deleted = await ctx.runMutation(internal.garmin.private.deletePendingOAuth, {
170
+ state: args.state,
171
+ });
172
+ const connectionId = await ctx.runMutation(api.public.connect, {
173
+ userId: pending.userId,
174
+ provider: "GARMIN",
175
+ });
176
+ const expiresAt = Math.floor(Date.now() / 1000) + tokenResult.expires_in;
177
+ const _stored = await ctx.runMutation(internal.garmin.private.storeTokens, {
178
+ connectionId,
179
+ accessToken: tokenResult.access_token,
180
+ refreshToken: tokenResult.refresh_token,
181
+ expiresAt,
182
+ });
183
+ // Best-effort: resolve Garmin user ID for webhook mapping
184
+ const wellnessClient = createWellnessClient(tokenResult.access_token);
185
+ const { data: userIdData } = await sdkUserId({ client: wellnessClient });
186
+ const garminUserId = userIdData?.userId ?? null;
187
+ if (garminUserId) {
188
+ const _updated = await ctx.runMutation(api.public.updateConnection, {
189
+ connectionId,
190
+ providerUserId: garminUserId,
191
+ });
192
+ }
193
+ const now = Math.floor(Date.now() / 1000);
194
+ const thirtyDaysAgo = now - DEFAULT_SYNC_DAYS * 86400;
195
+ const timeRange = {
196
+ uploadStartTimeInSeconds: thirtyDaysAgo,
197
+ uploadEndTimeInSeconds: now,
198
+ };
199
+ const result = await ctx.runAction(api.garmin.public.syncAllTypes, {
200
+ accessToken: tokenResult.access_token,
201
+ connectionId,
202
+ userId: pending.userId,
203
+ uploadStartTimeInSeconds: timeRange.uploadStartTimeInSeconds,
204
+ uploadEndTimeInSeconds: timeRange.uploadEndTimeInSeconds,
205
+ });
206
+ const _updated = await ctx.runMutation(api.public.updateConnection, {
207
+ connectionId,
208
+ lastDataUpdate: new Date().toISOString(),
209
+ });
210
+ return {
211
+ connectionId,
212
+ synced: result.synced,
213
+ errors: result.errors,
214
+ };
215
+ },
216
+ });
217
+ /**
218
+ * Incremental Garmin sync for an already-connected user.
219
+ *
220
+ * Looks up the stored tokens, refreshes if expired, and syncs all data
221
+ * types for the specified time range (defaults to last 30 days).
222
+ */
223
+ export const syncGarmin = action({
224
+ args: {
225
+ userId: v.string(),
226
+ clientId: v.string(),
227
+ clientSecret: v.string(),
228
+ startTimeInSeconds: v.optional(v.number()),
229
+ endTimeInSeconds: v.optional(v.number()),
230
+ },
231
+ handler: async (ctx, args) => {
232
+ const connection = await ctx.runQuery(internal.private.getConnectionByProvider, { userId: args.userId, provider: "GARMIN" });
233
+ if (!connection) {
234
+ throw new Error(`No Garmin connection found for user "${args.userId}". ` +
235
+ "Call connectGarmin first.");
236
+ }
237
+ if (!connection.active) {
238
+ throw new Error(`Garmin connection for user "${args.userId}" is inactive. Reconnect first.`);
239
+ }
240
+ const connectionId = connection._id;
241
+ const tokenDoc = await ctx.runQuery(internal.garmin.private.getTokens, {
242
+ connectionId,
243
+ });
244
+ if (!tokenDoc) {
245
+ throw new Error("No Garmin tokens found for this connection. " +
246
+ "The connection may have been created before token storage was available.");
247
+ }
248
+ let accessToken = tokenDoc.accessToken;
249
+ // Refresh the token if it's expired or about to expire
250
+ const nowSeconds = Math.floor(Date.now() / 1000);
251
+ if (tokenDoc.expiresAt &&
252
+ tokenDoc.refreshToken &&
253
+ nowSeconds >= tokenDoc.expiresAt - REFRESH_BUFFER_SECONDS) {
254
+ const refreshed = await refreshToken({
255
+ clientId: args.clientId,
256
+ clientSecret: args.clientSecret,
257
+ refreshToken: tokenDoc.refreshToken,
258
+ });
259
+ accessToken = refreshed.access_token;
260
+ const newExpiresAt = nowSeconds + refreshed.expires_in;
261
+ const _refreshed = await ctx.runMutation(internal.garmin.private.storeTokens, {
262
+ connectionId,
263
+ accessToken: refreshed.access_token,
264
+ refreshToken: refreshed.refresh_token,
265
+ expiresAt: newExpiresAt,
266
+ });
267
+ }
268
+ // Lazy backfill: resolve Garmin user ID if missing (for webhook mapping)
269
+ if (!connection.providerUserId) {
270
+ const wellnessClient = createWellnessClient(accessToken);
271
+ const { data: userIdData } = await sdkUserId({ client: wellnessClient });
272
+ const garminUserId = userIdData?.userId ?? null;
273
+ if (garminUserId) {
274
+ const _updated = await ctx.runMutation(api.public.updateConnection, {
275
+ connectionId,
276
+ providerUserId: garminUserId,
277
+ });
278
+ }
279
+ }
280
+ const now = Math.floor(Date.now() / 1000);
281
+ const timeRange = {
282
+ uploadStartTimeInSeconds: args.startTimeInSeconds ?? now - DEFAULT_SYNC_DAYS * 86400,
283
+ uploadEndTimeInSeconds: args.endTimeInSeconds ?? now,
284
+ };
285
+ const result = await ctx.runAction(api.garmin.public.syncAllTypes, {
286
+ accessToken,
287
+ connectionId,
288
+ userId: args.userId,
289
+ uploadStartTimeInSeconds: timeRange.uploadStartTimeInSeconds,
290
+ uploadEndTimeInSeconds: timeRange.uploadEndTimeInSeconds,
291
+ });
292
+ const _updated = await ctx.runMutation(api.public.updateConnection, {
293
+ connectionId,
294
+ lastDataUpdate: new Date().toISOString(),
295
+ });
296
+ return result;
297
+ },
298
+ });
299
+ /**
300
+ * Disconnect a user from Garmin.
301
+ *
302
+ * Deregisters the user via the Garmin API (best-effort), deletes stored
303
+ * tokens, and sets the connection to inactive.
304
+ */
305
+ export const disconnectGarmin = action({
306
+ args: {
307
+ userId: v.string(),
308
+ },
309
+ handler: async (ctx, args) => {
310
+ const connection = await ctx.runQuery(internal.private.getConnectionByProvider, { userId: args.userId, provider: "GARMIN" });
311
+ if (!connection) {
312
+ throw new Error(`No Garmin connection found for user "${args.userId}".`);
313
+ }
314
+ const connectionId = connection._id;
315
+ // Best-effort: deregister user at Garmin
316
+ const tokenDoc = await ctx.runQuery(internal.garmin.private.getTokens, {
317
+ connectionId,
318
+ });
319
+ if (tokenDoc) {
320
+ try {
321
+ const wellnessClient = createWellnessClient(tokenDoc.accessToken);
322
+ await sdkDereg({ client: wellnessClient });
323
+ }
324
+ catch {
325
+ // Deregistration is best-effort; proceed with local cleanup
326
+ }
327
+ }
328
+ const _deleted = await ctx.runMutation(internal.garmin.private.deleteTokens, { connectionId });
329
+ const _disconnected = await ctx.runMutation(api.public.disconnect, {
330
+ userId: args.userId,
331
+ provider: "GARMIN",
332
+ });
333
+ return null;
334
+ },
335
+ });
336
+ // ─── Training API ────────────────────────────────────────────────────────────
337
+ /**
338
+ * Push a planned workout from Soma's DB to Garmin Connect.
339
+ *
340
+ * Reads the planned workout document, transforms it to Garmin Training API V2
341
+ * format, creates the workout at Garmin, and optionally schedules it if a
342
+ * `planned_date` is set in the metadata.
343
+ *
344
+ * Returns the Garmin workout ID and schedule ID (if scheduled).
345
+ */
346
+ export const pushPlannedWorkout = action({
347
+ args: {
348
+ userId: v.string(),
349
+ clientId: v.string(),
350
+ clientSecret: v.string(),
351
+ plannedWorkoutId: v.string(),
352
+ workoutProvider: v.optional(v.string()),
353
+ },
354
+ handler: async (ctx, args) => {
355
+ const connection = await ctx.runQuery(internal.private.getConnectionByProvider, { userId: args.userId, provider: "GARMIN" });
356
+ if (!connection) {
357
+ throw new Error(`No Garmin connection found for user "${args.userId}". ` +
358
+ "Call connectGarmin first.");
359
+ }
360
+ if (!connection.active) {
361
+ throw new Error(`Garmin connection for user "${args.userId}" is inactive. Reconnect first.`);
362
+ }
363
+ const connectionId = connection._id;
364
+ const tokenDoc = await ctx.runQuery(internal.garmin.private.getTokens, {
365
+ connectionId,
366
+ });
367
+ if (!tokenDoc) {
368
+ throw new Error("No Garmin tokens found for this connection. " +
369
+ "The connection may have been created before token storage was available.");
370
+ }
371
+ // Always force-refresh the token for Training API calls to rule out
372
+ // stale tokens (the initial sync swallows 401 errors silently).
373
+ let accessToken = tokenDoc.accessToken;
374
+ if (tokenDoc.refreshToken) {
375
+ try {
376
+ const refreshed = await refreshToken({
377
+ clientId: args.clientId,
378
+ clientSecret: args.clientSecret,
379
+ refreshToken: tokenDoc.refreshToken,
380
+ });
381
+ accessToken = refreshed.access_token;
382
+ const nowSeconds = Math.floor(Date.now() / 1000);
383
+ const newExpiresAt = nowSeconds + refreshed.expires_in;
384
+ const _refreshed = await ctx.runMutation(internal.garmin.private.storeTokens, {
385
+ connectionId,
386
+ accessToken: refreshed.access_token,
387
+ refreshToken: refreshed.refresh_token,
388
+ expiresAt: newExpiresAt,
389
+ });
390
+ }
391
+ catch (refreshErr) {
392
+ throw new Error(`Garmin token refresh failed: ${refreshErr instanceof Error ? refreshErr.message : String(refreshErr)}. ` +
393
+ "The user may need to reconnect their Garmin account.");
394
+ }
395
+ }
396
+ const plannedWorkout = await ctx.runQuery(api.public.getPlannedWorkout, { plannedWorkoutId: args.plannedWorkoutId });
397
+ if (!plannedWorkout) {
398
+ throw new Error(`Planned workout "${args.plannedWorkoutId}" not found.`);
399
+ }
400
+ const providerName = args.workoutProvider ?? "Soma";
401
+ const garminWorkout = transformPlannedWorkoutToGarmin(plannedWorkout, providerName);
402
+ const trainingClient = createTrainingClient(accessToken);
403
+ const { data: created, error: createError } = await sdkCreateWorkoutV2({
404
+ client: trainingClient,
405
+ body: garminWorkout,
406
+ });
407
+ if (createError || !created) {
408
+ throw new Error(`Garmin API error creating workout: ${createError ? JSON.stringify(createError) : "No data"}`);
409
+ }
410
+ if (!created.workoutId) {
411
+ throw new Error("Garmin API did not return a workoutId after creation.");
412
+ }
413
+ let garminScheduleId = null;
414
+ const plannedDate = plannedWorkout.metadata?.planned_date;
415
+ if (plannedDate) {
416
+ const { data: scheduleId, error: scheduleError } = await sdkCreateWorkoutSchedule({
417
+ client: trainingClient,
418
+ body: { workoutId: Number(created.workoutId), date: plannedDate },
419
+ });
420
+ if (scheduleError) {
421
+ throw new Error(`Garmin API error creating schedule: ${JSON.stringify(scheduleError)}`);
422
+ }
423
+ garminScheduleId = scheduleId ?? null;
424
+ }
425
+ // Store the Garmin workout/schedule IDs back on the planned workout
426
+ // so the host app can match completed activities to planned sessions.
427
+ const _ingested = await ctx.runMutation(api.public.ingestPlannedWorkout, {
428
+ ...plannedWorkout,
429
+ _id: undefined,
430
+ _creationTime: undefined,
431
+ metadata: {
432
+ ...plannedWorkout.metadata,
433
+ provider_workout_id: String(created.workoutId),
434
+ provider_schedule_id: garminScheduleId != null ? String(garminScheduleId) : undefined,
435
+ },
436
+ });
437
+ return {
438
+ garminWorkoutId: created.workoutId,
439
+ garminScheduleId,
440
+ };
441
+ },
442
+ });
443
+ // ─── Sync Engine ────────────────────────────────────────────────────────────
444
+ /**
445
+ * Fetch and ingest all Garmin wellness data types for a time range.
446
+ *
447
+ * Called by the public actions (connectGarmin, completeGarminOAuth, syncGarmin)
448
+ * after obtaining a valid access token.
449
+ */
450
+ export const syncAllTypes = action({
451
+ args: {
452
+ accessToken: v.string(),
453
+ connectionId: v.id("connections"),
454
+ userId: v.string(),
455
+ uploadStartTimeInSeconds: v.number(),
456
+ uploadEndTimeInSeconds: v.number(),
457
+ },
458
+ handler: async (ctx, args) => {
459
+ const { accessToken, connectionId, userId } = args;
460
+ const timeRange = {
461
+ uploadStartTimeInSeconds: args.uploadStartTimeInSeconds,
462
+ uploadEndTimeInSeconds: args.uploadEndTimeInSeconds,
463
+ };
464
+ const wellnessClient = createWellnessClient(accessToken);
465
+ const query = timeRangeQuery(timeRange, accessToken);
466
+ const synced = {
467
+ activities: 0, dailies: 0, sleep: 0, body: 0, menstruation: 0,
468
+ bloodPressures: 0, skinTemp: 0, userMetrics: 0,
469
+ hrv: 0, stressDetails: 0, pulseOx: 0, respiration: 0,
470
+ };
471
+ const errors = [];
472
+ // ── Activities ──────────────────────────────────────────────────────────
473
+ try {
474
+ const { data: activities, error } = await getActivities({ client: wellnessClient, query });
475
+ if (error || !activities)
476
+ throw new Error(error ? JSON.stringify(error) : "No data");
477
+ for (const activity of activities) {
478
+ try {
479
+ const data = transformActivity(activity);
480
+ await ctx.runMutation(api.public.ingestActivity, {
481
+ connectionId,
482
+ userId,
483
+ ...data,
484
+ });
485
+ synced.activities++;
486
+ }
487
+ catch (err) {
488
+ errors.push({
489
+ type: "activity",
490
+ id: activity.summaryId ?? String(activity.activityId),
491
+ error: err instanceof Error ? err.message : String(err),
492
+ });
493
+ }
494
+ }
495
+ }
496
+ catch (err) {
497
+ errors.push({
498
+ type: "activity",
499
+ id: "fetch",
500
+ error: err instanceof Error ? err.message : String(err),
501
+ });
502
+ }
503
+ // ── Dailies ─────────────────────────────────────────────────────────────
504
+ try {
505
+ const { data: dailies, error } = await getDailies({ client: wellnessClient, query });
506
+ if (error || !dailies)
507
+ throw new Error(error ? JSON.stringify(error) : "No data");
508
+ for (const daily of dailies) {
509
+ try {
510
+ const data = transformDailies(daily);
511
+ if (!data)
512
+ continue;
513
+ await ctx.runMutation(api.public.ingestDaily, {
514
+ connectionId,
515
+ userId,
516
+ ...data,
517
+ });
518
+ synced.dailies++;
519
+ }
520
+ catch (err) {
521
+ errors.push({
522
+ type: "daily",
523
+ id: daily.summaryId ?? daily.calendarDate ?? "unknown",
524
+ error: err instanceof Error ? err.message : String(err),
525
+ });
526
+ }
527
+ }
528
+ }
529
+ catch (err) {
530
+ errors.push({
531
+ type: "daily",
532
+ id: "fetch",
533
+ error: err instanceof Error ? err.message : String(err),
534
+ });
535
+ }
536
+ // ── Sleep ───────────────────────────────────────────────────────────────
537
+ try {
538
+ const { data: sleeps, error } = await getSleeps({ client: wellnessClient, query });
539
+ if (error || !sleeps)
540
+ throw new Error(error ? JSON.stringify(error) : "No data");
541
+ for (const sleep of sleeps) {
542
+ try {
543
+ const data = transformSleeps(sleep);
544
+ await ctx.runMutation(api.public.ingestSleep, {
545
+ connectionId,
546
+ userId,
547
+ ...data,
548
+ });
549
+ synced.sleep++;
550
+ }
551
+ catch (err) {
552
+ errors.push({
553
+ type: "sleep",
554
+ id: sleep.summaryId ?? sleep.calendarDate ?? "unknown",
555
+ error: err instanceof Error ? err.message : String(err),
556
+ });
557
+ }
558
+ }
559
+ }
560
+ catch (err) {
561
+ errors.push({
562
+ type: "sleep",
563
+ id: "fetch",
564
+ error: err instanceof Error ? err.message : String(err),
565
+ });
566
+ }
567
+ // ── Body ────────────────────────────────────────────────────────────────
568
+ try {
569
+ const { data: bodyComps, error } = await getBodyComps({ client: wellnessClient, query });
570
+ if (error || !bodyComps)
571
+ throw new Error(error ? JSON.stringify(error) : "No data");
572
+ for (const body of bodyComps) {
573
+ try {
574
+ const data = transformBodyComposition(body);
575
+ if (!data)
576
+ continue;
577
+ await ctx.runMutation(api.public.ingestBody, {
578
+ connectionId,
579
+ userId,
580
+ ...data,
581
+ });
582
+ synced.body++;
583
+ }
584
+ catch (err) {
585
+ errors.push({
586
+ type: "body",
587
+ id: body.summaryId ?? String(body.measurementTimeInSeconds),
588
+ error: err instanceof Error ? err.message : String(err),
589
+ });
590
+ }
591
+ }
592
+ }
593
+ catch (err) {
594
+ errors.push({
595
+ type: "body",
596
+ id: "fetch",
597
+ error: err instanceof Error ? err.message : String(err),
598
+ });
599
+ }
600
+ // ── Menstruation ────────────────────────────────────────────────────────
601
+ try {
602
+ const { data: records, error } = await getMct({ client: wellnessClient, query });
603
+ if (error || !records)
604
+ throw new Error(error ? JSON.stringify(error) : "No data");
605
+ for (const record of records) {
606
+ try {
607
+ const data = transformMenstrualCycleTracking(record);
608
+ await ctx.runMutation(api.public.ingestMenstruation, {
609
+ connectionId,
610
+ userId,
611
+ ...data,
612
+ });
613
+ synced.menstruation++;
614
+ }
615
+ catch (err) {
616
+ errors.push({
617
+ type: "menstruation",
618
+ id: record.summaryId ?? record.periodStartDate ?? "unknown",
619
+ error: err instanceof Error ? err.message : String(err),
620
+ });
621
+ }
622
+ }
623
+ }
624
+ catch (err) {
625
+ errors.push({
626
+ type: "menstruation",
627
+ id: "fetch",
628
+ error: err instanceof Error ? err.message : String(err),
629
+ });
630
+ }
631
+ // ── Blood Pressures (→ body) ───────────────────────────────────────────
632
+ try {
633
+ const { data: bpRecords, error } = await getBloodPressures({ client: wellnessClient, query });
634
+ if (error || !bpRecords)
635
+ throw new Error(error ? JSON.stringify(error) : "No data");
636
+ for (const bp of bpRecords) {
637
+ try {
638
+ const data = transformBloodPressure(bp);
639
+ if (!data)
640
+ continue;
641
+ await ctx.runMutation(api.public.ingestBody, {
642
+ connectionId, userId, ...data,
643
+ });
644
+ synced.bloodPressures++;
645
+ }
646
+ catch (err) {
647
+ errors.push({
648
+ type: "bloodPressure",
649
+ id: bp.summaryId ?? String(bp.measurementTimeInSeconds),
650
+ error: err instanceof Error ? err.message : String(err),
651
+ });
652
+ }
653
+ }
654
+ }
655
+ catch (err) {
656
+ errors.push({ type: "bloodPressure", id: "fetch", error: err instanceof Error ? err.message : String(err) });
657
+ }
658
+ // ── Skin Temperature (→ body) ──────────────────────────────────────────
659
+ try {
660
+ const { data: skinRecords, error } = await getSkinTemp({ client: wellnessClient, query });
661
+ if (error || !skinRecords)
662
+ throw new Error(error ? JSON.stringify(error) : "No data");
663
+ for (const skin of skinRecords) {
664
+ try {
665
+ const data = transformSkinTemperature(skin);
666
+ if (!data)
667
+ continue;
668
+ await ctx.runMutation(api.public.ingestBody, {
669
+ connectionId, userId, ...data,
670
+ });
671
+ synced.skinTemp++;
672
+ }
673
+ catch (err) {
674
+ errors.push({
675
+ type: "skinTemp",
676
+ id: skin.summaryId ?? skin.calendarDate ?? "unknown",
677
+ error: err instanceof Error ? err.message : String(err),
678
+ });
679
+ }
680
+ }
681
+ }
682
+ catch (err) {
683
+ errors.push({ type: "skinTemp", id: "fetch", error: err instanceof Error ? err.message : String(err) });
684
+ }
685
+ // ── User Metrics (→ body) ──────────────────────────────────────────────
686
+ try {
687
+ const { data: metricsRecords, error } = await getUserMetrics({ client: wellnessClient, query });
688
+ if (error || !metricsRecords)
689
+ throw new Error(error ? JSON.stringify(error) : "No data");
690
+ for (const metrics of metricsRecords) {
691
+ try {
692
+ const data = transformUserMetrics(metrics);
693
+ if (!data)
694
+ continue;
695
+ await ctx.runMutation(api.public.ingestBody, {
696
+ connectionId, userId, ...data,
697
+ });
698
+ synced.userMetrics++;
699
+ }
700
+ catch (err) {
701
+ errors.push({
702
+ type: "userMetrics",
703
+ id: metrics.summaryId ?? metrics.calendarDate ?? "unknown",
704
+ error: err instanceof Error ? err.message : String(err),
705
+ });
706
+ }
707
+ }
708
+ }
709
+ catch (err) {
710
+ errors.push({ type: "userMetrics", id: "fetch", error: err instanceof Error ? err.message : String(err) });
711
+ }
712
+ // ── HRV (enriches daily) ──────────────────────────────────────────────
713
+ try {
714
+ const { data: hrvRecords, error } = await getHrv({ client: wellnessClient, query });
715
+ if (error || !hrvRecords)
716
+ throw new Error(error ? JSON.stringify(error) : "No data");
717
+ for (const hrv of hrvRecords) {
718
+ try {
719
+ const data = transformHRVSummary(hrv);
720
+ if (data) {
721
+ await ctx.runMutation(api.public.ingestDaily, {
722
+ connectionId, userId, ...data,
723
+ });
724
+ synced.hrv++;
725
+ }
726
+ }
727
+ catch (err) {
728
+ errors.push({
729
+ type: "hrv",
730
+ id: hrv.summaryId ?? hrv.calendarDate ?? "unknown",
731
+ error: err instanceof Error ? err.message : String(err),
732
+ });
733
+ }
734
+ }
735
+ }
736
+ catch (err) {
737
+ errors.push({ type: "hrv", id: "fetch", error: err instanceof Error ? err.message : String(err) });
738
+ }
739
+ // ── Stress Details (enriches daily) ────────────────────────────────────
740
+ try {
741
+ const { data: stressRecords, error } = await getStressDetails({ client: wellnessClient, query });
742
+ if (error || !stressRecords)
743
+ throw new Error(error ? JSON.stringify(error) : "No data");
744
+ for (const stress of stressRecords) {
745
+ try {
746
+ const data = transformStress(stress);
747
+ if (data) {
748
+ await ctx.runMutation(api.public.ingestDaily, {
749
+ connectionId, userId, ...data,
750
+ });
751
+ synced.stressDetails++;
752
+ }
753
+ }
754
+ catch (err) {
755
+ errors.push({
756
+ type: "stressDetails",
757
+ id: stress.summaryId ?? stress.calendarDate ?? "unknown",
758
+ error: err instanceof Error ? err.message : String(err),
759
+ });
760
+ }
761
+ }
762
+ }
763
+ catch (err) {
764
+ errors.push({ type: "stressDetails", id: "fetch", error: err instanceof Error ? err.message : String(err) });
765
+ }
766
+ // ── Pulse Ox (enriches daily) ──────────────────────────────────────────
767
+ try {
768
+ const { data: pulseOxRecords, error } = await getPulseox({ client: wellnessClient, query });
769
+ if (error || !pulseOxRecords)
770
+ throw new Error(error ? JSON.stringify(error) : "No data");
771
+ for (const po of pulseOxRecords) {
772
+ try {
773
+ const data = transformPulseOx(po);
774
+ if (data) {
775
+ await ctx.runMutation(api.public.ingestDaily, {
776
+ connectionId, userId, ...data,
777
+ });
778
+ synced.pulseOx++;
779
+ }
780
+ }
781
+ catch (err) {
782
+ errors.push({
783
+ type: "pulseOx",
784
+ id: po.summaryId ?? po.calendarDate ?? "unknown",
785
+ error: err instanceof Error ? err.message : String(err),
786
+ });
787
+ }
788
+ }
789
+ }
790
+ catch (err) {
791
+ errors.push({ type: "pulseOx", id: "fetch", error: err instanceof Error ? err.message : String(err) });
792
+ }
793
+ // ── Respiration (enriches daily) ───────────────────────────────────────
794
+ try {
795
+ const { data: respRecords, error } = await getRespiration({ client: wellnessClient, query });
796
+ if (error || !respRecords)
797
+ throw new Error(error ? JSON.stringify(error) : "No data");
798
+ for (const resp of respRecords) {
799
+ try {
800
+ const data = transformRespiration(resp);
801
+ if (data) {
802
+ await ctx.runMutation(api.public.ingestDaily, {
803
+ connectionId, userId, ...data,
804
+ });
805
+ synced.respiration++;
806
+ }
807
+ }
808
+ catch (err) {
809
+ errors.push({
810
+ type: "respiration",
811
+ id: resp.summaryId ?? "unknown",
812
+ error: err instanceof Error ? err.message : String(err),
813
+ });
814
+ }
815
+ }
816
+ }
817
+ catch (err) {
818
+ errors.push({ type: "respiration", id: "fetch", error: err instanceof Error ? err.message : String(err) });
819
+ }
820
+ return { synced, errors };
821
+ },
822
+ });
823
+ //# sourceMappingURL=public.js.map