@zykeco/sync-server 0.3.0 → 0.4.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 (2) hide show
  1. package/README.md +131 -0
  2. package/package.json +3 -3
package/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # @zykeco/sync-server
2
+
3
+ Self-hosted sync server for the Zyke mobile app. A small [Hono](https://hono.dev) HTTP service backed by [libsql](https://github.com/tursodatabase/libsql) and [Drizzle ORM](https://orm.drizzle.team), validated end-to-end with [TypeBox](https://github.com/sinclairzx81/typebox) schemas from [`@zykeco/sync-protocol`](https://www.npmjs.com/package/@zykeco/sync-protocol).
4
+
5
+ - **Single-tenant, secret-gated.** One server per deployment; two bearer secrets (`READ_SECRET`, `WRITE_SECRET`).
6
+ - **Writes + hard-deletes only.** No read API surface — the mobile client is the source of truth, the server is a durable buffer for backup/restore.
7
+ - **Schemaless `sleep_sessions`.** Domain fields live inside a JSON `payload`, so the mobile app evolves the shape without a server release.
8
+ - **Three CLI bins.** `zyke-sync-startup`, `zyke-sync-upgrade`, and `zyke-sync-migrate` cover first-run setup, version bumps, and ad-hoc migrations.
9
+
10
+ Requires **Node ≥ 24** and **npm ≥ 11**.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install @zykeco/sync-server
16
+ ```
17
+
18
+ For a deployment-ready starter that already wires up `startup` / `start` / `upgrade`, see the [`@zykeco/sync-self-host`](https://github.com/zykeco/sync/tree/main/apps/self-host) template — copy it onto your server and you're done.
19
+
20
+ ## Quick start (manual)
21
+
22
+ ```bash
23
+ # 1. Create a project directory with @zykeco/sync-server installed.
24
+ mkdir my-sync && cd my-sync
25
+ npm init -y && npm pkg set type=module
26
+ npm install @zykeco/sync-server
27
+
28
+ # 2. Generate .env (READ_SECRET / WRITE_SECRET) and run migrations.
29
+ npx zyke-sync-startup
30
+
31
+ # 3. Create index.js with one line, then start.
32
+ echo "import '@zykeco/sync-server';" > index.js
33
+ node index.js
34
+ # → zyke-sync listening on http://localhost:3000
35
+ ```
36
+
37
+ ## Bins
38
+
39
+ | Command | Purpose |
40
+ | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
41
+ | `zyke-sync-startup` | First-run setup. Runs `npm install`, generates/updates `.env` with crypto-random `READ_SECRET` and `WRITE_SECRET` (mode `0600`), creates the libsql data dir, then runs migrations. Idempotent. |
42
+ | `zyke-sync-upgrade` | Upgrades the package and migrates. `zyke-sync-upgrade --to 0.5.0` for a specific version; no arg defaults to `latest`. |
43
+ | `zyke-sync-migrate` | Applies all pending Drizzle migrations against `DATABASE_URL`. Run by `startup` / `upgrade`; useful on its own for ad-hoc migrations. |
44
+
45
+ ## Environment
46
+
47
+ The server reads these via `process.env` (and `.env` if present):
48
+
49
+ | Var | Default | Purpose |
50
+ | -------------- | --------------------- | -------------------------------------------------------------------------------- |
51
+ | `PORT` | `3000` | HTTP listen port. |
52
+ | `DATABASE_URL` | `file:./data/sync.db` | libsql connection string. Accepts local SQLite (`file:`) or remote libsql/Turso. |
53
+ | `READ_SECRET` | _required_ | Bearer token for read endpoints (currently unused — reads are not exposed). |
54
+ | `WRITE_SECRET` | _required_ | Bearer token for write + delete + wipe endpoints. |
55
+
56
+ `zyke-sync-startup` generates 32-byte hex values for both secrets if they're missing, writes the file with mode `0600`, and leaves existing values alone on subsequent runs.
57
+
58
+ ## HTTP API
59
+
60
+ All write endpoints take `Authorization: Bearer ${WRITE_SECRET}` and respond with JSON.
61
+
62
+ ### Health
63
+
64
+ ```
65
+ GET /v1/health → { ok: true }
66
+ ```
67
+
68
+ ### Per-namespace batch upsert
69
+
70
+ ```
71
+ POST /v1/sync/daily-metrics/batch
72
+ POST /v1/sync/weekly-metrics/batch
73
+ POST /v1/sync/sleep-sessions/batch
74
+
75
+ body: { rows: [...] } // max 500 daily/weekly, 200 sleep
76
+ reply: { stored: number[], serverNowMs: number }
77
+ ```
78
+
79
+ Upserts by `id` (client-generated integer PK) with a **last-write-wins** guard on `updatedAt` — older writes are silently ignored.
80
+
81
+ ### Per-namespace hard-delete
82
+
83
+ ```
84
+ POST /v1/sync/daily-metrics/delete
85
+ POST /v1/sync/weekly-metrics/delete
86
+ POST /v1/sync/sleep-sessions/delete
87
+
88
+ body: { ids: number[] } // max 200
89
+ reply: { deleted: number[], serverNowMs: number }
90
+ ```
91
+
92
+ Missing ids are silent successes — safe to retry.
93
+
94
+ ### Wipe everything (destructive)
95
+
96
+ ```
97
+ POST /v1/sync/wipe
98
+
99
+ body: { confirm: "wipe-all-data" }
100
+ reply: { wiped: { dailyMetrics, weeklyMetrics, sleepSessions: number }, serverNowMs }
101
+ ```
102
+
103
+ Deletes every row across the three sync namespaces (blobs untouched). The literal `confirm` string is enforced at the protocol layer.
104
+
105
+ ## Data model
106
+
107
+ - **`daily_metrics`**, **`weekly_metrics`** — `{ id (PK), isoDate / weekStartIsoDate, metricKey, value, createdAt, updatedAt }`. Composite unique on `(date, metricKey)`.
108
+ - **`sleep_sessions`** — schemaless envelope: `{ id (PK), isoDate, updatedAt, payloadVersion, payload (JSON) }`.
109
+
110
+ All timestamps are epoch milliseconds. `id`s are client-generated integers (no autoincrement on the server).
111
+
112
+ ## Programmatic use
113
+
114
+ ```ts
115
+ import '@zykeco/sync-server'; // auto-starts on import using process.env
116
+ ```
117
+
118
+ There is no module API to embed the server in another process — the package is import-to-run by design.
119
+
120
+ ## Compatibility
121
+
122
+ | Runtime | Status |
123
+ | ---------- | -------------------------- |
124
+ | Node ≥ 24 | ✅ |
125
+ | Bun / Deno | ❌ (libsql native binding) |
126
+
127
+ For embedded/edge runtimes, point a stock Node deployment at a remote libsql (Turso) URL.
128
+
129
+ ## License
130
+
131
+ AGPL-3.0-or-later — see [LICENSE](./LICENSE).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zykeco/sync-server",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Self-hosted Zyke sync server (Hono + Drizzle + libsql). Imports to auto-start; ships a migrate CLI.",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "author": "P2LS9K GmbH <office@p2ls9k.com>",
@@ -54,8 +54,8 @@
54
54
  "dependencies": {
55
55
  "@hono/node-server": "^2.0.2",
56
56
  "@libsql/client": "^0.17.3",
57
- "@zykeco/server-core": "^0.3.0",
58
- "@zykeco/sync-protocol": "^0.3.0",
57
+ "@zykeco/server-core": "^0.4.0",
58
+ "@zykeco/sync-protocol": "^0.4.0",
59
59
  "dotenv": "^17.4.2",
60
60
  "drizzle-orm": "^0.45.2",
61
61
  "hono": "^4.6.0"