@zykeco/sync-server 0.4.0 → 0.6.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.
Files changed (69) hide show
  1. package/dist/app.d.ts +4 -0
  2. package/dist/app.js +56 -0
  3. package/dist/app.js.map +1 -0
  4. package/dist/db/schema.d.ts +1009 -0
  5. package/dist/db/schema.js +80 -1
  6. package/dist/db/schema.js.map +1 -1
  7. package/dist/env.d.ts +6 -0
  8. package/dist/env.js +9 -1
  9. package/dist/env.js.map +1 -1
  10. package/dist/index.js +2 -23
  11. package/dist/index.js.map +1 -1
  12. package/dist/mcp/metric-types.d.ts +2 -0
  13. package/dist/mcp/metric-types.js +42 -0
  14. package/dist/mcp/metric-types.js.map +1 -0
  15. package/dist/mcp/oauth.d.ts +41 -0
  16. package/dist/mcp/oauth.js +90 -0
  17. package/dist/mcp/oauth.js.map +1 -0
  18. package/dist/mcp/server.d.ts +35 -0
  19. package/dist/mcp/server.js +94 -0
  20. package/dist/mcp/server.js.map +1 -0
  21. package/dist/mcp/timezones.d.ts +17 -0
  22. package/dist/mcp/timezones.js +32 -0
  23. package/dist/mcp/timezones.js.map +1 -0
  24. package/dist/mcp/tools.d.ts +4 -0
  25. package/dist/mcp/tools.js +236 -0
  26. package/dist/mcp/tools.js.map +1 -0
  27. package/dist/mcp/transforms.d.ts +14 -0
  28. package/dist/mcp/transforms.js +45 -0
  29. package/dist/mcp/transforms.js.map +1 -0
  30. package/dist/routes/daily-stress-burden.d.ts +3 -0
  31. package/dist/routes/daily-stress-burden.js +24 -0
  32. package/dist/routes/daily-stress-burden.js.map +1 -0
  33. package/dist/routes/heart-rate-minute.d.ts +3 -0
  34. package/dist/routes/heart-rate-minute.js +24 -0
  35. package/dist/routes/heart-rate-minute.js.map +1 -0
  36. package/dist/routes/hr-zone-history.d.ts +3 -0
  37. package/dist/routes/hr-zone-history.js +24 -0
  38. package/dist/routes/hr-zone-history.js.map +1 -0
  39. package/dist/routes/mcp.d.ts +9 -0
  40. package/dist/routes/mcp.js +96 -0
  41. package/dist/routes/mcp.js.map +1 -0
  42. package/dist/routes/user-profile.d.ts +3 -0
  43. package/dist/routes/user-profile.js +24 -0
  44. package/dist/routes/user-profile.js.map +1 -0
  45. package/dist/routes/user-timezones.d.ts +3 -0
  46. package/dist/routes/user-timezones.js +24 -0
  47. package/dist/routes/user-timezones.js.map +1 -0
  48. package/dist/routes/wipe.d.ts +6 -1
  49. package/dist/routes/wipe.js +16 -2
  50. package/dist/routes/wipe.js.map +1 -1
  51. package/dist/stores/daily-stress-burden.d.ts +3 -0
  52. package/dist/stores/daily-stress-burden.js +58 -0
  53. package/dist/stores/daily-stress-burden.js.map +1 -0
  54. package/dist/stores/heart-rate-minute.d.ts +3 -0
  55. package/dist/stores/heart-rate-minute.js +48 -0
  56. package/dist/stores/heart-rate-minute.js.map +1 -0
  57. package/dist/stores/hr-zone-history.d.ts +3 -0
  58. package/dist/stores/hr-zone-history.js +49 -0
  59. package/dist/stores/hr-zone-history.js.map +1 -0
  60. package/dist/stores/user-profile.d.ts +3 -0
  61. package/dist/stores/user-profile.js +76 -0
  62. package/dist/stores/user-profile.js.map +1 -0
  63. package/dist/stores/user-timezones.d.ts +3 -0
  64. package/dist/stores/user-timezones.js +43 -0
  65. package/dist/stores/user-timezones.js.map +1 -0
  66. package/drizzle/0001_sweet_firebird.sql +78 -0
  67. package/drizzle/meta/0001_snapshot.json +733 -0
  68. package/drizzle/meta/_journal.json +7 -0
  69. package/package.json +4 -4
@@ -0,0 +1,236 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { and, asc, desc, eq, gt, gte, lte } from 'drizzle-orm';
3
+ import { dailyMetrics, dailyStressBurden, heartRateMinute, hrZoneHistory, sleepSessions, userProfile, userTimezones, weeklyMetrics, } from '../db/schema.js';
4
+ import { inferValueType } from './metric-types.js';
5
+ import { formatHmsFromSeconds, formatTzIso } from './transforms.js';
6
+ const Limit = Type.Optional(Type.Integer({ minimum: 1, maximum: 500, default: 100 }));
7
+ const IsoDate = Type.String({ pattern: '^\\d{4}-\\d{2}-\\d{2}$' });
8
+ const UnixMs = Type.Integer({ minimum: 0 });
9
+ function tzIso(resolver, utcMs) {
10
+ const row = resolver.resolveAt(utcMs);
11
+ if (!row)
12
+ return null;
13
+ return formatTzIso(utcMs, row.utcOffsetMinutes);
14
+ }
15
+ function applyLimit(n) {
16
+ if (n === undefined)
17
+ return 100;
18
+ return Math.min(Math.max(1, n), 500);
19
+ }
20
+ function and$(...parts) {
21
+ const filtered = parts.filter((p) => p !== undefined);
22
+ if (filtered.length === 0)
23
+ return undefined;
24
+ if (filtered.length === 1)
25
+ return filtered[0];
26
+ return and(...filtered);
27
+ }
28
+ export function buildTools(db, tz) {
29
+ return [
30
+ {
31
+ name: 'list_user_timezones',
32
+ description: 'List user timezone history entries (initial / travel / DST). Each row records the timezone that became active at `effectiveFrom` (UTC ms).',
33
+ inputSchema: Type.Object({
34
+ since: Type.Optional(UnixMs),
35
+ until: Type.Optional(UnixMs),
36
+ limit: Limit,
37
+ }, { additionalProperties: false }),
38
+ async handler(args) {
39
+ await tz.reload();
40
+ const where = and$(args.since !== undefined ? gte(userTimezones.effectiveFrom, args.since) : undefined, args.until !== undefined ? lte(userTimezones.effectiveFrom, args.until) : undefined);
41
+ const q = db.select().from(userTimezones).limit(applyLimit(args.limit));
42
+ const rows = where
43
+ ? await q.where(where).orderBy(desc(userTimezones.effectiveFrom))
44
+ : await q.orderBy(desc(userTimezones.effectiveFrom));
45
+ return { rows };
46
+ },
47
+ },
48
+ {
49
+ name: 'get_user_profile',
50
+ description: 'Return the singleton user profile row, or null if none has been synced.',
51
+ inputSchema: Type.Object({}, { additionalProperties: false }),
52
+ async handler() {
53
+ const rows = await db.select().from(userProfile).where(eq(userProfile.id, 1)).limit(1);
54
+ return { profile: rows[0] ?? null };
55
+ },
56
+ },
57
+ {
58
+ name: 'list_daily_metrics',
59
+ description: 'List daily metrics with a `valueType` annotation inferred from the metric key (e.g. sleep_optimum_s → seconds).',
60
+ inputSchema: Type.Object({
61
+ isoDateFrom: Type.Optional(IsoDate),
62
+ isoDateTo: Type.Optional(IsoDate),
63
+ metricKey: Type.Optional(Type.String({ minLength: 1, maxLength: 64 })),
64
+ limit: Limit,
65
+ }, { additionalProperties: false }),
66
+ async handler(args) {
67
+ const where = and$(args.isoDateFrom ? gte(dailyMetrics.isoDate, args.isoDateFrom) : undefined, args.isoDateTo ? lte(dailyMetrics.isoDate, args.isoDateTo) : undefined, args.metricKey ? eq(dailyMetrics.metricKey, args.metricKey) : undefined);
68
+ const q = db
69
+ .select()
70
+ .from(dailyMetrics)
71
+ .orderBy(desc(dailyMetrics.isoDate), asc(dailyMetrics.metricKey))
72
+ .limit(applyLimit(args.limit));
73
+ const rows = where ? await q.where(where) : await q;
74
+ return {
75
+ rows: rows.map((r) => ({ ...r, valueType: inferValueType(r.metricKey) })),
76
+ };
77
+ },
78
+ },
79
+ {
80
+ name: 'list_weekly_metrics',
81
+ description: 'List weekly metrics with `valueType` annotations.',
82
+ inputSchema: Type.Object({
83
+ weekStartFrom: Type.Optional(IsoDate),
84
+ weekStartTo: Type.Optional(IsoDate),
85
+ metricKey: Type.Optional(Type.String({ minLength: 1, maxLength: 64 })),
86
+ limit: Limit,
87
+ }, { additionalProperties: false }),
88
+ async handler(args) {
89
+ const where = and$(args.weekStartFrom ? gte(weeklyMetrics.weekStartIsoDate, args.weekStartFrom) : undefined, args.weekStartTo ? lte(weeklyMetrics.weekStartIsoDate, args.weekStartTo) : undefined, args.metricKey ? eq(weeklyMetrics.metricKey, args.metricKey) : undefined);
90
+ const q = db
91
+ .select()
92
+ .from(weeklyMetrics)
93
+ .orderBy(desc(weeklyMetrics.weekStartIsoDate), asc(weeklyMetrics.metricKey))
94
+ .limit(applyLimit(args.limit));
95
+ const rows = where ? await q.where(where) : await q;
96
+ return {
97
+ rows: rows.map((r) => ({ ...r, valueType: inferValueType(r.metricKey) })),
98
+ };
99
+ },
100
+ },
101
+ {
102
+ name: 'list_daily_stress_burden',
103
+ description: 'List daily stress burden summaries. `peakScoreTz` is the offset-aware ISO string of `peakScoreUtc`.',
104
+ inputSchema: Type.Object({
105
+ isoDateFrom: Type.Optional(IsoDate),
106
+ isoDateTo: Type.Optional(IsoDate),
107
+ limit: Limit,
108
+ }, { additionalProperties: false }),
109
+ async handler(args) {
110
+ await tz.reload();
111
+ const where = and$(args.isoDateFrom ? gte(dailyStressBurden.isoDate, args.isoDateFrom) : undefined, args.isoDateTo ? lte(dailyStressBurden.isoDate, args.isoDateTo) : undefined);
112
+ const q = db
113
+ .select()
114
+ .from(dailyStressBurden)
115
+ .orderBy(desc(dailyStressBurden.isoDate))
116
+ .limit(applyLimit(args.limit));
117
+ const rows = where ? await q.where(where) : await q;
118
+ return {
119
+ rows: rows.map((r) => ({ ...r, peakScoreTz: tzIso(tz, r.peakScoreUtc) })),
120
+ };
121
+ },
122
+ },
123
+ {
124
+ name: 'list_heart_rate_minute',
125
+ description: 'List minute-aggregated heart rate rows. `minuteStartTz` is the offset-aware ISO string of `minuteStartUtc`. Use cursor pagination for large windows.',
126
+ inputSchema: Type.Object({
127
+ fromUtcMs: Type.Optional(UnixMs),
128
+ toUtcMs: Type.Optional(UnixMs),
129
+ deviceId: Type.Optional(Type.Integer()),
130
+ cursor: Type.Optional(UnixMs),
131
+ limit: Limit,
132
+ }, { additionalProperties: false }),
133
+ async handler(args) {
134
+ await tz.reload();
135
+ const lim = applyLimit(args.limit);
136
+ const where = and$(args.fromUtcMs !== undefined
137
+ ? gte(heartRateMinute.minuteStartUtc, args.fromUtcMs)
138
+ : undefined, args.toUtcMs !== undefined
139
+ ? lte(heartRateMinute.minuteStartUtc, args.toUtcMs)
140
+ : undefined, args.deviceId !== undefined ? eq(heartRateMinute.deviceId, args.deviceId) : undefined, args.cursor !== undefined ? gt(heartRateMinute.minuteStartUtc, args.cursor) : undefined);
141
+ const q = db
142
+ .select()
143
+ .from(heartRateMinute)
144
+ .orderBy(asc(heartRateMinute.minuteStartUtc))
145
+ .limit(lim);
146
+ const rows = where ? await q.where(where) : await q;
147
+ const decorated = rows.map((r) => ({ ...r, minuteStartTz: tzIso(tz, r.minuteStartUtc) }));
148
+ const last = rows[rows.length - 1];
149
+ const nextCursor = rows.length === lim && last ? last.minuteStartUtc : null;
150
+ return { rows: decorated, nextCursor };
151
+ },
152
+ },
153
+ {
154
+ name: 'list_sleep_sessions',
155
+ description: 'List sleep sessions with timezone-aware timestamps (sleepOnsetTz, wakeTimeTz, cycle startTz/endTz) and human-readable durations (wasoR, restorativeSleepR, sleepDeficitR as hh:mm:ss).',
156
+ inputSchema: Type.Object({
157
+ isoDateFrom: Type.Optional(IsoDate),
158
+ isoDateTo: Type.Optional(IsoDate),
159
+ limit: Limit,
160
+ }, { additionalProperties: false }),
161
+ async handler(args) {
162
+ await tz.reload();
163
+ const where = and$(args.isoDateFrom ? gte(sleepSessions.isoDate, args.isoDateFrom) : undefined, args.isoDateTo ? lte(sleepSessions.isoDate, args.isoDateTo) : undefined);
164
+ const q = db
165
+ .select()
166
+ .from(sleepSessions)
167
+ .orderBy(desc(sleepSessions.isoDate))
168
+ .limit(applyLimit(args.limit));
169
+ const rows = where ? await q.where(where) : await q;
170
+ return { rows: rows.map((r) => decorateSleepSession(r, tz)) };
171
+ },
172
+ },
173
+ {
174
+ name: 'list_hr_zone_history',
175
+ description: 'List HR zone boundary history. Each row records the bpm lower bounds for zones 1..5 effective from `effectiveFromIsoDate`.',
176
+ inputSchema: Type.Object({
177
+ effectiveFromDate: Type.Optional(IsoDate),
178
+ limit: Limit,
179
+ }, { additionalProperties: false }),
180
+ async handler(args) {
181
+ const where = args.effectiveFromDate
182
+ ? gte(hrZoneHistory.effectiveFromIsoDate, args.effectiveFromDate)
183
+ : undefined;
184
+ const q = db
185
+ .select()
186
+ .from(hrZoneHistory)
187
+ .orderBy(desc(hrZoneHistory.effectiveFromIsoDate))
188
+ .limit(applyLimit(args.limit));
189
+ const rows = where ? await q.where(where) : await q;
190
+ return { rows };
191
+ },
192
+ },
193
+ ];
194
+ }
195
+ /**
196
+ * Decorate a sleep session row with timezone-aware timestamps and
197
+ * human-readable duration strings. The mobile schema deliberately stores the
198
+ * domain shape as opaque JSON, so we narrow defensively per field.
199
+ */
200
+ function decorateSleepSession(row, tz) {
201
+ const payload = row.payload ?? {};
202
+ const decoratedPayload = { ...payload };
203
+ const sleepOnsetS = numberOrNull(payload.sleepOnsetS);
204
+ const wakeTimeS = numberOrNull(payload.wakeTimeS);
205
+ const wasoS = numberOrNull(payload.wasoS);
206
+ const restorativeSleepS = numberOrNull(payload.restorativeSleepS);
207
+ const sleepDeficitS = numberOrNull(payload.sleepDeficitS);
208
+ if (sleepOnsetS !== null)
209
+ decoratedPayload.sleepOnsetTz = tzIso(tz, sleepOnsetS * 1000);
210
+ if (wakeTimeS !== null)
211
+ decoratedPayload.wakeTimeTz = tzIso(tz, wakeTimeS * 1000);
212
+ if (wasoS !== null)
213
+ decoratedPayload.wasoR = formatHmsFromSeconds(wasoS);
214
+ if (restorativeSleepS !== null)
215
+ decoratedPayload.restorativeSleepR = formatHmsFromSeconds(restorativeSleepS);
216
+ if (sleepDeficitS !== null)
217
+ decoratedPayload.sleepDeficitR = formatHmsFromSeconds(sleepDeficitS);
218
+ const cycles = Array.isArray(payload.cycles) ? payload.cycles : [];
219
+ decoratedPayload.cycles = cycles.map((c) => {
220
+ if (!c || typeof c !== 'object')
221
+ return c;
222
+ const cycle = c;
223
+ const startS = numberOrNull(cycle.startS);
224
+ const endS = numberOrNull(cycle.endS);
225
+ return {
226
+ ...cycle,
227
+ ...(startS !== null ? { startTz: tzIso(tz, startS * 1000) } : {}),
228
+ ...(endS !== null ? { endTz: tzIso(tz, endS * 1000) } : {}),
229
+ };
230
+ });
231
+ return { ...row, payload: decoratedPayload };
232
+ }
233
+ function numberOrNull(v) {
234
+ return typeof v === 'number' && Number.isFinite(v) ? v : null;
235
+ }
236
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Format a UTC instant as an ISO 8601 string with a timezone offset attached.
3
+ *
4
+ * formatTzIso(1716115262000, 120) === '2024-05-19T12:01:02+02:00'
5
+ *
6
+ * Seconds precision only — sub-second is intentionally dropped because none of
7
+ * the source timestamps carry it meaningfully.
8
+ */
9
+ export declare function formatTzIso(utcMs: number, offsetMinutes: number): string;
10
+ /**
11
+ * Format a signed duration in seconds as `hh:mm:ss` (or `-hh:mm:ss`). Supports
12
+ * durations larger than 24h — hours are not modulo'd.
13
+ */
14
+ export declare function formatHmsFromSeconds(totalSeconds: number): string;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Format a UTC instant as an ISO 8601 string with a timezone offset attached.
3
+ *
4
+ * formatTzIso(1716115262000, 120) === '2024-05-19T12:01:02+02:00'
5
+ *
6
+ * Seconds precision only — sub-second is intentionally dropped because none of
7
+ * the source timestamps carry it meaningfully.
8
+ */
9
+ export function formatTzIso(utcMs, offsetMinutes) {
10
+ if (!Number.isFinite(utcMs) || !Number.isFinite(offsetMinutes)) {
11
+ throw new Error(`formatTzIso: non-finite input (${utcMs}, ${offsetMinutes})`);
12
+ }
13
+ const shifted = new Date(utcMs + offsetMinutes * 60_000);
14
+ const yyyy = shifted.getUTCFullYear().toString().padStart(4, '0');
15
+ const mm = (shifted.getUTCMonth() + 1).toString().padStart(2, '0');
16
+ const dd = shifted.getUTCDate().toString().padStart(2, '0');
17
+ const HH = shifted.getUTCHours().toString().padStart(2, '0');
18
+ const MM = shifted.getUTCMinutes().toString().padStart(2, '0');
19
+ const SS = shifted.getUTCSeconds().toString().padStart(2, '0');
20
+ const sign = offsetMinutes >= 0 ? '+' : '-';
21
+ const abs = Math.abs(offsetMinutes);
22
+ const offH = Math.floor(abs / 60)
23
+ .toString()
24
+ .padStart(2, '0');
25
+ const offM = (abs % 60).toString().padStart(2, '0');
26
+ return `${yyyy}-${mm}-${dd}T${HH}:${MM}:${SS}${sign}${offH}:${offM}`;
27
+ }
28
+ /**
29
+ * Format a signed duration in seconds as `hh:mm:ss` (or `-hh:mm:ss`). Supports
30
+ * durations larger than 24h — hours are not modulo'd.
31
+ */
32
+ export function formatHmsFromSeconds(totalSeconds) {
33
+ if (!Number.isFinite(totalSeconds)) {
34
+ throw new Error(`formatHmsFromSeconds: non-finite input (${totalSeconds})`);
35
+ }
36
+ const sign = totalSeconds < 0 ? '-' : '';
37
+ const abs = Math.floor(Math.abs(totalSeconds));
38
+ const h = Math.floor(abs / 3600);
39
+ const m = Math.floor((abs % 3600) / 60);
40
+ const s = abs % 60;
41
+ return `${sign}${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s
42
+ .toString()
43
+ .padStart(2, '0')}`;
44
+ }
45
+ //# sourceMappingURL=transforms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transforms.js","sourceRoot":"","sources":["../../src/mcp/transforms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AuthConfig, DailyStressBurdenStore } from '@zykeco/server-core';
2
+ import { Hono } from 'hono';
3
+ export declare function dailyStressBurdenRoutes(store: DailyStressBurdenStore, auth: AuthConfig): Hono;
@@ -0,0 +1,24 @@
1
+ import { DailyStressBurdensBatchWrite, DeletionsBatchWrite } from '@zykeco/sync-protocol';
2
+ import { Hono } from 'hono';
3
+ import { requireAuth } from './auth.js';
4
+ import { parseJsonBody } from './validate.js';
5
+ export function dailyStressBurdenRoutes(store, auth) {
6
+ const app = new Hono();
7
+ app.post('/batch', requireAuth('write', auth), async (c) => {
8
+ const body = await parseJsonBody(c, DailyStressBurdensBatchWrite);
9
+ if (body instanceof Response)
10
+ return body;
11
+ const serverNowMs = Date.now();
12
+ const stored = await store.upsertBatch(body.rows, serverNowMs);
13
+ return c.json({ stored, serverNowMs });
14
+ });
15
+ app.post('/delete', requireAuth('write', auth), async (c) => {
16
+ const body = await parseJsonBody(c, DeletionsBatchWrite);
17
+ if (body instanceof Response)
18
+ return body;
19
+ const deleted = await store.deleteBatch(body.ids);
20
+ return c.json({ deleted, serverNowMs: Date.now() });
21
+ });
22
+ return app;
23
+ }
24
+ //# sourceMappingURL=daily-stress-burden.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-stress-burden.js","sourceRoot":"","sources":["../../src/routes/daily-stress-burden.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,UAAU,uBAAuB,CAAC,KAA6B,EAAE,IAAgB;IACrF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACzD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,EAAE,4BAA4B,CAAC,CAAC;QAClE,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC/D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1D,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACzD,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AuthConfig, HeartRateMinuteStore } from '@zykeco/server-core';
2
+ import { Hono } from 'hono';
3
+ export declare function heartRateMinuteRoutes(store: HeartRateMinuteStore, auth: AuthConfig): Hono;
@@ -0,0 +1,24 @@
1
+ import { DeletionsBatchWrite, HeartRateMinutesBatchWrite } from '@zykeco/sync-protocol';
2
+ import { Hono } from 'hono';
3
+ import { requireAuth } from './auth.js';
4
+ import { parseJsonBody } from './validate.js';
5
+ export function heartRateMinuteRoutes(store, auth) {
6
+ const app = new Hono();
7
+ app.post('/batch', requireAuth('write', auth), async (c) => {
8
+ const body = await parseJsonBody(c, HeartRateMinutesBatchWrite);
9
+ if (body instanceof Response)
10
+ return body;
11
+ const serverNowMs = Date.now();
12
+ const stored = await store.upsertBatch(body.rows, serverNowMs);
13
+ return c.json({ stored, serverNowMs });
14
+ });
15
+ app.post('/delete', requireAuth('write', auth), async (c) => {
16
+ const body = await parseJsonBody(c, DeletionsBatchWrite);
17
+ if (body instanceof Response)
18
+ return body;
19
+ const deleted = await store.deleteBatch(body.ids);
20
+ return c.json({ deleted, serverNowMs: Date.now() });
21
+ });
22
+ return app;
23
+ }
24
+ //# sourceMappingURL=heart-rate-minute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heart-rate-minute.js","sourceRoot":"","sources":["../../src/routes/heart-rate-minute.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,UAAU,qBAAqB,CAAC,KAA2B,EAAE,IAAgB;IACjF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACzD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,EAAE,0BAA0B,CAAC,CAAC;QAChE,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC/D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1D,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACzD,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AuthConfig, HrZoneHistoryStore } from '@zykeco/server-core';
2
+ import { Hono } from 'hono';
3
+ export declare function hrZoneHistoryRoutes(store: HrZoneHistoryStore, auth: AuthConfig): Hono;
@@ -0,0 +1,24 @@
1
+ import { DeletionsBatchWrite, HrZoneHistoriesBatchWrite } from '@zykeco/sync-protocol';
2
+ import { Hono } from 'hono';
3
+ import { requireAuth } from './auth.js';
4
+ import { parseJsonBody } from './validate.js';
5
+ export function hrZoneHistoryRoutes(store, auth) {
6
+ const app = new Hono();
7
+ app.post('/batch', requireAuth('write', auth), async (c) => {
8
+ const body = await parseJsonBody(c, HrZoneHistoriesBatchWrite);
9
+ if (body instanceof Response)
10
+ return body;
11
+ const serverNowMs = Date.now();
12
+ const stored = await store.upsertBatch(body.rows, serverNowMs);
13
+ return c.json({ stored, serverNowMs });
14
+ });
15
+ app.post('/delete', requireAuth('write', auth), async (c) => {
16
+ const body = await parseJsonBody(c, DeletionsBatchWrite);
17
+ if (body instanceof Response)
18
+ return body;
19
+ const deleted = await store.deleteBatch(body.ids);
20
+ return c.json({ deleted, serverNowMs: Date.now() });
21
+ });
22
+ return app;
23
+ }
24
+ //# sourceMappingURL=hr-zone-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hr-zone-history.js","sourceRoot":"","sources":["../../src/routes/hr-zone-history.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,UAAU,mBAAmB,CAAC,KAAyB,EAAE,IAAgB;IAC7E,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACzD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,EAAE,yBAAyB,CAAC,CAAC;QAC/D,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC/D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1D,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACzD,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Hono } from 'hono';
2
+ import type { Env, McpEnv } from '../env.js';
3
+ import type { Db } from '../db/client.js';
4
+ export interface McpDeps {
5
+ db: Db;
6
+ env: Env;
7
+ mcp: McpEnv;
8
+ }
9
+ export declare function mcpRoutes(deps: McpDeps): Hono;
@@ -0,0 +1,96 @@
1
+ import { Hono } from 'hono';
2
+ import { grantClientCredentials, verifyToken } from '../mcp/oauth.js';
3
+ import { createMcpServer } from '../mcp/server.js';
4
+ import { buildTools } from '../mcp/tools.js';
5
+ import { createTimezoneResolver } from '../mcp/timezones.js';
6
+ export function mcpRoutes(deps) {
7
+ const { db, env, mcp } = deps;
8
+ const tz = createTimezoneResolver(db);
9
+ const server = createMcpServer(buildTools(db, tz));
10
+ const app = new Hono();
11
+ // OAuth: client_credentials grant.
12
+ app.post('/oauth/token', async (c) => {
13
+ let params;
14
+ const ct = c.req.header('content-type') ?? '';
15
+ try {
16
+ if (ct.includes('application/x-www-form-urlencoded')) {
17
+ params = new URLSearchParams(await c.req.text());
18
+ }
19
+ else if (ct.includes('application/json')) {
20
+ const body = (await c.req.json());
21
+ params = new URLSearchParams();
22
+ for (const [k, v] of Object.entries(body)) {
23
+ if (typeof v === 'string')
24
+ params.set(k, v);
25
+ }
26
+ }
27
+ else {
28
+ return c.json({ error: 'invalid_request', error_description: 'unsupported content-type' }, 400);
29
+ }
30
+ }
31
+ catch {
32
+ return c.json({ error: 'invalid_request', error_description: 'malformed body' }, 400);
33
+ }
34
+ // RFC 6749 §2.3.1: client credentials may also be supplied via Basic auth.
35
+ let clientId = params.get('client_id') ?? '';
36
+ let clientSecret = params.get('client_secret') ?? '';
37
+ const basic = c.req.header('authorization');
38
+ if (basic?.toLowerCase().startsWith('basic ')) {
39
+ const decoded = Buffer.from(basic.slice(6), 'base64').toString('utf8');
40
+ const sep = decoded.indexOf(':');
41
+ if (sep > 0) {
42
+ if (!clientId)
43
+ clientId = decoded.slice(0, sep);
44
+ if (!clientSecret)
45
+ clientSecret = decoded.slice(sep + 1);
46
+ }
47
+ }
48
+ const result = grantClientCredentials({ clientId, clientSecret, grantType: params.get('grant_type') ?? '' }, mcp, env.readSecret);
49
+ if (!result.ok) {
50
+ return c.json({
51
+ error: result.error,
52
+ ...(result.description ? { error_description: result.description } : {}),
53
+ }, result.status);
54
+ }
55
+ return c.json({
56
+ access_token: result.token.accessToken,
57
+ token_type: 'Bearer',
58
+ expires_in: result.token.expiresIn,
59
+ });
60
+ });
61
+ // OAuth metadata discovery (RFC 8414).
62
+ app.get('/oauth/.well-known/oauth-authorization-server', (c) => {
63
+ const base = new URL(c.req.url);
64
+ const issuer = `${base.protocol}//${base.host}`;
65
+ return c.json({
66
+ issuer,
67
+ token_endpoint: `${issuer}/mcp/oauth/token`,
68
+ grant_types_supported: ['client_credentials'],
69
+ token_endpoint_auth_methods_supported: ['client_secret_post', 'client_secret_basic'],
70
+ response_types_supported: [],
71
+ });
72
+ });
73
+ // MCP endpoint (JSON-RPC over POST). Requires Bearer token.
74
+ app.post('/', async (c) => {
75
+ const auth = c.req.header('authorization') ?? '';
76
+ if (!auth.toLowerCase().startsWith('bearer ')) {
77
+ return c.json({ error: 'unauthorized' }, 401);
78
+ }
79
+ const token = auth.slice(7).trim();
80
+ const v = verifyToken(token, mcp);
81
+ if (!v.ok) {
82
+ return c.json({ error: 'unauthorized', reason: v.reason }, 401);
83
+ }
84
+ let body;
85
+ try {
86
+ body = await c.req.json();
87
+ }
88
+ catch {
89
+ return c.json({ jsonrpc: '2.0', id: null, error: { code: -32700, message: 'parse error' } }, 400);
90
+ }
91
+ const response = await server.handle(body);
92
+ return c.json(response);
93
+ });
94
+ return app;
95
+ }
96
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/routes/mcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AuthConfig, UserProfileStore } from '@zykeco/server-core';
2
+ import { Hono } from 'hono';
3
+ export declare function userProfileRoutes(store: UserProfileStore, auth: AuthConfig): Hono;
@@ -0,0 +1,24 @@
1
+ import { DeletionsBatchWrite, UserProfilesBatchWrite } from '@zykeco/sync-protocol';
2
+ import { Hono } from 'hono';
3
+ import { requireAuth } from './auth.js';
4
+ import { parseJsonBody } from './validate.js';
5
+ export function userProfileRoutes(store, auth) {
6
+ const app = new Hono();
7
+ app.post('/batch', requireAuth('write', auth), async (c) => {
8
+ const body = await parseJsonBody(c, UserProfilesBatchWrite);
9
+ if (body instanceof Response)
10
+ return body;
11
+ const serverNowMs = Date.now();
12
+ const stored = await store.upsertBatch(body.rows, serverNowMs);
13
+ return c.json({ stored, serverNowMs });
14
+ });
15
+ app.post('/delete', requireAuth('write', auth), async (c) => {
16
+ const body = await parseJsonBody(c, DeletionsBatchWrite);
17
+ if (body instanceof Response)
18
+ return body;
19
+ const deleted = await store.deleteBatch(body.ids);
20
+ return c.json({ deleted, serverNowMs: Date.now() });
21
+ });
22
+ return app;
23
+ }
24
+ //# sourceMappingURL=user-profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-profile.js","sourceRoot":"","sources":["../../src/routes/user-profile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,UAAU,iBAAiB,CAAC,KAAuB,EAAE,IAAgB;IACzE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACzD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC5D,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC/D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1D,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACzD,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AuthConfig, UserTimezonesStore } from '@zykeco/server-core';
2
+ import { Hono } from 'hono';
3
+ export declare function userTimezonesRoutes(store: UserTimezonesStore, auth: AuthConfig): Hono;
@@ -0,0 +1,24 @@
1
+ import { DeletionsBatchWrite, UserTimezonesBatchWrite } from '@zykeco/sync-protocol';
2
+ import { Hono } from 'hono';
3
+ import { requireAuth } from './auth.js';
4
+ import { parseJsonBody } from './validate.js';
5
+ export function userTimezonesRoutes(store, auth) {
6
+ const app = new Hono();
7
+ app.post('/batch', requireAuth('write', auth), async (c) => {
8
+ const body = await parseJsonBody(c, UserTimezonesBatchWrite);
9
+ if (body instanceof Response)
10
+ return body;
11
+ const serverNowMs = Date.now();
12
+ const stored = await store.upsertBatch(body.rows, serverNowMs);
13
+ return c.json({ stored, serverNowMs });
14
+ });
15
+ app.post('/delete', requireAuth('write', auth), async (c) => {
16
+ const body = await parseJsonBody(c, DeletionsBatchWrite);
17
+ if (body instanceof Response)
18
+ return body;
19
+ const deleted = await store.deleteBatch(body.ids);
20
+ return c.json({ deleted, serverNowMs: Date.now() });
21
+ });
22
+ return app;
23
+ }
24
+ //# sourceMappingURL=user-timezones.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-timezones.js","sourceRoot":"","sources":["../../src/routes/user-timezones.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,UAAU,mBAAmB,CAAC,KAAyB,EAAE,IAAgB;IAC7E,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACzD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,EAAE,uBAAuB,CAAC,CAAC;QAC7D,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC/D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1D,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;QACzD,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClD,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1,7 +1,12 @@
1
- import type { AuthConfig, DailyMetricsStore, SleepSessionsStore, WeeklyMetricsStore } from '@zykeco/server-core';
1
+ import type { AuthConfig, DailyMetricsStore, DailyStressBurdenStore, HeartRateMinuteStore, HrZoneHistoryStore, SleepSessionsStore, UserProfileStore, UserTimezonesStore, WeeklyMetricsStore } from '@zykeco/server-core';
2
2
  import { Hono } from 'hono';
3
3
  export declare function wipeRoutes(stores: {
4
4
  dailyMetrics: DailyMetricsStore;
5
5
  weeklyMetrics: WeeklyMetricsStore;
6
6
  sleepSessions: SleepSessionsStore;
7
+ userTimezones: UserTimezonesStore;
8
+ userProfile: UserProfileStore;
9
+ dailyStressBurden: DailyStressBurdenStore;
10
+ heartRateMinute: HeartRateMinuteStore;
11
+ hrZoneHistory: HrZoneHistoryStore;
7
12
  }, auth: AuthConfig): Hono;