@nativesquare/soma 0.7.3 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.d.ts +17 -55
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +63 -13
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts +80 -4
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +153 -120
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/garmin/private.d.ts +475 -0
- package/dist/component/garmin/private.d.ts.map +1 -0
- package/dist/component/garmin/private.js +1614 -0
- package/dist/component/garmin/private.js.map +1 -0
- package/dist/component/{garmin.d.ts → garmin/public.d.ts} +25 -52
- package/dist/component/garmin/public.d.ts.map +1 -0
- package/dist/component/{garmin.js → garmin/public.js} +301 -215
- package/dist/component/garmin/public.js.map +1 -0
- package/dist/component/garmin/schemas/activity.d.ts +94 -0
- package/dist/component/garmin/schemas/activity.d.ts.map +1 -0
- package/dist/component/garmin/schemas/activity.js +27 -0
- package/dist/component/garmin/schemas/activity.js.map +1 -0
- package/dist/component/garmin/schemas/activityDetails.d.ts +146 -0
- package/dist/component/garmin/schemas/activityDetails.d.ts.map +1 -0
- package/dist/component/garmin/schemas/activityDetails.js +27 -0
- package/dist/component/garmin/schemas/activityDetails.js.map +1 -0
- package/dist/component/garmin/schemas/bloodPressure.d.ts +38 -0
- package/dist/component/garmin/schemas/bloodPressure.d.ts.map +1 -0
- package/dist/component/garmin/schemas/bloodPressure.js +27 -0
- package/dist/component/garmin/schemas/bloodPressure.js.map +1 -0
- package/dist/component/garmin/schemas/bodyCompositions.d.ts +42 -0
- package/dist/component/garmin/schemas/bodyCompositions.d.ts.map +1 -0
- package/dist/component/garmin/schemas/bodyCompositions.js +27 -0
- package/dist/component/garmin/schemas/bodyCompositions.js.map +1 -0
- package/dist/component/garmin/schemas/dailies.d.ts +98 -0
- package/dist/component/garmin/schemas/dailies.d.ts.map +1 -0
- package/dist/component/garmin/schemas/dailies.js +27 -0
- package/dist/component/garmin/schemas/dailies.js.map +1 -0
- package/dist/component/garmin/schemas/epochs.d.ts +54 -0
- package/dist/component/garmin/schemas/epochs.d.ts.map +1 -0
- package/dist/component/garmin/schemas/epochs.js +27 -0
- package/dist/component/garmin/schemas/epochs.js.map +1 -0
- package/dist/component/garmin/schemas/healthSnapshot.d.ts +48 -0
- package/dist/component/garmin/schemas/healthSnapshot.d.ts.map +1 -0
- package/dist/component/garmin/schemas/healthSnapshot.js +27 -0
- package/dist/component/garmin/schemas/healthSnapshot.js.map +1 -0
- package/dist/component/garmin/schemas/hrvSummary.d.ts +40 -0
- package/dist/component/garmin/schemas/hrvSummary.d.ts.map +1 -0
- package/dist/component/garmin/schemas/hrvSummary.js +27 -0
- package/dist/component/garmin/schemas/hrvSummary.js.map +1 -0
- package/dist/component/garmin/schemas/manuallyUpdatedActivities.d.ts +94 -0
- package/dist/component/garmin/schemas/manuallyUpdatedActivities.d.ts.map +1 -0
- package/dist/component/garmin/schemas/manuallyUpdatedActivities.js +27 -0
- package/dist/component/garmin/schemas/manuallyUpdatedActivities.js.map +1 -0
- package/dist/component/garmin/schemas/menstrualCycleTracking.d.ts +100 -0
- package/dist/component/garmin/schemas/menstrualCycleTracking.d.ts.map +1 -0
- package/dist/component/garmin/schemas/menstrualCycleTracking.js +28 -0
- package/dist/component/garmin/schemas/menstrualCycleTracking.js.map +1 -0
- package/dist/component/garmin/schemas/moveIQ.d.ts +40 -0
- package/dist/component/garmin/schemas/moveIQ.d.ts.map +1 -0
- package/dist/component/garmin/schemas/moveIQ.js +27 -0
- package/dist/component/garmin/schemas/moveIQ.js.map +1 -0
- package/dist/component/garmin/schemas/pulseOx.d.ts +38 -0
- package/dist/component/garmin/schemas/pulseOx.d.ts.map +1 -0
- package/dist/component/garmin/schemas/pulseOx.js +28 -0
- package/dist/component/garmin/schemas/pulseOx.js.map +1 -0
- package/dist/component/garmin/schemas/respiration.d.ts +34 -0
- package/dist/component/garmin/schemas/respiration.d.ts.map +1 -0
- package/dist/component/garmin/schemas/respiration.js +28 -0
- package/dist/component/garmin/schemas/respiration.js.map +1 -0
- package/dist/component/garmin/schemas/skinTemperature.d.ts +36 -0
- package/dist/component/garmin/schemas/skinTemperature.d.ts.map +1 -0
- package/dist/component/garmin/schemas/skinTemperature.js +28 -0
- package/dist/component/garmin/schemas/skinTemperature.js.map +1 -0
- package/dist/component/garmin/schemas/sleeps.d.ts +88 -0
- package/dist/component/garmin/schemas/sleeps.d.ts.map +1 -0
- package/dist/component/garmin/schemas/sleeps.js +27 -0
- package/dist/component/garmin/schemas/sleeps.js.map +1 -0
- package/dist/component/garmin/schemas/stress.d.ts +70 -0
- package/dist/component/garmin/schemas/stress.d.ts.map +1 -0
- package/dist/component/garmin/schemas/stress.js +28 -0
- package/dist/component/garmin/schemas/stress.js.map +1 -0
- package/dist/component/garmin/schemas/userMetrics.d.ts +36 -0
- package/dist/component/garmin/schemas/userMetrics.d.ts.map +1 -0
- package/dist/component/garmin/schemas/userMetrics.js +28 -0
- package/dist/component/garmin/schemas/userMetrics.js.map +1 -0
- package/dist/component/garmin/transform/activity.d.ts +13 -0
- package/dist/component/garmin/transform/activity.d.ts.map +1 -0
- package/dist/component/garmin/transform/activity.js +111 -0
- package/dist/component/garmin/transform/activity.js.map +1 -0
- package/dist/component/garmin/transform/activityDetails.d.ts +13 -0
- package/dist/component/garmin/transform/activityDetails.d.ts.map +1 -0
- package/dist/component/garmin/transform/activityDetails.js +173 -0
- package/dist/component/garmin/transform/activityDetails.js.map +1 -0
- package/dist/component/garmin/transform/bloodPressure.d.ts +12 -0
- package/dist/component/garmin/transform/bloodPressure.d.ts.map +1 -0
- package/dist/component/garmin/transform/bloodPressure.js +33 -0
- package/dist/component/garmin/transform/bloodPressure.js.map +1 -0
- package/dist/component/garmin/transform/bodyCompositions.d.ts +12 -0
- package/dist/component/garmin/transform/bodyCompositions.d.ts.map +1 -0
- package/dist/component/garmin/transform/bodyCompositions.js +42 -0
- package/dist/component/garmin/transform/bodyCompositions.js.map +1 -0
- package/dist/component/garmin/transform/dailies.d.ts +12 -0
- package/dist/component/garmin/transform/dailies.d.ts.map +1 -0
- package/dist/component/garmin/transform/dailies.js +132 -0
- package/dist/component/garmin/transform/dailies.js.map +1 -0
- package/dist/component/garmin/transform/epochs.d.ts +13 -0
- package/dist/component/garmin/transform/epochs.d.ts.map +1 -0
- package/dist/component/garmin/transform/epochs.js +76 -0
- package/dist/component/garmin/transform/epochs.js.map +1 -0
- package/dist/component/garmin/transform/healthSnapshot.d.ts +12 -0
- package/dist/component/garmin/transform/healthSnapshot.d.ts.map +1 -0
- package/dist/component/garmin/transform/healthSnapshot.js +111 -0
- package/dist/component/garmin/transform/healthSnapshot.js.map +1 -0
- package/dist/component/garmin/transform/hrvSummary.d.ts +12 -0
- package/dist/component/garmin/transform/hrvSummary.d.ts.map +1 -0
- package/dist/component/garmin/transform/hrvSummary.js +45 -0
- package/dist/component/garmin/transform/hrvSummary.js.map +1 -0
- package/dist/component/garmin/transform/manuallyUpdatedActivities.d.ts +11 -0
- package/dist/component/garmin/transform/manuallyUpdatedActivities.d.ts.map +1 -0
- package/dist/component/garmin/transform/manuallyUpdatedActivities.js +20 -0
- package/dist/component/garmin/transform/manuallyUpdatedActivities.js.map +1 -0
- package/dist/component/garmin/transform/menstrualCycleTracking.d.ts +10 -0
- package/dist/component/garmin/transform/menstrualCycleTracking.d.ts.map +1 -0
- package/dist/component/garmin/transform/menstrualCycleTracking.js +43 -0
- package/dist/component/garmin/transform/menstrualCycleTracking.js.map +1 -0
- package/dist/component/garmin/transform/moveIQ.d.ts +17 -0
- package/dist/component/garmin/transform/moveIQ.d.ts.map +1 -0
- package/dist/component/garmin/transform/moveIQ.js +41 -0
- package/dist/component/garmin/transform/moveIQ.js.map +1 -0
- package/dist/component/garmin/transform/pulseOx.d.ts +12 -0
- package/dist/component/garmin/transform/pulseOx.d.ts.map +1 -0
- package/dist/component/garmin/transform/pulseOx.js +46 -0
- package/dist/component/garmin/transform/pulseOx.js.map +1 -0
- package/dist/component/garmin/transform/respiration.d.ts +12 -0
- package/dist/component/garmin/transform/respiration.d.ts.map +1 -0
- package/dist/component/garmin/transform/respiration.js +54 -0
- package/dist/component/garmin/transform/respiration.js.map +1 -0
- package/dist/component/garmin/transform/skinTemperature.d.ts +12 -0
- package/dist/component/garmin/transform/skinTemperature.d.ts.map +1 -0
- package/dist/component/garmin/transform/skinTemperature.js +38 -0
- package/dist/component/garmin/transform/skinTemperature.js.map +1 -0
- package/dist/component/garmin/transform/sleeps.d.ts +55 -0
- package/dist/component/garmin/transform/sleeps.d.ts.map +1 -0
- package/dist/component/garmin/transform/sleeps.js +120 -0
- package/dist/component/garmin/transform/sleeps.js.map +1 -0
- package/dist/component/garmin/transform/stress.d.ts +12 -0
- package/dist/component/garmin/transform/stress.d.ts.map +1 -0
- package/dist/component/garmin/transform/stress.js +56 -0
- package/dist/component/garmin/transform/stress.js.map +1 -0
- package/dist/component/garmin/transform/userMetrics.d.ts +12 -0
- package/dist/component/garmin/transform/userMetrics.d.ts.map +1 -0
- package/dist/component/garmin/transform/userMetrics.js +48 -0
- package/dist/component/garmin/transform/userMetrics.js.map +1 -0
- package/dist/component/garmin/types/garmin.d.ts +21 -0
- package/dist/component/garmin/types/garmin.d.ts.map +1 -0
- package/dist/component/garmin/types/garmin.js +6 -0
- package/dist/component/garmin/types/garmin.js.map +1 -0
- package/dist/component/garmin/types/zod/zod.gen.d.ts +1319 -0
- package/dist/component/garmin/types/zod/zod.gen.d.ts.map +1 -0
- package/dist/component/garmin/types/zod/zod.gen.js +784 -0
- package/dist/component/garmin/types/zod/zod.gen.js.map +1 -0
- package/dist/component/garmin/webhooks.d.ts +141 -0
- package/dist/component/garmin/webhooks.d.ts.map +1 -0
- package/dist/component/garmin/webhooks.js +766 -0
- package/dist/component/garmin/webhooks.js.map +1 -0
- package/dist/component/private.d.ts +20 -2
- package/dist/component/private.d.ts.map +1 -1
- package/dist/component/private.js +18 -0
- package/dist/component/private.js.map +1 -1
- package/dist/component/public.d.ts +433 -387
- package/dist/component/public.d.ts.map +1 -1
- package/dist/component/public.js +12 -2
- package/dist/component/public.js.map +1 -1
- package/dist/component/schema.d.ts +217 -162
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +2 -1
- package/dist/component/schema.js.map +1 -1
- package/dist/component/strava/private.d.ts +30 -0
- package/dist/component/strava/private.d.ts.map +1 -0
- package/dist/component/strava/private.js +71 -0
- package/dist/component/strava/private.js.map +1 -0
- package/dist/component/{strava.d.ts → strava/public.d.ts} +3 -31
- package/dist/component/strava/public.d.ts.map +1 -0
- package/dist/component/{strava.js → strava/public.js} +22 -101
- package/dist/component/strava/public.js.map +1 -0
- package/dist/component/validators/activity.d.ts +6 -0
- package/dist/component/validators/activity.d.ts.map +1 -1
- package/dist/component/validators/activity.js.map +1 -1
- package/dist/component/validators/body.d.ts +20 -14
- package/dist/component/validators/body.d.ts.map +1 -1
- package/dist/component/validators/body.js.map +1 -1
- package/dist/component/validators/connection.d.ts +1 -0
- package/dist/component/validators/connection.d.ts.map +1 -1
- package/dist/component/validators/connection.js +2 -0
- package/dist/component/validators/connection.js.map +1 -1
- package/dist/component/validators/daily.d.ts +46 -5
- package/dist/component/validators/daily.d.ts.map +1 -1
- package/dist/component/validators/daily.js +10 -1
- package/dist/component/validators/daily.js.map +1 -1
- package/dist/component/validators/enums.d.ts +2 -2
- package/dist/component/validators/menstruation.d.ts +5 -0
- package/dist/component/validators/menstruation.d.ts.map +1 -1
- package/dist/component/validators/menstruation.js.map +1 -1
- package/dist/component/validators/plannedWorkout.d.ts +5 -1
- package/dist/component/validators/plannedWorkout.d.ts.map +1 -1
- package/dist/component/validators/plannedWorkout.js +4 -0
- package/dist/component/validators/plannedWorkout.js.map +1 -1
- package/dist/component/validators/sleep.d.ts +8 -8
- package/dist/garmin/bloodPressure.d.ts +28 -0
- package/dist/garmin/bloodPressure.d.ts.map +1 -0
- package/dist/garmin/bloodPressure.js +34 -0
- package/dist/garmin/bloodPressure.js.map +1 -0
- package/dist/garmin/body.js +1 -1
- package/dist/garmin/body.js.map +1 -1
- package/dist/garmin/client.d.ts +117 -17
- package/dist/garmin/client.d.ts.map +1 -1
- package/dist/garmin/client.js +337 -43
- package/dist/garmin/client.js.map +1 -1
- package/dist/garmin/daily.d.ts.map +1 -1
- package/dist/garmin/daily.js +3 -3
- package/dist/garmin/daily.js.map +1 -1
- package/dist/garmin/hrv.d.ts +30 -0
- package/dist/garmin/hrv.d.ts.map +1 -0
- package/dist/garmin/hrv.js +45 -0
- package/dist/garmin/hrv.js.map +1 -0
- package/dist/garmin/index.d.ts +16 -4
- package/dist/garmin/index.d.ts.map +1 -1
- package/dist/garmin/index.js +8 -2
- package/dist/garmin/index.js.map +1 -1
- package/dist/garmin/maps/activity-type.d.ts +1 -2
- package/dist/garmin/maps/activity-type.d.ts.map +1 -1
- package/dist/garmin/maps/activity-type.js +1 -0
- package/dist/garmin/maps/activity-type.js.map +1 -1
- package/dist/garmin/menstruation.d.ts +6 -4
- package/dist/garmin/menstruation.d.ts.map +1 -1
- package/dist/garmin/menstruation.js +12 -8
- package/dist/garmin/menstruation.js.map +1 -1
- package/dist/garmin/pulseOx.d.ts +24 -0
- package/dist/garmin/pulseOx.d.ts.map +1 -0
- package/dist/garmin/pulseOx.js +33 -0
- package/dist/garmin/pulseOx.js.map +1 -0
- package/dist/garmin/respiration.d.ts +29 -0
- package/dist/garmin/respiration.d.ts.map +1 -0
- package/dist/garmin/respiration.js +42 -0
- package/dist/garmin/respiration.js.map +1 -0
- package/dist/garmin/skinTemp.d.ts +27 -0
- package/dist/garmin/skinTemp.d.ts.map +1 -0
- package/dist/garmin/skinTemp.js +35 -0
- package/dist/garmin/skinTemp.js.map +1 -0
- package/dist/garmin/sleep.d.ts +4 -4
- package/dist/garmin/sleep.d.ts.map +1 -1
- package/dist/garmin/sleep.js +15 -9
- package/dist/garmin/sleep.js.map +1 -1
- package/dist/garmin/stressDetails.d.ts +30 -0
- package/dist/garmin/stressDetails.d.ts.map +1 -0
- package/dist/garmin/stressDetails.js +49 -0
- package/dist/garmin/stressDetails.js.map +1 -0
- package/dist/garmin/sync.d.ts +14 -0
- package/dist/garmin/sync.d.ts.map +1 -1
- package/dist/garmin/sync.js +290 -7
- package/dist/garmin/sync.js.map +1 -1
- package/dist/garmin/types.d.ts +77 -186
- package/dist/garmin/types.d.ts.map +1 -1
- package/dist/garmin/types.js +4 -2
- package/dist/garmin/types.js.map +1 -1
- package/dist/garmin/userMetrics.d.ts +23 -0
- package/dist/garmin/userMetrics.d.ts.map +1 -0
- package/dist/garmin/userMetrics.js +41 -0
- package/dist/garmin/userMetrics.js.map +1 -0
- package/dist/validators.d.ts +138 -56
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +2 -2
- package/dist/validators.js.map +1 -1
- package/package.json +130 -124
- package/src/client/index.ts +86 -18
- package/src/component/_generated/api.ts +96 -4
- package/src/component/_generated/component.ts +271 -144
- package/src/{garmin → component/garmin}/auth.ts +8 -1
- package/src/component/garmin/client.ts +39 -0
- package/src/component/garmin/private.ts +1798 -0
- package/src/component/garmin/public.ts +938 -0
- package/src/component/garmin/schemas/activity.ts +40 -0
- package/src/component/garmin/schemas/activityDetails.ts +45 -0
- package/src/component/garmin/schemas/bloodPressure.ts +38 -0
- package/src/component/garmin/schemas/bodyCompositions.ts +38 -0
- package/src/component/garmin/schemas/dailies.ts +38 -0
- package/src/component/garmin/schemas/epochs.ts +38 -0
- package/src/component/garmin/schemas/healthSnapshot.ts +38 -0
- package/src/component/garmin/schemas/hrvSummary.ts +38 -0
- package/src/component/garmin/schemas/manuallyUpdatedActivities.ts +49 -0
- package/src/component/garmin/schemas/menstrualCycleTracking.ts +39 -0
- package/src/component/garmin/schemas/moveIQ.ts +38 -0
- package/src/component/garmin/schemas/pulseOx.ts +39 -0
- package/src/component/garmin/schemas/respiration.ts +39 -0
- package/src/component/garmin/schemas/skinTemperature.ts +39 -0
- package/src/component/garmin/schemas/sleeps.ts +38 -0
- package/src/component/garmin/schemas/stress.ts +43 -0
- package/src/component/garmin/schemas/userMetrics.ts +39 -0
- package/src/component/garmin/transform/activity.ts +143 -0
- package/src/component/garmin/transform/activityDetails.ts +236 -0
- package/src/component/garmin/transform/bloodPressure.ts +39 -0
- package/src/component/garmin/transform/bodyCompositions.ts +51 -0
- package/src/component/garmin/transform/dailies.ts +179 -0
- package/src/component/garmin/transform/epochs.ts +94 -0
- package/src/component/garmin/transform/healthSnapshot.ts +152 -0
- package/src/component/garmin/transform/hrvSummary.ts +56 -0
- package/src/component/garmin/transform/manuallyUpdatedActivities.ts +27 -0
- package/src/{garmin/maps/activity-type.ts → component/garmin/transform/maps/activityType.ts} +116 -116
- package/src/{garmin/maps/sleep-level.ts → component/garmin/transform/maps/sleepLevel.ts} +22 -22
- package/src/component/garmin/transform/menstrualCycleTracking.ts +48 -0
- package/src/component/garmin/transform/moveIQ.ts +48 -0
- package/src/{garmin → component/garmin/transform}/plannedWorkout.ts +328 -333
- package/src/component/garmin/transform/pulseOx.ts +64 -0
- package/src/component/garmin/transform/respiration.ts +73 -0
- package/src/component/garmin/transform/skinTemperature.ts +44 -0
- package/src/component/garmin/transform/sleeps.ts +159 -0
- package/src/component/garmin/transform/stress.ts +78 -0
- package/src/component/garmin/transform/userMetrics.ts +56 -0
- package/src/component/garmin/types/specs/training-api-workouts.json +699 -0
- package/src/component/garmin/types/specs/wellness-api.json +1 -0
- package/src/component/garmin/types/trainingApiWorkouts/client/client.gen.ts +290 -0
- package/src/component/garmin/types/trainingApiWorkouts/client/index.ts +25 -0
- package/src/component/garmin/types/trainingApiWorkouts/client/types.gen.ts +214 -0
- package/src/component/garmin/types/trainingApiWorkouts/client/utils.gen.ts +316 -0
- package/src/component/garmin/types/trainingApiWorkouts/client.gen.ts +16 -0
- package/src/component/garmin/types/trainingApiWorkouts/core/auth.gen.ts +41 -0
- package/src/component/garmin/types/trainingApiWorkouts/core/bodySerializer.gen.ts +82 -0
- package/src/component/garmin/types/trainingApiWorkouts/core/params.gen.ts +169 -0
- package/src/component/garmin/types/trainingApiWorkouts/core/pathSerializer.gen.ts +171 -0
- package/src/component/garmin/types/trainingApiWorkouts/core/queryKeySerializer.gen.ts +117 -0
- package/src/component/garmin/types/trainingApiWorkouts/core/serverSentEvents.gen.ts +243 -0
- package/src/component/garmin/types/trainingApiWorkouts/core/types.gen.ts +104 -0
- package/src/component/garmin/types/trainingApiWorkouts/core/utils.gen.ts +140 -0
- package/src/component/garmin/types/trainingApiWorkouts/index.ts +4 -0
- package/src/component/garmin/types/trainingApiWorkouts/sdk.gen.ts +126 -0
- package/src/component/garmin/types/trainingApiWorkouts/types.gen.ts +387 -0
- package/src/component/garmin/types/trainingApiWorkouts/zod.gen.ts +423 -0
- package/src/component/garmin/types/wellnessApi/client/client.gen.ts +290 -0
- package/src/component/garmin/types/wellnessApi/client/index.ts +25 -0
- package/src/component/garmin/types/wellnessApi/client/types.gen.ts +214 -0
- package/src/component/garmin/types/wellnessApi/client/utils.gen.ts +316 -0
- package/src/component/garmin/types/wellnessApi/client.gen.ts +16 -0
- package/src/component/garmin/types/wellnessApi/core/auth.gen.ts +41 -0
- package/src/component/garmin/types/wellnessApi/core/bodySerializer.gen.ts +82 -0
- package/src/component/garmin/types/wellnessApi/core/params.gen.ts +169 -0
- package/src/component/garmin/types/wellnessApi/core/pathSerializer.gen.ts +171 -0
- package/src/component/garmin/types/wellnessApi/core/queryKeySerializer.gen.ts +117 -0
- package/src/component/garmin/types/wellnessApi/core/serverSentEvents.gen.ts +243 -0
- package/src/component/garmin/types/wellnessApi/core/types.gen.ts +104 -0
- package/src/component/garmin/types/wellnessApi/core/utils.gen.ts +140 -0
- package/src/component/garmin/types/wellnessApi/index.ts +4 -0
- package/src/component/garmin/types/wellnessApi/sdk.gen.ts +207 -0
- package/src/component/garmin/types/wellnessApi/types.gen.ts +2942 -0
- package/src/component/garmin/types/wellnessApi/zod.gen.ts +878 -0
- package/src/component/garmin/utils.ts +25 -0
- package/src/component/garmin/webhooks.ts +852 -0
- package/src/component/private.ts +21 -0
- package/src/component/public.ts +11 -2
- package/src/component/schema.ts +2 -1
- package/src/component/strava/private.ts +89 -0
- package/src/component/{strava.ts → strava/public.ts} +341 -404
- package/src/component/validators/activity.ts +5 -0
- package/src/component/validators/body.ts +5 -0
- package/src/component/validators/connection.ts +2 -0
- package/src/component/validators/daily.ts +20 -0
- package/src/component/validators/menstruation.ts +5 -1
- package/src/component/validators/plannedWorkout.ts +9 -0
- package/src/validators.ts +12 -2
- package/dist/component/garmin.d.ts.map +0 -1
- package/dist/component/garmin.js.map +0 -1
- package/dist/component/strava.d.ts.map +0 -1
- package/dist/component/strava.js.map +0 -1
- package/dist/garmin/activity.d.ts +0 -101
- package/dist/garmin/activity.d.ts.map +0 -1
- package/dist/garmin/activity.js +0 -207
- package/dist/garmin/activity.js.map +0 -1
- package/src/component/garmin.ts +0 -850
- package/src/garmin/activity.test.ts +0 -178
- package/src/garmin/activity.ts +0 -272
- package/src/garmin/auth.test.ts +0 -103
- package/src/garmin/body.ts +0 -59
- package/src/garmin/client.ts +0 -407
- package/src/garmin/daily.ts +0 -211
- package/src/garmin/index.ts +0 -75
- package/src/garmin/maps/activity-type.test.ts +0 -78
- package/src/garmin/menstruation.ts +0 -42
- package/src/garmin/sleep.test.ts +0 -110
- package/src/garmin/sleep.ts +0 -170
- package/src/garmin/sync.ts +0 -223
- package/src/garmin/types.ts +0 -480
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { transformActivity } from "./activity.js";
|
|
3
|
-
import type { GarminActivity } from "./types.js";
|
|
4
|
-
|
|
5
|
-
const baseActivity: GarminActivity = {
|
|
6
|
-
userId: "garmin_user_1",
|
|
7
|
-
userAccessToken: "token",
|
|
8
|
-
summaryId: "summary_12345",
|
|
9
|
-
activityId: 12345,
|
|
10
|
-
activityName: "Morning Run",
|
|
11
|
-
activityType: "RUNNING",
|
|
12
|
-
durationInSeconds: 3600,
|
|
13
|
-
startTimeInSeconds: 1700000000,
|
|
14
|
-
startTimeOffsetInSeconds: -18000,
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
describe("transformActivity", () => {
|
|
18
|
-
it("maps metadata correctly", () => {
|
|
19
|
-
const result = transformActivity(baseActivity);
|
|
20
|
-
|
|
21
|
-
expect(result.metadata.summary_id).toBe("summary_12345");
|
|
22
|
-
expect(result.metadata.start_time).toBe("2023-11-14T22:13:20.000Z");
|
|
23
|
-
expect(result.metadata.end_time).toBe("2023-11-14T23:13:20.000Z");
|
|
24
|
-
expect(result.metadata.type).toBe(8); // RUNNING → Terra Running
|
|
25
|
-
expect(result.metadata.upload_type).toBe(1); // Automatic
|
|
26
|
-
expect(result.metadata.name).toBe("Morning Run");
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("maps manual upload type", () => {
|
|
30
|
-
const manual = { ...baseActivity, manual: true };
|
|
31
|
-
const result = transformActivity(manual);
|
|
32
|
-
expect(result.metadata.upload_type).toBe(2);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("maps duration data", () => {
|
|
36
|
-
const result = transformActivity(baseActivity);
|
|
37
|
-
expect(result.active_durations_data.activity_seconds).toBe(3600);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it("maps calories data", () => {
|
|
41
|
-
const withCalories: GarminActivity = {
|
|
42
|
-
...baseActivity,
|
|
43
|
-
activeKilocalories: 450,
|
|
44
|
-
bmrKilocalories: 75,
|
|
45
|
-
};
|
|
46
|
-
const result = transformActivity(withCalories);
|
|
47
|
-
|
|
48
|
-
expect(result.calories_data).toBeDefined();
|
|
49
|
-
expect(result.calories_data!.net_activity_calories).toBe(450);
|
|
50
|
-
expect(result.calories_data!.BMR_calories).toBe(75);
|
|
51
|
-
expect(result.calories_data!.total_burned_calories).toBe(525);
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("returns undefined calories_data when no calorie fields present", () => {
|
|
55
|
-
const result = transformActivity(baseActivity);
|
|
56
|
-
expect(result.calories_data).toBeUndefined();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("maps distance data", () => {
|
|
60
|
-
const withDistance: GarminActivity = {
|
|
61
|
-
...baseActivity,
|
|
62
|
-
distanceInMeters: 10000,
|
|
63
|
-
elevationGainInMeters: 150,
|
|
64
|
-
elevationLossInMeters: 120,
|
|
65
|
-
steps: 12000,
|
|
66
|
-
};
|
|
67
|
-
const result = transformActivity(withDistance);
|
|
68
|
-
|
|
69
|
-
expect(result.distance_data).toBeDefined();
|
|
70
|
-
expect(result.distance_data!.summary!.distance_meters).toBe(10000);
|
|
71
|
-
expect(result.distance_data!.summary!.steps).toBe(12000);
|
|
72
|
-
expect(result.distance_data!.summary!.elevation!.gain_actual_meters).toBe(150);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("maps heart rate summary", () => {
|
|
76
|
-
const withHR: GarminActivity = {
|
|
77
|
-
...baseActivity,
|
|
78
|
-
averageHeartRateInBeatsPerMinute: 155,
|
|
79
|
-
maxHeartRateInBeatsPerMinute: 185,
|
|
80
|
-
};
|
|
81
|
-
const result = transformActivity(withHR);
|
|
82
|
-
|
|
83
|
-
expect(result.heart_rate_data).toBeDefined();
|
|
84
|
-
expect(result.heart_rate_data!.summary!.avg_hr_bpm).toBe(155);
|
|
85
|
-
expect(result.heart_rate_data!.summary!.max_hr_bpm).toBe(185);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it("maps movement data with speed and cadence", () => {
|
|
89
|
-
const withMovement: GarminActivity = {
|
|
90
|
-
...baseActivity,
|
|
91
|
-
averageSpeedInMetersPerSecond: 3.5,
|
|
92
|
-
maxSpeedInMetersPerSecond: 5.2,
|
|
93
|
-
averageRunCadenceInStepsPerMinute: 170,
|
|
94
|
-
maxRunCadenceInStepsPerMinute: 190,
|
|
95
|
-
};
|
|
96
|
-
const result = transformActivity(withMovement);
|
|
97
|
-
|
|
98
|
-
expect(result.movement_data).toBeDefined();
|
|
99
|
-
expect(result.movement_data!.avg_speed_meters_per_second).toBe(3.5);
|
|
100
|
-
expect(result.movement_data!.max_speed_meters_per_second).toBe(5.2);
|
|
101
|
-
expect(result.movement_data!.avg_cadence_rpm).toBe(170);
|
|
102
|
-
expect(result.movement_data!.max_cadence_rpm).toBe(190);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it("maps device data", () => {
|
|
106
|
-
const withDevice: GarminActivity = {
|
|
107
|
-
...baseActivity,
|
|
108
|
-
deviceName: "Garmin Forerunner 265",
|
|
109
|
-
};
|
|
110
|
-
const result = transformActivity(withDevice);
|
|
111
|
-
|
|
112
|
-
expect(result.device_data).toBeDefined();
|
|
113
|
-
expect(result.device_data!.name).toBe("Garmin Forerunner 265");
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it("maps position data", () => {
|
|
117
|
-
const withPosition: GarminActivity = {
|
|
118
|
-
...baseActivity,
|
|
119
|
-
startingLatitudeInDegree: 37.7749,
|
|
120
|
-
startingLongitudeInDegree: -122.4194,
|
|
121
|
-
};
|
|
122
|
-
const result = transformActivity(withPosition);
|
|
123
|
-
|
|
124
|
-
expect(result.position_data).toBeDefined();
|
|
125
|
-
expect(result.position_data!.start_pos_lat_lng_deg).toEqual([37.7749, -122.4194]);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
it("maps power data", () => {
|
|
129
|
-
const withPower: GarminActivity = {
|
|
130
|
-
...baseActivity,
|
|
131
|
-
activityType: "CYCLING",
|
|
132
|
-
averagePowerInWatts: 200,
|
|
133
|
-
maxPowerInWatts: 450,
|
|
134
|
-
};
|
|
135
|
-
const result = transformActivity(withPower);
|
|
136
|
-
|
|
137
|
-
expect(result.power_data).toBeDefined();
|
|
138
|
-
expect(result.power_data!.avg_watts).toBe(200);
|
|
139
|
-
expect(result.power_data!.max_watts).toBe(450);
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it("maps lap data", () => {
|
|
143
|
-
const withLaps: GarminActivity = {
|
|
144
|
-
...baseActivity,
|
|
145
|
-
laps: [
|
|
146
|
-
{
|
|
147
|
-
startTimeInSeconds: 1700000000,
|
|
148
|
-
timerDurationInSeconds: 600,
|
|
149
|
-
totalDistanceInMeters: 1600,
|
|
150
|
-
heartRate: 150,
|
|
151
|
-
maxSpeed: 4.5,
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
startTimeInSeconds: 1700000600,
|
|
155
|
-
timerDurationInSeconds: 600,
|
|
156
|
-
totalDistanceInMeters: 1650,
|
|
157
|
-
heartRate: 158,
|
|
158
|
-
maxSpeed: 4.8,
|
|
159
|
-
},
|
|
160
|
-
],
|
|
161
|
-
};
|
|
162
|
-
const result = transformActivity(withLaps);
|
|
163
|
-
|
|
164
|
-
expect(result.lap_data).toBeDefined();
|
|
165
|
-
expect(result.lap_data!.laps).toHaveLength(2);
|
|
166
|
-
expect(result.lap_data!.laps![0].distance_meters).toBe(1600);
|
|
167
|
-
expect(result.lap_data!.laps![0].avg_hr_bpm).toBe(150);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it("uses summaryId as summary_id and falls back to activityId", () => {
|
|
171
|
-
const withoutSummaryId = {
|
|
172
|
-
...baseActivity,
|
|
173
|
-
summaryId: undefined as unknown as string,
|
|
174
|
-
};
|
|
175
|
-
const result = transformActivity(withoutSummaryId);
|
|
176
|
-
expect(result.metadata.summary_id).toBe("12345");
|
|
177
|
-
});
|
|
178
|
-
});
|
package/src/garmin/activity.ts
DELETED
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
// ─── Activity Transformer ────────────────────────────────────────────────────
|
|
2
|
-
// Transforms a Garmin activity into the Soma Activity schema shape.
|
|
3
|
-
|
|
4
|
-
import type { GarminActivity } from "./types.js";
|
|
5
|
-
import { mapActivityType } from "./maps/activity-type.js";
|
|
6
|
-
|
|
7
|
-
export type ActivityData = ReturnType<typeof transformActivity>;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Transform a Garmin activity into a Soma Activity document shape.
|
|
11
|
-
*
|
|
12
|
-
* The returned object is ready to be spread into an `ingestActivity` call
|
|
13
|
-
* alongside `connectionId` and `userId`.
|
|
14
|
-
*
|
|
15
|
-
* @param activity - The Garmin activity from the Health API
|
|
16
|
-
* @returns Soma Activity fields (without connectionId/userId)
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```ts
|
|
20
|
-
* const data = transformActivity(garminActivity);
|
|
21
|
-
* await soma.ingestActivity(ctx, { connectionId, userId, ...data });
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
export function transformActivity(activity: GarminActivity) {
|
|
25
|
-
const startMs = activity.startTimeInSeconds * 1000;
|
|
26
|
-
const endMs = startMs + activity.durationInSeconds * 1000;
|
|
27
|
-
const startDate = new Date(startMs).toISOString();
|
|
28
|
-
const endDate = new Date(endMs).toISOString();
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
metadata: {
|
|
32
|
-
summary_id: activity.summaryId ?? String(activity.activityId),
|
|
33
|
-
start_time: startDate,
|
|
34
|
-
end_time: endDate,
|
|
35
|
-
type: mapActivityType(activity.activityType),
|
|
36
|
-
upload_type: activity.manual ? 2 : 1,
|
|
37
|
-
name: activity.activityName,
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
active_durations_data: {
|
|
41
|
-
activity_seconds: activity.durationInSeconds,
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
calories_data: buildCaloriesData(activity),
|
|
45
|
-
|
|
46
|
-
device_data: activity.deviceName
|
|
47
|
-
? { name: activity.deviceName }
|
|
48
|
-
: undefined,
|
|
49
|
-
|
|
50
|
-
distance_data: buildDistanceData(activity),
|
|
51
|
-
|
|
52
|
-
heart_rate_data: buildHeartRateData(activity),
|
|
53
|
-
|
|
54
|
-
movement_data: buildMovementData(activity),
|
|
55
|
-
|
|
56
|
-
position_data: buildPositionData(activity),
|
|
57
|
-
|
|
58
|
-
power_data: buildPowerData(activity),
|
|
59
|
-
|
|
60
|
-
lap_data: buildLapData(activity),
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
65
|
-
|
|
66
|
-
function buildCaloriesData(activity: GarminActivity) {
|
|
67
|
-
if (
|
|
68
|
-
activity.activeKilocalories == null &&
|
|
69
|
-
activity.bmrKilocalories == null
|
|
70
|
-
) {
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const total =
|
|
75
|
-
(activity.activeKilocalories ?? 0) + (activity.bmrKilocalories ?? 0);
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
net_activity_calories: activity.activeKilocalories,
|
|
79
|
-
BMR_calories: activity.bmrKilocalories,
|
|
80
|
-
total_burned_calories: total || undefined,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function buildDistanceData(activity: GarminActivity) {
|
|
85
|
-
if (activity.distanceInMeters == null && activity.elevationGainInMeters == null) {
|
|
86
|
-
return undefined;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
summary: {
|
|
91
|
-
distance_meters: activity.distanceInMeters,
|
|
92
|
-
steps: activity.steps,
|
|
93
|
-
elevation:
|
|
94
|
-
activity.elevationGainInMeters != null
|
|
95
|
-
? {
|
|
96
|
-
gain_actual_meters: activity.elevationGainInMeters,
|
|
97
|
-
loss_actual_meters: activity.elevationLossInMeters,
|
|
98
|
-
}
|
|
99
|
-
: undefined,
|
|
100
|
-
},
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function buildHeartRateData(activity: GarminActivity) {
|
|
105
|
-
const hasHrSummary =
|
|
106
|
-
activity.averageHeartRateInBeatsPerMinute != null ||
|
|
107
|
-
activity.maxHeartRateInBeatsPerMinute != null;
|
|
108
|
-
const hasSamples = activity.samples && activity.samples.length > 0;
|
|
109
|
-
|
|
110
|
-
if (!hasHrSummary && !hasSamples) return undefined;
|
|
111
|
-
|
|
112
|
-
const hrSamples = hasSamples
|
|
113
|
-
? activity.samples!
|
|
114
|
-
.filter((s) => s.heartRate != null && s.startTimeInSeconds != null)
|
|
115
|
-
.map((s) => ({
|
|
116
|
-
timestamp: new Date(s.startTimeInSeconds! * 1000).toISOString(),
|
|
117
|
-
bpm: s.heartRate!,
|
|
118
|
-
}))
|
|
119
|
-
: undefined;
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
summary: hasHrSummary
|
|
123
|
-
? {
|
|
124
|
-
avg_hr_bpm: activity.averageHeartRateInBeatsPerMinute,
|
|
125
|
-
max_hr_bpm: activity.maxHeartRateInBeatsPerMinute,
|
|
126
|
-
}
|
|
127
|
-
: undefined,
|
|
128
|
-
detailed:
|
|
129
|
-
hrSamples && hrSamples.length > 0
|
|
130
|
-
? { hr_samples: hrSamples }
|
|
131
|
-
: undefined,
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function buildMovementData(activity: GarminActivity) {
|
|
136
|
-
const avgCadence =
|
|
137
|
-
activity.averageRunCadenceInStepsPerMinute ??
|
|
138
|
-
activity.averageBikeCadenceInRoundsPerMinute;
|
|
139
|
-
const maxCadence =
|
|
140
|
-
activity.maxRunCadenceInStepsPerMinute ??
|
|
141
|
-
activity.maxBikeCadenceInRoundsPerMinute;
|
|
142
|
-
|
|
143
|
-
const hasMovement =
|
|
144
|
-
activity.averageSpeedInMetersPerSecond != null ||
|
|
145
|
-
activity.maxSpeedInMetersPerSecond != null ||
|
|
146
|
-
avgCadence != null;
|
|
147
|
-
|
|
148
|
-
const hasSamples = activity.samples && activity.samples.length > 0;
|
|
149
|
-
|
|
150
|
-
if (!hasMovement && !hasSamples) return undefined;
|
|
151
|
-
|
|
152
|
-
const speedSamples = hasSamples
|
|
153
|
-
? activity.samples!
|
|
154
|
-
.filter(
|
|
155
|
-
(s) =>
|
|
156
|
-
s.speedMetersPerSecond != null && s.startTimeInSeconds != null,
|
|
157
|
-
)
|
|
158
|
-
.map((s) => ({
|
|
159
|
-
timestamp: new Date(s.startTimeInSeconds! * 1000).toISOString(),
|
|
160
|
-
speed_meters_per_second: s.speedMetersPerSecond!,
|
|
161
|
-
}))
|
|
162
|
-
: undefined;
|
|
163
|
-
|
|
164
|
-
const cadenceSamples = hasSamples
|
|
165
|
-
? activity.samples!
|
|
166
|
-
.filter(
|
|
167
|
-
(s) =>
|
|
168
|
-
(s.runCadenceInStepsPerMinute != null ||
|
|
169
|
-
s.bikeCadenceInRPM != null) &&
|
|
170
|
-
s.startTimeInSeconds != null,
|
|
171
|
-
)
|
|
172
|
-
.map((s) => ({
|
|
173
|
-
timestamp: new Date(s.startTimeInSeconds! * 1000).toISOString(),
|
|
174
|
-
cadence_rpm:
|
|
175
|
-
s.runCadenceInStepsPerMinute ?? s.bikeCadenceInRPM ?? 0,
|
|
176
|
-
}))
|
|
177
|
-
: undefined;
|
|
178
|
-
|
|
179
|
-
return {
|
|
180
|
-
avg_speed_meters_per_second: activity.averageSpeedInMetersPerSecond,
|
|
181
|
-
max_speed_meters_per_second: activity.maxSpeedInMetersPerSecond,
|
|
182
|
-
avg_pace_minutes_per_kilometer: activity.averagePaceInMinutesPerKilometer,
|
|
183
|
-
max_pace_minutes_per_kilometer: activity.maxPaceInMinutesPerKilometer,
|
|
184
|
-
avg_cadence_rpm: avgCadence,
|
|
185
|
-
max_cadence_rpm: maxCadence,
|
|
186
|
-
speed_samples:
|
|
187
|
-
speedSamples && speedSamples.length > 0 ? speedSamples : undefined,
|
|
188
|
-
cadence_samples:
|
|
189
|
-
cadenceSamples && cadenceSamples.length > 0
|
|
190
|
-
? cadenceSamples
|
|
191
|
-
: undefined,
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function buildPositionData(activity: GarminActivity) {
|
|
196
|
-
const hasStartPos =
|
|
197
|
-
activity.startingLatitudeInDegree != null &&
|
|
198
|
-
activity.startingLongitudeInDegree != null;
|
|
199
|
-
const hasSamples = activity.samples && activity.samples.length > 0;
|
|
200
|
-
|
|
201
|
-
if (!hasStartPos && !hasSamples) return undefined;
|
|
202
|
-
|
|
203
|
-
const positionSamples = hasSamples
|
|
204
|
-
? activity.samples!
|
|
205
|
-
.filter(
|
|
206
|
-
(s) =>
|
|
207
|
-
s.latitudeInDegree != null &&
|
|
208
|
-
s.longitudeInDegree != null &&
|
|
209
|
-
s.startTimeInSeconds != null,
|
|
210
|
-
)
|
|
211
|
-
.map((s) => ({
|
|
212
|
-
timestamp: new Date(s.startTimeInSeconds! * 1000).toISOString(),
|
|
213
|
-
coords_lat_lng_deg: [s.latitudeInDegree!, s.longitudeInDegree!],
|
|
214
|
-
}))
|
|
215
|
-
: undefined;
|
|
216
|
-
|
|
217
|
-
return {
|
|
218
|
-
start_pos_lat_lng_deg: hasStartPos
|
|
219
|
-
? [
|
|
220
|
-
activity.startingLatitudeInDegree!,
|
|
221
|
-
activity.startingLongitudeInDegree!,
|
|
222
|
-
]
|
|
223
|
-
: undefined,
|
|
224
|
-
position_samples:
|
|
225
|
-
positionSamples && positionSamples.length > 0
|
|
226
|
-
? positionSamples
|
|
227
|
-
: undefined,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function buildPowerData(activity: GarminActivity) {
|
|
232
|
-
const hasPowerSummary =
|
|
233
|
-
activity.averagePowerInWatts != null ||
|
|
234
|
-
activity.maxPowerInWatts != null;
|
|
235
|
-
const hasSamples = activity.samples && activity.samples.length > 0;
|
|
236
|
-
|
|
237
|
-
if (!hasPowerSummary && !hasSamples) return undefined;
|
|
238
|
-
|
|
239
|
-
const powerSamples = hasSamples
|
|
240
|
-
? activity.samples!
|
|
241
|
-
.filter(
|
|
242
|
-
(s) => s.powerInWatts != null && s.startTimeInSeconds != null,
|
|
243
|
-
)
|
|
244
|
-
.map((s) => ({
|
|
245
|
-
timestamp: new Date(s.startTimeInSeconds! * 1000).toISOString(),
|
|
246
|
-
watts: s.powerInWatts!,
|
|
247
|
-
}))
|
|
248
|
-
: undefined;
|
|
249
|
-
|
|
250
|
-
return {
|
|
251
|
-
avg_watts: activity.averagePowerInWatts,
|
|
252
|
-
max_watts: activity.maxPowerInWatts,
|
|
253
|
-
power_samples:
|
|
254
|
-
powerSamples && powerSamples.length > 0 ? powerSamples : undefined,
|
|
255
|
-
};
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function buildLapData(activity: GarminActivity) {
|
|
259
|
-
if (!activity.laps || activity.laps.length === 0) return undefined;
|
|
260
|
-
|
|
261
|
-
return {
|
|
262
|
-
laps: activity.laps.map((lap) => ({
|
|
263
|
-
start_time: new Date(lap.startTimeInSeconds * 1000).toISOString(),
|
|
264
|
-
end_time: new Date(
|
|
265
|
-
(lap.startTimeInSeconds + lap.timerDurationInSeconds) * 1000,
|
|
266
|
-
).toISOString(),
|
|
267
|
-
distance_meters: lap.totalDistanceInMeters,
|
|
268
|
-
avg_hr_bpm: lap.heartRate,
|
|
269
|
-
avg_speed_meters_per_second: lap.maxSpeed,
|
|
270
|
-
})),
|
|
271
|
-
};
|
|
272
|
-
}
|
package/src/garmin/auth.test.ts
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
generateCodeVerifier,
|
|
4
|
-
generateCodeChallenge,
|
|
5
|
-
generateState,
|
|
6
|
-
buildAuthUrl,
|
|
7
|
-
} from "./auth.js";
|
|
8
|
-
|
|
9
|
-
describe("generateCodeVerifier", () => {
|
|
10
|
-
it("returns a 64-character string by default", () => {
|
|
11
|
-
const verifier = generateCodeVerifier();
|
|
12
|
-
expect(verifier).toHaveLength(64);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it("only contains valid PKCE characters", () => {
|
|
16
|
-
const verifier = generateCodeVerifier();
|
|
17
|
-
expect(verifier).toMatch(/^[A-Za-z0-9\-._~]+$/);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("respects custom length", () => {
|
|
21
|
-
const verifier = generateCodeVerifier(128);
|
|
22
|
-
expect(verifier).toHaveLength(128);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("generates unique values", () => {
|
|
26
|
-
const v1 = generateCodeVerifier();
|
|
27
|
-
const v2 = generateCodeVerifier();
|
|
28
|
-
expect(v1).not.toBe(v2);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe("generateState", () => {
|
|
33
|
-
it("returns a 64-character hex string", () => {
|
|
34
|
-
const state = generateState();
|
|
35
|
-
expect(state).toHaveLength(64);
|
|
36
|
-
expect(state).toMatch(/^[0-9a-f]+$/);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("generates unique values", () => {
|
|
40
|
-
const s1 = generateState();
|
|
41
|
-
const s2 = generateState();
|
|
42
|
-
expect(s1).not.toBe(s2);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
describe("generateCodeChallenge", () => {
|
|
47
|
-
it("produces a base64url-encoded string", async () => {
|
|
48
|
-
const verifier = generateCodeVerifier();
|
|
49
|
-
const challenge = await generateCodeChallenge(verifier);
|
|
50
|
-
expect(challenge).toMatch(/^[A-Za-z0-9\-_]+$/);
|
|
51
|
-
expect(challenge).not.toContain("+");
|
|
52
|
-
expect(challenge).not.toContain("/");
|
|
53
|
-
expect(challenge).not.toContain("=");
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("produces different challenges for different verifiers", async () => {
|
|
57
|
-
const c1 = await generateCodeChallenge("verifier_one_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
|
58
|
-
const c2 = await generateCodeChallenge("verifier_two_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
|
59
|
-
expect(c1).not.toBe(c2);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("produces consistent challenges for the same verifier", async () => {
|
|
63
|
-
const verifier = "consistent_verifier_test_aaaaaaaaaaaaaaaaaa";
|
|
64
|
-
const c1 = await generateCodeChallenge(verifier);
|
|
65
|
-
const c2 = await generateCodeChallenge(verifier);
|
|
66
|
-
expect(c1).toBe(c2);
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe("buildAuthUrl", () => {
|
|
71
|
-
it("builds a valid authorization URL with required params", () => {
|
|
72
|
-
const url = buildAuthUrl({
|
|
73
|
-
clientId: "test-client-id",
|
|
74
|
-
codeChallenge: "test-challenge",
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
expect(url).toContain("https://connect.garmin.com/oauth2Confirm?");
|
|
78
|
-
expect(url).toContain("client_id=test-client-id");
|
|
79
|
-
expect(url).toContain("response_type=code");
|
|
80
|
-
expect(url).toContain("code_challenge=test-challenge");
|
|
81
|
-
expect(url).toContain("code_challenge_method=S256");
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it("includes optional redirect_uri", () => {
|
|
85
|
-
const url = buildAuthUrl({
|
|
86
|
-
clientId: "test-client-id",
|
|
87
|
-
codeChallenge: "test-challenge",
|
|
88
|
-
redirectUri: "https://example.com/callback",
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
expect(url).toContain("redirect_uri=https%3A%2F%2Fexample.com%2Fcallback");
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it("includes optional state", () => {
|
|
95
|
-
const url = buildAuthUrl({
|
|
96
|
-
clientId: "test-client-id",
|
|
97
|
-
codeChallenge: "test-challenge",
|
|
98
|
-
state: "my-state-value",
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
expect(url).toContain("state=my-state-value");
|
|
102
|
-
});
|
|
103
|
-
});
|
package/src/garmin/body.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
// ─── Body Transformer ────────────────────────────────────────────────────────
|
|
2
|
-
// Transforms Garmin body composition data into the Soma Body schema shape.
|
|
3
|
-
|
|
4
|
-
import type { GarminBodyComposition } from "./types.js";
|
|
5
|
-
|
|
6
|
-
export type BodyData = ReturnType<typeof transformBody>;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Transform a Garmin body composition record into a Soma Body document shape.
|
|
10
|
-
*
|
|
11
|
-
* @param body - The Garmin body composition data from the Health API
|
|
12
|
-
* @returns Soma Body fields (without connectionId/userId)
|
|
13
|
-
*/
|
|
14
|
-
export function transformBody(body: GarminBodyComposition) {
|
|
15
|
-
const measurementMs = body.measurementTimeInSeconds * 1000;
|
|
16
|
-
const timestamp = new Date(measurementMs).toISOString();
|
|
17
|
-
|
|
18
|
-
return {
|
|
19
|
-
metadata: {
|
|
20
|
-
start_time: timestamp,
|
|
21
|
-
end_time: timestamp,
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
measurements_data: buildMeasurementsData(body, timestamp),
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
29
|
-
|
|
30
|
-
function buildMeasurementsData(
|
|
31
|
-
body: GarminBodyComposition,
|
|
32
|
-
timestamp: string,
|
|
33
|
-
) {
|
|
34
|
-
if (
|
|
35
|
-
body.weightInGrams == null &&
|
|
36
|
-
body.bodyFatInPercent == null &&
|
|
37
|
-
body.bodyMassIndex == null &&
|
|
38
|
-
body.muscleMassInGrams == null &&
|
|
39
|
-
body.boneMassInGrams == null &&
|
|
40
|
-
body.bodyWaterInPercent == null
|
|
41
|
-
) {
|
|
42
|
-
return undefined;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
measurements: [
|
|
47
|
-
{
|
|
48
|
-
measurement_time: timestamp,
|
|
49
|
-
weight_kg:
|
|
50
|
-
body.weightInGrams != null ? body.weightInGrams / 1000 : undefined,
|
|
51
|
-
BMI: body.bodyMassIndex,
|
|
52
|
-
bodyfat_percentage: body.bodyFatInPercent,
|
|
53
|
-
muscle_mass_g: body.muscleMassInGrams,
|
|
54
|
-
bone_mass_g: body.boneMassInGrams,
|
|
55
|
-
water_percentage: body.bodyWaterInPercent,
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
};
|
|
59
|
-
}
|