@zykeco/sync-server 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/db/client.d.ts +5 -0
  2. package/dist/db/client.js +8 -0
  3. package/dist/db/client.js.map +1 -0
  4. package/dist/db/migrate.d.ts +2 -0
  5. package/dist/db/migrate.js +9 -0
  6. package/dist/db/migrate.js.map +1 -0
  7. package/dist/db/schema.d.ts +433 -0
  8. package/dist/db/schema.js +38 -0
  9. package/dist/db/schema.js.map +1 -0
  10. package/dist/env.d.ts +8 -0
  11. package/dist/env.js +16 -0
  12. package/dist/env.js.map +1 -0
  13. package/dist/index.d.ts +1 -0
  14. package/dist/index.js +34 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/migrate-cli.d.ts +2 -0
  17. package/dist/migrate-cli.js +9 -0
  18. package/dist/migrate-cli.js.map +1 -0
  19. package/dist/routes/auth.d.ts +6 -0
  20. package/dist/routes/auth.js +20 -0
  21. package/dist/routes/auth.js.map +1 -0
  22. package/dist/routes/daily-metrics.d.ts +3 -0
  23. package/dist/routes/daily-metrics.js +24 -0
  24. package/dist/routes/daily-metrics.js.map +1 -0
  25. package/dist/routes/health.d.ts +3 -0
  26. package/dist/routes/health.js +16 -0
  27. package/dist/routes/health.js.map +1 -0
  28. package/dist/routes/sleep-sessions.d.ts +3 -0
  29. package/dist/routes/sleep-sessions.js +24 -0
  30. package/dist/routes/sleep-sessions.js.map +1 -0
  31. package/dist/routes/validate.d.ts +3 -0
  32. package/dist/routes/validate.js +17 -0
  33. package/dist/routes/validate.js.map +1 -0
  34. package/dist/routes/weekly-metrics.d.ts +3 -0
  35. package/dist/routes/weekly-metrics.js +24 -0
  36. package/dist/routes/weekly-metrics.js.map +1 -0
  37. package/dist/routes/wipe.d.ts +7 -0
  38. package/dist/routes/wipe.js +23 -0
  39. package/dist/routes/wipe.js.map +1 -0
  40. package/dist/startup-cli.d.ts +2 -0
  41. package/dist/startup-cli.js +57 -0
  42. package/dist/startup-cli.js.map +1 -0
  43. package/dist/stores/daily-metrics.d.ts +3 -0
  44. package/dist/stores/daily-metrics.js +45 -0
  45. package/dist/stores/daily-metrics.js.map +1 -0
  46. package/dist/stores/sleep-sessions.d.ts +3 -0
  47. package/dist/stores/sleep-sessions.js +42 -0
  48. package/dist/stores/sleep-sessions.js.map +1 -0
  49. package/dist/stores/weekly-metrics.d.ts +3 -0
  50. package/dist/stores/weekly-metrics.js +44 -0
  51. package/dist/stores/weekly-metrics.js.map +1 -0
  52. package/dist/upgrade-cli.d.ts +2 -0
  53. package/dist/upgrade-cli.js +23 -0
  54. package/dist/upgrade-cli.js.map +1 -0
  55. package/drizzle/0000_parallel_juggernaut.sql +37 -0
  56. package/drizzle/meta/0000_snapshot.json +238 -0
  57. package/drizzle/meta/_journal.json +13 -0
  58. package/package.json +67 -0
@@ -0,0 +1,24 @@
1
+ import { DailyMetricsBatchWrite, 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 dailyMetricsRoutes(store, auth) {
6
+ const app = new Hono();
7
+ app.post('/batch', requireAuth('write', auth), async (c) => {
8
+ const body = await parseJsonBody(c, DailyMetricsBatchWrite);
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-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-metrics.js","sourceRoot":"","sources":["../../src/routes/daily-metrics.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,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,kBAAkB,CAAC,KAAwB,EAAE,IAAgB;IAC3E,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 { Hono } from 'hono';
2
+ import type { Db } from '../db/client.js';
3
+ export declare function healthRoutes(db: Db): Hono;
@@ -0,0 +1,16 @@
1
+ import { sql } from 'drizzle-orm';
2
+ import { Hono } from 'hono';
3
+ export function healthRoutes(db) {
4
+ const app = new Hono();
5
+ app.get('/', async (c) => {
6
+ try {
7
+ await db.run(sql `SELECT 1`);
8
+ return c.json({ ok: true }, 200);
9
+ }
10
+ catch (err) {
11
+ return c.json({ ok: false, error: err instanceof Error ? err.message : 'db unreachable' }, 503);
12
+ }
13
+ });
14
+ return app;
15
+ }
16
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/routes/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,MAAM,UAAU,YAAY,CAAC,EAAM;IACjC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACvB,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAA,UAAU,CAAC,CAAC;YAC5B,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,CAAC,IAAI,CACX,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,EAAE,EAC3E,GAAG,CACJ,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AuthConfig, SleepSessionsStore } from '@zykeco/server-core';
2
+ import { Hono } from 'hono';
3
+ export declare function sleepSessionsRoutes(store: SleepSessionsStore, auth: AuthConfig): Hono;
@@ -0,0 +1,24 @@
1
+ import { DeletionsBatchWrite, SleepSessionsBatchWrite } from '@zykeco/sync-protocol';
2
+ import { Hono } from 'hono';
3
+ import { requireAuth } from './auth.js';
4
+ import { parseJsonBody } from './validate.js';
5
+ export function sleepSessionsRoutes(store, auth) {
6
+ const app = new Hono();
7
+ app.post('/batch', requireAuth('write', auth), async (c) => {
8
+ const body = await parseJsonBody(c, SleepSessionsBatchWrite);
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=sleep-sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep-sessions.js","sourceRoot":"","sources":["../../src/routes/sleep-sessions.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"}
@@ -0,0 +1,3 @@
1
+ import type { TSchema, Static } from '@sinclair/typebox';
2
+ import type { Context } from 'hono';
3
+ export declare function parseJsonBody<T extends TSchema>(c: Context, schema: T): Promise<Static<T> | Response>;
@@ -0,0 +1,17 @@
1
+ import { Value } from '@sinclair/typebox/value';
2
+ export async function parseJsonBody(c, schema) {
3
+ let body;
4
+ try {
5
+ body = await c.req.json();
6
+ }
7
+ catch {
8
+ return c.json({ code: 'bad_request', message: 'invalid JSON body' }, 400);
9
+ }
10
+ if (!Value.Check(schema, body)) {
11
+ const first = [...Value.Errors(schema, body)][0];
12
+ const message = first ? `${first.path} ${first.message}`.trim() : 'invalid request body';
13
+ return c.json({ code: 'bad_request', message }, 400);
14
+ }
15
+ return body;
16
+ }
17
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/routes/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAIhD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,CAAU,EACV,MAAS;IAET,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,mBAAmB,EAAE,EAAE,GAAG,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,sBAAsB,CAAC;QACzF,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,IAAiB,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AuthConfig, WeeklyMetricsStore } from '@zykeco/server-core';
2
+ import { Hono } from 'hono';
3
+ export declare function weeklyMetricsRoutes(store: WeeklyMetricsStore, auth: AuthConfig): Hono;
@@ -0,0 +1,24 @@
1
+ import { DeletionsBatchWrite, WeeklyMetricsBatchWrite } from '@zykeco/sync-protocol';
2
+ import { Hono } from 'hono';
3
+ import { requireAuth } from './auth.js';
4
+ import { parseJsonBody } from './validate.js';
5
+ export function weeklyMetricsRoutes(store, auth) {
6
+ const app = new Hono();
7
+ app.post('/batch', requireAuth('write', auth), async (c) => {
8
+ const body = await parseJsonBody(c, WeeklyMetricsBatchWrite);
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=weekly-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weekly-metrics.js","sourceRoot":"","sources":["../../src/routes/weekly-metrics.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"}
@@ -0,0 +1,7 @@
1
+ import type { AuthConfig, DailyMetricsStore, SleepSessionsStore, WeeklyMetricsStore } from '@zykeco/server-core';
2
+ import { Hono } from 'hono';
3
+ export declare function wipeRoutes(stores: {
4
+ dailyMetrics: DailyMetricsStore;
5
+ weeklyMetrics: WeeklyMetricsStore;
6
+ sleepSessions: SleepSessionsStore;
7
+ }, auth: AuthConfig): Hono;
@@ -0,0 +1,23 @@
1
+ import { WipeRequest } from '@zykeco/sync-protocol';
2
+ import { Hono } from 'hono';
3
+ import { requireAuth } from './auth.js';
4
+ import { parseJsonBody } from './validate.js';
5
+ export function wipeRoutes(stores, auth) {
6
+ const app = new Hono();
7
+ app.post('/', requireAuth('write', auth), async (c) => {
8
+ const body = await parseJsonBody(c, WipeRequest);
9
+ if (body instanceof Response)
10
+ return body;
11
+ const [dailyMetrics, weeklyMetrics, sleepSessions] = await Promise.all([
12
+ stores.dailyMetrics.wipeAll(),
13
+ stores.weeklyMetrics.wipeAll(),
14
+ stores.sleepSessions.wipeAll(),
15
+ ]);
16
+ return c.json({
17
+ wiped: { dailyMetrics, weeklyMetrics, sleepSessions },
18
+ serverNowMs: Date.now(),
19
+ });
20
+ });
21
+ return app;
22
+ }
23
+ //# sourceMappingURL=wipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wipe.js","sourceRoot":"","sources":["../../src/routes/wipe.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,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,UAAU,CACxB,MAIC,EACD,IAAgB;IAEhB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACpD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QACjD,IAAI,IAAI,YAAY,QAAQ;YAAE,OAAO,IAAI,CAAC;QAE1C,MAAM,CAAC,YAAY,EAAE,aAAa,EAAE,aAAa,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACrE,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE;YAC7B,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE;YAC9B,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE;SAC/B,CAAC,CAAC;QAEH,OAAO,CAAC,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE;YACrD,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;SACxB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+ import { execSync } from 'node:child_process';
3
+ import { randomBytes } from 'node:crypto';
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
5
+ import { dirname, resolve } from 'node:path';
6
+ const cwd = process.cwd();
7
+ const envPath = resolve(cwd, '.env');
8
+ function sh(cmd) {
9
+ execSync(cmd, { cwd, stdio: 'inherit' });
10
+ }
11
+ function genSecret() {
12
+ return randomBytes(32).toString('hex');
13
+ }
14
+ function parseEnv(text) {
15
+ const out = {};
16
+ for (const line of text.split(/\r?\n/)) {
17
+ const m = /^\s*([A-Z0-9_]+)\s*=\s*(.*?)\s*$/i.exec(line);
18
+ if (m)
19
+ out[m[1]] = m[2];
20
+ }
21
+ return out;
22
+ }
23
+ function serializeEnv(obj) {
24
+ return (Object.entries(obj)
25
+ .map(([k, v]) => `${k}=${v}`)
26
+ .join('\n') + '\n');
27
+ }
28
+ console.info('zyke-sync: installing dependencies...');
29
+ sh('npm install');
30
+ const existing = existsSync(envPath)
31
+ ? parseEnv(readFileSync(envPath, 'utf8'))
32
+ : {};
33
+ const env = {
34
+ PORT: existing.PORT ?? '3000',
35
+ DATABASE_URL: existing.DATABASE_URL ?? 'file:./data/sync.db',
36
+ READ_SECRET: existing.READ_SECRET || genSecret(),
37
+ WRITE_SECRET: existing.WRITE_SECRET || genSecret(),
38
+ };
39
+ const created = !existsSync(envPath);
40
+ const secretsChanged = env.READ_SECRET !== existing.READ_SECRET || env.WRITE_SECRET !== existing.WRITE_SECRET;
41
+ if (created || secretsChanged) {
42
+ writeFileSync(envPath, serializeEnv(env), { mode: 0o600 });
43
+ console.info(`zyke-sync: ${created ? 'created' : 'updated'} .env with generated secrets`);
44
+ }
45
+ else {
46
+ console.info('zyke-sync: .env already has secrets, leaving them untouched');
47
+ }
48
+ // Ensure the data dir exists for file-backed libsql databases.
49
+ const fileMatch = /^file:(.*)$/.exec(env.DATABASE_URL);
50
+ if (fileMatch) {
51
+ const dbPath = resolve(cwd, fileMatch[1]);
52
+ mkdirSync(dirname(dbPath), { recursive: true });
53
+ }
54
+ console.info('zyke-sync: running migrations...');
55
+ sh('npx zyke-sync-migrate');
56
+ console.info('zyke-sync: startup complete. Run `npm run start` to launch.');
57
+ //# sourceMappingURL=startup-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startup-cli.js","sourceRoot":"","sources":["../src/startup-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { DailyMetricsStore } from '@zykeco/server-core';
2
+ import type { Db } from '../db/client.js';
3
+ export declare function createDailyMetricsStore(db: Db): DailyMetricsStore;
@@ -0,0 +1,45 @@
1
+ import { inArray, sql } from 'drizzle-orm';
2
+ import { dailyMetrics } from '../db/schema.js';
3
+ export function createDailyMetricsStore(db) {
4
+ return {
5
+ async upsertBatch(rows, _serverNowMs) {
6
+ if (rows.length === 0)
7
+ return [];
8
+ const values = rows.map((r) => ({
9
+ id: r.id,
10
+ isoDate: r.isoDate,
11
+ metricKey: r.metricKey,
12
+ value: r.value,
13
+ createdAt: r.createdAt,
14
+ updatedAt: r.updatedAt,
15
+ }));
16
+ await db
17
+ .insert(dailyMetrics)
18
+ .values(values)
19
+ .onConflictDoUpdate({
20
+ target: dailyMetrics.id,
21
+ set: {
22
+ isoDate: sql `excluded.iso_date`,
23
+ metricKey: sql `excluded.metric_key`,
24
+ value: sql `excluded.value`,
25
+ createdAt: sql `excluded.created_at`,
26
+ updatedAt: sql `excluded.updated_at`,
27
+ },
28
+ // LWW guard
29
+ where: sql `excluded.updated_at > ${dailyMetrics.updatedAt}`,
30
+ });
31
+ return rows.map((r) => r.id);
32
+ },
33
+ async deleteBatch(ids) {
34
+ if (ids.length === 0)
35
+ return [];
36
+ await db.delete(dailyMetrics).where(inArray(dailyMetrics.id, [...ids]));
37
+ return [...ids];
38
+ },
39
+ async wipeAll() {
40
+ const result = await db.delete(dailyMetrics);
41
+ return result.rowsAffected;
42
+ },
43
+ };
44
+ }
45
+ //# sourceMappingURL=daily-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daily-metrics.js","sourceRoot":"","sources":["../../src/stores/daily-metrics.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,UAAU,uBAAuB,CAAC,EAAM;IAC5C,OAAO;QACL,KAAK,CAAC,WAAW,CAAC,IAAiC,EAAE,YAAoB;YACvE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC9B,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,SAAS,EAAE,CAAC,CAAC,SAAS;aACvB,CAAC,CAAC,CAAC;YACJ,MAAM,EAAE;iBACL,MAAM,CAAC,YAAY,CAAC;iBACpB,MAAM,CAAC,MAAM,CAAC;iBACd,kBAAkB,CAAC;gBAClB,MAAM,EAAE,YAAY,CAAC,EAAE;gBACvB,GAAG,EAAE;oBACH,OAAO,EAAE,GAAG,CAAA,mBAAmB;oBAC/B,SAAS,EAAE,GAAG,CAAA,qBAAqB;oBACnC,KAAK,EAAE,GAAG,CAAA,gBAAgB;oBAC1B,SAAS,EAAE,GAAG,CAAA,qBAAqB;oBACnC,SAAS,EAAE,GAAG,CAAA,qBAAqB;iBACpC;gBACD,YAAY;gBACZ,KAAK,EAAE,GAAG,CAAA,yBAAyB,YAAY,CAAC,SAAS,EAAE;aAC5D,CAAC,CAAC;YACL,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,CAAC,WAAW,CAAC,GAAsB;YACtC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YAChC,MAAM,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;QAClB,CAAC;QAED,KAAK,CAAC,OAAO;YACX,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YAC7C,OAAO,MAAM,CAAC,YAAY,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SleepSessionsStore } from '@zykeco/server-core';
2
+ import type { Db } from '../db/client.js';
3
+ export declare function createSleepSessionsStore(db: Db): SleepSessionsStore;
@@ -0,0 +1,42 @@
1
+ import { inArray, sql } from 'drizzle-orm';
2
+ import { sleepSessions } from '../db/schema.js';
3
+ export function createSleepSessionsStore(db) {
4
+ return {
5
+ async upsertBatch(rows, _serverNowMs) {
6
+ if (rows.length === 0)
7
+ return [];
8
+ const values = rows.map((r) => ({
9
+ id: r.id,
10
+ isoDate: r.isoDate,
11
+ updatedAt: r.updatedAt,
12
+ payloadVersion: r.payloadVersion,
13
+ payload: r.payload,
14
+ }));
15
+ await db
16
+ .insert(sleepSessions)
17
+ .values(values)
18
+ .onConflictDoUpdate({
19
+ target: sleepSessions.id,
20
+ set: {
21
+ isoDate: sql `excluded.iso_date`,
22
+ updatedAt: sql `excluded.updated_at`,
23
+ payloadVersion: sql `excluded.payload_version`,
24
+ payload: sql `excluded.payload`,
25
+ },
26
+ where: sql `excluded.updated_at > ${sleepSessions.updatedAt}`,
27
+ });
28
+ return rows.map((r) => r.id);
29
+ },
30
+ async deleteBatch(ids) {
31
+ if (ids.length === 0)
32
+ return [];
33
+ await db.delete(sleepSessions).where(inArray(sleepSessions.id, [...ids]));
34
+ return [...ids];
35
+ },
36
+ async wipeAll() {
37
+ const result = await db.delete(sleepSessions);
38
+ return result.rowsAffected;
39
+ },
40
+ };
41
+ }
42
+ //# sourceMappingURL=sleep-sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep-sessions.js","sourceRoot":"","sources":["../../src/stores/sleep-sessions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,UAAU,wBAAwB,CAAC,EAAM;IAC7C,OAAO;QACL,KAAK,CAAC,WAAW,CAAC,IAAkC,EAAE,YAAoB;YACxE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC9B,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,cAAc,EAAE,CAAC,CAAC,cAAc;gBAChC,OAAO,EAAE,CAAC,CAAC,OAAO;aACnB,CAAC,CAAC,CAAC;YACJ,MAAM,EAAE;iBACL,MAAM,CAAC,aAAa,CAAC;iBACrB,MAAM,CAAC,MAAM,CAAC;iBACd,kBAAkB,CAAC;gBAClB,MAAM,EAAE,aAAa,CAAC,EAAE;gBACxB,GAAG,EAAE;oBACH,OAAO,EAAE,GAAG,CAAA,mBAAmB;oBAC/B,SAAS,EAAE,GAAG,CAAA,qBAAqB;oBACnC,cAAc,EAAE,GAAG,CAAA,0BAA0B;oBAC7C,OAAO,EAAE,GAAG,CAAA,kBAAkB;iBAC/B;gBACD,KAAK,EAAE,GAAG,CAAA,yBAAyB,aAAa,CAAC,SAAS,EAAE;aAC7D,CAAC,CAAC;YACL,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,CAAC,WAAW,CAAC,GAAsB;YACtC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YAChC,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YAC1E,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;QAClB,CAAC;QAED,KAAK,CAAC,OAAO;YACX,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAC9C,OAAO,MAAM,CAAC,YAAY,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { WeeklyMetricsStore } from '@zykeco/server-core';
2
+ import type { Db } from '../db/client.js';
3
+ export declare function createWeeklyMetricsStore(db: Db): WeeklyMetricsStore;
@@ -0,0 +1,44 @@
1
+ import { inArray, sql } from 'drizzle-orm';
2
+ import { weeklyMetrics } from '../db/schema.js';
3
+ export function createWeeklyMetricsStore(db) {
4
+ return {
5
+ async upsertBatch(rows, _serverNowMs) {
6
+ if (rows.length === 0)
7
+ return [];
8
+ const values = rows.map((r) => ({
9
+ id: r.id,
10
+ weekStartIsoDate: r.weekStartIsoDate,
11
+ metricKey: r.metricKey,
12
+ value: r.value,
13
+ createdAt: r.createdAt,
14
+ updatedAt: r.updatedAt,
15
+ }));
16
+ await db
17
+ .insert(weeklyMetrics)
18
+ .values(values)
19
+ .onConflictDoUpdate({
20
+ target: weeklyMetrics.id,
21
+ set: {
22
+ weekStartIsoDate: sql `excluded.week_start_iso_date`,
23
+ metricKey: sql `excluded.metric_key`,
24
+ value: sql `excluded.value`,
25
+ createdAt: sql `excluded.created_at`,
26
+ updatedAt: sql `excluded.updated_at`,
27
+ },
28
+ where: sql `excluded.updated_at > ${weeklyMetrics.updatedAt}`,
29
+ });
30
+ return rows.map((r) => r.id);
31
+ },
32
+ async deleteBatch(ids) {
33
+ if (ids.length === 0)
34
+ return [];
35
+ await db.delete(weeklyMetrics).where(inArray(weeklyMetrics.id, [...ids]));
36
+ return [...ids];
37
+ },
38
+ async wipeAll() {
39
+ const result = await db.delete(weeklyMetrics);
40
+ return result.rowsAffected;
41
+ },
42
+ };
43
+ }
44
+ //# sourceMappingURL=weekly-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weekly-metrics.js","sourceRoot":"","sources":["../../src/stores/weekly-metrics.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,UAAU,wBAAwB,CAAC,EAAM;IAC7C,OAAO;QACL,KAAK,CAAC,WAAW,CAAC,IAAkC,EAAE,YAAoB;YACxE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC9B,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,gBAAgB,EAAE,CAAC,CAAC,gBAAgB;gBACpC,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,SAAS,EAAE,CAAC,CAAC,SAAS;aACvB,CAAC,CAAC,CAAC;YACJ,MAAM,EAAE;iBACL,MAAM,CAAC,aAAa,CAAC;iBACrB,MAAM,CAAC,MAAM,CAAC;iBACd,kBAAkB,CAAC;gBAClB,MAAM,EAAE,aAAa,CAAC,EAAE;gBACxB,GAAG,EAAE;oBACH,gBAAgB,EAAE,GAAG,CAAA,8BAA8B;oBACnD,SAAS,EAAE,GAAG,CAAA,qBAAqB;oBACnC,KAAK,EAAE,GAAG,CAAA,gBAAgB;oBAC1B,SAAS,EAAE,GAAG,CAAA,qBAAqB;oBACnC,SAAS,EAAE,GAAG,CAAA,qBAAqB;iBACpC;gBACD,KAAK,EAAE,GAAG,CAAA,yBAAyB,aAAa,CAAC,SAAS,EAAE;aAC7D,CAAC,CAAC;YACL,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,CAAC,WAAW,CAAC,GAAsB;YACtC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YAChC,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YAC1E,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;QAClB,CAAC;QAED,KAAK,CAAC,OAAO;YACX,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAC9C,OAAO,MAAM,CAAC,YAAY,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ import { execSync } from 'node:child_process';
3
+ const cwd = process.cwd();
4
+ function sh(cmd) {
5
+ execSync(cmd, { cwd, stdio: 'inherit' });
6
+ }
7
+ function parseTarget(argv) {
8
+ // Supports `npm run upgrade -- --to <version>` or `--to=<version>`.
9
+ const i = argv.indexOf('--to');
10
+ if (i >= 0 && argv[i + 1])
11
+ return argv[i + 1];
12
+ const flag = argv.find((a) => a.startsWith('--to='));
13
+ if (flag)
14
+ return flag.slice('--to='.length);
15
+ return 'latest';
16
+ }
17
+ const target = parseTarget(process.argv.slice(2));
18
+ console.info(`zyke-sync: upgrading @zykeco/sync-server to ${target}...`);
19
+ sh(`npm install @zykeco/sync-server@${target}`);
20
+ console.info('zyke-sync: running migrations...');
21
+ sh('npx zyke-sync-migrate');
22
+ console.info('zyke-sync: upgrade complete.');
23
+ //# sourceMappingURL=upgrade-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-cli.js","sourceRoot":"","sources":["../src/upgrade-cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAE1B,SAAS,EAAE,CAAC,GAAW;IACrB,QAAQ,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,WAAW,CAAC,IAAc;IACjC,oEAAoE;IACpE,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,OAAO,CAAC,IAAI,CAAC,+CAA+C,MAAM,KAAK,CAAC,CAAC;AACzE,EAAE,CAAC,mCAAmC,MAAM,EAAE,CAAC,CAAC;AAEhD,OAAO,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;AACjD,EAAE,CAAC,uBAAuB,CAAC,CAAC;AAE5B,OAAO,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC"}
@@ -0,0 +1,37 @@
1
+ CREATE TABLE `blobs` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `content_type` text NOT NULL,
4
+ `size` integer NOT NULL,
5
+ `bytes` blob NOT NULL,
6
+ `created_at` integer NOT NULL,
7
+ `updated_at` integer NOT NULL
8
+ );
9
+ --> statement-breakpoint
10
+ CREATE TABLE `daily_metrics` (
11
+ `id` integer PRIMARY KEY NOT NULL,
12
+ `iso_date` text NOT NULL,
13
+ `metric_key` text NOT NULL,
14
+ `value` real NOT NULL,
15
+ `created_at` integer NOT NULL,
16
+ `updated_at` integer NOT NULL
17
+ );
18
+ --> statement-breakpoint
19
+ CREATE UNIQUE INDEX `dm_natural_key_idx` ON `daily_metrics` (`iso_date`,`metric_key`);--> statement-breakpoint
20
+ CREATE TABLE `sleep_sessions` (
21
+ `id` integer PRIMARY KEY NOT NULL,
22
+ `iso_date` text NOT NULL,
23
+ `updated_at` integer NOT NULL,
24
+ `payload_version` integer DEFAULT 1 NOT NULL,
25
+ `payload` text NOT NULL
26
+ );
27
+ --> statement-breakpoint
28
+ CREATE TABLE `weekly_metrics` (
29
+ `id` integer PRIMARY KEY NOT NULL,
30
+ `week_start_iso_date` text NOT NULL,
31
+ `metric_key` text NOT NULL,
32
+ `value` real NOT NULL,
33
+ `created_at` integer NOT NULL,
34
+ `updated_at` integer NOT NULL
35
+ );
36
+ --> statement-breakpoint
37
+ CREATE UNIQUE INDEX `wm_natural_key_idx` ON `weekly_metrics` (`week_start_iso_date`,`metric_key`);