@nativesquare/soma 0.7.3 → 0.8.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 +83 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +131 -0
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/component.d.ts +159 -0
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/garmin.d.ts +190 -6
- package/dist/component/garmin.d.ts.map +1 -1
- package/dist/component/garmin.js +805 -25
- package/dist/component/garmin.js.map +1 -1
- package/dist/component/private.d.ts +18 -0
- 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 +88 -42
- 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 +87 -32
- 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/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 +40 -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 +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/activity.d.ts +7 -16
- package/dist/garmin/activity.d.ts.map +1 -1
- package/dist/garmin/activity.js +17 -23
- package/dist/garmin/activity.js.map +1 -1
- 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 -2
- package/dist/garmin/index.d.ts.map +1 -1
- package/dist/garmin/index.js +8 -1
- 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 +287 -5
- 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 +107 -28
- package/dist/validators.d.ts.map +1 -1
- package/package.json +133 -124
- package/src/client/index.ts +199 -0
- package/src/component/_generated/component.ts +161 -2
- package/src/component/garmin.ts +898 -26
- package/src/component/private.ts +21 -0
- package/src/component/public.ts +11 -2
- package/src/component/schema.ts +2 -1
- package/src/component/validators/connection.ts +2 -0
- package/src/component/validators/daily.ts +15 -0
- package/src/component/validators/plannedWorkout.ts +4 -0
- package/src/garmin/activity.test.ts +13 -21
- package/src/garmin/activity.ts +38 -45
- package/src/garmin/bloodPressure.ts +41 -0
- package/src/garmin/body.ts +1 -1
- package/src/garmin/client.ts +550 -71
- package/src/garmin/daily.ts +8 -4
- package/src/garmin/hrv.ts +57 -0
- package/src/garmin/index.ts +77 -7
- package/src/garmin/maps/activity-type.ts +2 -2
- package/src/garmin/menstruation.ts +14 -12
- package/src/garmin/pulseOx.ts +45 -0
- package/src/garmin/respiration.ts +55 -0
- package/src/garmin/skinTemp.ts +42 -0
- package/src/garmin/sleep.test.ts +5 -6
- package/src/garmin/sleep.ts +22 -16
- package/src/garmin/spec/wellness-api.json +1 -0
- package/src/garmin/stressDetails.ts +71 -0
- package/src/garmin/sync.ts +348 -5
- package/src/garmin/types.ts +88 -300
- package/src/garmin/userMetrics.ts +50 -0
- package/src/garmin/wellness-api.d.ts +5637 -0
package/src/garmin/sync.ts
CHANGED
|
@@ -11,6 +11,13 @@ import { transformDaily } from "./daily.js";
|
|
|
11
11
|
import { transformSleep } from "./sleep.js";
|
|
12
12
|
import { transformBody } from "./body.js";
|
|
13
13
|
import { transformMenstruation } from "./menstruation.js";
|
|
14
|
+
import { transformBloodPressure } from "./bloodPressure.js";
|
|
15
|
+
import { transformSkinTemp } from "./skinTemp.js";
|
|
16
|
+
import { transformUserMetrics } from "./userMetrics.js";
|
|
17
|
+
import { transformHRV } from "./hrv.js";
|
|
18
|
+
import { transformStressDetails } from "./stressDetails.js";
|
|
19
|
+
import { transformPulseOx } from "./pulseOx.js";
|
|
20
|
+
import { transformRespiration } from "./respiration.js";
|
|
14
21
|
|
|
15
22
|
// ─── Shared Types ────────────────────────────────────────────────────────────
|
|
16
23
|
|
|
@@ -34,6 +41,13 @@ export interface SyncAllResult {
|
|
|
34
41
|
sleep: SyncResult;
|
|
35
42
|
body: SyncResult;
|
|
36
43
|
menstruation: SyncResult;
|
|
44
|
+
bloodPressures: SyncResult;
|
|
45
|
+
skinTemp: SyncResult;
|
|
46
|
+
userMetrics: SyncResult;
|
|
47
|
+
hrv: SyncResult;
|
|
48
|
+
stressDetails: SyncResult;
|
|
49
|
+
pulseOx: SyncResult;
|
|
50
|
+
respiration: SyncResult;
|
|
37
51
|
}
|
|
38
52
|
|
|
39
53
|
// ─── Sync All ────────────────────────────────────────────────────────────────
|
|
@@ -45,15 +59,48 @@ export interface SyncAllResult {
|
|
|
45
59
|
* block the others.
|
|
46
60
|
*/
|
|
47
61
|
export async function syncAll(opts: SyncOptions): Promise<SyncAllResult> {
|
|
48
|
-
const [
|
|
62
|
+
const [
|
|
63
|
+
activities,
|
|
64
|
+
dailies,
|
|
65
|
+
sleep,
|
|
66
|
+
body,
|
|
67
|
+
menstruation,
|
|
68
|
+
bloodPressures,
|
|
69
|
+
skinTemp,
|
|
70
|
+
userMetrics,
|
|
71
|
+
hrv,
|
|
72
|
+
stressDetails,
|
|
73
|
+
pulseOx,
|
|
74
|
+
respiration,
|
|
75
|
+
] = await Promise.all([
|
|
49
76
|
syncActivities(opts),
|
|
50
77
|
syncDailies(opts),
|
|
51
78
|
syncSleep(opts),
|
|
52
79
|
syncBody(opts),
|
|
53
80
|
syncMenstruation(opts),
|
|
81
|
+
syncBloodPressures(opts),
|
|
82
|
+
syncSkinTemp(opts),
|
|
83
|
+
syncUserMetrics(opts),
|
|
84
|
+
syncHRV(opts),
|
|
85
|
+
syncStressDetails(opts),
|
|
86
|
+
syncPulseOx(opts),
|
|
87
|
+
syncRespiration(opts),
|
|
54
88
|
]);
|
|
55
89
|
|
|
56
|
-
return {
|
|
90
|
+
return {
|
|
91
|
+
activities,
|
|
92
|
+
dailies,
|
|
93
|
+
sleep,
|
|
94
|
+
body,
|
|
95
|
+
menstruation,
|
|
96
|
+
bloodPressures,
|
|
97
|
+
skinTemp,
|
|
98
|
+
userMetrics,
|
|
99
|
+
hrv,
|
|
100
|
+
stressDetails,
|
|
101
|
+
pulseOx,
|
|
102
|
+
respiration,
|
|
103
|
+
};
|
|
57
104
|
}
|
|
58
105
|
|
|
59
106
|
// ─── Activities ──────────────────────────────────────────────────────────────
|
|
@@ -105,7 +152,7 @@ export async function syncDailies(opts: SyncOptions): Promise<SyncResult> {
|
|
|
105
152
|
synced++;
|
|
106
153
|
} catch (err) {
|
|
107
154
|
errors.push({
|
|
108
|
-
id: daily.summaryId ?? daily.calendarDate,
|
|
155
|
+
id: daily.summaryId ?? daily.calendarDate ?? "unknown",
|
|
109
156
|
error: err instanceof Error ? err.message : String(err),
|
|
110
157
|
});
|
|
111
158
|
}
|
|
@@ -137,7 +184,7 @@ export async function syncSleep(opts: SyncOptions): Promise<SyncResult> {
|
|
|
137
184
|
synced++;
|
|
138
185
|
} catch (err) {
|
|
139
186
|
errors.push({
|
|
140
|
-
id: sleep.summaryId ?? sleep.calendarDate,
|
|
187
|
+
id: sleep.summaryId ?? sleep.calendarDate ?? "unknown",
|
|
141
188
|
error: err instanceof Error ? err.message : String(err),
|
|
142
189
|
});
|
|
143
190
|
}
|
|
@@ -207,7 +254,303 @@ export async function syncMenstruation(
|
|
|
207
254
|
synced++;
|
|
208
255
|
} catch (err) {
|
|
209
256
|
errors.push({
|
|
210
|
-
id: record.summaryId ?? record.
|
|
257
|
+
id: record.summaryId ?? record.periodStartDate ?? "unknown",
|
|
258
|
+
error: err instanceof Error ? err.message : String(err),
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
} catch (err) {
|
|
263
|
+
errors.push({
|
|
264
|
+
id: "fetch",
|
|
265
|
+
error: err instanceof Error ? err.message : String(err),
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return { synced, errors };
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// ─── Blood Pressures ────────────────────────────────────────────────────────
|
|
273
|
+
|
|
274
|
+
export async function syncBloodPressures(
|
|
275
|
+
opts: SyncOptions,
|
|
276
|
+
): Promise<SyncResult> {
|
|
277
|
+
const { client, soma, ctx, connectionId, userId, timeRange } = opts;
|
|
278
|
+
let synced = 0;
|
|
279
|
+
const errors: SyncResult["errors"] = [];
|
|
280
|
+
|
|
281
|
+
try {
|
|
282
|
+
const records = await client.getBloodPressures(timeRange);
|
|
283
|
+
|
|
284
|
+
for (const record of records) {
|
|
285
|
+
try {
|
|
286
|
+
const data = transformBloodPressure(record);
|
|
287
|
+
await soma.ingestBody(ctx, { connectionId, userId, ...data });
|
|
288
|
+
synced++;
|
|
289
|
+
} catch (err) {
|
|
290
|
+
errors.push({
|
|
291
|
+
id: record.summaryId ?? String(record.measurementTimeInSeconds),
|
|
292
|
+
error: err instanceof Error ? err.message : String(err),
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
} catch (err) {
|
|
297
|
+
errors.push({
|
|
298
|
+
id: "fetch",
|
|
299
|
+
error: err instanceof Error ? err.message : String(err),
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return { synced, errors };
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ─── Skin Temperature ───────────────────────────────────────────────────────
|
|
307
|
+
|
|
308
|
+
export async function syncSkinTemp(opts: SyncOptions): Promise<SyncResult> {
|
|
309
|
+
const { client, soma, ctx, connectionId, userId, timeRange } = opts;
|
|
310
|
+
let synced = 0;
|
|
311
|
+
const errors: SyncResult["errors"] = [];
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
const records = await client.getSkinTemperature(timeRange);
|
|
315
|
+
|
|
316
|
+
for (const record of records) {
|
|
317
|
+
try {
|
|
318
|
+
const data = transformSkinTemp(record);
|
|
319
|
+
await soma.ingestBody(ctx, { connectionId, userId, ...data });
|
|
320
|
+
synced++;
|
|
321
|
+
} catch (err) {
|
|
322
|
+
errors.push({
|
|
323
|
+
id: record.summaryId ?? record.calendarDate ?? "unknown",
|
|
324
|
+
error: err instanceof Error ? err.message : String(err),
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
} catch (err) {
|
|
329
|
+
errors.push({
|
|
330
|
+
id: "fetch",
|
|
331
|
+
error: err instanceof Error ? err.message : String(err),
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return { synced, errors };
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// ─── User Metrics ───────────────────────────────────────────────────────────
|
|
339
|
+
|
|
340
|
+
export async function syncUserMetrics(opts: SyncOptions): Promise<SyncResult> {
|
|
341
|
+
const { client, soma, ctx, connectionId, userId, timeRange } = opts;
|
|
342
|
+
let synced = 0;
|
|
343
|
+
const errors: SyncResult["errors"] = [];
|
|
344
|
+
|
|
345
|
+
try {
|
|
346
|
+
const records = await client.getUserMetrics(timeRange);
|
|
347
|
+
|
|
348
|
+
for (const record of records) {
|
|
349
|
+
try {
|
|
350
|
+
const data = transformUserMetrics(record);
|
|
351
|
+
await soma.ingestBody(ctx, { connectionId, userId, ...data });
|
|
352
|
+
synced++;
|
|
353
|
+
} catch (err) {
|
|
354
|
+
errors.push({
|
|
355
|
+
id: record.summaryId ?? record.calendarDate ?? "unknown",
|
|
356
|
+
error: err instanceof Error ? err.message : String(err),
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
} catch (err) {
|
|
361
|
+
errors.push({
|
|
362
|
+
id: "fetch",
|
|
363
|
+
error: err instanceof Error ? err.message : String(err),
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return { synced, errors };
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// ─── HRV (enriches Daily) ───────────────────────────────────────────────────
|
|
371
|
+
|
|
372
|
+
export async function syncHRV(opts: SyncOptions): Promise<SyncResult> {
|
|
373
|
+
const { client, soma, ctx, connectionId, userId, timeRange } = opts;
|
|
374
|
+
let synced = 0;
|
|
375
|
+
const errors: SyncResult["errors"] = [];
|
|
376
|
+
|
|
377
|
+
try {
|
|
378
|
+
const records = await client.getHRV(timeRange);
|
|
379
|
+
|
|
380
|
+
for (const record of records) {
|
|
381
|
+
try {
|
|
382
|
+
const data = transformHRV(record);
|
|
383
|
+
if (data.heart_rate_data) {
|
|
384
|
+
await soma.ingestDaily(ctx, {
|
|
385
|
+
connectionId,
|
|
386
|
+
userId,
|
|
387
|
+
metadata: {
|
|
388
|
+
start_time: new Date(
|
|
389
|
+
(record.startTimeInSeconds ?? 0) * 1000,
|
|
390
|
+
).toISOString(),
|
|
391
|
+
end_time: new Date(
|
|
392
|
+
((record.startTimeInSeconds ?? 0) +
|
|
393
|
+
(record.durationInSeconds ?? 86400)) *
|
|
394
|
+
1000,
|
|
395
|
+
).toISOString(),
|
|
396
|
+
upload_type: 1,
|
|
397
|
+
},
|
|
398
|
+
heart_rate_data: data.heart_rate_data,
|
|
399
|
+
});
|
|
400
|
+
synced++;
|
|
401
|
+
}
|
|
402
|
+
} catch (err) {
|
|
403
|
+
errors.push({
|
|
404
|
+
id: record.summaryId ?? record.calendarDate ?? "unknown",
|
|
405
|
+
error: err instanceof Error ? err.message : String(err),
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
} catch (err) {
|
|
410
|
+
errors.push({
|
|
411
|
+
id: "fetch",
|
|
412
|
+
error: err instanceof Error ? err.message : String(err),
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return { synced, errors };
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// ─── Stress Details (enriches Daily) ────────────────────────────────────────
|
|
420
|
+
|
|
421
|
+
export async function syncStressDetails(
|
|
422
|
+
opts: SyncOptions,
|
|
423
|
+
): Promise<SyncResult> {
|
|
424
|
+
const { client, soma, ctx, connectionId, userId, timeRange } = opts;
|
|
425
|
+
let synced = 0;
|
|
426
|
+
const errors: SyncResult["errors"] = [];
|
|
427
|
+
|
|
428
|
+
try {
|
|
429
|
+
const records = await client.getStressDetails(timeRange);
|
|
430
|
+
|
|
431
|
+
for (const record of records) {
|
|
432
|
+
try {
|
|
433
|
+
const data = transformStressDetails(record);
|
|
434
|
+
if (data.stress_data) {
|
|
435
|
+
await soma.ingestDaily(ctx, {
|
|
436
|
+
connectionId,
|
|
437
|
+
userId,
|
|
438
|
+
metadata: {
|
|
439
|
+
start_time: new Date(
|
|
440
|
+
(record.startTimeInSeconds ?? 0) * 1000,
|
|
441
|
+
).toISOString(),
|
|
442
|
+
end_time: new Date(
|
|
443
|
+
((record.startTimeInSeconds ?? 0) +
|
|
444
|
+
(record.durationInSeconds ?? 86400)) *
|
|
445
|
+
1000,
|
|
446
|
+
).toISOString(),
|
|
447
|
+
upload_type: 1,
|
|
448
|
+
},
|
|
449
|
+
stress_data: data.stress_data,
|
|
450
|
+
});
|
|
451
|
+
synced++;
|
|
452
|
+
}
|
|
453
|
+
} catch (err) {
|
|
454
|
+
errors.push({
|
|
455
|
+
id: record.summaryId ?? record.calendarDate ?? "unknown",
|
|
456
|
+
error: err instanceof Error ? err.message : String(err),
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
} catch (err) {
|
|
461
|
+
errors.push({
|
|
462
|
+
id: "fetch",
|
|
463
|
+
error: err instanceof Error ? err.message : String(err),
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
return { synced, errors };
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// ─── Pulse Ox (enriches Daily) ──────────────────────────────────────────────
|
|
471
|
+
|
|
472
|
+
export async function syncPulseOx(opts: SyncOptions): Promise<SyncResult> {
|
|
473
|
+
const { client, soma, ctx, connectionId, userId, timeRange } = opts;
|
|
474
|
+
let synced = 0;
|
|
475
|
+
const errors: SyncResult["errors"] = [];
|
|
476
|
+
|
|
477
|
+
try {
|
|
478
|
+
const records = await client.getPulseOx(timeRange);
|
|
479
|
+
|
|
480
|
+
for (const record of records) {
|
|
481
|
+
try {
|
|
482
|
+
const data = transformPulseOx(record);
|
|
483
|
+
if (data.oxygen_data) {
|
|
484
|
+
await soma.ingestDaily(ctx, {
|
|
485
|
+
connectionId,
|
|
486
|
+
userId,
|
|
487
|
+
metadata: {
|
|
488
|
+
start_time: new Date(
|
|
489
|
+
(record.startTimeInSeconds ?? 0) * 1000,
|
|
490
|
+
).toISOString(),
|
|
491
|
+
end_time: new Date(
|
|
492
|
+
((record.startTimeInSeconds ?? 0) +
|
|
493
|
+
(record.durationInSeconds ?? 86400)) *
|
|
494
|
+
1000,
|
|
495
|
+
).toISOString(),
|
|
496
|
+
upload_type: 1,
|
|
497
|
+
},
|
|
498
|
+
oxygen_data: data.oxygen_data,
|
|
499
|
+
});
|
|
500
|
+
synced++;
|
|
501
|
+
}
|
|
502
|
+
} catch (err) {
|
|
503
|
+
errors.push({
|
|
504
|
+
id: record.summaryId ?? record.calendarDate ?? "unknown",
|
|
505
|
+
error: err instanceof Error ? err.message : String(err),
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
} catch (err) {
|
|
510
|
+
errors.push({
|
|
511
|
+
id: "fetch",
|
|
512
|
+
error: err instanceof Error ? err.message : String(err),
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
return { synced, errors };
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// ─── Respiration (enriches Daily) ───────────────────────────────────────────
|
|
520
|
+
|
|
521
|
+
export async function syncRespiration(opts: SyncOptions): Promise<SyncResult> {
|
|
522
|
+
const { client, soma, ctx, connectionId, userId, timeRange } = opts;
|
|
523
|
+
let synced = 0;
|
|
524
|
+
const errors: SyncResult["errors"] = [];
|
|
525
|
+
|
|
526
|
+
try {
|
|
527
|
+
const records = await client.getRespiration(timeRange);
|
|
528
|
+
|
|
529
|
+
for (const record of records) {
|
|
530
|
+
try {
|
|
531
|
+
const data = transformRespiration(record);
|
|
532
|
+
if (data.respiration_data) {
|
|
533
|
+
await soma.ingestDaily(ctx, {
|
|
534
|
+
connectionId,
|
|
535
|
+
userId,
|
|
536
|
+
metadata: {
|
|
537
|
+
start_time: new Date(
|
|
538
|
+
(record.startTimeInSeconds ?? 0) * 1000,
|
|
539
|
+
).toISOString(),
|
|
540
|
+
end_time: new Date(
|
|
541
|
+
((record.startTimeInSeconds ?? 0) +
|
|
542
|
+
(record.durationInSeconds ?? 86400)) *
|
|
543
|
+
1000,
|
|
544
|
+
).toISOString(),
|
|
545
|
+
upload_type: 1,
|
|
546
|
+
},
|
|
547
|
+
respiration_data: data.respiration_data,
|
|
548
|
+
});
|
|
549
|
+
synced++;
|
|
550
|
+
}
|
|
551
|
+
} catch (err) {
|
|
552
|
+
errors.push({
|
|
553
|
+
id: record.summaryId ?? "unknown",
|
|
211
554
|
error: err instanceof Error ? err.message : String(err),
|
|
212
555
|
});
|
|
213
556
|
}
|