@clipin/convex-wearables 0.2.0 → 0.3.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 +3 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +6 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/types.d.ts +13 -1
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client/types.js +1 -1
- package/dist/client/types.js.map +1 -1
- package/dist/component/garminBackfill.d.ts +9 -1
- package/dist/component/garminBackfill.d.ts.map +1 -1
- package/dist/component/garminBackfill.js +27 -6
- package/dist/component/garminBackfill.js.map +1 -1
- package/dist/component/garminWebhooks.d.ts +44 -0
- package/dist/component/garminWebhooks.d.ts.map +1 -1
- package/dist/component/garminWebhooks.js +248 -14
- package/dist/component/garminWebhooks.js.map +1 -1
- package/dist/component/oauthActions.d.ts.map +1 -1
- package/dist/component/oauthActions.js +5 -0
- package/dist/component/oauthActions.js.map +1 -1
- package/dist/component/providers/garmin.d.ts +4 -0
- package/dist/component/providers/garmin.d.ts.map +1 -1
- package/dist/component/providers/garmin.js +23 -8
- package/dist/component/providers/garmin.js.map +1 -1
- package/dist/component/schema.d.ts +27 -0
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +19 -0
- package/dist/component/schema.js.map +1 -1
- package/dist/component/sdkPush.d.ts +24 -0
- package/dist/component/sdkPush.d.ts.map +1 -1
- package/dist/component/sdkPush.js +101 -6
- package/dist/component/sdkPush.js.map +1 -1
- package/dist/component/syncWorkflow.d.ts.map +1 -1
- package/dist/component/syncWorkflow.js +5 -3
- package/dist/component/syncWorkflow.js.map +1 -1
- package/dist/test.d.ts +27 -0
- package/dist/test.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +13 -1
- package/src/client/types.ts +13 -1
- package/src/component/garminBackfill.ts +33 -6
- package/src/component/garminWebhooks.test.ts +112 -9
- package/src/component/garminWebhooks.ts +279 -14
- package/src/component/oauthActions.ts +6 -0
- package/src/component/providers/garmin.ts +36 -12
- package/src/component/schema.ts +25 -0
- package/src/component/sdkPush.test.ts +54 -0
- package/src/component/sdkPush.ts +120 -6
- package/src/component/syncWorkflow.ts +5 -3
package/src/component/sdkPush.ts
CHANGED
|
@@ -13,6 +13,14 @@ const MAX_DATA_POINTS_PER_REQUEST = 10000;
|
|
|
13
13
|
const MAX_SUMMARIES_PER_REQUEST = 1000;
|
|
14
14
|
const SERIES_TYPE_ALIASES = {
|
|
15
15
|
hrv_rmssd: "heart_rate_variability_rmssd",
|
|
16
|
+
POWER: "power",
|
|
17
|
+
power: "power",
|
|
18
|
+
SPEED: "speed",
|
|
19
|
+
speed: "speed",
|
|
20
|
+
CYCLING_PEDALING_CADENCE: "cadence",
|
|
21
|
+
cycling_pedaling_cadence: "cadence",
|
|
22
|
+
TOTAL_CALORIES_BURNED: "total_calories",
|
|
23
|
+
total_calories_burned: "total_calories",
|
|
16
24
|
} as const;
|
|
17
25
|
const validSeriesTypes = new Set(Object.keys(SERIES_TYPES));
|
|
18
26
|
|
|
@@ -22,6 +30,10 @@ const deviceMetadataValidator = v.object({
|
|
|
22
30
|
source: v.optional(v.string()),
|
|
23
31
|
deviceType: v.optional(v.string()),
|
|
24
32
|
originalSourceName: v.optional(v.string()),
|
|
33
|
+
appId: v.optional(v.string()),
|
|
34
|
+
app_id: v.optional(v.string()),
|
|
35
|
+
bundleIdentifier: v.optional(v.string()),
|
|
36
|
+
bundle_identifier: v.optional(v.string()),
|
|
25
37
|
});
|
|
26
38
|
|
|
27
39
|
const sourceMetadataValidator = v.object({
|
|
@@ -30,6 +42,10 @@ const sourceMetadataValidator = v.object({
|
|
|
30
42
|
source: v.optional(v.string()),
|
|
31
43
|
deviceType: v.optional(v.string()),
|
|
32
44
|
originalSourceName: v.optional(v.string()),
|
|
45
|
+
appId: v.optional(v.string()),
|
|
46
|
+
app_id: v.optional(v.string()),
|
|
47
|
+
bundleIdentifier: v.optional(v.string()),
|
|
48
|
+
bundle_identifier: v.optional(v.string()),
|
|
33
49
|
});
|
|
34
50
|
|
|
35
51
|
const sdkEventValidator = v.object({
|
|
@@ -76,6 +92,10 @@ const sdkEventValidator = v.object({
|
|
|
76
92
|
source: v.optional(v.string()),
|
|
77
93
|
deviceType: v.optional(v.string()),
|
|
78
94
|
originalSourceName: v.optional(v.string()),
|
|
95
|
+
appId: v.optional(v.string()),
|
|
96
|
+
app_id: v.optional(v.string()),
|
|
97
|
+
bundleIdentifier: v.optional(v.string()),
|
|
98
|
+
bundle_identifier: v.optional(v.string()),
|
|
79
99
|
});
|
|
80
100
|
|
|
81
101
|
const sdkDataPointValidator = v.object({
|
|
@@ -88,6 +108,10 @@ const sdkDataPointValidator = v.object({
|
|
|
88
108
|
source: v.optional(v.string()),
|
|
89
109
|
deviceType: v.optional(v.string()),
|
|
90
110
|
originalSourceName: v.optional(v.string()),
|
|
111
|
+
appId: v.optional(v.string()),
|
|
112
|
+
app_id: v.optional(v.string()),
|
|
113
|
+
bundleIdentifier: v.optional(v.string()),
|
|
114
|
+
bundle_identifier: v.optional(v.string()),
|
|
91
115
|
});
|
|
92
116
|
|
|
93
117
|
const sdkSummaryValidator = v.object({
|
|
@@ -95,6 +119,10 @@ const sdkSummaryValidator = v.object({
|
|
|
95
119
|
category: v.string(),
|
|
96
120
|
source: v.optional(v.string()),
|
|
97
121
|
originalSourceName: v.optional(v.string()),
|
|
122
|
+
appId: v.optional(v.string()),
|
|
123
|
+
app_id: v.optional(v.string()),
|
|
124
|
+
bundleIdentifier: v.optional(v.string()),
|
|
125
|
+
bundle_identifier: v.optional(v.string()),
|
|
98
126
|
totalSteps: v.optional(v.number()),
|
|
99
127
|
totalCalories: v.optional(v.number()),
|
|
100
128
|
activeCalories: v.optional(v.number()),
|
|
@@ -133,6 +161,10 @@ type SourceMetadata = {
|
|
|
133
161
|
source?: string;
|
|
134
162
|
deviceType?: string;
|
|
135
163
|
originalSourceName?: string;
|
|
164
|
+
appId?: string;
|
|
165
|
+
app_id?: string;
|
|
166
|
+
bundleIdentifier?: string;
|
|
167
|
+
bundle_identifier?: string;
|
|
136
168
|
};
|
|
137
169
|
|
|
138
170
|
type DataSourceCache = Map<string, Id<"dataSources">>;
|
|
@@ -158,7 +190,17 @@ function resolveSourceMetadata(
|
|
|
158
190
|
softwareVersion: item.softwareVersion ?? defaults?.softwareVersion,
|
|
159
191
|
source: item.source ?? defaults?.source,
|
|
160
192
|
deviceType: item.deviceType ?? defaults?.deviceType,
|
|
161
|
-
originalSourceName:
|
|
193
|
+
originalSourceName:
|
|
194
|
+
item.originalSourceName ??
|
|
195
|
+
item.appId ??
|
|
196
|
+
item.app_id ??
|
|
197
|
+
item.bundleIdentifier ??
|
|
198
|
+
item.bundle_identifier ??
|
|
199
|
+
defaults?.originalSourceName,
|
|
200
|
+
appId: item.appId ?? defaults?.appId,
|
|
201
|
+
app_id: item.app_id ?? defaults?.app_id,
|
|
202
|
+
bundleIdentifier: item.bundleIdentifier ?? defaults?.bundleIdentifier,
|
|
203
|
+
bundle_identifier: item.bundle_identifier ?? defaults?.bundle_identifier,
|
|
162
204
|
};
|
|
163
205
|
}
|
|
164
206
|
|
|
@@ -245,6 +287,10 @@ export const ingestNormalizedPayload = action({
|
|
|
245
287
|
source: event.source,
|
|
246
288
|
deviceType: event.deviceType,
|
|
247
289
|
originalSourceName: event.originalSourceName,
|
|
290
|
+
appId: event.appId,
|
|
291
|
+
app_id: event.app_id,
|
|
292
|
+
bundleIdentifier: event.bundleIdentifier,
|
|
293
|
+
bundle_identifier: event.bundle_identifier,
|
|
248
294
|
});
|
|
249
295
|
const dataSourceId = await ensureDataSource(
|
|
250
296
|
ctx,
|
|
@@ -261,7 +307,7 @@ export const ingestNormalizedPayload = action({
|
|
|
261
307
|
dataSourceId,
|
|
262
308
|
userId: args.userId,
|
|
263
309
|
category: event.category,
|
|
264
|
-
type: event.type,
|
|
310
|
+
type: event.category === "workout" ? normalizeWorkoutType(event.type) : event.type,
|
|
265
311
|
sourceName: event.sourceName ?? defaultSourceName(args.provider),
|
|
266
312
|
durationSeconds: event.durationSeconds,
|
|
267
313
|
startDatetime: event.startDatetime,
|
|
@@ -322,6 +368,10 @@ export const ingestNormalizedPayload = action({
|
|
|
322
368
|
source: point.source,
|
|
323
369
|
deviceType: point.deviceType,
|
|
324
370
|
originalSourceName: point.originalSourceName,
|
|
371
|
+
appId: point.appId,
|
|
372
|
+
app_id: point.app_id,
|
|
373
|
+
bundleIdentifier: point.bundleIdentifier,
|
|
374
|
+
bundle_identifier: point.bundle_identifier,
|
|
325
375
|
});
|
|
326
376
|
const dataSourceId = await ensureDataSource(
|
|
327
377
|
ctx,
|
|
@@ -360,12 +410,27 @@ export const ingestNormalizedPayload = action({
|
|
|
360
410
|
}
|
|
361
411
|
|
|
362
412
|
for (const summary of summaries) {
|
|
413
|
+
const {
|
|
414
|
+
appId,
|
|
415
|
+
app_id,
|
|
416
|
+
bundleIdentifier,
|
|
417
|
+
bundle_identifier,
|
|
418
|
+
originalSourceName,
|
|
419
|
+
source,
|
|
420
|
+
...summaryMetrics
|
|
421
|
+
} = summary;
|
|
363
422
|
await ctx.runMutation(internal.summaries.upsert, {
|
|
364
423
|
userId: args.userId,
|
|
365
424
|
provider: args.provider,
|
|
366
|
-
...
|
|
367
|
-
source:
|
|
368
|
-
originalSourceName:
|
|
425
|
+
...summaryMetrics,
|
|
426
|
+
source: source ?? defaultMetadata.source,
|
|
427
|
+
originalSourceName:
|
|
428
|
+
originalSourceName ??
|
|
429
|
+
appId ??
|
|
430
|
+
app_id ??
|
|
431
|
+
bundleIdentifier ??
|
|
432
|
+
bundle_identifier ??
|
|
433
|
+
defaultMetadata.originalSourceName,
|
|
369
434
|
});
|
|
370
435
|
}
|
|
371
436
|
|
|
@@ -390,6 +455,10 @@ function sourceMetadataFromDevice(
|
|
|
390
455
|
source?: string;
|
|
391
456
|
deviceType?: string;
|
|
392
457
|
originalSourceName?: string;
|
|
458
|
+
appId?: string;
|
|
459
|
+
app_id?: string;
|
|
460
|
+
bundleIdentifier?: string;
|
|
461
|
+
bundle_identifier?: string;
|
|
393
462
|
}
|
|
394
463
|
| undefined,
|
|
395
464
|
): SourceMetadata | undefined {
|
|
@@ -399,7 +468,16 @@ function sourceMetadataFromDevice(
|
|
|
399
468
|
softwareVersion: device.softwareVersion,
|
|
400
469
|
source: device.source,
|
|
401
470
|
deviceType: device.deviceType,
|
|
402
|
-
originalSourceName:
|
|
471
|
+
originalSourceName:
|
|
472
|
+
device.originalSourceName ??
|
|
473
|
+
device.appId ??
|
|
474
|
+
device.app_id ??
|
|
475
|
+
device.bundleIdentifier ??
|
|
476
|
+
device.bundle_identifier,
|
|
477
|
+
appId: device.appId,
|
|
478
|
+
app_id: device.app_id,
|
|
479
|
+
bundleIdentifier: device.bundleIdentifier,
|
|
480
|
+
bundle_identifier: device.bundle_identifier,
|
|
403
481
|
};
|
|
404
482
|
}
|
|
405
483
|
|
|
@@ -412,6 +490,42 @@ function normalizeSeriesType(seriesType: string): string {
|
|
|
412
490
|
return normalized;
|
|
413
491
|
}
|
|
414
492
|
|
|
493
|
+
const SDK_WORKOUT_TYPE_ALIASES: Record<string, string> = {
|
|
494
|
+
cycling_stationary: "indoor_cycling",
|
|
495
|
+
boot_camp: "cardio_training",
|
|
496
|
+
calisthenics: "strength_training",
|
|
497
|
+
dancing: "dance",
|
|
498
|
+
exercise_class: "cardio_training",
|
|
499
|
+
football_american: "american_football",
|
|
500
|
+
football_australian: "football",
|
|
501
|
+
frisbee_disc: "disc_sports",
|
|
502
|
+
guided_breathing: "meditation",
|
|
503
|
+
ice_hockey: "hockey",
|
|
504
|
+
ice_skating: "ice_skating",
|
|
505
|
+
paddling: "paddling",
|
|
506
|
+
paragliding: "paragliding",
|
|
507
|
+
rock_climbing: "rock_climbing",
|
|
508
|
+
roller_hockey: "hockey",
|
|
509
|
+
rowing_machine: "rowing_machine",
|
|
510
|
+
running_treadmill: "treadmill",
|
|
511
|
+
scuba_diving: "diving",
|
|
512
|
+
skiing: "alpine_skiing",
|
|
513
|
+
snowshoeing: "snowshoeing",
|
|
514
|
+
stair_climbing_machine: "stair_climbing",
|
|
515
|
+
stretching: "stretching",
|
|
516
|
+
swimming_open_water: "open_water_swimming",
|
|
517
|
+
swimming_pool: "pool_swimming",
|
|
518
|
+
weightlifting: "strength_training",
|
|
519
|
+
wheelchair: "wheelchair",
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
function normalizeWorkoutType(type: string | undefined): string | undefined {
|
|
523
|
+
if (type === undefined) return undefined;
|
|
524
|
+
const normalized = type.trim().toLowerCase();
|
|
525
|
+
if (!normalized) return undefined;
|
|
526
|
+
return SDK_WORKOUT_TYPE_ALIASES[normalized] ?? normalized;
|
|
527
|
+
}
|
|
528
|
+
|
|
415
529
|
function assertPayloadWithinLimits(args: {
|
|
416
530
|
events: unknown[];
|
|
417
531
|
dataPoints: unknown[];
|
|
@@ -525,9 +525,11 @@ export const runConnectionSync = durableWorkflow.define({
|
|
|
525
525
|
}
|
|
526
526
|
}
|
|
527
527
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
528
|
+
if (processed > 0) {
|
|
529
|
+
await step.runMutation(internal.connections.markSynced, {
|
|
530
|
+
connectionId: connection._id,
|
|
531
|
+
});
|
|
532
|
+
}
|
|
531
533
|
|
|
532
534
|
return { recordsProcessed: processed };
|
|
533
535
|
},
|