@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,258 @@
1
+ import { v } from "convex/values";
2
+ import { internalMutation, query } from "./_generated/server";
3
+ // ---------------------------------------------------------------------------
4
+ // Queries
5
+ // ---------------------------------------------------------------------------
6
+ /**
7
+ * Get time-series data points with cursor-based pagination.
8
+ * Uses the by_source_type_time index for efficient range queries.
9
+ */
10
+ export const getTimeSeries = query({
11
+ args: {
12
+ dataSourceId: v.id("dataSources"),
13
+ seriesType: v.string(),
14
+ startDate: v.number(),
15
+ endDate: v.number(),
16
+ limit: v.optional(v.number()),
17
+ cursor: v.optional(v.string()),
18
+ order: v.optional(v.union(v.literal("asc"), v.literal("desc"))),
19
+ },
20
+ returns: v.object({
21
+ points: v.array(v.object({
22
+ timestamp: v.number(),
23
+ value: v.number(),
24
+ })),
25
+ nextCursor: v.union(v.string(), v.null()),
26
+ hasMore: v.boolean(),
27
+ }),
28
+ handler: async (ctx, args) => {
29
+ const limit = Math.min(args.limit ?? 500, 2000);
30
+ const order = args.order ?? "asc";
31
+ const startDate = args.cursor ? Number(args.cursor) : args.startDate;
32
+ const results = await ctx.db
33
+ .query("dataPoints")
34
+ .withIndex("by_source_type_time", (idx) => order === "asc"
35
+ ? idx
36
+ .eq("dataSourceId", args.dataSourceId)
37
+ .eq("seriesType", args.seriesType)
38
+ .gte("recordedAt", startDate)
39
+ .lte("recordedAt", args.endDate)
40
+ : idx
41
+ .eq("dataSourceId", args.dataSourceId)
42
+ .eq("seriesType", args.seriesType)
43
+ .gte("recordedAt", args.startDate)
44
+ .lte("recordedAt", startDate))
45
+ .order(order)
46
+ .take(limit + 1);
47
+ const hasMore = results.length > limit;
48
+ const items = hasMore ? results.slice(0, limit) : results;
49
+ const points = items.map((dp) => ({
50
+ timestamp: dp.recordedAt,
51
+ value: dp.value,
52
+ }));
53
+ const nextCursor = hasMore && items.length > 0 ? String(items[items.length - 1].recordedAt) : null;
54
+ return { points, nextCursor, hasMore };
55
+ },
56
+ });
57
+ /**
58
+ * Get time-series data for a user across all their data sources for a given series type.
59
+ * This is a user-facing query that resolves data sources internally.
60
+ */
61
+ export const getTimeSeriesForUser = query({
62
+ args: {
63
+ userId: v.string(),
64
+ seriesType: v.string(),
65
+ startDate: v.number(),
66
+ endDate: v.number(),
67
+ limit: v.optional(v.number()),
68
+ },
69
+ returns: v.array(v.object({
70
+ timestamp: v.number(),
71
+ value: v.number(),
72
+ })),
73
+ handler: async (ctx, args) => {
74
+ const limit = Math.min(args.limit ?? 500, 2000);
75
+ // Get all data sources for this user
76
+ const sources = await ctx.db
77
+ .query("dataSources")
78
+ .withIndex("by_user_provider", (idx) => idx.eq("userId", args.userId))
79
+ .collect();
80
+ // Collect data from all sources (merge and sort)
81
+ const allPoints = [];
82
+ for (const source of sources) {
83
+ const points = await ctx.db
84
+ .query("dataPoints")
85
+ .withIndex("by_source_type_time", (idx) => idx
86
+ .eq("dataSourceId", source._id)
87
+ .eq("seriesType", args.seriesType)
88
+ .gte("recordedAt", args.startDate)
89
+ .lte("recordedAt", args.endDate))
90
+ .take(limit);
91
+ for (const dp of points) {
92
+ allPoints.push({ timestamp: dp.recordedAt, value: dp.value });
93
+ }
94
+ }
95
+ // Sort by timestamp and limit
96
+ allPoints.sort((a, b) => a.timestamp - b.timestamp);
97
+ return allPoints.slice(0, limit);
98
+ },
99
+ });
100
+ /**
101
+ * Get the latest data point for a user and series type.
102
+ */
103
+ export const getLatestDataPoint = query({
104
+ args: {
105
+ userId: v.string(),
106
+ seriesType: v.string(),
107
+ },
108
+ returns: v.union(v.object({
109
+ timestamp: v.number(),
110
+ value: v.number(),
111
+ provider: v.string(),
112
+ }), v.null()),
113
+ handler: async (ctx, args) => {
114
+ const sources = await ctx.db
115
+ .query("dataSources")
116
+ .withIndex("by_user_provider", (idx) => idx.eq("userId", args.userId))
117
+ .collect();
118
+ let latest = null;
119
+ for (const source of sources) {
120
+ const point = await ctx.db
121
+ .query("dataPoints")
122
+ .withIndex("by_source_type_time", (idx) => idx.eq("dataSourceId", source._id).eq("seriesType", args.seriesType))
123
+ .order("desc")
124
+ .first();
125
+ if (point && (latest === null || point.recordedAt > latest.timestamp)) {
126
+ latest = {
127
+ timestamp: point.recordedAt,
128
+ value: point.value,
129
+ provider: source.provider,
130
+ };
131
+ }
132
+ }
133
+ return latest;
134
+ },
135
+ });
136
+ /**
137
+ * Get all available series types for a user (i.e., types that have at least one data point).
138
+ */
139
+ export const getAvailableSeriesTypes = query({
140
+ args: { userId: v.string() },
141
+ returns: v.array(v.string()),
142
+ handler: async (ctx, args) => {
143
+ const sources = await ctx.db
144
+ .query("dataSources")
145
+ .withIndex("by_user_provider", (idx) => idx.eq("userId", args.userId))
146
+ .collect();
147
+ const types = new Set();
148
+ for (const source of sources) {
149
+ // Sample a few data points to discover types
150
+ // This is efficient because we only need one per type
151
+ const points = await ctx.db
152
+ .query("dataPoints")
153
+ .withIndex("by_source_type_time", (idx) => idx.eq("dataSourceId", source._id))
154
+ .take(200);
155
+ for (const point of points) {
156
+ types.add(point.seriesType);
157
+ }
158
+ }
159
+ return Array.from(types).sort();
160
+ },
161
+ });
162
+ // ---------------------------------------------------------------------------
163
+ // Mutations
164
+ // ---------------------------------------------------------------------------
165
+ /**
166
+ * Store a single data point. Deduplicates by (source, type, time).
167
+ */
168
+ export const storeDataPoint = internalMutation({
169
+ args: {
170
+ dataSourceId: v.id("dataSources"),
171
+ seriesType: v.string(),
172
+ recordedAt: v.number(),
173
+ value: v.number(),
174
+ externalId: v.optional(v.string()),
175
+ },
176
+ returns: v.id("dataPoints"),
177
+ handler: async (ctx, args) => {
178
+ // Deduplicate by (source, type, time)
179
+ const existing = await ctx.db
180
+ .query("dataPoints")
181
+ .withIndex("by_source_type_time", (idx) => idx
182
+ .eq("dataSourceId", args.dataSourceId)
183
+ .eq("seriesType", args.seriesType)
184
+ .eq("recordedAt", args.recordedAt))
185
+ .first();
186
+ if (existing) {
187
+ await ctx.db.patch(existing._id, { value: args.value });
188
+ return existing._id;
189
+ }
190
+ return await ctx.db.insert("dataPoints", args);
191
+ },
192
+ });
193
+ /**
194
+ * Store a batch of data points. Used by sync workflows.
195
+ * Must complete within 1 second — caller is responsible for batch sizing.
196
+ */
197
+ export const storeBatch = internalMutation({
198
+ args: {
199
+ dataSourceId: v.id("dataSources"),
200
+ seriesType: v.string(),
201
+ points: v.array(v.object({
202
+ recordedAt: v.number(),
203
+ value: v.number(),
204
+ externalId: v.optional(v.string()),
205
+ })),
206
+ },
207
+ returns: v.number(),
208
+ handler: async (ctx, args) => {
209
+ let count = 0;
210
+ for (const point of args.points) {
211
+ // Deduplicate by (source, type, time)
212
+ const existing = await ctx.db
213
+ .query("dataPoints")
214
+ .withIndex("by_source_type_time", (idx) => idx
215
+ .eq("dataSourceId", args.dataSourceId)
216
+ .eq("seriesType", args.seriesType)
217
+ .eq("recordedAt", point.recordedAt))
218
+ .first();
219
+ if (existing) {
220
+ await ctx.db.patch(existing._id, { value: point.value });
221
+ }
222
+ else {
223
+ await ctx.db.insert("dataPoints", {
224
+ dataSourceId: args.dataSourceId,
225
+ seriesType: args.seriesType,
226
+ recordedAt: point.recordedAt,
227
+ value: point.value,
228
+ externalId: point.externalId,
229
+ });
230
+ }
231
+ count++;
232
+ }
233
+ return count;
234
+ },
235
+ });
236
+ /**
237
+ * Delete all data points for a data source. Used during user/connection cleanup.
238
+ */
239
+ export const deleteByDataSource = internalMutation({
240
+ args: { dataSourceId: v.id("dataSources") },
241
+ handler: async (ctx, args) => {
242
+ // Delete in batches to avoid hitting limits
243
+ let batch = await ctx.db
244
+ .query("dataPoints")
245
+ .withIndex("by_source_type_time", (idx) => idx.eq("dataSourceId", args.dataSourceId))
246
+ .take(1000);
247
+ while (batch.length > 0) {
248
+ for (const dp of batch) {
249
+ await ctx.db.delete(dp._id);
250
+ }
251
+ batch = await ctx.db
252
+ .query("dataPoints")
253
+ .withIndex("by_source_type_time", (idx) => idx.eq("dataSourceId", args.dataSourceId))
254
+ .take(1000);
255
+ }
256
+ },
257
+ });
258
+ //# sourceMappingURL=dataPoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataPoints.js","sourceRoot":"","sources":["../../src/component/dataPoints.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Get all data sources for a user.
3
+ */
4
+ export declare const getByUser: import("convex/server").RegisteredQuery<"public", {
5
+ userId: string;
6
+ }, Promise<{
7
+ _id: import("convex/values").GenericId<"dataSources">;
8
+ _creationTime: number;
9
+ connectionId?: import("convex/values").GenericId<"connections"> | undefined;
10
+ deviceModel?: string | undefined;
11
+ softwareVersion?: string | undefined;
12
+ source?: string | undefined;
13
+ deviceType?: string | undefined;
14
+ originalSourceName?: string | undefined;
15
+ provider: "garmin" | "suunto" | "polar" | "whoop" | "strava" | "apple" | "samsung" | "google";
16
+ userId: string;
17
+ }[]>>;
18
+ /**
19
+ * Get data sources for a user + provider combination.
20
+ */
21
+ export declare const getByUserProvider: import("convex/server").RegisteredQuery<"public", {
22
+ provider: "garmin" | "suunto" | "polar" | "whoop" | "strava" | "apple" | "samsung" | "google";
23
+ userId: string;
24
+ }, Promise<{
25
+ _id: import("convex/values").GenericId<"dataSources">;
26
+ _creationTime: number;
27
+ connectionId?: import("convex/values").GenericId<"connections"> | undefined;
28
+ deviceModel?: string | undefined;
29
+ softwareVersion?: string | undefined;
30
+ source?: string | undefined;
31
+ deviceType?: string | undefined;
32
+ originalSourceName?: string | undefined;
33
+ provider: "garmin" | "suunto" | "polar" | "whoop" | "strava" | "apple" | "samsung" | "google";
34
+ userId: string;
35
+ }[]>>;
36
+ /**
37
+ * Get or create a data source. Used during data ingestion to ensure
38
+ * a data source exists for a given user/provider/device combination.
39
+ */
40
+ export declare const getOrCreate: import("convex/server").RegisteredMutation<"public", {
41
+ connectionId?: import("convex/values").GenericId<"connections"> | undefined;
42
+ deviceModel?: string | undefined;
43
+ softwareVersion?: string | undefined;
44
+ source?: string | undefined;
45
+ deviceType?: string | undefined;
46
+ originalSourceName?: string | undefined;
47
+ provider: "garmin" | "suunto" | "polar" | "whoop" | "strava" | "apple" | "samsung" | "google";
48
+ userId: string;
49
+ }, Promise<import("convex/values").GenericId<"dataSources">>>;
50
+ /**
51
+ * Delete all data sources for a user. Used during account deletion.
52
+ */
53
+ export declare const deleteByUser: import("convex/server").RegisteredMutation<"internal", {
54
+ userId: string;
55
+ }, Promise<void>>;
56
+ //# sourceMappingURL=dataSources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataSources.d.ts","sourceRoot":"","sources":["../../src/component/dataSources.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;KASpB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;KAc5B,CAAC;AAMH;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;6DA0CtB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,YAAY;;iBAYvB,CAAC"}
@@ -0,0 +1,95 @@
1
+ import { v } from "convex/values";
2
+ import { internalMutation, mutation, query } from "./_generated/server";
3
+ import { providerName } from "./schema";
4
+ // ---------------------------------------------------------------------------
5
+ // Queries
6
+ // ---------------------------------------------------------------------------
7
+ /**
8
+ * Get all data sources for a user.
9
+ */
10
+ export const getByUser = query({
11
+ args: { userId: v.string() },
12
+ returns: v.array(v.any()),
13
+ handler: async (ctx, args) => {
14
+ return await ctx.db
15
+ .query("dataSources")
16
+ .withIndex("by_user_provider", (idx) => idx.eq("userId", args.userId))
17
+ .collect();
18
+ },
19
+ });
20
+ /**
21
+ * Get data sources for a user + provider combination.
22
+ */
23
+ export const getByUserProvider = query({
24
+ args: {
25
+ userId: v.string(),
26
+ provider: providerName,
27
+ },
28
+ returns: v.array(v.any()),
29
+ handler: async (ctx, args) => {
30
+ return await ctx.db
31
+ .query("dataSources")
32
+ .withIndex("by_user_provider", (idx) => idx.eq("userId", args.userId).eq("provider", args.provider))
33
+ .collect();
34
+ },
35
+ });
36
+ // ---------------------------------------------------------------------------
37
+ // Mutations
38
+ // ---------------------------------------------------------------------------
39
+ /**
40
+ * Get or create a data source. Used during data ingestion to ensure
41
+ * a data source exists for a given user/provider/device combination.
42
+ */
43
+ export const getOrCreate = mutation({
44
+ args: {
45
+ userId: v.string(),
46
+ provider: providerName,
47
+ connectionId: v.optional(v.id("connections")),
48
+ deviceModel: v.optional(v.string()),
49
+ softwareVersion: v.optional(v.string()),
50
+ source: v.optional(v.string()),
51
+ deviceType: v.optional(v.string()),
52
+ originalSourceName: v.optional(v.string()),
53
+ },
54
+ returns: v.id("dataSources"),
55
+ handler: async (ctx, args) => {
56
+ // Look for existing data source matching this user/provider/device/source
57
+ const existing = await ctx.db
58
+ .query("dataSources")
59
+ .withIndex("by_user_provider_device", (idx) => idx
60
+ .eq("userId", args.userId)
61
+ .eq("provider", args.provider)
62
+ .eq("deviceModel", args.deviceModel ?? undefined)
63
+ .eq("source", args.source ?? undefined))
64
+ .first();
65
+ if (existing) {
66
+ // Update fields that may have changed
67
+ if (args.softwareVersion !== existing.softwareVersion ||
68
+ args.deviceType !== existing.deviceType) {
69
+ await ctx.db.patch(existing._id, {
70
+ softwareVersion: args.softwareVersion,
71
+ deviceType: args.deviceType,
72
+ connectionId: args.connectionId ?? existing.connectionId,
73
+ });
74
+ }
75
+ return existing._id;
76
+ }
77
+ return await ctx.db.insert("dataSources", args);
78
+ },
79
+ });
80
+ /**
81
+ * Delete all data sources for a user. Used during account deletion.
82
+ */
83
+ export const deleteByUser = internalMutation({
84
+ args: { userId: v.string() },
85
+ handler: async (ctx, args) => {
86
+ const sources = await ctx.db
87
+ .query("dataSources")
88
+ .withIndex("by_user_provider", (idx) => idx.eq("userId", args.userId))
89
+ .collect();
90
+ for (const source of sources) {
91
+ await ctx.db.delete(source._id);
92
+ }
93
+ },
94
+ });
95
+ //# sourceMappingURL=dataSources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataSources.js","sourceRoot":"","sources":["../../src/component/dataSources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,203 @@
1
+ import type { Id } from "./_generated/dataModel";
2
+ /**
3
+ * Get events (workouts or sleep) for a user with cursor-based pagination.
4
+ */
5
+ export declare const getEvents: import("convex/server").RegisteredQuery<"public", {
6
+ cursor?: string | undefined;
7
+ limit?: number | undefined;
8
+ startDate?: number | undefined;
9
+ endDate?: number | undefined;
10
+ category: "workout" | "sleep";
11
+ userId: string;
12
+ }, Promise<{
13
+ events: {
14
+ _id: import("convex/values").GenericId<"events">;
15
+ _creationTime: number;
16
+ type?: string | undefined;
17
+ sourceName?: string | undefined;
18
+ durationSeconds?: number | undefined;
19
+ endDatetime?: number | undefined;
20
+ externalId?: string | undefined;
21
+ heartRateMin?: number | undefined;
22
+ heartRateMax?: number | undefined;
23
+ heartRateAvg?: number | undefined;
24
+ energyBurned?: number | undefined;
25
+ distance?: number | undefined;
26
+ stepsCount?: number | undefined;
27
+ maxSpeed?: number | undefined;
28
+ maxWatts?: number | undefined;
29
+ movingTimeSeconds?: number | undefined;
30
+ totalElevationGain?: number | undefined;
31
+ averageSpeed?: number | undefined;
32
+ averageWatts?: number | undefined;
33
+ elevHigh?: number | undefined;
34
+ elevLow?: number | undefined;
35
+ sleepTotalDurationMinutes?: number | undefined;
36
+ sleepTimeInBedMinutes?: number | undefined;
37
+ sleepEfficiencyScore?: number | undefined;
38
+ sleepDeepMinutes?: number | undefined;
39
+ sleepRemMinutes?: number | undefined;
40
+ sleepLightMinutes?: number | undefined;
41
+ sleepAwakeMinutes?: number | undefined;
42
+ isNap?: boolean | undefined;
43
+ sleepStages?: {
44
+ stage: string;
45
+ startTime: number;
46
+ endTime: number;
47
+ }[] | undefined;
48
+ category: "workout" | "sleep";
49
+ startDatetime: number;
50
+ userId: string;
51
+ dataSourceId: import("convex/values").GenericId<"dataSources">;
52
+ }[];
53
+ nextCursor: string | null;
54
+ hasMore: boolean;
55
+ }>>;
56
+ /**
57
+ * Get a single event by its ID.
58
+ */
59
+ export declare const getEvent: import("convex/server").RegisteredQuery<"public", {
60
+ eventId: import("convex/values").GenericId<"events">;
61
+ }, Promise<{
62
+ _id: import("convex/values").GenericId<"events">;
63
+ _creationTime: number;
64
+ type?: string | undefined;
65
+ sourceName?: string | undefined;
66
+ durationSeconds?: number | undefined;
67
+ endDatetime?: number | undefined;
68
+ externalId?: string | undefined;
69
+ heartRateMin?: number | undefined;
70
+ heartRateMax?: number | undefined;
71
+ heartRateAvg?: number | undefined;
72
+ energyBurned?: number | undefined;
73
+ distance?: number | undefined;
74
+ stepsCount?: number | undefined;
75
+ maxSpeed?: number | undefined;
76
+ maxWatts?: number | undefined;
77
+ movingTimeSeconds?: number | undefined;
78
+ totalElevationGain?: number | undefined;
79
+ averageSpeed?: number | undefined;
80
+ averageWatts?: number | undefined;
81
+ elevHigh?: number | undefined;
82
+ elevLow?: number | undefined;
83
+ sleepTotalDurationMinutes?: number | undefined;
84
+ sleepTimeInBedMinutes?: number | undefined;
85
+ sleepEfficiencyScore?: number | undefined;
86
+ sleepDeepMinutes?: number | undefined;
87
+ sleepRemMinutes?: number | undefined;
88
+ sleepLightMinutes?: number | undefined;
89
+ sleepAwakeMinutes?: number | undefined;
90
+ isNap?: boolean | undefined;
91
+ sleepStages?: {
92
+ stage: string;
93
+ startTime: number;
94
+ endTime: number;
95
+ }[] | undefined;
96
+ category: "workout" | "sleep";
97
+ startDatetime: number;
98
+ userId: string;
99
+ dataSourceId: import("convex/values").GenericId<"dataSources">;
100
+ } | null>>;
101
+ /**
102
+ * Get an event by its external ID (for deduplication checks).
103
+ */
104
+ export declare const getByExternalId: import("convex/server").RegisteredQuery<"internal", {
105
+ externalId: string;
106
+ }, Promise<{
107
+ _id: import("convex/values").GenericId<"events">;
108
+ _creationTime: number;
109
+ type?: string | undefined;
110
+ sourceName?: string | undefined;
111
+ durationSeconds?: number | undefined;
112
+ endDatetime?: number | undefined;
113
+ externalId?: string | undefined;
114
+ heartRateMin?: number | undefined;
115
+ heartRateMax?: number | undefined;
116
+ heartRateAvg?: number | undefined;
117
+ energyBurned?: number | undefined;
118
+ distance?: number | undefined;
119
+ stepsCount?: number | undefined;
120
+ maxSpeed?: number | undefined;
121
+ maxWatts?: number | undefined;
122
+ movingTimeSeconds?: number | undefined;
123
+ totalElevationGain?: number | undefined;
124
+ averageSpeed?: number | undefined;
125
+ averageWatts?: number | undefined;
126
+ elevHigh?: number | undefined;
127
+ elevLow?: number | undefined;
128
+ sleepTotalDurationMinutes?: number | undefined;
129
+ sleepTimeInBedMinutes?: number | undefined;
130
+ sleepEfficiencyScore?: number | undefined;
131
+ sleepDeepMinutes?: number | undefined;
132
+ sleepRemMinutes?: number | undefined;
133
+ sleepLightMinutes?: number | undefined;
134
+ sleepAwakeMinutes?: number | undefined;
135
+ isNap?: boolean | undefined;
136
+ sleepStages?: {
137
+ stage: string;
138
+ startTime: number;
139
+ endTime: number;
140
+ }[] | undefined;
141
+ category: "workout" | "sleep";
142
+ startDatetime: number;
143
+ userId: string;
144
+ dataSourceId: import("convex/values").GenericId<"dataSources">;
145
+ } | null>>;
146
+ /**
147
+ * Store a single event (workout or sleep). Deduplicates by externalId if provided.
148
+ */
149
+ export declare const storeEvent: import("convex/server").RegisteredMutation<"internal", {
150
+ type?: string | undefined;
151
+ sourceName?: string | undefined;
152
+ durationSeconds?: number | undefined;
153
+ endDatetime?: number | undefined;
154
+ externalId?: string | undefined;
155
+ heartRateMin?: number | undefined;
156
+ heartRateMax?: number | undefined;
157
+ heartRateAvg?: number | undefined;
158
+ energyBurned?: number | undefined;
159
+ distance?: number | undefined;
160
+ stepsCount?: number | undefined;
161
+ maxSpeed?: number | undefined;
162
+ maxWatts?: number | undefined;
163
+ movingTimeSeconds?: number | undefined;
164
+ totalElevationGain?: number | undefined;
165
+ averageSpeed?: number | undefined;
166
+ averageWatts?: number | undefined;
167
+ elevHigh?: number | undefined;
168
+ elevLow?: number | undefined;
169
+ sleepTotalDurationMinutes?: number | undefined;
170
+ sleepTimeInBedMinutes?: number | undefined;
171
+ sleepEfficiencyScore?: number | undefined;
172
+ sleepDeepMinutes?: number | undefined;
173
+ sleepRemMinutes?: number | undefined;
174
+ sleepLightMinutes?: number | undefined;
175
+ sleepAwakeMinutes?: number | undefined;
176
+ isNap?: boolean | undefined;
177
+ sleepStages?: {
178
+ stage: string;
179
+ startTime: number;
180
+ endTime: number;
181
+ }[] | undefined;
182
+ category: "workout" | "sleep";
183
+ startDatetime: number;
184
+ userId: string;
185
+ dataSourceId: import("convex/values").GenericId<"dataSources">;
186
+ }, Promise<import("convex/values").GenericId<"events">>>;
187
+ /**
188
+ * Store a batch of events. Used by sync workflows to write multiple events
189
+ * in a single mutation (must complete within 1 second).
190
+ */
191
+ export declare const storeEventBatch: import("convex/server").RegisteredMutation<"internal", {
192
+ events: any[];
193
+ }, Promise<Id<"events">[]>>;
194
+ export declare const deleteByExternalId: import("convex/server").RegisteredMutation<"internal", {
195
+ externalId: string;
196
+ }, Promise<void>>;
197
+ /**
198
+ * Delete all events for a user. Used for GDPR/account deletion.
199
+ */
200
+ export declare const deleteUserEvents: import("convex/server").RegisteredMutation<"internal", {
201
+ userId: string;
202
+ }, Promise<void>>;
203
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/component/events.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,wBAAwB,CAAC;AAQjD;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsFpB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAMnB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAS1B,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wDA8ErB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe;;2BAuC1B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;iBAc7B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB;;iBAW3B,CAAC"}