@nativesquare/soma 0.9.2 → 0.9.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.
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "bugs": {
7
7
  "url": "https://github.com/NativeSquare/soma/issues"
8
8
  },
9
- "version": "0.9.2",
9
+ "version": "0.9.3",
10
10
  "license": "Apache-2.0",
11
11
  "keywords": [
12
12
  "convex",
@@ -1282,6 +1282,8 @@ export interface GarminWebhookEvent {
1282
1282
  dataType: string;
1283
1283
  processed: number;
1284
1284
  errors: Array<{ type: string; id: string; error: string }>;
1285
+ /** Users whose data was affected by this webhook. */
1286
+ affectedUsers: Array<{ userId: string; connectionId: string }>;
1285
1287
  }
1286
1288
 
1287
1289
  // ─── Garmin Route Options ───────────────────────────────────────────────────
@@ -1603,7 +1605,7 @@ export function registerRoutes(
1603
1605
  return new Response("Invalid JSON body", { status: 400 });
1604
1606
  }
1605
1607
 
1606
- let result: { processed: number; errors: Array<{ type: string; id: string; error: string }> } | undefined;
1608
+ let result: { processed: number; errors: Array<{ type: string; id: string; error: string }>; affectedUsers: Array<{ userId: string; connectionId: string }> } | undefined;
1607
1609
  try {
1608
1610
  result = await ctx.runAction(route.action, { payload }) as typeof result;
1609
1611
  } catch (error) {
@@ -1620,6 +1622,7 @@ export function registerRoutes(
1620
1622
  dataType,
1621
1623
  processed: result.processed,
1622
1624
  errors: result.errors,
1625
+ affectedUsers: result.affectedUsers,
1623
1626
  };
1624
1627
 
1625
1628
  const specificHandler = webhookCfg.events?.[dataType];
@@ -325,7 +325,7 @@ export const processActivityPingPayload = internalAction({
325
325
  console.log(
326
326
  `[garmin:webhook:activities] Ping mode not yet implemented, acknowledging ${activities.length} items`,
327
327
  );
328
- return { processed: 0, errors: [] };
328
+ return { processed: 0, errors: [], affectedUsers: [] };
329
329
  },
330
330
  });
331
331
 
@@ -416,7 +416,7 @@ export const processActivityDetailsPingPayload = internalAction({
416
416
  console.log(
417
417
  `[garmin:webhook:activityDetails] Ping mode not yet implemented, acknowledging ${activityDetails.length} items`,
418
418
  );
419
- return { processed: 0, errors: [] };
419
+ return { processed: 0, errors: [], affectedUsers: [] };
420
420
  },
421
421
  });
422
422
 
@@ -507,7 +507,7 @@ export const processManuallyUpdatedActivitiesPingPayload = internalAction({
507
507
  console.log(
508
508
  `[garmin:webhook:manuallyUpdatedActivities] Ping mode not yet implemented, acknowledging ${manuallyUpdatedActivities.length} items`,
509
509
  );
510
- return { processed: 0, errors: [] };
510
+ return { processed: 0, errors: [], affectedUsers: [] };
511
511
  },
512
512
  });
513
513
 
@@ -600,7 +600,7 @@ export const processMoveIQPingPayload = internalAction({
600
600
  console.log(
601
601
  `[garmin:webhook:moveIQ] Ping mode not yet implemented, acknowledging ${moveIQActivities.length} items`,
602
602
  );
603
- return { processed: 0, errors: [] };
603
+ return { processed: 0, errors: [], affectedUsers: [] };
604
604
  },
605
605
  });
606
606
 
@@ -692,7 +692,7 @@ export const processBloodPressurePingPayload = internalAction({
692
692
  console.log(
693
693
  `[garmin:webhook:bloodPressures] Ping mode not yet implemented, acknowledging ${bloodPressures.length} items`,
694
694
  );
695
- return { processed: 0, errors: [] };
695
+ return { processed: 0, errors: [], affectedUsers: [] };
696
696
  },
697
697
  });
698
698
 
@@ -784,7 +784,7 @@ export const processBodyCompositionsPingPayload = internalAction({
784
784
  console.log(
785
785
  `[garmin:webhook:bodyCompositions] Ping mode not yet implemented, acknowledging ${bodyComps.length} items`,
786
786
  );
787
- return { processed: 0, errors: [] };
787
+ return { processed: 0, errors: [], affectedUsers: [] };
788
788
  },
789
789
  });
790
790
 
@@ -876,7 +876,7 @@ export const processDailiesPingPayload = internalAction({
876
876
  console.log(
877
877
  `[garmin:webhook:dailies] Ping mode not yet implemented, acknowledging ${dailies.length} items`,
878
878
  );
879
- return { processed: 0, errors: [] };
879
+ return { processed: 0, errors: [], affectedUsers: [] };
880
880
  },
881
881
  });
882
882
 
@@ -968,7 +968,7 @@ export const processHealthSnapshotPingPayload = internalAction({
968
968
  console.log(
969
969
  `[garmin:webhook:healthSnapshot] Ping mode not yet implemented, acknowledging ${healthSnapshot.length} items`,
970
970
  );
971
- return { processed: 0, errors: [] };
971
+ return { processed: 0, errors: [], affectedUsers: [] };
972
972
  },
973
973
  });
974
974
 
@@ -1060,7 +1060,7 @@ export const processHRVSummaryPingPayload = internalAction({
1060
1060
  console.log(
1061
1061
  `[garmin:webhook:hrvSummary] Ping mode not yet implemented, acknowledging ${hrv.length} items`,
1062
1062
  );
1063
- return { processed: 0, errors: [] };
1063
+ return { processed: 0, errors: [], affectedUsers: [] };
1064
1064
  },
1065
1065
  });
1066
1066
 
@@ -1152,7 +1152,7 @@ export const processEpochPingPayload = internalAction({
1152
1152
  console.log(
1153
1153
  `[garmin:webhook:epochs] Ping mode not yet implemented, acknowledging ${epochs.length} items`,
1154
1154
  );
1155
- return { processed: 0, errors: [] };
1155
+ return { processed: 0, errors: [], affectedUsers: [] };
1156
1156
  },
1157
1157
  });
1158
1158
 
@@ -1244,7 +1244,7 @@ export const processPulseOxPingPayload = internalAction({
1244
1244
  console.log(
1245
1245
  `[garmin:webhook:pulseOx] Ping mode not yet implemented, acknowledging ${pulseox.length} items`,
1246
1246
  );
1247
- return { processed: 0, errors: [] };
1247
+ return { processed: 0, errors: [], affectedUsers: [] };
1248
1248
  },
1249
1249
  });
1250
1250
 
@@ -1336,7 +1336,7 @@ export const processRespirationPingPayload = internalAction({
1336
1336
  console.log(
1337
1337
  `[garmin:webhook:respiration] Ping mode not yet implemented, acknowledging ${allDayRespiration.length} items`,
1338
1338
  );
1339
- return { processed: 0, errors: [] };
1339
+ return { processed: 0, errors: [], affectedUsers: [] };
1340
1340
  },
1341
1341
  });
1342
1342
 
@@ -1428,7 +1428,7 @@ export const processStressPingPayload = internalAction({
1428
1428
  console.log(
1429
1429
  `[garmin:webhook:stressDetails] Ping mode not yet implemented, acknowledging ${stressDetails.length} items`,
1430
1430
  );
1431
- return { processed: 0, errors: [] };
1431
+ return { processed: 0, errors: [], affectedUsers: [] };
1432
1432
  },
1433
1433
  });
1434
1434
 
@@ -1520,7 +1520,7 @@ export const processSkinTemperaturePingPayload = internalAction({
1520
1520
  console.log(
1521
1521
  `[garmin:webhook:skinTemperature] Ping mode not yet implemented, acknowledging ${skinTemp.length} items`,
1522
1522
  );
1523
- return { processed: 0, errors: [] };
1523
+ return { processed: 0, errors: [], affectedUsers: [] };
1524
1524
  },
1525
1525
  });
1526
1526
 
@@ -1609,7 +1609,7 @@ export const processSleepsPingPayload = internalAction({
1609
1609
  console.log(
1610
1610
  `[garmin:webhook:sleeps] Ping mode not yet implemented, acknowledging ${sleeps.length} items`,
1611
1611
  );
1612
- return { processed: 0, errors: [] };
1612
+ return { processed: 0, errors: [], affectedUsers: [] };
1613
1613
  },
1614
1614
  });
1615
1615
 
@@ -1701,7 +1701,7 @@ export const processUserMetricsPingPayload = internalAction({
1701
1701
  console.log(
1702
1702
  `[garmin:webhook:userMetrics] Ping mode not yet implemented, acknowledging ${userMetrics.length} items`,
1703
1703
  );
1704
- return { processed: 0, errors: [] };
1704
+ return { processed: 0, errors: [], affectedUsers: [] };
1705
1705
  },
1706
1706
  });
1707
1707
 
@@ -1792,7 +1792,7 @@ export const processMenstrualCycleTrackingPingPayload = internalAction({
1792
1792
  console.log(
1793
1793
  `[garmin:webhook:menstrualCycleTracking] Ping mode not yet implemented, acknowledging ${mct.length} items`,
1794
1794
  );
1795
- return { processed: 0, errors: [] };
1795
+ return { processed: 0, errors: [], affectedUsers: [] };
1796
1796
  },
1797
1797
  });
1798
1798
 
@@ -106,6 +106,7 @@ function isWebhookPushMode(payload: unknown): boolean {
106
106
  type WebhookResult = {
107
107
  processed: number;
108
108
  errors: Array<{ type: string; id: string; error: string }>;
109
+ affectedUsers: Array<{ userId: string; connectionId: string }>;
109
110
  };
110
111
 
111
112
  type ProcessResult = {
@@ -126,6 +127,7 @@ async function ingestAndUpdate(
126
127
  let processed = 0;
127
128
  const errors = [...result.errors];
128
129
  const connectionsToUpdate = new Set<string>();
130
+ const userMap = new Map<string, { userId: string; connectionId: string }>();
129
131
 
130
132
  for (const item of result.items) {
131
133
  try {
@@ -136,6 +138,10 @@ async function ingestAndUpdate(
136
138
  } as never);
137
139
  processed++;
138
140
  connectionsToUpdate.add(item.connectionId);
141
+ userMap.set(`${item.userId}:${item.connectionId}`, {
142
+ userId: item.userId,
143
+ connectionId: item.connectionId,
144
+ });
139
145
  } catch (err) {
140
146
  errors.push({
141
147
  type: "ingest",
@@ -152,7 +158,7 @@ async function ingestAndUpdate(
152
158
  } as never);
153
159
  }
154
160
 
155
- return { processed, errors };
161
+ return { processed, errors, affectedUsers: [...userMap.values()] };
156
162
  }
157
163
 
158
164
  // ─── Webhook Handlers ────────────────────────────────────────────────────────
@@ -185,7 +191,7 @@ export const handleGarminWebhookActivities = action({
185
191
  console.warn(
186
192
  `[garmin:webhook:activities] Payload matched neither ping nor push schema`,
187
193
  );
188
- return { processed: 0, errors: [] };
194
+ return { processed: 0, errors: [], affectedUsers: [] };
189
195
  },
190
196
  });
191
197
 
@@ -225,7 +231,7 @@ export const handleGarminWebhookActivityDetails = action({
225
231
  console.warn(
226
232
  `[garmin:webhook:activityDetails] Payload matched neither ping nor push schema`,
227
233
  );
228
- return { processed: 0, errors: [] };
234
+ return { processed: 0, errors: [], affectedUsers: [] };
229
235
  },
230
236
  });
231
237
 
@@ -271,7 +277,7 @@ export const handleGarminWebhookManuallyUpdatedActivities = action({
271
277
  console.warn(
272
278
  `[garmin:webhook:manuallyUpdatedActivities] Payload matched neither ping nor push schema`,
273
279
  );
274
- return { processed: 0, errors: [] };
280
+ return { processed: 0, errors: [], affectedUsers: [] };
275
281
  },
276
282
  });
277
283
 
@@ -311,7 +317,7 @@ export const handleGarminWebhookMoveIQ = action({
311
317
  console.warn(
312
318
  `[garmin:webhook:moveIQ] Payload matched neither ping nor push schema`,
313
319
  );
314
- return { processed: 0, errors: [] };
320
+ return { processed: 0, errors: [], affectedUsers: [] };
315
321
  },
316
322
  });
317
323
 
@@ -351,7 +357,7 @@ export const handleGarminWebhookBloodPressures = action({
351
357
  console.warn(
352
358
  `[garmin:webhook:bloodPressures] Payload matched neither ping nor push schema`,
353
359
  );
354
- return { processed: 0, errors: [] };
360
+ return { processed: 0, errors: [], affectedUsers: [] };
355
361
  },
356
362
  });
357
363
 
@@ -391,7 +397,7 @@ export const handleGarminWebhookBodyCompositions = action({
391
397
  console.warn(
392
398
  `[garmin:webhook:bodyCompositions] Payload matched neither ping nor push schema`,
393
399
  );
394
- return { processed: 0, errors: [] };
400
+ return { processed: 0, errors: [], affectedUsers: [] };
395
401
  },
396
402
  });
397
403
 
@@ -431,7 +437,7 @@ export const handleGarminWebhookDailies = action({
431
437
  console.warn(
432
438
  `[garmin:webhook:dailies] Payload matched neither ping nor push schema`,
433
439
  );
434
- return { processed: 0, errors: [] };
440
+ return { processed: 0, errors: [], affectedUsers: [] };
435
441
  },
436
442
  });
437
443
 
@@ -471,7 +477,7 @@ export const handleGarminWebhookEpochs = action({
471
477
  console.warn(
472
478
  `[garmin:webhook:epochs] Payload matched neither ping nor push schema`,
473
479
  );
474
- return { processed: 0, errors: [] };
480
+ return { processed: 0, errors: [], affectedUsers: [] };
475
481
  },
476
482
  });
477
483
 
@@ -511,7 +517,7 @@ export const handleGarminWebhookHealthSnapshot = action({
511
517
  console.warn(
512
518
  `[garmin:webhook:healthSnapshot] Payload matched neither ping nor push schema`,
513
519
  );
514
- return { processed: 0, errors: [] };
520
+ return { processed: 0, errors: [], affectedUsers: [] };
515
521
  },
516
522
  });
517
523
 
@@ -553,7 +559,7 @@ export const handleGarminWebhookSleeps = action({
553
559
  console.warn(
554
560
  `[garmin:webhook:sleeps] Payload matched neither ping nor push schema`,
555
561
  );
556
- return { processed: 0, errors: [] };
562
+ return { processed: 0, errors: [], affectedUsers: [] };
557
563
  },
558
564
  });
559
565
 
@@ -595,7 +601,7 @@ export const handleGarminWebhookSkinTemp = action({
595
601
  console.warn(
596
602
  `[garmin:webhook:skinTemperature] Payload matched neither ping nor push schema`,
597
603
  );
598
- return { processed: 0, errors: [] };
604
+ return { processed: 0, errors: [], affectedUsers: [] };
599
605
  },
600
606
  });
601
607
 
@@ -637,7 +643,7 @@ export const handleGarminWebhookUserMetrics = action({
637
643
  console.warn(
638
644
  `[garmin:webhook:userMetrics] Payload matched neither ping nor push schema`,
639
645
  );
640
- return { processed: 0, errors: [] };
646
+ return { processed: 0, errors: [], affectedUsers: [] };
641
647
  },
642
648
  });
643
649
 
@@ -679,7 +685,7 @@ export const handleGarminWebhookMenstrualCycleTracking = action({
679
685
  console.warn(
680
686
  `[garmin:webhook:menstrualCycleTracking] Payload matched neither ping nor push schema`,
681
687
  );
682
- return { processed: 0, errors: [] };
688
+ return { processed: 0, errors: [], affectedUsers: [] };
683
689
  },
684
690
  });
685
691
 
@@ -721,7 +727,7 @@ export const handleGarminWebhookHRVSummary = action({
721
727
  console.warn(
722
728
  `[garmin:webhook:hrvSummary] Payload matched neither ping nor push schema`,
723
729
  );
724
- return { processed: 0, errors: [] };
730
+ return { processed: 0, errors: [], affectedUsers: [] };
725
731
  },
726
732
  });
727
733
 
@@ -763,7 +769,7 @@ export const handleGarminWebhookStress = action({
763
769
  console.warn(
764
770
  `[garmin:webhook:stressDetails] Payload matched neither ping nor push schema`,
765
771
  );
766
- return { processed: 0, errors: [] };
772
+ return { processed: 0, errors: [], affectedUsers: [] };
767
773
  },
768
774
  });
769
775
 
@@ -805,7 +811,7 @@ export const handleGarminWebhookPulseOx = action({
805
811
  console.warn(
806
812
  `[garmin:webhook:pulseOx] Payload matched neither ping nor push schema`,
807
813
  );
808
- return { processed: 0, errors: [] };
814
+ return { processed: 0, errors: [], affectedUsers: [] };
809
815
  },
810
816
  });
811
817
 
@@ -847,6 +853,6 @@ export const handleGarminWebhookRespiration = action({
847
853
  console.warn(
848
854
  `[garmin:webhook:respiration] Payload matched neither ping nor push schema`,
849
855
  );
850
- return { processed: 0, errors: [] };
856
+ return { processed: 0, errors: [], affectedUsers: [] };
851
857
  },
852
858
  });