@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,852 @@
1
+ // ─── Garmin Webhook Handlers (Push Mode) ─────────────────────────────────────
2
+ // Each handler receives full Garmin data objects from push-mode webhooks.
3
+ // Separate actions per data type because the Garmin developer portal
4
+ // configures separate URLs per type.
5
+
6
+ import { v } from "convex/values";
7
+ import { action, type ActionCtx } from "../_generated/server";
8
+ import { api, internal } from "../_generated/api";
9
+ import {
10
+ garminSkinTemperaturePingPayloadSchema,
11
+ garminSkinTemperaturePushPayloadSchema,
12
+ } from "./schemas/skinTemperature.js";
13
+ import {
14
+ garminSleepsPingPayloadSchema,
15
+ garminSleepsPushPayloadSchema,
16
+ } from "./schemas/sleeps.js";
17
+ import {
18
+ garminStressPingPayloadSchema,
19
+ garminStressPushPayloadSchema,
20
+ } from "./schemas/stress.js";
21
+ import {
22
+ garminActivityPingPayloadSchema,
23
+ garminActivityPushPayloadSchema,
24
+ } from "./schemas/activity.js";
25
+ import {
26
+ garminActivityDetailsPingPayloadSchema,
27
+ garminActivityDetailsPushPayloadSchema,
28
+ } from "./schemas/activityDetails.js";
29
+ import {
30
+ garminManuallyUpdatedActivitiesPingPayloadSchema,
31
+ garminManuallyUpdatedActivitiesPushPayloadSchema,
32
+ } from "./schemas/manuallyUpdatedActivities.js";
33
+ import {
34
+ garminMoveIQPingPayloadSchema,
35
+ garminMoveIQPushPayloadSchema,
36
+ } from "./schemas/moveIQ.js";
37
+ import {
38
+ garminBloodPressurePingPayloadSchema,
39
+ garminBloodPressurePushPayloadSchema,
40
+ } from "./schemas/bloodPressure.js";
41
+ import {
42
+ garminBodyCompositionsPingPayloadSchema,
43
+ garminBodyCompositionsPushPayloadSchema,
44
+ } from "./schemas/bodyCompositions.js";
45
+ import {
46
+ garminDailiesPingPayloadSchema,
47
+ garminDailiesPushPayloadSchema,
48
+ } from "./schemas/dailies.js";
49
+ import {
50
+ garminEpochPingPayloadSchema,
51
+ garminEpochPushPayloadSchema,
52
+ } from "./schemas/epochs.js";
53
+ import {
54
+ garminHealthSnapshotPingPayloadSchema,
55
+ garminHealthSnapshotPushPayloadSchema,
56
+ } from "./schemas/healthSnapshot.js";
57
+ import {
58
+ garminHRVSummaryPingPayloadSchema,
59
+ garminHRVSummaryPushPayloadSchema,
60
+ } from "./schemas/hrvSummary.js";
61
+ import {
62
+ garminPulseOxPingPayloadSchema,
63
+ garminPulseOxPushPayloadSchema,
64
+ } from "./schemas/pulseOx.js";
65
+ import {
66
+ garminRespirationPingPayloadSchema,
67
+ garminRespirationPushPayloadSchema,
68
+ } from "./schemas/respiration.js";
69
+ import {
70
+ garminUserMetricsPingPayloadSchema,
71
+ garminUserMetricsPushPayloadSchema,
72
+ } from "./schemas/userMetrics.js";
73
+ import {
74
+ garminMenstrualCycleTrackingPingPayloadSchema,
75
+ garminMenstrualCycleTrackingPushPayloadSchema,
76
+ } from "./schemas/menstrualCycleTracking.js";
77
+
78
+ /**
79
+ * Discriminate push vs ping webhook payloads.
80
+ *
81
+ * Per the Garmin Activity API docs:
82
+ * - Ping items always carry `callbackURL` (absent only for deregistrations)
83
+ * - Push items never carry `callbackURL`, they contain the full summary data
84
+ *
85
+ * Zod schema validation alone can't distinguish the two because both schemas
86
+ * have all-optional fields and would accept either payload shape.
87
+ */
88
+ function isWebhookPushMode(payload: unknown): boolean {
89
+ if (payload == null || typeof payload !== "object") return false;
90
+
91
+ // The payload is either a keyed object like { activities: [...] }
92
+ // or a flat array of items. Extract the first item either way.
93
+ let firstItem: unknown;
94
+ if (Array.isArray(payload)) {
95
+ firstItem = payload[0];
96
+ } else {
97
+ const key = Object.keys(payload)[0];
98
+ const list = (payload as Record<string, unknown>)[key];
99
+ firstItem = Array.isArray(list) ? list[0] : undefined;
100
+ }
101
+
102
+ if (firstItem == null || typeof firstItem !== "object") return false;
103
+ return !("callbackURL" in firstItem);
104
+ }
105
+
106
+ type WebhookResult = {
107
+ processed: number;
108
+ errors: Array<{ type: string; id: string; error: string }>;
109
+ };
110
+
111
+ type ProcessResult = {
112
+ items: Array<{ connectionId: string; userId: string; data: Record<string, unknown> }>;
113
+ errors: Array<{ type: string; id: string; error: string }>;
114
+ };
115
+
116
+ /**
117
+ * Ingest transformed items from a private handler and update connections.
118
+ * Shared orchestration logic for all push-mode webhook handlers.
119
+ */
120
+ async function ingestAndUpdate(
121
+ ctx: ActionCtx,
122
+ result: ProcessResult,
123
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
124
+ ingestMutation: any,
125
+ ): Promise<WebhookResult> {
126
+ let processed = 0;
127
+ const errors = [...result.errors];
128
+ const connectionsToUpdate = new Set<string>();
129
+
130
+ for (const item of result.items) {
131
+ try {
132
+ await ctx.runMutation(ingestMutation, {
133
+ connectionId: item.connectionId,
134
+ userId: item.userId,
135
+ ...item.data,
136
+ } as never);
137
+ processed++;
138
+ connectionsToUpdate.add(item.connectionId);
139
+ } catch (err) {
140
+ errors.push({
141
+ type: "ingest",
142
+ id: "unknown",
143
+ error: err instanceof Error ? err.message : String(err),
144
+ });
145
+ }
146
+ }
147
+
148
+ for (const connectionId of connectionsToUpdate) {
149
+ await ctx.runMutation(api.public.updateConnection, {
150
+ connectionId,
151
+ lastDataUpdate: new Date().toISOString(),
152
+ } as never);
153
+ }
154
+
155
+ return { processed, errors };
156
+ }
157
+
158
+ // ─── Webhook Handlers ────────────────────────────────────────────────────────
159
+
160
+ /**
161
+ * Handle a webhook for Garmin activities (push or ping mode).
162
+ */
163
+ export const handleGarminWebhookActivities = action({
164
+ args: { payload: v.any() },
165
+ handler: async (ctx, args): Promise<WebhookResult> => {
166
+ if (isWebhookPushMode(args.payload)) {
167
+ const pushResult = garminActivityPushPayloadSchema.safeParse(args.payload);
168
+ if (pushResult.success && pushResult.data.activities.length > 0) {
169
+ const result: ProcessResult = await ctx.runAction(
170
+ internal.garmin.private.processActivityPushPayload,
171
+ { payload: args.payload },
172
+ );
173
+ return await ingestAndUpdate(ctx, result, api.public.ingestActivity);
174
+ }
175
+ } else {
176
+ const pingResult = garminActivityPingPayloadSchema.safeParse(args.payload);
177
+ if (pingResult.success && pingResult.data.activities.length > 0) {
178
+ return await ctx.runAction(
179
+ internal.garmin.private.processActivityPingPayload,
180
+ { payload: args.payload },
181
+ );
182
+ }
183
+ }
184
+
185
+ console.warn(
186
+ `[garmin:webhook:activities] Payload matched neither ping nor push schema`,
187
+ );
188
+ return { processed: 0, errors: [] };
189
+ },
190
+ });
191
+
192
+ /**
193
+ * Handle a webhook for Garmin activity details (push or ping mode).
194
+ */
195
+ export const handleGarminWebhookActivityDetails = action({
196
+ args: { payload: v.any() },
197
+ handler: async (ctx, args): Promise<WebhookResult> => {
198
+ if (isWebhookPushMode(args.payload)) {
199
+ const pushResult =
200
+ garminActivityDetailsPushPayloadSchema.safeParse(args.payload);
201
+ if (
202
+ pushResult.success &&
203
+ pushResult.data.activityDetails.length > 0
204
+ ) {
205
+ const result: ProcessResult = await ctx.runAction(
206
+ internal.garmin.private.processActivityDetailsPushPayload,
207
+ { payload: args.payload },
208
+ );
209
+ return await ingestAndUpdate(ctx, result, api.public.ingestActivity);
210
+ }
211
+ } else {
212
+ const pingResult =
213
+ garminActivityDetailsPingPayloadSchema.safeParse(args.payload);
214
+ if (
215
+ pingResult.success &&
216
+ pingResult.data.activityDetails.length > 0
217
+ ) {
218
+ return await ctx.runAction(
219
+ internal.garmin.private.processActivityDetailsPingPayload,
220
+ { payload: args.payload },
221
+ );
222
+ }
223
+ }
224
+
225
+ console.warn(
226
+ `[garmin:webhook:activityDetails] Payload matched neither ping nor push schema`,
227
+ );
228
+ return { processed: 0, errors: [] };
229
+ },
230
+ });
231
+
232
+ /**
233
+ * Handle a webhook for Garmin manually updated activities (push or ping mode).
234
+ */
235
+ export const handleGarminWebhookManuallyUpdatedActivities = action({
236
+ args: { payload: v.any() },
237
+ handler: async (ctx, args): Promise<WebhookResult> => {
238
+ if (isWebhookPushMode(args.payload)) {
239
+ const pushResult =
240
+ garminManuallyUpdatedActivitiesPushPayloadSchema.safeParse(
241
+ args.payload,
242
+ );
243
+ if (
244
+ pushResult.success &&
245
+ pushResult.data.manuallyUpdatedActivities.length > 0
246
+ ) {
247
+ const result: ProcessResult = await ctx.runAction(
248
+ internal.garmin.private
249
+ .processManuallyUpdatedActivitiesPushPayload,
250
+ { payload: args.payload },
251
+ );
252
+ return await ingestAndUpdate(ctx, result, api.public.ingestActivity);
253
+ }
254
+ } else {
255
+ const pingResult =
256
+ garminManuallyUpdatedActivitiesPingPayloadSchema.safeParse(
257
+ args.payload,
258
+ );
259
+ if (
260
+ pingResult.success &&
261
+ pingResult.data.manuallyUpdatedActivities.length > 0
262
+ ) {
263
+ return await ctx.runAction(
264
+ internal.garmin.private
265
+ .processManuallyUpdatedActivitiesPingPayload,
266
+ { payload: args.payload },
267
+ );
268
+ }
269
+ }
270
+
271
+ console.warn(
272
+ `[garmin:webhook:manuallyUpdatedActivities] Payload matched neither ping nor push schema`,
273
+ );
274
+ return { processed: 0, errors: [] };
275
+ },
276
+ });
277
+
278
+ /**
279
+ * Handle a webhook for Garmin Move IQ auto-detected activities (push or ping mode).
280
+ */
281
+ export const handleGarminWebhookMoveIQ = action({
282
+ args: { payload: v.any() },
283
+ handler: async (ctx, args): Promise<WebhookResult> => {
284
+ if (isWebhookPushMode(args.payload)) {
285
+ const pushResult =
286
+ garminMoveIQPushPayloadSchema.safeParse(args.payload);
287
+ if (
288
+ pushResult.success &&
289
+ pushResult.data.moveIQActivities.length > 0
290
+ ) {
291
+ const result: ProcessResult = await ctx.runAction(
292
+ internal.garmin.private.processMoveIQPushPayload,
293
+ { payload: args.payload },
294
+ );
295
+ return await ingestAndUpdate(ctx, result, api.public.ingestActivity);
296
+ }
297
+ } else {
298
+ const pingResult =
299
+ garminMoveIQPingPayloadSchema.safeParse(args.payload);
300
+ if (
301
+ pingResult.success &&
302
+ pingResult.data.moveIQActivities.length > 0
303
+ ) {
304
+ return await ctx.runAction(
305
+ internal.garmin.private.processMoveIQPingPayload,
306
+ { payload: args.payload },
307
+ );
308
+ }
309
+ }
310
+
311
+ console.warn(
312
+ `[garmin:webhook:moveIQ] Payload matched neither ping nor push schema`,
313
+ );
314
+ return { processed: 0, errors: [] };
315
+ },
316
+ });
317
+
318
+ /**
319
+ * Handle a webhook for Garmin blood pressure summaries (push or ping mode).
320
+ */
321
+ export const handleGarminWebhookBloodPressures = action({
322
+ args: { payload: v.any() },
323
+ handler: async (ctx, args): Promise<WebhookResult> => {
324
+ if (isWebhookPushMode(args.payload)) {
325
+ const pushResult =
326
+ garminBloodPressurePushPayloadSchema.safeParse(args.payload);
327
+ if (
328
+ pushResult.success &&
329
+ pushResult.data.bloodPressures.length > 0
330
+ ) {
331
+ const result: ProcessResult = await ctx.runAction(
332
+ internal.garmin.private.processBloodPressurePushPayload,
333
+ { payload: args.payload },
334
+ );
335
+ return await ingestAndUpdate(ctx, result, api.public.ingestBody);
336
+ }
337
+ } else {
338
+ const pingResult =
339
+ garminBloodPressurePingPayloadSchema.safeParse(args.payload);
340
+ if (
341
+ pingResult.success &&
342
+ pingResult.data.bloodPressures.length > 0
343
+ ) {
344
+ return await ctx.runAction(
345
+ internal.garmin.private.processBloodPressurePingPayload,
346
+ { payload: args.payload },
347
+ );
348
+ }
349
+ }
350
+
351
+ console.warn(
352
+ `[garmin:webhook:bloodPressures] Payload matched neither ping nor push schema`,
353
+ );
354
+ return { processed: 0, errors: [] };
355
+ },
356
+ });
357
+
358
+ /**
359
+ * Handle a webhook for Garmin body composition summaries (push or ping mode).
360
+ */
361
+ export const handleGarminWebhookBodyCompositions = action({
362
+ args: { payload: v.any() },
363
+ handler: async (ctx, args): Promise<WebhookResult> => {
364
+ if (isWebhookPushMode(args.payload)) {
365
+ const pushResult =
366
+ garminBodyCompositionsPushPayloadSchema.safeParse(args.payload);
367
+ if (
368
+ pushResult.success &&
369
+ pushResult.data.bodyComps.length > 0
370
+ ) {
371
+ const result: ProcessResult = await ctx.runAction(
372
+ internal.garmin.private.processBodyCompositionsPushPayload,
373
+ { payload: args.payload },
374
+ );
375
+ return await ingestAndUpdate(ctx, result, api.public.ingestBody);
376
+ }
377
+ } else {
378
+ const pingResult =
379
+ garminBodyCompositionsPingPayloadSchema.safeParse(args.payload);
380
+ if (
381
+ pingResult.success &&
382
+ pingResult.data.bodyComps.length > 0
383
+ ) {
384
+ return await ctx.runAction(
385
+ internal.garmin.private.processBodyCompositionsPingPayload,
386
+ { payload: args.payload },
387
+ );
388
+ }
389
+ }
390
+
391
+ console.warn(
392
+ `[garmin:webhook:bodyCompositions] Payload matched neither ping nor push schema`,
393
+ );
394
+ return { processed: 0, errors: [] };
395
+ },
396
+ });
397
+
398
+ /**
399
+ * Handle a webhook for Garmin daily summaries (push or ping mode).
400
+ */
401
+ export const handleGarminWebhookDailies = action({
402
+ args: { payload: v.any() },
403
+ handler: async (ctx, args): Promise<WebhookResult> => {
404
+ if (isWebhookPushMode(args.payload)) {
405
+ const pushResult =
406
+ garminDailiesPushPayloadSchema.safeParse(args.payload);
407
+ if (
408
+ pushResult.success &&
409
+ pushResult.data.dailies.length > 0
410
+ ) {
411
+ const result: ProcessResult = await ctx.runAction(
412
+ internal.garmin.private.processDailiesPushPayload,
413
+ { payload: args.payload },
414
+ );
415
+ return await ingestAndUpdate(ctx, result, api.public.ingestDaily);
416
+ }
417
+ } else {
418
+ const pingResult =
419
+ garminDailiesPingPayloadSchema.safeParse(args.payload);
420
+ if (
421
+ pingResult.success &&
422
+ pingResult.data.dailies.length > 0
423
+ ) {
424
+ return await ctx.runAction(
425
+ internal.garmin.private.processDailiesPingPayload,
426
+ { payload: args.payload },
427
+ );
428
+ }
429
+ }
430
+
431
+ console.warn(
432
+ `[garmin:webhook:dailies] Payload matched neither ping nor push schema`,
433
+ );
434
+ return { processed: 0, errors: [] };
435
+ },
436
+ });
437
+
438
+ /**
439
+ * Handle a webhook for Garmin epoch summaries (push or ping mode).
440
+ */
441
+ export const handleGarminWebhookEpochs = action({
442
+ args: { payload: v.any() },
443
+ handler: async (ctx, args): Promise<WebhookResult> => {
444
+ if (isWebhookPushMode(args.payload)) {
445
+ const pushResult =
446
+ garminEpochPushPayloadSchema.safeParse(args.payload);
447
+ if (
448
+ pushResult.success &&
449
+ pushResult.data.epochs.length > 0
450
+ ) {
451
+ const result: ProcessResult = await ctx.runAction(
452
+ internal.garmin.private.processEpochPushPayload,
453
+ { payload: args.payload },
454
+ );
455
+ return await ingestAndUpdate(ctx, result, api.public.ingestDaily);
456
+ }
457
+ } else {
458
+ const pingResult =
459
+ garminEpochPingPayloadSchema.safeParse(args.payload);
460
+ if (
461
+ pingResult.success &&
462
+ pingResult.data.epochs.length > 0
463
+ ) {
464
+ return await ctx.runAction(
465
+ internal.garmin.private.processEpochPingPayload,
466
+ { payload: args.payload },
467
+ );
468
+ }
469
+ }
470
+
471
+ console.warn(
472
+ `[garmin:webhook:epochs] Payload matched neither ping nor push schema`,
473
+ );
474
+ return { processed: 0, errors: [] };
475
+ },
476
+ });
477
+
478
+ /**
479
+ * Handle a webhook for Garmin health snapshot summaries (push or ping mode).
480
+ */
481
+ export const handleGarminWebhookHealthSnapshot = action({
482
+ args: { payload: v.any() },
483
+ handler: async (ctx, args): Promise<WebhookResult> => {
484
+ if (isWebhookPushMode(args.payload)) {
485
+ const pushResult =
486
+ garminHealthSnapshotPushPayloadSchema.safeParse(args.payload);
487
+ if (
488
+ pushResult.success &&
489
+ pushResult.data.healthSnapshot.length > 0
490
+ ) {
491
+ const result: ProcessResult = await ctx.runAction(
492
+ internal.garmin.private.processHealthSnapshotPushPayload,
493
+ { payload: args.payload },
494
+ );
495
+ return await ingestAndUpdate(ctx, result, api.public.ingestDaily);
496
+ }
497
+ } else {
498
+ const pingResult =
499
+ garminHealthSnapshotPingPayloadSchema.safeParse(args.payload);
500
+ if (
501
+ pingResult.success &&
502
+ pingResult.data.healthSnapshot.length > 0
503
+ ) {
504
+ return await ctx.runAction(
505
+ internal.garmin.private.processHealthSnapshotPingPayload,
506
+ { payload: args.payload },
507
+ );
508
+ }
509
+ }
510
+
511
+ console.warn(
512
+ `[garmin:webhook:healthSnapshot] Payload matched neither ping nor push schema`,
513
+ );
514
+ return { processed: 0, errors: [] };
515
+ },
516
+ });
517
+
518
+ /**
519
+ * Handle a webhook for Garmin sleep summaries (push or ping mode).
520
+ * Follows the structured dispatch pattern: validates with Zod, then delegates
521
+ * to internal actions for processing.
522
+ */
523
+ export const handleGarminWebhookSleeps = action({
524
+ args: { payload: v.any() },
525
+ handler: async (ctx, args): Promise<WebhookResult> => {
526
+ if (isWebhookPushMode(args.payload)) {
527
+ const pushResult =
528
+ garminSleepsPushPayloadSchema.safeParse(args.payload);
529
+ if (
530
+ pushResult.success &&
531
+ pushResult.data.sleeps.length > 0
532
+ ) {
533
+ const result: ProcessResult = await ctx.runAction(
534
+ internal.garmin.private.processSleepsPushPayload,
535
+ { payload: args.payload },
536
+ );
537
+ return await ingestAndUpdate(ctx, result, api.public.ingestSleep);
538
+ }
539
+ } else {
540
+ const pingResult =
541
+ garminSleepsPingPayloadSchema.safeParse(args.payload);
542
+ if (
543
+ pingResult.success &&
544
+ pingResult.data.sleeps.length > 0
545
+ ) {
546
+ return await ctx.runAction(
547
+ internal.garmin.private.processSleepsPingPayload,
548
+ { payload: args.payload },
549
+ );
550
+ }
551
+ }
552
+
553
+ console.warn(
554
+ `[garmin:webhook:sleeps] Payload matched neither ping nor push schema`,
555
+ );
556
+ return { processed: 0, errors: [] };
557
+ },
558
+ });
559
+
560
+ /**
561
+ * Handle a webhook for Garmin skin temperature summaries (push or ping mode).
562
+ * Follows the structured dispatch pattern: validates with Zod, then delegates
563
+ * to internal actions for processing.
564
+ */
565
+ export const handleGarminWebhookSkinTemp = action({
566
+ args: { payload: v.any() },
567
+ handler: async (ctx, args): Promise<WebhookResult> => {
568
+ if (isWebhookPushMode(args.payload)) {
569
+ const pushResult =
570
+ garminSkinTemperaturePushPayloadSchema.safeParse(args.payload);
571
+ if (
572
+ pushResult.success &&
573
+ pushResult.data.skinTemp.length > 0
574
+ ) {
575
+ const result: ProcessResult = await ctx.runAction(
576
+ internal.garmin.private.processSkinTemperaturePushPayload,
577
+ { payload: args.payload },
578
+ );
579
+ return await ingestAndUpdate(ctx, result, api.public.ingestBody);
580
+ }
581
+ } else {
582
+ const pingResult =
583
+ garminSkinTemperaturePingPayloadSchema.safeParse(args.payload);
584
+ if (
585
+ pingResult.success &&
586
+ pingResult.data.skinTemp.length > 0
587
+ ) {
588
+ return await ctx.runAction(
589
+ internal.garmin.private.processSkinTemperaturePingPayload,
590
+ { payload: args.payload },
591
+ );
592
+ }
593
+ }
594
+
595
+ console.warn(
596
+ `[garmin:webhook:skinTemperature] Payload matched neither ping nor push schema`,
597
+ );
598
+ return { processed: 0, errors: [] };
599
+ },
600
+ });
601
+
602
+ /**
603
+ * Handle a webhook for Garmin user metrics (push or ping mode).
604
+ * Follows the structured dispatch pattern: validates with Zod, then delegates
605
+ * to internal actions for processing.
606
+ */
607
+ export const handleGarminWebhookUserMetrics = action({
608
+ args: { payload: v.any() },
609
+ handler: async (ctx, args): Promise<WebhookResult> => {
610
+ if (isWebhookPushMode(args.payload)) {
611
+ const pushResult =
612
+ garminUserMetricsPushPayloadSchema.safeParse(args.payload);
613
+ if (
614
+ pushResult.success &&
615
+ pushResult.data.userMetrics.length > 0
616
+ ) {
617
+ const result: ProcessResult = await ctx.runAction(
618
+ internal.garmin.private.processUserMetricsPushPayload,
619
+ { payload: args.payload },
620
+ );
621
+ return await ingestAndUpdate(ctx, result, api.public.ingestBody);
622
+ }
623
+ } else {
624
+ const pingResult =
625
+ garminUserMetricsPingPayloadSchema.safeParse(args.payload);
626
+ if (
627
+ pingResult.success &&
628
+ pingResult.data.userMetrics.length > 0
629
+ ) {
630
+ return await ctx.runAction(
631
+ internal.garmin.private.processUserMetricsPingPayload,
632
+ { payload: args.payload },
633
+ );
634
+ }
635
+ }
636
+
637
+ console.warn(
638
+ `[garmin:webhook:userMetrics] Payload matched neither ping nor push schema`,
639
+ );
640
+ return { processed: 0, errors: [] };
641
+ },
642
+ });
643
+
644
+ /**
645
+ * Handle a webhook for Garmin menstrual cycle tracking (push or ping mode).
646
+ * Follows the structured dispatch pattern: validates with Zod, then delegates
647
+ * to internal actions for processing.
648
+ */
649
+ export const handleGarminWebhookMenstrualCycleTracking = action({
650
+ args: { payload: v.any() },
651
+ handler: async (ctx, args): Promise<WebhookResult> => {
652
+ if (isWebhookPushMode(args.payload)) {
653
+ const pushResult =
654
+ garminMenstrualCycleTrackingPushPayloadSchema.safeParse(args.payload);
655
+ if (
656
+ pushResult.success &&
657
+ pushResult.data.mct.length > 0
658
+ ) {
659
+ const result: ProcessResult = await ctx.runAction(
660
+ internal.garmin.private.processMenstrualCycleTrackingPushPayload,
661
+ { payload: args.payload },
662
+ );
663
+ return await ingestAndUpdate(ctx, result, api.public.ingestMenstruation);
664
+ }
665
+ } else {
666
+ const pingResult =
667
+ garminMenstrualCycleTrackingPingPayloadSchema.safeParse(args.payload);
668
+ if (
669
+ pingResult.success &&
670
+ pingResult.data.mct.length > 0
671
+ ) {
672
+ return await ctx.runAction(
673
+ internal.garmin.private.processMenstrualCycleTrackingPingPayload,
674
+ { payload: args.payload },
675
+ );
676
+ }
677
+ }
678
+
679
+ console.warn(
680
+ `[garmin:webhook:menstrualCycleTracking] Payload matched neither ping nor push schema`,
681
+ );
682
+ return { processed: 0, errors: [] };
683
+ },
684
+ });
685
+
686
+ /**
687
+ * Handle a webhook for Garmin HRV summaries (push or ping mode).
688
+ * Follows the structured dispatch pattern: validates with Zod, then delegates
689
+ * to internal actions for processing.
690
+ */
691
+ export const handleGarminWebhookHRVSummary = action({
692
+ args: { payload: v.any() },
693
+ handler: async (ctx, args): Promise<WebhookResult> => {
694
+ if (isWebhookPushMode(args.payload)) {
695
+ const pushResult =
696
+ garminHRVSummaryPushPayloadSchema.safeParse(args.payload);
697
+ if (
698
+ pushResult.success &&
699
+ pushResult.data.hrv.length > 0
700
+ ) {
701
+ const result: ProcessResult = await ctx.runAction(
702
+ internal.garmin.private.processHRVSummaryPushPayload,
703
+ { payload: args.payload },
704
+ );
705
+ return await ingestAndUpdate(ctx, result, api.public.ingestDaily);
706
+ }
707
+ } else {
708
+ const pingResult =
709
+ garminHRVSummaryPingPayloadSchema.safeParse(args.payload);
710
+ if (
711
+ pingResult.success &&
712
+ pingResult.data.hrv.length > 0
713
+ ) {
714
+ return await ctx.runAction(
715
+ internal.garmin.private.processHRVSummaryPingPayload,
716
+ { payload: args.payload },
717
+ );
718
+ }
719
+ }
720
+
721
+ console.warn(
722
+ `[garmin:webhook:hrvSummary] Payload matched neither ping nor push schema`,
723
+ );
724
+ return { processed: 0, errors: [] };
725
+ },
726
+ });
727
+
728
+ /**
729
+ * Handle a webhook for Garmin stress detail summaries (push or ping mode).
730
+ * Follows the structured dispatch pattern: validates with Zod, then delegates
731
+ * to internal actions for processing.
732
+ */
733
+ export const handleGarminWebhookStress = action({
734
+ args: { payload: v.any() },
735
+ handler: async (ctx, args): Promise<WebhookResult> => {
736
+ if (isWebhookPushMode(args.payload)) {
737
+ const pushResult =
738
+ garminStressPushPayloadSchema.safeParse(args.payload);
739
+ if (
740
+ pushResult.success &&
741
+ pushResult.data.stressDetails.length > 0
742
+ ) {
743
+ const result: ProcessResult = await ctx.runAction(
744
+ internal.garmin.private.processStressPushPayload,
745
+ { payload: args.payload },
746
+ );
747
+ return await ingestAndUpdate(ctx, result, api.public.ingestDaily);
748
+ }
749
+ } else {
750
+ const pingResult =
751
+ garminStressPingPayloadSchema.safeParse(args.payload);
752
+ if (
753
+ pingResult.success &&
754
+ pingResult.data.stressDetails.length > 0
755
+ ) {
756
+ return await ctx.runAction(
757
+ internal.garmin.private.processStressPingPayload,
758
+ { payload: args.payload },
759
+ );
760
+ }
761
+ }
762
+
763
+ console.warn(
764
+ `[garmin:webhook:stressDetails] Payload matched neither ping nor push schema`,
765
+ );
766
+ return { processed: 0, errors: [] };
767
+ },
768
+ });
769
+
770
+ /**
771
+ * Handle a webhook for Garmin pulse oximetry (SpO2) summaries (push or ping mode).
772
+ * Follows the structured dispatch pattern: validates with Zod, then delegates
773
+ * to internal actions for processing.
774
+ */
775
+ export const handleGarminWebhookPulseOx = action({
776
+ args: { payload: v.any() },
777
+ handler: async (ctx, args): Promise<WebhookResult> => {
778
+ if (isWebhookPushMode(args.payload)) {
779
+ const pushResult =
780
+ garminPulseOxPushPayloadSchema.safeParse(args.payload);
781
+ if (
782
+ pushResult.success &&
783
+ pushResult.data.pulseox.length > 0
784
+ ) {
785
+ const result: ProcessResult = await ctx.runAction(
786
+ internal.garmin.private.processPulseOxPushPayload,
787
+ { payload: args.payload },
788
+ );
789
+ return await ingestAndUpdate(ctx, result, api.public.ingestDaily);
790
+ }
791
+ } else {
792
+ const pingResult =
793
+ garminPulseOxPingPayloadSchema.safeParse(args.payload);
794
+ if (
795
+ pingResult.success &&
796
+ pingResult.data.pulseox.length > 0
797
+ ) {
798
+ return await ctx.runAction(
799
+ internal.garmin.private.processPulseOxPingPayload,
800
+ { payload: args.payload },
801
+ );
802
+ }
803
+ }
804
+
805
+ console.warn(
806
+ `[garmin:webhook:pulseOx] Payload matched neither ping nor push schema`,
807
+ );
808
+ return { processed: 0, errors: [] };
809
+ },
810
+ });
811
+
812
+ /**
813
+ * Handle a webhook for Garmin respiration summaries (push or ping mode).
814
+ * Follows the structured dispatch pattern: validates with Zod, then delegates
815
+ * to internal actions for processing.
816
+ */
817
+ export const handleGarminWebhookRespiration = action({
818
+ args: { payload: v.any() },
819
+ handler: async (ctx, args): Promise<WebhookResult> => {
820
+ if (isWebhookPushMode(args.payload)) {
821
+ const pushResult =
822
+ garminRespirationPushPayloadSchema.safeParse(args.payload);
823
+ if (
824
+ pushResult.success &&
825
+ pushResult.data.allDayRespiration.length > 0
826
+ ) {
827
+ const result: ProcessResult = await ctx.runAction(
828
+ internal.garmin.private.processRespirationPushPayload,
829
+ { payload: args.payload },
830
+ );
831
+ return await ingestAndUpdate(ctx, result, api.public.ingestDaily);
832
+ }
833
+ } else {
834
+ const pingResult =
835
+ garminRespirationPingPayloadSchema.safeParse(args.payload);
836
+ if (
837
+ pingResult.success &&
838
+ pingResult.data.allDayRespiration.length > 0
839
+ ) {
840
+ return await ctx.runAction(
841
+ internal.garmin.private.processRespirationPingPayload,
842
+ { payload: args.payload },
843
+ );
844
+ }
845
+ }
846
+
847
+ console.warn(
848
+ `[garmin:webhook:respiration] Payload matched neither ping nor push schema`,
849
+ );
850
+ return { processed: 0, errors: [] };
851
+ },
852
+ });