@clipin/convex-wearables 0.0.2 → 0.0.3

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 (88) hide show
  1. package/dist/client/index.d.ts +9 -4
  2. package/dist/client/index.d.ts.map +1 -1
  3. package/dist/client/index.js.map +1 -1
  4. package/dist/component/_generated/component.d.ts +50 -0
  5. package/dist/component/_generated/component.d.ts.map +1 -0
  6. package/dist/component/_generated/component.js +11 -0
  7. package/dist/component/_generated/component.js.map +1 -0
  8. package/dist/component/backfillJobs.d.ts +11 -11
  9. package/dist/component/connections.d.ts +9 -9
  10. package/dist/component/connections.d.ts.map +1 -1
  11. package/dist/component/connections.js +2 -0
  12. package/dist/component/connections.js.map +1 -1
  13. package/dist/component/dataPoints.d.ts +5 -5
  14. package/dist/component/events.d.ts +13 -13
  15. package/dist/component/garminBackfill.d.ts +2 -2
  16. package/dist/component/garminWebhooks.d.ts +2 -2
  17. package/dist/component/garminWebhooks.d.ts.map +1 -1
  18. package/dist/component/garminWebhooks.js +2 -0
  19. package/dist/component/garminWebhooks.js.map +1 -1
  20. package/dist/component/lifecycle.d.ts +1 -1
  21. package/dist/component/lifecycle.d.ts.map +1 -1
  22. package/dist/component/lifecycle.js +2 -0
  23. package/dist/component/lifecycle.js.map +1 -1
  24. package/dist/component/oauthStates.d.ts +3 -3
  25. package/dist/component/schema.d.ts +26 -26
  26. package/dist/component/sdkPush.d.ts +11 -11
  27. package/dist/component/summaries.d.ts +4 -4
  28. package/dist/component/syncJobs.d.ts +23 -23
  29. package/dist/component/syncWorkflow.d.ts +2 -2
  30. package/dist/test.d.ts +421 -0
  31. package/dist/test.d.ts.map +1 -0
  32. package/dist/test.js +17 -0
  33. package/dist/test.js.map +1 -0
  34. package/package.json +12 -2
  35. package/src/client/_generated/_ignore.ts +2 -0
  36. package/src/client/index.test.ts +52 -0
  37. package/src/client/index.ts +784 -0
  38. package/src/client/types.ts +533 -0
  39. package/src/component/_generated/_ignore.ts +2 -0
  40. package/src/component/_generated/api.ts +16 -0
  41. package/src/component/_generated/component.ts +74 -0
  42. package/src/component/_generated/dataModel.ts +40 -0
  43. package/src/component/_generated/server.ts +48 -0
  44. package/src/component/backfillJobs.test.ts +47 -0
  45. package/src/component/backfillJobs.ts +245 -0
  46. package/src/component/connections.test.ts +297 -0
  47. package/src/component/connections.ts +329 -0
  48. package/src/component/convex.config.ts +7 -0
  49. package/src/component/dataPoints.test.ts +282 -0
  50. package/src/component/dataPoints.ts +305 -0
  51. package/src/component/dataSources.test.ts +247 -0
  52. package/src/component/dataSources.ts +109 -0
  53. package/src/component/events.test.ts +380 -0
  54. package/src/component/events.ts +288 -0
  55. package/src/component/garminBackfill.ts +343 -0
  56. package/src/component/garminWebhooks.test.ts +609 -0
  57. package/src/component/garminWebhooks.ts +656 -0
  58. package/src/component/httpHandlers.ts +153 -0
  59. package/src/component/lifecycle.test.ts +179 -0
  60. package/src/component/lifecycle.ts +87 -0
  61. package/src/component/menstrualCycles.ts +124 -0
  62. package/src/component/oauthActions.ts +261 -0
  63. package/src/component/oauthStates.test.ts +170 -0
  64. package/src/component/oauthStates.ts +85 -0
  65. package/src/component/providerSettings.ts +66 -0
  66. package/src/component/providers/additionalProviders.test.ts +401 -0
  67. package/src/component/providers/garmin.ts +1169 -0
  68. package/src/component/providers/oauth.test.ts +174 -0
  69. package/src/component/providers/oauth.ts +246 -0
  70. package/src/component/providers/polar.ts +220 -0
  71. package/src/component/providers/registry.ts +37 -0
  72. package/src/component/providers/strava.test.ts +195 -0
  73. package/src/component/providers/strava.ts +253 -0
  74. package/src/component/providers/suunto.ts +592 -0
  75. package/src/component/providers/types.ts +189 -0
  76. package/src/component/providers/whoop.ts +600 -0
  77. package/src/component/schema.ts +339 -0
  78. package/src/component/sdkPush.test.ts +367 -0
  79. package/src/component/sdkPush.ts +440 -0
  80. package/src/component/summaries.test.ts +201 -0
  81. package/src/component/summaries.ts +143 -0
  82. package/src/component/syncJobs.test.ts +254 -0
  83. package/src/component/syncJobs.ts +140 -0
  84. package/src/component/syncWorkflow.test.ts +87 -0
  85. package/src/component/syncWorkflow.ts +739 -0
  86. package/src/component/test.setup.ts +6 -0
  87. package/src/component/workflowManager.ts +19 -0
  88. package/src/test.ts +25 -0
@@ -0,0 +1,533 @@
1
+ /**
2
+ * Shared types for @clipin/convex-wearables.
3
+ *
4
+ * These types are used by both the component internals and the host app.
5
+ */
6
+
7
+ // ---------------------------------------------------------------------------
8
+ // Provider types
9
+ // ---------------------------------------------------------------------------
10
+
11
+ export type ProviderName =
12
+ | "garmin"
13
+ | "suunto"
14
+ | "polar"
15
+ | "whoop"
16
+ | "strava"
17
+ | "apple"
18
+ | "samsung"
19
+ | "google";
20
+
21
+ export type ConnectionStatus = "active" | "inactive" | "revoked" | "expired" | "error";
22
+
23
+ export type EventCategory = "workout" | "sleep";
24
+
25
+ export type SyncJobStatus = "queued" | "running" | "completed" | "failed" | "canceled";
26
+
27
+ export type BackfillJobStatus = "queued" | "running" | "completed" | "failed" | "canceled";
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Provider configuration (passed by app)
31
+ // ---------------------------------------------------------------------------
32
+
33
+ export interface ProviderCredentials {
34
+ clientId: string;
35
+ clientSecret: string;
36
+ /** Suunto requires an additional subscription key. */
37
+ subscriptionKey?: string;
38
+ }
39
+
40
+ export interface WearablesConfig {
41
+ providers: Partial<Record<ProviderName, ProviderCredentials>>;
42
+ /**
43
+ * Optional function reference called when new data is synced.
44
+ * The host app can use this to trigger downstream processing.
45
+ */
46
+ onDataSynced?: unknown; // FunctionReference — typed loosely to avoid coupling
47
+ }
48
+
49
+ export interface GarminRoutesConfig {
50
+ /** Route that receives Garmin push notifications. */
51
+ webhookPath?: string;
52
+ /** Optional health-check route for the Garmin webhook integration. */
53
+ healthPath?: string | false;
54
+ /** Expected Garmin client ID. Defaults to `process.env.GARMIN_CLIENT_ID`. */
55
+ clientId?: string;
56
+ /** Garmin client secret. Defaults to `process.env.GARMIN_CLIENT_SECRET`. */
57
+ clientSecret?: string;
58
+ /** Route that receives the Garmin OAuth callback. */
59
+ oauthCallbackPath?: string | false;
60
+ /** Where to redirect after a successful OAuth callback. */
61
+ successRedirectUrl?: string;
62
+ /** Query parameter set on successful OAuth redirect. */
63
+ successQueryParam?: string;
64
+ }
65
+
66
+ export interface SdkRoutesConfig {
67
+ /** Route that receives normalized SDK/mobile health pushes. */
68
+ syncPath?: string | false;
69
+ /**
70
+ * Optional shared bearer token expected on the SDK sync route.
71
+ * Defaults to `process.env.WEARABLES_SDK_AUTH_TOKEN` when omitted.
72
+ */
73
+ authToken?: string;
74
+ }
75
+
76
+ export interface RegisterRoutesConfig {
77
+ /**
78
+ * Garmin webhook routes.
79
+ * Pass `false` to skip registering Garmin routes.
80
+ */
81
+ garmin?: GarminRoutesConfig | false;
82
+ /**
83
+ * Normalized SDK push route for Apple Health / Google Health Connect / Samsung Health.
84
+ * Omitted by default; pass a config object to register it.
85
+ */
86
+ sdk?: SdkRoutesConfig | false;
87
+ }
88
+
89
+ export type SdkProviderName = "apple" | "google" | "samsung";
90
+
91
+ export interface SdkDeviceMetadata {
92
+ model?: string;
93
+ softwareVersion?: string;
94
+ source?: string;
95
+ deviceType?: string;
96
+ originalSourceName?: string;
97
+ }
98
+
99
+ export interface SdkSourceMetadata {
100
+ deviceModel?: string;
101
+ softwareVersion?: string;
102
+ source?: string;
103
+ deviceType?: string;
104
+ originalSourceName?: string;
105
+ }
106
+
107
+ export interface SdkPushEvent extends SdkSourceMetadata {
108
+ category: EventCategory;
109
+ type?: string;
110
+ sourceName?: string;
111
+ durationSeconds?: number;
112
+ startDatetime: number;
113
+ endDatetime?: number;
114
+ externalId?: string;
115
+ heartRateMin?: number;
116
+ heartRateMax?: number;
117
+ heartRateAvg?: number;
118
+ energyBurned?: number;
119
+ distance?: number;
120
+ stepsCount?: number;
121
+ maxSpeed?: number;
122
+ maxWatts?: number;
123
+ movingTimeSeconds?: number;
124
+ totalElevationGain?: number;
125
+ averageSpeed?: number;
126
+ averageWatts?: number;
127
+ elevHigh?: number;
128
+ elevLow?: number;
129
+ sleepTotalDurationMinutes?: number;
130
+ sleepTimeInBedMinutes?: number;
131
+ sleepEfficiencyScore?: number;
132
+ sleepDeepMinutes?: number;
133
+ sleepRemMinutes?: number;
134
+ sleepLightMinutes?: number;
135
+ sleepAwakeMinutes?: number;
136
+ isNap?: boolean;
137
+ sleepStages?: Array<{
138
+ stage: string;
139
+ startTime: number;
140
+ endTime: number;
141
+ }>;
142
+ }
143
+
144
+ export interface SdkPushDataPoint extends SdkSourceMetadata {
145
+ seriesType: string;
146
+ recordedAt: number;
147
+ value: number;
148
+ externalId?: string;
149
+ }
150
+
151
+ export interface SdkPushSummary {
152
+ date: string;
153
+ category: string;
154
+ totalSteps?: number;
155
+ totalCalories?: number;
156
+ activeCalories?: number;
157
+ activeMinutes?: number;
158
+ totalDistance?: number;
159
+ floorsClimbed?: number;
160
+ avgHeartRate?: number;
161
+ maxHeartRate?: number;
162
+ minHeartRate?: number;
163
+ sleepDurationMinutes?: number;
164
+ sleepEfficiency?: number;
165
+ deepSleepMinutes?: number;
166
+ remSleepMinutes?: number;
167
+ lightSleepMinutes?: number;
168
+ awakeDuringMinutes?: number;
169
+ timeInBedMinutes?: number;
170
+ hrvAvg?: number;
171
+ hrvRmssd?: number;
172
+ restingHeartRate?: number;
173
+ recoveryScore?: number;
174
+ weight?: number;
175
+ bodyFatPercentage?: number;
176
+ bodyMassIndex?: number;
177
+ leanBodyMass?: number;
178
+ bodyTemperature?: number;
179
+ avgStressLevel?: number;
180
+ bodyBattery?: number;
181
+ spo2Avg?: number;
182
+ }
183
+
184
+ export interface SdkPushPayload {
185
+ userId: string;
186
+ provider: SdkProviderName;
187
+ providerUserId?: string;
188
+ providerUsername?: string;
189
+ syncTimestamp?: number;
190
+ /**
191
+ * Compatibility alias for older mobile payloads.
192
+ * Prefer `sourceMetadata` for new integrations.
193
+ */
194
+ device?: SdkDeviceMetadata;
195
+ sourceMetadata?: SdkSourceMetadata;
196
+ events?: SdkPushEvent[];
197
+ dataPoints?: SdkPushDataPoint[];
198
+ summaries?: SdkPushSummary[];
199
+ /**
200
+ * Compatibility alias for older mobile payloads.
201
+ * Prefer `summaries` for new integrations.
202
+ */
203
+ dailySummaries?: SdkPushSummary[];
204
+ }
205
+
206
+ export type SdkSyncPayload = SdkPushPayload;
207
+
208
+ // ---------------------------------------------------------------------------
209
+ // Connection types
210
+ // ---------------------------------------------------------------------------
211
+
212
+ export interface Connection {
213
+ _id: string;
214
+ userId: string;
215
+ provider: ProviderName;
216
+ providerUserId?: string;
217
+ providerUsername?: string;
218
+ status: ConnectionStatus;
219
+ lastSyncedAt?: number;
220
+ }
221
+
222
+ // ---------------------------------------------------------------------------
223
+ // Event types
224
+ // ---------------------------------------------------------------------------
225
+
226
+ export interface WorkoutEvent {
227
+ _id: string;
228
+ userId: string;
229
+ category: "workout";
230
+ type?: string;
231
+ sourceName?: string;
232
+ durationSeconds?: number;
233
+ startDatetime: number;
234
+ endDatetime?: number;
235
+ externalId?: string;
236
+ // Workout details
237
+ heartRateMin?: number;
238
+ heartRateMax?: number;
239
+ heartRateAvg?: number;
240
+ energyBurned?: number;
241
+ distance?: number;
242
+ stepsCount?: number;
243
+ maxSpeed?: number;
244
+ maxWatts?: number;
245
+ movingTimeSeconds?: number;
246
+ totalElevationGain?: number;
247
+ averageSpeed?: number;
248
+ averageWatts?: number;
249
+ elevHigh?: number;
250
+ elevLow?: number;
251
+ }
252
+
253
+ export interface SleepStage {
254
+ stage: string;
255
+ startTime: number;
256
+ endTime: number;
257
+ }
258
+
259
+ export interface SleepEvent {
260
+ _id: string;
261
+ userId: string;
262
+ category: "sleep";
263
+ type?: string;
264
+ sourceName?: string;
265
+ durationSeconds?: number;
266
+ startDatetime: number;
267
+ endDatetime?: number;
268
+ externalId?: string;
269
+ // Sleep details
270
+ sleepTotalDurationMinutes?: number;
271
+ sleepTimeInBedMinutes?: number;
272
+ sleepEfficiencyScore?: number;
273
+ sleepDeepMinutes?: number;
274
+ sleepRemMinutes?: number;
275
+ sleepLightMinutes?: number;
276
+ sleepAwakeMinutes?: number;
277
+ isNap?: boolean;
278
+ sleepStages?: SleepStage[];
279
+ }
280
+
281
+ export type HealthEvent = WorkoutEvent | SleepEvent;
282
+
283
+ // ---------------------------------------------------------------------------
284
+ // Data point types
285
+ // ---------------------------------------------------------------------------
286
+
287
+ export interface DataPoint {
288
+ timestamp: number;
289
+ value: number;
290
+ }
291
+
292
+ export interface TimeSeriesPage {
293
+ points: DataPoint[];
294
+ nextCursor: string | null;
295
+ hasMore: boolean;
296
+ }
297
+
298
+ // ---------------------------------------------------------------------------
299
+ // Events page
300
+ // ---------------------------------------------------------------------------
301
+
302
+ export interface EventsPage {
303
+ events: HealthEvent[];
304
+ nextCursor: string | null;
305
+ hasMore: boolean;
306
+ }
307
+
308
+ // ---------------------------------------------------------------------------
309
+ // Summary types
310
+ // ---------------------------------------------------------------------------
311
+
312
+ export interface DailySummary {
313
+ _id: string;
314
+ userId: string;
315
+ date: string;
316
+ category: string;
317
+ // Activity
318
+ totalSteps?: number;
319
+ totalCalories?: number;
320
+ activeCalories?: number;
321
+ activeMinutes?: number;
322
+ totalDistance?: number;
323
+ floorsClimbed?: number;
324
+ avgHeartRate?: number;
325
+ maxHeartRate?: number;
326
+ minHeartRate?: number;
327
+ // Sleep
328
+ sleepDurationMinutes?: number;
329
+ sleepEfficiency?: number;
330
+ deepSleepMinutes?: number;
331
+ remSleepMinutes?: number;
332
+ lightSleepMinutes?: number;
333
+ awakeDuringMinutes?: number;
334
+ timeInBedMinutes?: number;
335
+ // Recovery
336
+ hrvAvg?: number;
337
+ hrvRmssd?: number;
338
+ restingHeartRate?: number;
339
+ recoveryScore?: number;
340
+ // Body
341
+ weight?: number;
342
+ bodyFatPercentage?: number;
343
+ bodyMassIndex?: number;
344
+ leanBodyMass?: number;
345
+ bodyTemperature?: number;
346
+ // Other
347
+ avgStressLevel?: number;
348
+ bodyBattery?: number;
349
+ spo2Avg?: number;
350
+ }
351
+
352
+ export interface AggregateStats {
353
+ sum: number;
354
+ count: number;
355
+ avg: number;
356
+ min: number | null;
357
+ max: number | null;
358
+ }
359
+
360
+ // ---------------------------------------------------------------------------
361
+ // Sync status
362
+ // ---------------------------------------------------------------------------
363
+
364
+ export interface SyncJob {
365
+ _id: string;
366
+ connectionId: string;
367
+ userId: string;
368
+ provider: ProviderName;
369
+ status: SyncJobStatus;
370
+ mode?: "manual" | "cron" | "webhook";
371
+ triggerSource?: string;
372
+ startedAt: number;
373
+ completedAt?: number;
374
+ error?: string;
375
+ recordsProcessed?: number;
376
+ workflowId?: string;
377
+ windowStart?: number;
378
+ windowEnd?: number;
379
+ attempt?: number;
380
+ lastHeartbeatAt?: number;
381
+ cursor?: string;
382
+ currentPhase?: "events" | "dataPoints" | "summaries";
383
+ }
384
+
385
+ export interface SyncStatus {
386
+ provider: ProviderName;
387
+ connectionStatus: ConnectionStatus;
388
+ lastSyncedAt?: number;
389
+ syncJobStatus: SyncJobStatus | null;
390
+ syncJobError: string | null;
391
+ }
392
+
393
+ export interface BackfillJob {
394
+ _id: string;
395
+ connectionId: string;
396
+ userId: string;
397
+ provider: ProviderName;
398
+ dataType: string;
399
+ status: BackfillJobStatus;
400
+ startedAt: number;
401
+ completedAt?: number;
402
+ error?: string;
403
+ workflowId?: string;
404
+ windowStart?: number;
405
+ windowEnd?: number;
406
+ currentDataType?: string;
407
+ currentAttempt?: number;
408
+ currentEventId?: string;
409
+ completedDataTypes?: string[];
410
+ lastHeartbeatAt?: number;
411
+ }
412
+
413
+ // ---------------------------------------------------------------------------
414
+ // Series type definitions — all 48 pre-defined metric types
415
+ // ---------------------------------------------------------------------------
416
+
417
+ export const SERIES_TYPES = {
418
+ // Heart & Cardiovascular
419
+ heart_rate: { id: 1, unit: "bpm" },
420
+ resting_heart_rate: { id: 2, unit: "bpm" },
421
+ heart_rate_variability_sdnn: { id: 3, unit: "ms" },
422
+ heart_rate_recovery_one_minute: { id: 4, unit: "bpm" },
423
+ walking_heart_rate_average: { id: 5, unit: "bpm" },
424
+ recovery_score: { id: 6, unit: "score" },
425
+ heart_rate_variability_rmssd: { id: 7, unit: "ms" },
426
+
427
+ // Blood & Respiratory
428
+ oxygen_saturation: { id: 20, unit: "percent" },
429
+ blood_glucose: { id: 21, unit: "mg_dl" },
430
+ blood_pressure_systolic: { id: 22, unit: "mmHg" },
431
+ blood_pressure_diastolic: { id: 23, unit: "mmHg" },
432
+ respiratory_rate: { id: 24, unit: "brpm" },
433
+ sleeping_breathing_disturbances: { id: 25, unit: "count" },
434
+ blood_alcohol_content: { id: 26, unit: "mg_dl" },
435
+ peripheral_perfusion_index: { id: 27, unit: "score" },
436
+ forced_vital_capacity: { id: 28, unit: "liters" },
437
+ forced_expiratory_volume_1: { id: 29, unit: "liters" },
438
+ peak_expiratory_flow_rate: { id: 30, unit: "liters" },
439
+
440
+ // Body Composition
441
+ height: { id: 40, unit: "cm" },
442
+ weight: { id: 41, unit: "kg" },
443
+ body_fat_percentage: { id: 42, unit: "percent" },
444
+ body_mass_index: { id: 43, unit: "kg_m2" },
445
+ lean_body_mass: { id: 44, unit: "kg" },
446
+ body_temperature: { id: 45, unit: "celsius" },
447
+ skin_temperature: { id: 46, unit: "celsius" },
448
+ waist_circumference: { id: 47, unit: "cm" },
449
+ body_fat_mass: { id: 48, unit: "kg" },
450
+ skeletal_muscle_mass: { id: 49, unit: "kg" },
451
+
452
+ // Fitness
453
+ vo2_max: { id: 60, unit: "ml_kg_min" },
454
+ six_minute_walk_test_distance: { id: 61, unit: "meters" },
455
+
456
+ // Activity — Basic
457
+ steps: { id: 80, unit: "count" },
458
+ energy: { id: 81, unit: "kcal" },
459
+ basal_energy: { id: 82, unit: "kcal" },
460
+ total_calories: { id: 88, unit: "kcal" },
461
+ active_calories: { id: 89, unit: "kcal" },
462
+ stand_time: { id: 83, unit: "minutes" },
463
+ exercise_time: { id: 84, unit: "minutes" },
464
+ physical_effort: { id: 85, unit: "score" },
465
+ flights_climbed: { id: 86, unit: "count" },
466
+ floors_climbed: { id: 90, unit: "count" },
467
+ average_met: { id: 87, unit: "met" },
468
+
469
+ // Activity — Distance
470
+ distance: { id: 99, unit: "meters" },
471
+ distance_walking_running: { id: 100, unit: "meters" },
472
+ distance_cycling: { id: 101, unit: "meters" },
473
+ distance_swimming: { id: 102, unit: "meters" },
474
+ distance_downhill_snow_sports: { id: 103, unit: "meters" },
475
+ distance_other: { id: 104, unit: "meters" },
476
+ elevation_gain: { id: 105, unit: "meters" },
477
+
478
+ // Activity — Walking
479
+ walking_step_length: { id: 120, unit: "cm" },
480
+ walking_speed: { id: 121, unit: "m_per_s" },
481
+ walking_double_support_percentage: { id: 122, unit: "percent" },
482
+ walking_asymmetry_percentage: { id: 123, unit: "percent" },
483
+ walking_steadiness: { id: 124, unit: "percent" },
484
+ stair_descent_speed: { id: 125, unit: "m_per_s" },
485
+ stair_ascent_speed: { id: 126, unit: "m_per_s" },
486
+
487
+ // Activity — Running
488
+ running_power: { id: 140, unit: "watts" },
489
+ running_speed: { id: 141, unit: "m_per_s" },
490
+ running_vertical_oscillation: { id: 142, unit: "cm" },
491
+ running_ground_contact_time: { id: 143, unit: "ms" },
492
+ running_stride_length: { id: 144, unit: "cm" },
493
+
494
+ // Activity — Swimming
495
+ swimming_stroke_count: { id: 160, unit: "count" },
496
+ underwater_depth: { id: 161, unit: "meters" },
497
+
498
+ // Activity — Generic
499
+ cadence: { id: 180, unit: "rpm" },
500
+ power: { id: 181, unit: "watts" },
501
+ speed: { id: 182, unit: "m_per_s" },
502
+ workout_effort_score: { id: 183, unit: "score" },
503
+ estimated_workout_effort_score: { id: 184, unit: "score" },
504
+
505
+ // Environmental
506
+ environmental_audio_exposure: { id: 200, unit: "dB" },
507
+ headphone_audio_exposure: { id: 201, unit: "dB" },
508
+ environmental_sound_reduction: { id: 202, unit: "dB" },
509
+ time_in_daylight: { id: 203, unit: "minutes" },
510
+ water_temperature: { id: 204, unit: "celsius" },
511
+ uv_exposure: { id: 205, unit: "count" },
512
+ inhaler_usage: { id: 206, unit: "count" },
513
+ weather_temperature: { id: 207, unit: "celsius" },
514
+ weather_humidity: { id: 208, unit: "percent" },
515
+
516
+ // Garmin-Specific
517
+ garmin_stress_level: { id: 220, unit: "score" },
518
+ garmin_skin_temperature: { id: 221, unit: "celsius" },
519
+ garmin_fitness_age: { id: 222, unit: "years" },
520
+ garmin_body_battery: { id: 223, unit: "percent" },
521
+
522
+ // Other
523
+ electrodermal_activity: { id: 500, unit: "count" },
524
+ push_count: { id: 501, unit: "count" },
525
+ atrial_fibrillation_burden: { id: 502, unit: "count" },
526
+ insulin_delivery: { id: 503, unit: "count" },
527
+ number_of_times_fallen: { id: 504, unit: "count" },
528
+ number_of_alcoholic_beverages: { id: 505, unit: "count" },
529
+ nike_fuel: { id: 506, unit: "count" },
530
+ hydration: { id: 507, unit: "mL" },
531
+ } as const;
532
+
533
+ export type SeriesType = keyof typeof SERIES_TYPES;
@@ -0,0 +1,2 @@
1
+ // This file exists so that the _generated directory is tracked by git.
2
+ // The actual generated files are created by `npx convex dev` or `npx convex codegen`.
@@ -0,0 +1,16 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * Generated API.
4
+ *
5
+ * THIS CODE IS AUTOMATICALLY GENERATED.
6
+ *
7
+ * To regenerate, run `npx convex dev`.
8
+ * @module
9
+ */
10
+
11
+ import type { AnyApi, AnyComponents } from "convex/server";
12
+ import { anyApi, componentsGeneric } from "convex/server";
13
+
14
+ export const api: AnyApi = anyApi;
15
+ export const internal: AnyApi = anyApi;
16
+ export const components: AnyComponents = componentsGeneric();
@@ -0,0 +1,74 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * Generated `ComponentApi` utility.
4
+ *
5
+ * THIS CODE IS AUTOMATICALLY GENERATED.
6
+ *
7
+ * To regenerate, run `npx convex dev`.
8
+ * @module
9
+ */
10
+
11
+ import type { ApiFromModules, FilterApi, FunctionReference } from "convex/server";
12
+ import type { GenericId as ConvexId } from "convex/values";
13
+
14
+ type Modules = {
15
+ backfillJobs: typeof import("../backfillJobs.js");
16
+ connections: typeof import("../connections.js");
17
+ dataPoints: typeof import("../dataPoints.js");
18
+ dataSources: typeof import("../dataSources.js");
19
+ events: typeof import("../events.js");
20
+ garminBackfill: typeof import("../garminBackfill.js");
21
+ garminWebhooks: typeof import("../garminWebhooks.js");
22
+ lifecycle: typeof import("../lifecycle.js");
23
+ menstrualCycles: typeof import("../menstrualCycles.js");
24
+ oauthActions: typeof import("../oauthActions.js");
25
+ sdkPush: typeof import("../sdkPush.js");
26
+ summaries: typeof import("../summaries.js");
27
+ syncJobs: typeof import("../syncJobs.js");
28
+ syncWorkflow: typeof import("../syncWorkflow.js");
29
+ };
30
+
31
+ type PublicApi = FilterApi<
32
+ ApiFromModules<Modules>,
33
+ FunctionReference<any, "public", any, any>
34
+ >;
35
+
36
+ type ConvertComponentBoundary<T> =
37
+ T extends ConvexId<string>
38
+ ? string
39
+ : T extends readonly (infer Item)[]
40
+ ? Array<ConvertComponentBoundary<Item>>
41
+ : T extends object
42
+ ? { [Key in keyof T]: ConvertComponentBoundary<T[Key]> }
43
+ : T;
44
+
45
+ type ConvertComponentArgs<Args extends Record<string, any>> = {
46
+ [Key in keyof Args]: ConvertComponentBoundary<Args[Key]>;
47
+ };
48
+
49
+ type ToComponentApi<API, Name extends string | undefined> =
50
+ API extends FunctionReference<infer Type, any, infer Args, infer ReturnType>
51
+ ? FunctionReference<
52
+ Type,
53
+ "internal",
54
+ ConvertComponentArgs<Args>,
55
+ ConvertComponentBoundary<ReturnType>,
56
+ Name
57
+ >
58
+ : API extends object
59
+ ? { [Key in keyof API]: ToComponentApi<API[Key], Name> }
60
+ : never;
61
+
62
+ /**
63
+ * A utility for referencing a Convex component's exposed API.
64
+ *
65
+ * Useful when expecting a parameter like `components.myComponent`.
66
+ * Usage:
67
+ * ```ts
68
+ * async function myFunction(ctx: QueryCtx, component: ComponentApi) {
69
+ * return ctx.runQuery(component.someFile.someQuery, { ...args });
70
+ * }
71
+ * ```
72
+ */
73
+ export type ComponentApi<Name extends string | undefined = string | undefined> =
74
+ ToComponentApi<PublicApi, Name>;
@@ -0,0 +1,40 @@
1
+ /* eslint-disable */
2
+ /**
3
+ * Generated data model types.
4
+ *
5
+ * THIS CODE IS AUTOMATICALLY GENERATED.
6
+ *
7
+ * To regenerate, run `npx convex dev`.
8
+ * @module
9
+ */
10
+
11
+ import type {
12
+ DataModelFromSchemaDefinition,
13
+ DocumentByName,
14
+ TableNamesInDataModel,
15
+ } from "convex/server";
16
+ import type { GenericId } from "convex/values";
17
+ import schema from "../schema.js";
18
+
19
+ /**
20
+ * The names of all of your Convex tables.
21
+ */
22
+ export type TableNames = TableNamesInDataModel<DataModel>;
23
+
24
+ /**
25
+ * The type of a document stored in Convex.
26
+ */
27
+ export type Doc<TableName extends TableNames> = DocumentByName<
28
+ DataModel,
29
+ TableName
30
+ >;
31
+
32
+ /**
33
+ * An identifier for a document in Convex.
34
+ */
35
+ export type Id<TableName extends TableNames> = GenericId<TableName>;
36
+
37
+ /**
38
+ * A type describing your Convex data model.
39
+ */
40
+ export type DataModel = DataModelFromSchemaDefinition<typeof schema>;