@clipin/convex-wearables 0.0.1

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 (143) hide show
  1. package/LICENSE +203 -0
  2. package/README.md +616 -0
  3. package/dist/client/_generated/_ignore.d.ts +1 -0
  4. package/dist/client/_generated/_ignore.d.ts.map +1 -0
  5. package/dist/client/_generated/_ignore.js +4 -0
  6. package/dist/client/_generated/_ignore.js.map +1 -0
  7. package/dist/client/index.d.ts +244 -0
  8. package/dist/client/index.d.ts.map +1 -0
  9. package/dist/client/index.js +555 -0
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/client/types.d.ts +689 -0
  12. package/dist/client/types.d.ts.map +1 -0
  13. package/dist/client/types.js +112 -0
  14. package/dist/client/types.js.map +1 -0
  15. package/dist/component/_generated/_ignore.d.ts +1 -0
  16. package/dist/component/_generated/_ignore.d.ts.map +1 -0
  17. package/dist/component/_generated/_ignore.js +4 -0
  18. package/dist/component/_generated/_ignore.js.map +1 -0
  19. package/dist/component/_generated/api.d.ts +13 -0
  20. package/dist/component/_generated/api.d.ts.map +1 -0
  21. package/dist/component/_generated/api.js +14 -0
  22. package/dist/component/_generated/api.js.map +1 -0
  23. package/dist/component/_generated/dataModel.d.ts +28 -0
  24. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  25. package/dist/component/_generated/dataModel.js +11 -0
  26. package/dist/component/_generated/dataModel.js.map +1 -0
  27. package/dist/component/_generated/server.d.ts +23 -0
  28. package/dist/component/_generated/server.d.ts.map +1 -0
  29. package/dist/component/_generated/server.js +18 -0
  30. package/dist/component/_generated/server.js.map +1 -0
  31. package/dist/component/backfillJobs.d.ts +121 -0
  32. package/dist/component/backfillJobs.d.ts.map +1 -0
  33. package/dist/component/backfillJobs.js +233 -0
  34. package/dist/component/backfillJobs.js.map +1 -0
  35. package/dist/component/connections.d.ts +159 -0
  36. package/dist/component/connections.d.ts.map +1 -0
  37. package/dist/component/connections.js +288 -0
  38. package/dist/component/connections.js.map +1 -0
  39. package/dist/component/convex.config.d.ts +3 -0
  40. package/dist/component/convex.config.d.ts.map +1 -0
  41. package/dist/component/convex.config.js +6 -0
  42. package/dist/component/convex.config.js.map +1 -0
  43. package/dist/component/dataPoints.d.ts +81 -0
  44. package/dist/component/dataPoints.d.ts.map +1 -0
  45. package/dist/component/dataPoints.js +258 -0
  46. package/dist/component/dataPoints.js.map +1 -0
  47. package/dist/component/dataSources.d.ts +56 -0
  48. package/dist/component/dataSources.d.ts.map +1 -0
  49. package/dist/component/dataSources.js +95 -0
  50. package/dist/component/dataSources.js.map +1 -0
  51. package/dist/component/events.d.ts +203 -0
  52. package/dist/component/events.d.ts.map +1 -0
  53. package/dist/component/events.js +251 -0
  54. package/dist/component/events.js.map +1 -0
  55. package/dist/component/garminBackfill.d.ts +40 -0
  56. package/dist/component/garminBackfill.d.ts.map +1 -0
  57. package/dist/component/garminBackfill.js +296 -0
  58. package/dist/component/garminBackfill.js.map +1 -0
  59. package/dist/component/garminWebhooks.d.ts +17 -0
  60. package/dist/component/garminWebhooks.d.ts.map +1 -0
  61. package/dist/component/garminWebhooks.js +505 -0
  62. package/dist/component/garminWebhooks.js.map +1 -0
  63. package/dist/component/httpHandlers.d.ts +32 -0
  64. package/dist/component/httpHandlers.d.ts.map +1 -0
  65. package/dist/component/httpHandlers.js +131 -0
  66. package/dist/component/httpHandlers.js.map +1 -0
  67. package/dist/component/lifecycle.d.ts +12 -0
  68. package/dist/component/lifecycle.d.ts.map +1 -0
  69. package/dist/component/lifecycle.js +79 -0
  70. package/dist/component/lifecycle.js.map +1 -0
  71. package/dist/component/menstrualCycles.d.ts +98 -0
  72. package/dist/component/menstrualCycles.d.ts.map +1 -0
  73. package/dist/component/menstrualCycles.js +112 -0
  74. package/dist/component/menstrualCycles.js.map +1 -0
  75. package/dist/component/oauthActions.d.ts +52 -0
  76. package/dist/component/oauthActions.d.ts.map +1 -0
  77. package/dist/component/oauthActions.js +208 -0
  78. package/dist/component/oauthActions.js.map +1 -0
  79. package/dist/component/oauthStates.d.ts +47 -0
  80. package/dist/component/oauthStates.d.ts.map +1 -0
  81. package/dist/component/oauthStates.js +77 -0
  82. package/dist/component/oauthStates.js.map +1 -0
  83. package/dist/component/providerSettings.d.ts +15 -0
  84. package/dist/component/providerSettings.d.ts.map +1 -0
  85. package/dist/component/providerSettings.js +57 -0
  86. package/dist/component/providerSettings.js.map +1 -0
  87. package/dist/component/providers/garmin.d.ts +306 -0
  88. package/dist/component/providers/garmin.d.ts.map +1 -0
  89. package/dist/component/providers/garmin.js +675 -0
  90. package/dist/component/providers/garmin.js.map +1 -0
  91. package/dist/component/providers/oauth.d.ts +42 -0
  92. package/dist/component/providers/oauth.d.ts.map +1 -0
  93. package/dist/component/providers/oauth.js +181 -0
  94. package/dist/component/providers/oauth.js.map +1 -0
  95. package/dist/component/providers/polar.d.ts +6 -0
  96. package/dist/component/providers/polar.d.ts.map +1 -0
  97. package/dist/component/providers/polar.js +175 -0
  98. package/dist/component/providers/polar.js.map +1 -0
  99. package/dist/component/providers/registry.d.ts +14 -0
  100. package/dist/component/providers/registry.d.ts.map +1 -0
  101. package/dist/component/providers/registry.js +32 -0
  102. package/dist/component/providers/registry.js.map +1 -0
  103. package/dist/component/providers/strava.d.ts +45 -0
  104. package/dist/component/providers/strava.d.ts.map +1 -0
  105. package/dist/component/providers/strava.js +182 -0
  106. package/dist/component/providers/strava.js.map +1 -0
  107. package/dist/component/providers/suunto.d.ts +5 -0
  108. package/dist/component/providers/suunto.d.ts.map +1 -0
  109. package/dist/component/providers/suunto.js +502 -0
  110. package/dist/component/providers/suunto.js.map +1 -0
  111. package/dist/component/providers/types.d.ts +139 -0
  112. package/dist/component/providers/types.d.ts.map +1 -0
  113. package/dist/component/providers/types.js +5 -0
  114. package/dist/component/providers/types.js.map +1 -0
  115. package/dist/component/providers/whoop.d.ts +4 -0
  116. package/dist/component/providers/whoop.d.ts.map +1 -0
  117. package/dist/component/providers/whoop.js +439 -0
  118. package/dist/component/providers/whoop.js.map +1 -0
  119. package/dist/component/schema.d.ts +429 -0
  120. package/dist/component/schema.d.ts.map +1 -0
  121. package/dist/component/schema.js +282 -0
  122. package/dist/component/schema.js.map +1 -0
  123. package/dist/component/sdkPush.d.ts +143 -0
  124. package/dist/component/sdkPush.d.ts.map +1 -0
  125. package/dist/component/sdkPush.js +338 -0
  126. package/dist/component/sdkPush.js.map +1 -0
  127. package/dist/component/summaries.d.ts +129 -0
  128. package/dist/component/summaries.d.ts.map +1 -0
  129. package/dist/component/summaries.js +129 -0
  130. package/dist/component/summaries.js.map +1 -0
  131. package/dist/component/syncJobs.d.ts +142 -0
  132. package/dist/component/syncJobs.d.ts.map +1 -0
  133. package/dist/component/syncJobs.js +136 -0
  134. package/dist/component/syncJobs.js.map +1 -0
  135. package/dist/component/syncWorkflow.d.ts +99 -0
  136. package/dist/component/syncWorkflow.d.ts.map +1 -0
  137. package/dist/component/syncWorkflow.js +579 -0
  138. package/dist/component/syncWorkflow.js.map +1 -0
  139. package/dist/component/workflowManager.d.ts +3 -0
  140. package/dist/component/workflowManager.d.ts.map +1 -0
  141. package/dist/component/workflowManager.js +17 -0
  142. package/dist/component/workflowManager.js.map +1 -0
  143. package/package.json +84 -0
@@ -0,0 +1,251 @@
1
+ import { v } from "convex/values";
2
+ import { internalMutation, internalQuery, query } from "./_generated/server";
3
+ import { eventCategory } from "./schema";
4
+ // ---------------------------------------------------------------------------
5
+ // Queries
6
+ // ---------------------------------------------------------------------------
7
+ /**
8
+ * Get events (workouts or sleep) for a user with cursor-based pagination.
9
+ */
10
+ export const getEvents = query({
11
+ args: {
12
+ userId: v.string(),
13
+ category: eventCategory,
14
+ startDate: v.optional(v.number()),
15
+ endDate: v.optional(v.number()),
16
+ limit: v.optional(v.number()),
17
+ cursor: v.optional(v.string()),
18
+ },
19
+ returns: v.object({
20
+ events: v.array(v.any()),
21
+ nextCursor: v.union(v.string(), v.null()),
22
+ hasMore: v.boolean(),
23
+ }),
24
+ handler: async (ctx, args) => {
25
+ const limit = Math.min(args.limit ?? 20, 100);
26
+ const buildQuery = () => {
27
+ if (args.cursor) {
28
+ const cursorTime = Number(args.cursor);
29
+ return ctx.db
30
+ .query("events")
31
+ .withIndex("by_user_category_time", (idx) => idx
32
+ .eq("userId", args.userId)
33
+ .eq("category", args.category)
34
+ .lt("startDatetime", cursorTime))
35
+ .order("desc");
36
+ }
37
+ if (args.startDate !== undefined && args.endDate !== undefined) {
38
+ const { startDate, endDate } = args;
39
+ return ctx.db
40
+ .query("events")
41
+ .withIndex("by_user_category_time", (idx) => idx
42
+ .eq("userId", args.userId)
43
+ .eq("category", args.category)
44
+ .gte("startDatetime", startDate)
45
+ .lte("startDatetime", endDate))
46
+ .order("desc");
47
+ }
48
+ if (args.startDate !== undefined) {
49
+ const { startDate } = args;
50
+ return ctx.db
51
+ .query("events")
52
+ .withIndex("by_user_category_time", (idx) => idx
53
+ .eq("userId", args.userId)
54
+ .eq("category", args.category)
55
+ .gte("startDatetime", startDate))
56
+ .order("desc");
57
+ }
58
+ if (args.endDate !== undefined) {
59
+ const { endDate } = args;
60
+ return ctx.db
61
+ .query("events")
62
+ .withIndex("by_user_category_time", (idx) => idx
63
+ .eq("userId", args.userId)
64
+ .eq("category", args.category)
65
+ .lte("startDatetime", endDate))
66
+ .order("desc");
67
+ }
68
+ return ctx.db
69
+ .query("events")
70
+ .withIndex("by_user_category_time", (idx) => idx.eq("userId", args.userId).eq("category", args.category))
71
+ .order("desc");
72
+ };
73
+ const q = buildQuery();
74
+ const results = await q.take(limit + 1);
75
+ const hasMore = results.length > limit;
76
+ const events = hasMore ? results.slice(0, limit) : results;
77
+ const nextCursor = hasMore && events.length > 0 ? String(events[events.length - 1].startDatetime) : null;
78
+ return { events, nextCursor, hasMore };
79
+ },
80
+ });
81
+ /**
82
+ * Get a single event by its ID.
83
+ */
84
+ export const getEvent = query({
85
+ args: { eventId: v.id("events") },
86
+ returns: v.any(),
87
+ handler: async (ctx, args) => {
88
+ return await ctx.db.get(args.eventId);
89
+ },
90
+ });
91
+ /**
92
+ * Get an event by its external ID (for deduplication checks).
93
+ */
94
+ export const getByExternalId = internalQuery({
95
+ args: { externalId: v.string() },
96
+ returns: v.any(),
97
+ handler: async (ctx, args) => {
98
+ return await ctx.db
99
+ .query("events")
100
+ .withIndex("by_external_id", (idx) => idx.eq("externalId", args.externalId))
101
+ .first();
102
+ },
103
+ });
104
+ // ---------------------------------------------------------------------------
105
+ // Mutations
106
+ // ---------------------------------------------------------------------------
107
+ /**
108
+ * Store a single event (workout or sleep). Deduplicates by externalId if provided.
109
+ */
110
+ export const storeEvent = internalMutation({
111
+ args: {
112
+ dataSourceId: v.id("dataSources"),
113
+ userId: v.string(),
114
+ category: eventCategory,
115
+ type: v.optional(v.string()),
116
+ sourceName: v.optional(v.string()),
117
+ durationSeconds: v.optional(v.number()),
118
+ startDatetime: v.number(),
119
+ endDatetime: v.optional(v.number()),
120
+ externalId: v.optional(v.string()),
121
+ // Workout fields
122
+ heartRateMin: v.optional(v.number()),
123
+ heartRateMax: v.optional(v.number()),
124
+ heartRateAvg: v.optional(v.number()),
125
+ energyBurned: v.optional(v.number()),
126
+ distance: v.optional(v.number()),
127
+ stepsCount: v.optional(v.number()),
128
+ maxSpeed: v.optional(v.number()),
129
+ maxWatts: v.optional(v.number()),
130
+ movingTimeSeconds: v.optional(v.number()),
131
+ totalElevationGain: v.optional(v.number()),
132
+ averageSpeed: v.optional(v.number()),
133
+ averageWatts: v.optional(v.number()),
134
+ elevHigh: v.optional(v.number()),
135
+ elevLow: v.optional(v.number()),
136
+ // Sleep fields
137
+ sleepTotalDurationMinutes: v.optional(v.number()),
138
+ sleepTimeInBedMinutes: v.optional(v.number()),
139
+ sleepEfficiencyScore: v.optional(v.number()),
140
+ sleepDeepMinutes: v.optional(v.number()),
141
+ sleepRemMinutes: v.optional(v.number()),
142
+ sleepLightMinutes: v.optional(v.number()),
143
+ sleepAwakeMinutes: v.optional(v.number()),
144
+ isNap: v.optional(v.boolean()),
145
+ sleepStages: v.optional(v.array(v.object({
146
+ stage: v.string(),
147
+ startTime: v.number(),
148
+ endTime: v.number(),
149
+ }))),
150
+ },
151
+ returns: v.id("events"),
152
+ handler: async (ctx, args) => {
153
+ // Deduplicate by externalId
154
+ if (args.externalId) {
155
+ const existing = await ctx.db
156
+ .query("events")
157
+ .withIndex("by_external_id", (idx) => idx.eq("externalId", args.externalId))
158
+ .first();
159
+ if (existing) {
160
+ // Update existing record
161
+ await ctx.db.patch(existing._id, args);
162
+ return existing._id;
163
+ }
164
+ }
165
+ // Deduplicate by source + start + end
166
+ const existing = await ctx.db
167
+ .query("events")
168
+ .withIndex("by_source_start_end", (idx) => idx
169
+ .eq("dataSourceId", args.dataSourceId)
170
+ .eq("startDatetime", args.startDatetime)
171
+ .eq("endDatetime", args.endDatetime ?? undefined))
172
+ .first();
173
+ if (existing) {
174
+ await ctx.db.patch(existing._id, args);
175
+ return existing._id;
176
+ }
177
+ return await ctx.db.insert("events", args);
178
+ },
179
+ });
180
+ /**
181
+ * Store a batch of events. Used by sync workflows to write multiple events
182
+ * in a single mutation (must complete within 1 second).
183
+ */
184
+ export const storeEventBatch = internalMutation({
185
+ args: {
186
+ events: v.array(v.any()),
187
+ },
188
+ returns: v.array(v.id("events")),
189
+ handler: async (ctx, args) => {
190
+ const ids = [];
191
+ for (const event of args.events) {
192
+ // Deduplicate by externalId
193
+ if (event.externalId) {
194
+ const existing = await ctx.db
195
+ .query("events")
196
+ .withIndex("by_external_id", (idx) => idx.eq("externalId", event.externalId))
197
+ .first();
198
+ if (existing) {
199
+ await ctx.db.patch(existing._id, event);
200
+ ids.push(existing._id);
201
+ continue;
202
+ }
203
+ }
204
+ const existing = await ctx.db
205
+ .query("events")
206
+ .withIndex("by_source_start_end", (idx) => idx
207
+ .eq("dataSourceId", event.dataSourceId)
208
+ .eq("startDatetime", event.startDatetime)
209
+ .eq("endDatetime", event.endDatetime ?? undefined))
210
+ .first();
211
+ if (existing) {
212
+ await ctx.db.patch(existing._id, event);
213
+ ids.push(existing._id);
214
+ continue;
215
+ }
216
+ const id = await ctx.db.insert("events", event);
217
+ ids.push(id);
218
+ }
219
+ return ids;
220
+ },
221
+ });
222
+ export const deleteByExternalId = internalMutation({
223
+ args: {
224
+ externalId: v.string(),
225
+ },
226
+ handler: async (ctx, args) => {
227
+ const event = await ctx.db
228
+ .query("events")
229
+ .withIndex("by_external_id", (idx) => idx.eq("externalId", args.externalId))
230
+ .first();
231
+ if (event) {
232
+ await ctx.db.delete(event._id);
233
+ }
234
+ },
235
+ });
236
+ /**
237
+ * Delete all events for a user. Used for GDPR/account deletion.
238
+ */
239
+ export const deleteUserEvents = internalMutation({
240
+ args: { userId: v.string() },
241
+ handler: async (ctx, args) => {
242
+ const events = await ctx.db
243
+ .query("events")
244
+ .withIndex("by_user_category_time", (idx) => idx.eq("userId", args.userId))
245
+ .collect();
246
+ for (const event of events) {
247
+ await ctx.db.delete(event._id);
248
+ }
249
+ },
250
+ });
251
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/component/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ export declare const GARMIN_BACKFILL_TYPES: readonly ["activities", "activityDetails", "dailies", "epochs", "sleeps", "bodyComps", "hrv", "stressDetails", "respiration", "pulseOx", "bloodPressures", "userMetrics", "skinTemp", "healthSnapshot", "moveiq", "mct"];
2
+ export declare const requestGarminBackfill: import("convex/server").RegisteredMutation<"internal", {
3
+ connectionId: import("convex/values").GenericId<"connections">;
4
+ windowStart: number;
5
+ windowEnd: number;
6
+ }, Promise<{
7
+ backfillJobId: import("convex/values").GenericId<"backfillJobs">;
8
+ workflowId: string;
9
+ deduped: boolean;
10
+ }>>;
11
+ export declare const triggerGarminBackfillType: import("convex/server").RegisteredAction<"internal", {
12
+ dataType: string;
13
+ backfillJobId: import("convex/values").GenericId<"backfillJobs">;
14
+ }, Promise<void>>;
15
+ export declare const runGarminBackfill: import("convex/server").RegisteredMutation<"internal", {
16
+ fn: "You should not call this directly, call workflow.start instead";
17
+ args: {
18
+ backfillJobId: import("convex/values").GenericId<"backfillJobs">;
19
+ };
20
+ }, {
21
+ completedTypes: string[];
22
+ }>;
23
+ export declare const handleGarminBackfillComplete: import("convex/server").RegisteredMutation<"internal", {
24
+ workflowId: string;
25
+ result: any;
26
+ context: {
27
+ backfillJobId: import("convex/values").GenericId<"backfillJobs">;
28
+ };
29
+ }, Promise<void>>;
30
+ export declare const startGarminBackfill: import("convex/server").RegisteredAction<"public", {
31
+ clientId?: string | undefined;
32
+ clientSecret?: string | undefined;
33
+ lookbackDays?: number | undefined;
34
+ connectionId: import("convex/values").GenericId<"connections">;
35
+ }, Promise<{
36
+ backfillJobId: string;
37
+ workflowId: any;
38
+ deduped: any;
39
+ }>>;
40
+ //# sourceMappingURL=garminBackfill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"garminBackfill.d.ts","sourceRoot":"","sources":["../../src/component/garminBackfill.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,qBAAqB,0NAiBxB,CAAC;AAIX,eAAO,MAAM,qBAAqB;;;;;;;;GAkEhC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;iBAgEpC,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;EAkF5B,CAAC;AAEH,eAAO,MAAM,4BAA4B;;;;;;iBA0CvC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;GAkD9B,CAAC"}
@@ -0,0 +1,296 @@
1
+ import { v } from "convex/values";
2
+ import { internal } from "./_generated/api";
3
+ import { action, internalAction, internalMutation } from "./_generated/server";
4
+ import { backfillSignal } from "./backfillJobs";
5
+ import { triggerBackfill } from "./providers/garmin";
6
+ import { durableWorkflow } from "./workflowManager";
7
+ const DEFAULT_LOOKBACK_DAYS = 30;
8
+ const BACKFILL_TIMEOUT_MS = 5 * 60 * 1000;
9
+ export const GARMIN_BACKFILL_TYPES = [
10
+ "activities",
11
+ "activityDetails",
12
+ "dailies",
13
+ "epochs",
14
+ "sleeps",
15
+ "bodyComps",
16
+ "hrv",
17
+ "stressDetails",
18
+ "respiration",
19
+ "pulseOx",
20
+ "bloodPressures",
21
+ "userMetrics",
22
+ "skinTemp",
23
+ "healthSnapshot",
24
+ "moveiq",
25
+ "mct",
26
+ ];
27
+ export const requestGarminBackfill = internalMutation({
28
+ args: {
29
+ connectionId: v.id("connections"),
30
+ windowStart: v.number(),
31
+ windowEnd: v.number(),
32
+ },
33
+ returns: v.object({
34
+ backfillJobId: v.id("backfillJobs"),
35
+ workflowId: v.string(),
36
+ deduped: v.boolean(),
37
+ }),
38
+ handler: async (ctx, args) => {
39
+ const connection = await ctx.db.get(args.connectionId);
40
+ if (!connection) {
41
+ throw new Error(`Connection ${args.connectionId} not found`);
42
+ }
43
+ if (connection.provider !== "garmin") {
44
+ throw new Error("Garmin backfill is only supported for Garmin connections");
45
+ }
46
+ const existing = await ctx.db
47
+ .query("backfillJobs")
48
+ .withIndex("by_connection", (idx) => idx.eq("connectionId", args.connectionId))
49
+ .order("desc")
50
+ .first();
51
+ if (existing && (existing.status === "queued" || existing.status === "running")) {
52
+ return {
53
+ backfillJobId: existing._id,
54
+ workflowId: existing.workflowId ?? "",
55
+ deduped: true,
56
+ };
57
+ }
58
+ const backfillJobId = await ctx.db.insert("backfillJobs", {
59
+ connectionId: connection._id,
60
+ userId: connection.userId,
61
+ provider: "garmin",
62
+ dataType: "full",
63
+ status: "queued",
64
+ startedAt: Date.now(),
65
+ windowStart: args.windowStart,
66
+ windowEnd: args.windowEnd,
67
+ completedDataTypes: [],
68
+ currentAttempt: 0,
69
+ });
70
+ const workflowId = await durableWorkflow.start(ctx, internal.garminBackfill.runGarminBackfill, { backfillJobId }, {
71
+ startAsync: true,
72
+ onComplete: internal.garminBackfill.handleGarminBackfillComplete,
73
+ context: { backfillJobId },
74
+ });
75
+ await ctx.db.patch(backfillJobId, { workflowId });
76
+ return {
77
+ backfillJobId,
78
+ workflowId,
79
+ deduped: false,
80
+ };
81
+ },
82
+ });
83
+ export const triggerGarminBackfillType = internalAction({
84
+ args: {
85
+ backfillJobId: v.id("backfillJobs"),
86
+ dataType: v.string(),
87
+ },
88
+ handler: async (ctx, args) => {
89
+ if (!GARMIN_BACKFILL_TYPES.includes(args.dataType)) {
90
+ throw new Error(`Unsupported Garmin backfill type: ${args.dataType}`);
91
+ }
92
+ const backfillJob = await ctx.runQuery(internal.backfillJobs.getById, {
93
+ backfillJobId: args.backfillJobId,
94
+ });
95
+ if (!backfillJob) {
96
+ throw new Error(`Backfill job ${args.backfillJobId} not found`);
97
+ }
98
+ const connection = await ctx.runQuery(internal.connections.getById, {
99
+ connectionId: backfillJob.connectionId,
100
+ });
101
+ if (!connection) {
102
+ throw new Error(`Connection ${backfillJob.connectionId} not found`);
103
+ }
104
+ const credentials = await ctx.runQuery(internal.providerSettings.getCredentials, {
105
+ provider: "garmin",
106
+ });
107
+ if (!credentials) {
108
+ throw new Error("Missing stored Garmin credentials");
109
+ }
110
+ try {
111
+ const accessToken = await ctx.runAction(internal.oauthActions.ensureValidToken, {
112
+ connectionId: connection._id,
113
+ provider: "garmin",
114
+ accessToken: connection.accessToken ?? "",
115
+ refreshToken: connection.refreshToken,
116
+ tokenExpiresAt: connection.tokenExpiresAt,
117
+ clientId: credentials.clientId,
118
+ clientSecret: credentials.clientSecret,
119
+ subscriptionKey: credentials.subscriptionKey,
120
+ });
121
+ await triggerBackfill(accessToken, args.dataType, Math.floor((backfillJob.windowStart ?? Date.now()) / 1000), Math.floor((backfillJob.windowEnd ?? Date.now()) / 1000));
122
+ }
123
+ catch (error) {
124
+ const message = error instanceof Error ? error.message : String(error);
125
+ if (message.includes("Authorization expired") ||
126
+ message.includes("Token expired") ||
127
+ message.includes("Token refresh failed")) {
128
+ await ctx.runMutation(internal.connections.updateStatus, {
129
+ connectionId: connection._id,
130
+ status: "expired",
131
+ });
132
+ }
133
+ throw error;
134
+ }
135
+ },
136
+ });
137
+ export const runGarminBackfill = durableWorkflow.define({
138
+ args: {
139
+ backfillJobId: v.id("backfillJobs"),
140
+ },
141
+ returns: v.object({
142
+ completedTypes: v.array(v.string()),
143
+ }),
144
+ handler: async (step, args) => {
145
+ const job = await step.runQuery(internal.backfillJobs.getById, {
146
+ backfillJobId: args.backfillJobId,
147
+ });
148
+ if (!job) {
149
+ throw new Error(`Backfill job ${args.backfillJobId} not found`);
150
+ }
151
+ await step.runMutation(internal.backfillJobs.updateStatus, {
152
+ backfillJobId: args.backfillJobId,
153
+ status: "running",
154
+ workflowId: job.workflowId,
155
+ lastHeartbeatAt: Date.now(),
156
+ });
157
+ const completed = new Set(job.completedDataTypes ?? []);
158
+ for (const dataType of GARMIN_BACKFILL_TYPES) {
159
+ if (completed.has(dataType)) {
160
+ continue;
161
+ }
162
+ let completedType = false;
163
+ for (let attempt = 1; attempt <= 2; attempt++) {
164
+ const eventId = await step.runMutation(internal.backfillJobs.beginAwaitingType, {
165
+ backfillJobId: args.backfillJobId,
166
+ workflowId: step.workflowId,
167
+ dataType,
168
+ attempt,
169
+ });
170
+ await step.runAction(internal.garminBackfill.triggerGarminBackfillType, {
171
+ backfillJobId: args.backfillJobId,
172
+ dataType,
173
+ });
174
+ await step.runMutation(internal.backfillJobs.scheduleTimeout, {
175
+ backfillJobId: args.backfillJobId,
176
+ eventId,
177
+ dataType,
178
+ delayMs: BACKFILL_TIMEOUT_MS,
179
+ });
180
+ const signal = await step.awaitEvent({
181
+ id: eventId,
182
+ validator: backfillSignal,
183
+ });
184
+ if (signal.kind === "webhook") {
185
+ await step.runMutation(internal.backfillJobs.markTypeCompleted, {
186
+ backfillJobId: args.backfillJobId,
187
+ dataType,
188
+ });
189
+ completed.add(dataType);
190
+ completedType = true;
191
+ break;
192
+ }
193
+ }
194
+ if (!completedType) {
195
+ throw new Error(`Garmin backfill timed out for ${dataType}`);
196
+ }
197
+ await step.runMutation(internal.backfillJobs.updateStatus, {
198
+ backfillJobId: args.backfillJobId,
199
+ status: "running",
200
+ completedDataTypes: Array.from(completed),
201
+ lastHeartbeatAt: Date.now(),
202
+ });
203
+ }
204
+ return {
205
+ completedTypes: Array.from(completed),
206
+ };
207
+ },
208
+ });
209
+ export const handleGarminBackfillComplete = internalMutation({
210
+ args: {
211
+ workflowId: v.string(),
212
+ result: v.any(),
213
+ context: v.object({
214
+ backfillJobId: v.id("backfillJobs"),
215
+ }),
216
+ },
217
+ handler: async (ctx, args) => {
218
+ const job = await ctx.db.get(args.context.backfillJobId);
219
+ if (!job)
220
+ return;
221
+ if (args.result.kind === "success") {
222
+ const returnValue = (args.result.returnValue ?? {});
223
+ await ctx.db.patch(job._id, {
224
+ status: "completed",
225
+ completedAt: Date.now(),
226
+ workflowId: args.workflowId,
227
+ completedDataTypes: returnValue.completedTypes ?? job.completedDataTypes ?? [],
228
+ lastHeartbeatAt: Date.now(),
229
+ });
230
+ return;
231
+ }
232
+ if (args.result.kind === "canceled") {
233
+ await ctx.db.patch(job._id, {
234
+ status: "canceled",
235
+ completedAt: Date.now(),
236
+ workflowId: args.workflowId,
237
+ lastHeartbeatAt: Date.now(),
238
+ });
239
+ return;
240
+ }
241
+ await ctx.db.patch(job._id, {
242
+ status: "failed",
243
+ completedAt: Date.now(),
244
+ error: args.result.error,
245
+ workflowId: args.workflowId,
246
+ lastHeartbeatAt: Date.now(),
247
+ });
248
+ },
249
+ });
250
+ export const startGarminBackfill = action({
251
+ args: {
252
+ connectionId: v.id("connections"),
253
+ lookbackDays: v.optional(v.number()),
254
+ clientId: v.optional(v.string()),
255
+ clientSecret: v.optional(v.string()),
256
+ },
257
+ returns: v.object({
258
+ backfillJobId: v.string(),
259
+ workflowId: v.string(),
260
+ deduped: v.boolean(),
261
+ }),
262
+ handler: async (ctx, args) => {
263
+ const connection = await ctx.runQuery(internal.connections.getById, {
264
+ connectionId: args.connectionId,
265
+ });
266
+ if (!connection) {
267
+ throw new Error(`Connection ${args.connectionId} not found`);
268
+ }
269
+ if (connection.provider !== "garmin") {
270
+ throw new Error("Garmin backfill is only supported for Garmin connections");
271
+ }
272
+ if ((args.clientId && !args.clientSecret) || (!args.clientId && args.clientSecret)) {
273
+ throw new Error("clientId and clientSecret must be provided together");
274
+ }
275
+ if (args.clientId && args.clientSecret) {
276
+ await ctx.runMutation(internal.providerSettings.upsertCredentials, {
277
+ provider: "garmin",
278
+ clientId: args.clientId,
279
+ clientSecret: args.clientSecret,
280
+ });
281
+ }
282
+ const now = Date.now();
283
+ const lookbackMs = (args.lookbackDays ?? DEFAULT_LOOKBACK_DAYS) * 24 * 60 * 60 * 1000;
284
+ const result = await ctx.runMutation(internal.garminBackfill.requestGarminBackfill, {
285
+ connectionId: args.connectionId,
286
+ windowStart: now - lookbackMs,
287
+ windowEnd: now,
288
+ });
289
+ return {
290
+ backfillJobId: String(result.backfillJobId),
291
+ workflowId: result.workflowId,
292
+ deduped: result.deduped,
293
+ };
294
+ },
295
+ });
296
+ //# sourceMappingURL=garminBackfill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"garminBackfill.js","sourceRoot":"","sources":["../../src/component/garminBackfill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Garmin webhook processing.
3
+ *
4
+ * Garmin pushes data to registered webhook endpoints. This module
5
+ * provides actions that process the push payloads and store the data.
6
+ */
7
+ /**
8
+ * Process a Garmin push webhook payload.
9
+ *
10
+ * Handles activities, sleep, dailies, and extended wellness feeds.
11
+ */
12
+ export declare const processPushPayload: import("convex/server").RegisteredAction<"public", {
13
+ payloadJson?: string | undefined;
14
+ payload?: any;
15
+ garminClientId: string;
16
+ }, Promise<void>>;
17
+ //# sourceMappingURL=garminWebhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"garminWebhooks.d.ts","sourceRoot":"","sources":["../../src/component/garminWebhooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA0CH;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;iBA+X7B,CAAC"}