@syncular/server 0.0.6-96 → 0.1.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 (597) hide show
  1. package/README.md +1 -2
  2. package/dist/auth-leases.d.ts +85 -0
  3. package/dist/auth-leases.d.ts.map +1 -0
  4. package/dist/auth-leases.js +368 -0
  5. package/dist/auth-leases.js.map +1 -0
  6. package/dist/better-sqlite3.d.ts +22 -0
  7. package/dist/better-sqlite3.d.ts.map +1 -0
  8. package/dist/better-sqlite3.js +16 -0
  9. package/dist/better-sqlite3.js.map +1 -0
  10. package/dist/blobs/access.d.ts +35 -0
  11. package/dist/blobs/access.d.ts.map +1 -0
  12. package/dist/blobs/access.js +149 -0
  13. package/dist/blobs/access.js.map +1 -0
  14. package/dist/blobs/adapters/database.d.ts +26 -9
  15. package/dist/blobs/adapters/database.d.ts.map +1 -1
  16. package/dist/blobs/adapters/database.js +68 -23
  17. package/dist/blobs/adapters/database.js.map +1 -1
  18. package/dist/blobs/index.d.ts +1 -0
  19. package/dist/blobs/index.d.ts.map +1 -1
  20. package/dist/blobs/index.js +1 -0
  21. package/dist/blobs/index.js.map +1 -1
  22. package/dist/blobs/manager.d.ts +69 -44
  23. package/dist/blobs/manager.d.ts.map +1 -1
  24. package/dist/blobs/manager.js +250 -65
  25. package/dist/blobs/manager.js.map +1 -1
  26. package/dist/blobs/migrate.d.ts.map +1 -1
  27. package/dist/blobs/migrate.js +16 -8
  28. package/dist/blobs/migrate.js.map +1 -1
  29. package/dist/blobs/types.d.ts +4 -0
  30. package/dist/blobs/types.d.ts.map +1 -1
  31. package/dist/bun-sqlite.d.ts +19 -0
  32. package/dist/bun-sqlite.d.ts.map +1 -0
  33. package/dist/bun-sqlite.js +19 -0
  34. package/dist/bun-sqlite.js.map +1 -0
  35. package/dist/clients.d.ts +1 -0
  36. package/dist/clients.d.ts.map +1 -1
  37. package/dist/clients.js.map +1 -1
  38. package/dist/cloudflare/durable-object.d.ts +93 -0
  39. package/dist/cloudflare/durable-object.d.ts.map +1 -0
  40. package/dist/cloudflare/durable-object.js +210 -0
  41. package/dist/cloudflare/durable-object.js.map +1 -0
  42. package/dist/cloudflare/index.d.ts +22 -0
  43. package/dist/cloudflare/index.d.ts.map +1 -0
  44. package/dist/cloudflare/index.js +22 -0
  45. package/dist/cloudflare/index.js.map +1 -0
  46. package/dist/cloudflare/r2.d.ts +180 -0
  47. package/dist/cloudflare/r2.d.ts.map +1 -0
  48. package/dist/cloudflare/r2.js +258 -0
  49. package/dist/cloudflare/r2.js.map +1 -0
  50. package/dist/cloudflare/scope-cache.d.ts +54 -0
  51. package/dist/cloudflare/scope-cache.d.ts.map +1 -0
  52. package/dist/cloudflare/scope-cache.js +223 -0
  53. package/dist/cloudflare/scope-cache.js.map +1 -0
  54. package/dist/cloudflare/sentry.d.ts +47 -0
  55. package/dist/cloudflare/sentry.d.ts.map +1 -0
  56. package/dist/cloudflare/sentry.js +163 -0
  57. package/dist/cloudflare/sentry.js.map +1 -0
  58. package/dist/cloudflare/worker.d.ts +46 -0
  59. package/dist/cloudflare/worker.d.ts.map +1 -0
  60. package/dist/cloudflare/worker.js +63 -0
  61. package/dist/cloudflare/worker.js.map +1 -0
  62. package/dist/commit-integrity.d.ts +38 -0
  63. package/dist/commit-integrity.d.ts.map +1 -0
  64. package/dist/commit-integrity.js +260 -0
  65. package/dist/commit-integrity.js.map +1 -0
  66. package/dist/compaction.js.map +1 -1
  67. package/dist/crdt-yjs/index.d.ts +99 -0
  68. package/dist/crdt-yjs/index.d.ts.map +1 -0
  69. package/dist/crdt-yjs/index.js +629 -0
  70. package/dist/crdt-yjs/index.js.map +1 -0
  71. package/dist/d1.d.ts +13 -0
  72. package/dist/d1.d.ts.map +1 -0
  73. package/dist/d1.js +14 -0
  74. package/dist/d1.js.map +1 -0
  75. package/dist/dialect/base.d.ts +11 -1
  76. package/dist/dialect/base.d.ts.map +1 -1
  77. package/dist/dialect/base.js +42 -5
  78. package/dist/dialect/base.js.map +1 -1
  79. package/dist/dialect/helpers.d.ts +6 -0
  80. package/dist/dialect/helpers.d.ts.map +1 -1
  81. package/dist/dialect/helpers.js +24 -0
  82. package/dist/dialect/helpers.js.map +1 -1
  83. package/dist/dialect/types.d.ts +40 -0
  84. package/dist/dialect/types.d.ts.map +1 -1
  85. package/dist/encrypted-crdt.d.ts +67 -0
  86. package/dist/encrypted-crdt.d.ts.map +1 -0
  87. package/dist/encrypted-crdt.js +426 -0
  88. package/dist/encrypted-crdt.js.map +1 -0
  89. package/dist/errors.d.ts +10 -0
  90. package/dist/errors.d.ts.map +1 -0
  91. package/dist/errors.js +13 -0
  92. package/dist/errors.js.map +1 -0
  93. package/dist/filesystem/index.d.ts +44 -0
  94. package/dist/filesystem/index.d.ts.map +1 -0
  95. package/dist/filesystem/index.js +164 -0
  96. package/dist/filesystem/index.js.map +1 -0
  97. package/dist/handlers/collection.d.ts +11 -3
  98. package/dist/handlers/collection.d.ts.map +1 -1
  99. package/dist/handlers/collection.js +34 -56
  100. package/dist/handlers/collection.js.map +1 -1
  101. package/dist/handlers/create-handler.d.ts +31 -7
  102. package/dist/handlers/create-handler.d.ts.map +1 -1
  103. package/dist/handlers/create-handler.js +332 -115
  104. package/dist/handlers/create-handler.js.map +1 -1
  105. package/dist/handlers/types.d.ts +86 -1
  106. package/dist/handlers/types.d.ts.map +1 -1
  107. package/dist/helpers/conflict.js.map +1 -1
  108. package/dist/helpers/emitted-change.js.map +1 -1
  109. package/dist/helpers/index.d.ts +2 -0
  110. package/dist/helpers/index.d.ts.map +1 -1
  111. package/dist/helpers/index.js +2 -0
  112. package/dist/helpers/index.js.map +1 -1
  113. package/dist/helpers/paginate.js.map +1 -1
  114. package/dist/helpers/scope-authorization.d.ts +7 -0
  115. package/dist/helpers/scope-authorization.d.ts.map +1 -0
  116. package/dist/helpers/scope-authorization.js +19 -0
  117. package/dist/helpers/scope-authorization.js.map +1 -0
  118. package/dist/helpers/scope-commit-index.d.ts +12 -0
  119. package/dist/helpers/scope-commit-index.d.ts.map +1 -0
  120. package/dist/helpers/scope-commit-index.js +35 -0
  121. package/dist/helpers/scope-commit-index.js.map +1 -0
  122. package/dist/helpers/scope-strings.js.map +1 -1
  123. package/dist/hono/api-key-auth.d.ts +49 -0
  124. package/dist/hono/api-key-auth.d.ts.map +1 -0
  125. package/dist/hono/api-key-auth.js +108 -0
  126. package/dist/hono/api-key-auth.js.map +1 -0
  127. package/dist/hono/audit-redaction.d.ts +20 -0
  128. package/dist/hono/audit-redaction.d.ts.map +1 -0
  129. package/dist/hono/audit-redaction.js +85 -0
  130. package/dist/hono/audit-redaction.js.map +1 -0
  131. package/dist/hono/blobs.d.ts +75 -0
  132. package/dist/hono/blobs.d.ts.map +1 -0
  133. package/dist/hono/blobs.js +586 -0
  134. package/dist/hono/blobs.js.map +1 -0
  135. package/dist/hono/console/gateway.d.ts +42 -0
  136. package/dist/hono/console/gateway.d.ts.map +1 -0
  137. package/dist/hono/console/gateway.js +2158 -0
  138. package/dist/hono/console/gateway.js.map +1 -0
  139. package/dist/hono/console/live-auth.d.ts +7 -0
  140. package/dist/hono/console/live-auth.d.ts.map +1 -0
  141. package/dist/hono/console/live-auth.js +39 -0
  142. package/dist/hono/console/live-auth.js.map +1 -0
  143. package/dist/hono/console/route-descriptor.d.ts +6 -0
  144. package/dist/hono/console/route-descriptor.d.ts.map +1 -0
  145. package/dist/hono/console/route-descriptor.js +16 -0
  146. package/dist/hono/console/route-descriptor.js.map +1 -0
  147. package/dist/hono/console/routes/api-keys.d.ts +8 -0
  148. package/dist/hono/console/routes/api-keys.d.ts.map +1 -0
  149. package/dist/hono/console/routes/api-keys.js +575 -0
  150. package/dist/hono/console/routes/api-keys.js.map +1 -0
  151. package/dist/hono/console/routes/clients.d.ts +8 -0
  152. package/dist/hono/console/routes/clients.d.ts.map +1 -0
  153. package/dist/hono/console/routes/clients.js +322 -0
  154. package/dist/hono/console/routes/clients.js.map +1 -0
  155. package/dist/hono/console/routes/commits.d.ts +8 -0
  156. package/dist/hono/console/routes/commits.d.ts.map +1 -0
  157. package/dist/hono/console/routes/commits.js +882 -0
  158. package/dist/hono/console/routes/commits.js.map +1 -0
  159. package/dist/hono/console/routes/context.d.ts +188 -0
  160. package/dist/hono/console/routes/context.d.ts.map +1 -0
  161. package/dist/hono/console/routes/context.js +633 -0
  162. package/dist/hono/console/routes/context.js.map +1 -0
  163. package/dist/hono/console/routes/events.d.ts +8 -0
  164. package/dist/hono/console/routes/events.d.ts.map +1 -0
  165. package/dist/hono/console/routes/events.js +501 -0
  166. package/dist/hono/console/routes/events.js.map +1 -0
  167. package/dist/hono/console/routes/maintenance.d.ts +8 -0
  168. package/dist/hono/console/routes/maintenance.d.ts.map +1 -0
  169. package/dist/hono/console/routes/maintenance.js +341 -0
  170. package/dist/hono/console/routes/maintenance.js.map +1 -0
  171. package/dist/hono/console/routes/shared.d.ts +174 -0
  172. package/dist/hono/console/routes/shared.d.ts.map +1 -0
  173. package/dist/hono/console/routes/shared.js +583 -0
  174. package/dist/hono/console/routes/shared.js.map +1 -0
  175. package/dist/hono/console/routes/stats.d.ts +8 -0
  176. package/dist/hono/console/routes/stats.d.ts.map +1 -0
  177. package/dist/hono/console/routes/stats.js +295 -0
  178. package/dist/hono/console/routes/stats.js.map +1 -0
  179. package/dist/hono/console/routes/storage.d.ts +8 -0
  180. package/dist/hono/console/routes/storage.d.ts.map +1 -0
  181. package/dist/hono/console/routes/storage.js +121 -0
  182. package/dist/hono/console/routes/storage.js.map +1 -0
  183. package/dist/hono/console/routes.d.ts +36 -0
  184. package/dist/hono/console/routes.d.ts.map +1 -0
  185. package/dist/hono/console/routes.js +112 -0
  186. package/dist/hono/console/routes.js.map +1 -0
  187. package/dist/hono/console/schema-errors.d.ts +2 -0
  188. package/dist/hono/console/schema-errors.d.ts.map +1 -0
  189. package/dist/hono/console/schema-errors.js +17 -0
  190. package/dist/hono/console/schema-errors.js.map +1 -0
  191. package/dist/hono/console/schemas.d.ts +1515 -0
  192. package/dist/hono/console/schemas.d.ts.map +1 -0
  193. package/dist/hono/console/schemas.js +661 -0
  194. package/dist/hono/console/schemas.js.map +1 -0
  195. package/dist/hono/console/types.d.ts +213 -0
  196. package/dist/hono/console/types.d.ts.map +1 -0
  197. package/dist/hono/console/types.js +2 -0
  198. package/dist/hono/console/types.js.map +1 -0
  199. package/dist/hono/console/ui.d.ts +38 -0
  200. package/dist/hono/console/ui.d.ts.map +1 -0
  201. package/dist/hono/console/ui.js +43 -0
  202. package/dist/hono/console/ui.js.map +1 -0
  203. package/dist/hono/create-server.d.ts +71 -0
  204. package/dist/hono/create-server.d.ts.map +1 -0
  205. package/dist/hono/create-server.js +121 -0
  206. package/dist/hono/create-server.js.map +1 -0
  207. package/dist/hono/errors.d.ts +13 -0
  208. package/dist/hono/errors.d.ts.map +1 -0
  209. package/dist/hono/errors.js +21 -0
  210. package/dist/hono/errors.js.map +1 -0
  211. package/dist/hono/index.d.ts +20 -0
  212. package/dist/hono/index.d.ts.map +1 -0
  213. package/dist/hono/index.js +31 -0
  214. package/dist/hono/index.js.map +1 -0
  215. package/dist/hono/openapi.d.ts +72 -0
  216. package/dist/hono/openapi.d.ts.map +1 -0
  217. package/dist/hono/openapi.js +99 -0
  218. package/dist/hono/openapi.js.map +1 -0
  219. package/dist/hono/proxy/connection-manager.d.ts +78 -0
  220. package/dist/hono/proxy/connection-manager.d.ts.map +1 -0
  221. package/dist/hono/proxy/connection-manager.js +251 -0
  222. package/dist/hono/proxy/connection-manager.js.map +1 -0
  223. package/dist/hono/proxy/index.d.ts +8 -0
  224. package/dist/hono/proxy/index.d.ts.map +1 -0
  225. package/dist/hono/proxy/index.js +8 -0
  226. package/dist/hono/proxy/index.js.map +1 -0
  227. package/dist/hono/proxy/routes.d.ts +86 -0
  228. package/dist/hono/proxy/routes.d.ts.map +1 -0
  229. package/dist/hono/proxy/routes.js +183 -0
  230. package/dist/hono/proxy/routes.js.map +1 -0
  231. package/dist/hono/rate-limit.d.ts +101 -0
  232. package/dist/hono/rate-limit.d.ts.map +1 -0
  233. package/dist/hono/rate-limit.js +184 -0
  234. package/dist/hono/rate-limit.js.map +1 -0
  235. package/dist/hono/realtime-sync-packs.d.ts +43 -0
  236. package/dist/hono/realtime-sync-packs.d.ts.map +1 -0
  237. package/dist/hono/realtime-sync-packs.js +219 -0
  238. package/dist/hono/realtime-sync-packs.js.map +1 -0
  239. package/dist/hono/routes/audit.d.ts +12 -0
  240. package/dist/hono/routes/audit.d.ts.map +1 -0
  241. package/dist/hono/routes/audit.js +385 -0
  242. package/dist/hono/routes/audit.js.map +1 -0
  243. package/dist/hono/routes/auth-leases.d.ts +8 -0
  244. package/dist/hono/routes/auth-leases.d.ts.map +1 -0
  245. package/dist/hono/routes/auth-leases.js +88 -0
  246. package/dist/hono/routes/auth-leases.js.map +1 -0
  247. package/dist/hono/routes/combined.d.ts +8 -0
  248. package/dist/hono/routes/combined.d.ts.map +1 -0
  249. package/dist/hono/routes/combined.js +392 -0
  250. package/dist/hono/routes/combined.js.map +1 -0
  251. package/dist/hono/routes/context.d.ts +314 -0
  252. package/dist/hono/routes/context.d.ts.map +1 -0
  253. package/dist/hono/routes/context.js +1147 -0
  254. package/dist/hono/routes/context.js.map +1 -0
  255. package/dist/hono/routes/health.d.ts +8 -0
  256. package/dist/hono/routes/health.d.ts.map +1 -0
  257. package/dist/hono/routes/health.js +16 -0
  258. package/dist/hono/routes/health.js.map +1 -0
  259. package/dist/hono/routes/realtime.d.ts +9 -0
  260. package/dist/hono/routes/realtime.d.ts.map +1 -0
  261. package/dist/hono/routes/realtime.js +626 -0
  262. package/dist/hono/routes/realtime.js.map +1 -0
  263. package/dist/hono/routes/shared.d.ts +689 -0
  264. package/dist/hono/routes/shared.d.ts.map +1 -0
  265. package/dist/hono/routes/shared.js +972 -0
  266. package/dist/hono/routes/shared.js.map +1 -0
  267. package/dist/hono/routes/snapshots.d.ts +10 -0
  268. package/dist/hono/routes/snapshots.d.ts.map +1 -0
  269. package/dist/hono/routes/snapshots.js +281 -0
  270. package/dist/hono/routes/snapshots.js.map +1 -0
  271. package/dist/hono/routes.d.ts +19 -0
  272. package/dist/hono/routes.d.ts.map +1 -0
  273. package/dist/hono/routes.js +37 -0
  274. package/dist/hono/routes.js.map +1 -0
  275. package/dist/hono/validation.d.ts +5 -0
  276. package/dist/hono/validation.d.ts.map +1 -0
  277. package/dist/hono/validation.js +47 -0
  278. package/dist/hono/validation.js.map +1 -0
  279. package/dist/hono/websocket-origin.d.ts +9 -0
  280. package/dist/hono/websocket-origin.d.ts.map +1 -0
  281. package/dist/hono/websocket-origin.js +96 -0
  282. package/dist/hono/websocket-origin.js.map +1 -0
  283. package/dist/hono/ws.d.ts +341 -0
  284. package/dist/hono/ws.d.ts.map +1 -0
  285. package/dist/hono/ws.js +711 -0
  286. package/dist/hono/ws.js.map +1 -0
  287. package/dist/index.d.ts +6 -0
  288. package/dist/index.d.ts.map +1 -1
  289. package/dist/index.js +6 -0
  290. package/dist/index.js.map +1 -1
  291. package/dist/libsql.d.ts +29 -0
  292. package/dist/libsql.d.ts.map +1 -0
  293. package/dist/libsql.js +25 -0
  294. package/dist/libsql.js.map +1 -0
  295. package/dist/migrate.js.map +1 -1
  296. package/dist/neon.d.ts +21 -0
  297. package/dist/neon.d.ts.map +1 -0
  298. package/dist/neon.js +22 -0
  299. package/dist/neon.js.map +1 -0
  300. package/dist/notify.d.ts +30 -0
  301. package/dist/notify.d.ts.map +1 -1
  302. package/dist/notify.js +160 -41
  303. package/dist/notify.js.map +1 -1
  304. package/dist/pglite.d.ts +37 -0
  305. package/dist/pglite.d.ts.map +1 -0
  306. package/dist/pglite.js +37 -0
  307. package/dist/pglite.js.map +1 -0
  308. package/dist/plugins/index.d.ts +2 -0
  309. package/dist/plugins/index.d.ts.map +1 -0
  310. package/dist/plugins/index.js +2 -0
  311. package/dist/plugins/index.js.map +1 -0
  312. package/dist/plugins/types.d.ts +73 -0
  313. package/dist/plugins/types.d.ts.map +1 -0
  314. package/dist/plugins/types.js +30 -0
  315. package/dist/plugins/types.js.map +1 -0
  316. package/dist/postgres/index.d.ts +68 -0
  317. package/dist/postgres/index.d.ts.map +1 -0
  318. package/dist/postgres/index.js +924 -0
  319. package/dist/postgres/index.js.map +1 -0
  320. package/dist/proxy/collection.d.ts +0 -2
  321. package/dist/proxy/collection.d.ts.map +1 -1
  322. package/dist/proxy/collection.js +2 -17
  323. package/dist/proxy/collection.js.map +1 -1
  324. package/dist/proxy/handler.d.ts +1 -1
  325. package/dist/proxy/handler.d.ts.map +1 -1
  326. package/dist/proxy/handler.js +1 -2
  327. package/dist/proxy/handler.js.map +1 -1
  328. package/dist/proxy/index.d.ts +1 -1
  329. package/dist/proxy/index.d.ts.map +1 -1
  330. package/dist/proxy/index.js +1 -1
  331. package/dist/proxy/index.js.map +1 -1
  332. package/dist/proxy/mutation-detector.js.map +1 -1
  333. package/dist/proxy/oplog.d.ts.map +1 -1
  334. package/dist/proxy/oplog.js +32 -8
  335. package/dist/proxy/oplog.js.map +1 -1
  336. package/dist/prune.d.ts +8 -1
  337. package/dist/prune.d.ts.map +1 -1
  338. package/dist/prune.js +68 -28
  339. package/dist/prune.js.map +1 -1
  340. package/dist/pull.d.ts +31 -0
  341. package/dist/pull.d.ts.map +1 -1
  342. package/dist/pull.js +1011 -471
  343. package/dist/pull.js.map +1 -1
  344. package/dist/push.d.ts +36 -2
  345. package/dist/push.d.ts.map +1 -1
  346. package/dist/push.js +603 -358
  347. package/dist/push.js.map +1 -1
  348. package/dist/realtime/in-memory.js.map +1 -1
  349. package/dist/realtime/index.d.ts +2 -1
  350. package/dist/realtime/index.d.ts.map +1 -1
  351. package/dist/realtime/index.js +1 -0
  352. package/dist/realtime/index.js.map +1 -1
  353. package/dist/realtime/types.d.ts +12 -0
  354. package/dist/realtime/types.d.ts.map +1 -1
  355. package/dist/realtime/types.js +13 -1
  356. package/dist/realtime/types.js.map +1 -1
  357. package/dist/relay/client-role/forward-engine.d.ts +63 -0
  358. package/dist/relay/client-role/forward-engine.d.ts.map +1 -0
  359. package/dist/relay/client-role/forward-engine.js +267 -0
  360. package/dist/relay/client-role/forward-engine.js.map +1 -0
  361. package/dist/relay/client-role/index.d.ts +9 -0
  362. package/dist/relay/client-role/index.d.ts.map +1 -0
  363. package/dist/relay/client-role/index.js +9 -0
  364. package/dist/relay/client-role/index.js.map +1 -0
  365. package/dist/relay/client-role/pull-engine.d.ts +72 -0
  366. package/dist/relay/client-role/pull-engine.d.ts.map +1 -0
  367. package/dist/relay/client-role/pull-engine.js +249 -0
  368. package/dist/relay/client-role/pull-engine.js.map +1 -0
  369. package/dist/relay/client-role/sequence-mapper.d.ts +65 -0
  370. package/dist/relay/client-role/sequence-mapper.d.ts.map +1 -0
  371. package/dist/relay/client-role/sequence-mapper.js +161 -0
  372. package/dist/relay/client-role/sequence-mapper.js.map +1 -0
  373. package/dist/relay/evaluation/relay-paths.d.ts +41 -0
  374. package/dist/relay/evaluation/relay-paths.d.ts.map +1 -0
  375. package/dist/relay/evaluation/relay-paths.js +504 -0
  376. package/dist/relay/evaluation/relay-paths.js.map +1 -0
  377. package/dist/relay/evaluation/rust-boundary.d.ts +47 -0
  378. package/dist/relay/evaluation/rust-boundary.d.ts.map +1 -0
  379. package/dist/relay/evaluation/rust-boundary.js +220 -0
  380. package/dist/relay/evaluation/rust-boundary.js.map +1 -0
  381. package/dist/relay/index.d.ts +37 -0
  382. package/dist/relay/index.d.ts.map +1 -0
  383. package/dist/relay/index.js +44 -0
  384. package/dist/relay/index.js.map +1 -0
  385. package/dist/relay/migrate.d.ts +18 -0
  386. package/dist/relay/migrate.d.ts.map +1 -0
  387. package/dist/relay/migrate.js +99 -0
  388. package/dist/relay/migrate.js.map +1 -0
  389. package/dist/relay/mode-manager.d.ts +60 -0
  390. package/dist/relay/mode-manager.d.ts.map +1 -0
  391. package/dist/relay/mode-manager.js +114 -0
  392. package/dist/relay/mode-manager.js.map +1 -0
  393. package/dist/relay/realtime.d.ts +90 -0
  394. package/dist/relay/realtime.d.ts.map +1 -0
  395. package/dist/relay/realtime.js +147 -0
  396. package/dist/relay/realtime.js.map +1 -0
  397. package/dist/relay/relay.d.ts +190 -0
  398. package/dist/relay/relay.d.ts.map +1 -0
  399. package/dist/relay/relay.js +320 -0
  400. package/dist/relay/relay.js.map +1 -0
  401. package/dist/relay/schema.d.ts +158 -0
  402. package/dist/relay/schema.d.ts.map +1 -0
  403. package/dist/relay/schema.js +7 -0
  404. package/dist/relay/schema.js.map +1 -0
  405. package/dist/relay/server-role/index.d.ts +56 -0
  406. package/dist/relay/server-role/index.d.ts.map +1 -0
  407. package/dist/relay/server-role/index.js +193 -0
  408. package/dist/relay/server-role/index.js.map +1 -0
  409. package/dist/relay/server-role/pull.d.ts +27 -0
  410. package/dist/relay/server-role/pull.d.ts.map +1 -0
  411. package/dist/relay/server-role/pull.js +24 -0
  412. package/dist/relay/server-role/pull.js.map +1 -0
  413. package/dist/relay/server-role/push.d.ts +29 -0
  414. package/dist/relay/server-role/push.d.ts.map +1 -0
  415. package/dist/relay/server-role/push.js +122 -0
  416. package/dist/relay/server-role/push.js.map +1 -0
  417. package/dist/s3/index.d.ts +83 -0
  418. package/dist/s3/index.d.ts.map +1 -0
  419. package/dist/s3/index.js +223 -0
  420. package/dist/s3/index.js.map +1 -0
  421. package/dist/schema.d.ts +137 -1
  422. package/dist/schema.d.ts.map +1 -1
  423. package/dist/schema.js +1 -0
  424. package/dist/schema.js.map +1 -1
  425. package/dist/service-worker/index.d.ts +114 -0
  426. package/dist/service-worker/index.d.ts.map +1 -0
  427. package/dist/service-worker/index.js +487 -0
  428. package/dist/service-worker/index.js.map +1 -0
  429. package/dist/snapshot-artifacts/sqlite-bun.d.ts +15 -0
  430. package/dist/snapshot-artifacts/sqlite-bun.d.ts.map +1 -0
  431. package/dist/snapshot-artifacts/sqlite-bun.js +128 -0
  432. package/dist/snapshot-artifacts/sqlite-bun.js.map +1 -0
  433. package/dist/snapshot-artifacts.d.ts +206 -0
  434. package/dist/snapshot-artifacts.d.ts.map +1 -0
  435. package/dist/snapshot-artifacts.js +545 -0
  436. package/dist/snapshot-artifacts.js.map +1 -0
  437. package/dist/snapshot-chunks/db-metadata.d.ts +18 -0
  438. package/dist/snapshot-chunks/db-metadata.d.ts.map +1 -1
  439. package/dist/snapshot-chunks/db-metadata.js +91 -63
  440. package/dist/snapshot-chunks/db-metadata.js.map +1 -1
  441. package/dist/snapshot-chunks/types.d.ts +2 -0
  442. package/dist/snapshot-chunks/types.d.ts.map +1 -1
  443. package/dist/snapshot-chunks.d.ts +33 -3
  444. package/dist/snapshot-chunks.d.ts.map +1 -1
  445. package/dist/snapshot-chunks.js +136 -55
  446. package/dist/snapshot-chunks.js.map +1 -1
  447. package/dist/sqlite/index.d.ts +53 -0
  448. package/dist/sqlite/index.d.ts.map +1 -0
  449. package/dist/sqlite/index.js +795 -0
  450. package/dist/sqlite/index.js.map +1 -0
  451. package/dist/sqlite3.d.ts +22 -0
  452. package/dist/sqlite3.d.ts.map +1 -0
  453. package/dist/sqlite3.js +99 -0
  454. package/dist/sqlite3.js.map +1 -0
  455. package/dist/stats.d.ts +8 -0
  456. package/dist/stats.d.ts.map +1 -1
  457. package/dist/stats.js +45 -13
  458. package/dist/stats.js.map +1 -1
  459. package/dist/subscriptions/cache.d.ts +3 -0
  460. package/dist/subscriptions/cache.d.ts.map +1 -1
  461. package/dist/subscriptions/cache.js +44 -0
  462. package/dist/subscriptions/cache.js.map +1 -1
  463. package/dist/subscriptions/resolve.d.ts +3 -1
  464. package/dist/subscriptions/resolve.d.ts.map +1 -1
  465. package/dist/subscriptions/resolve.js +90 -51
  466. package/dist/subscriptions/resolve.js.map +1 -1
  467. package/dist/sync.d.ts +3 -0
  468. package/dist/sync.d.ts.map +1 -1
  469. package/dist/sync.js +8 -4
  470. package/dist/sync.js.map +1 -1
  471. package/package.json +296 -7
  472. package/src/auth-leases.ts +649 -0
  473. package/src/better-sqlite3.ts +35 -0
  474. package/src/blobs/access.ts +244 -0
  475. package/src/blobs/adapters/database.ts +125 -43
  476. package/src/blobs/index.ts +1 -0
  477. package/src/blobs/manager.ts +366 -65
  478. package/src/blobs/migrate.ts +16 -8
  479. package/src/blobs/types.ts +4 -0
  480. package/src/bun-sqlite-ambient.d.ts +19 -0
  481. package/src/bun-sqlite.ts +27 -0
  482. package/src/clients.ts +1 -0
  483. package/src/cloudflare/durable-object.ts +289 -0
  484. package/src/cloudflare/index.ts +22 -0
  485. package/src/cloudflare/r2.ts +526 -0
  486. package/src/cloudflare/scope-cache.ts +341 -0
  487. package/src/cloudflare/sentry.ts +230 -0
  488. package/src/cloudflare/worker.ts +77 -0
  489. package/src/commit-integrity.ts +371 -0
  490. package/src/crdt-yjs/index.ts +931 -0
  491. package/src/d1.ts +16 -0
  492. package/src/dialect/base.ts +71 -5
  493. package/src/dialect/helpers.ts +31 -0
  494. package/src/dialect/types.ts +47 -0
  495. package/src/encrypted-crdt.ts +786 -0
  496. package/src/errors.ts +22 -0
  497. package/src/filesystem/index.ts +262 -0
  498. package/src/handlers/collection.ts +78 -78
  499. package/src/handlers/create-handler.ts +540 -147
  500. package/src/handlers/types.ts +116 -0
  501. package/src/helpers/index.ts +2 -0
  502. package/src/helpers/scope-authorization.ts +27 -0
  503. package/src/helpers/scope-commit-index.ts +52 -0
  504. package/src/hono/api-key-auth.ts +177 -0
  505. package/src/hono/audit-redaction.ts +135 -0
  506. package/src/hono/blobs.ts +851 -0
  507. package/src/hono/console/gateway.ts +3046 -0
  508. package/src/hono/console/live-auth.ts +46 -0
  509. package/src/hono/console/route-descriptor.ts +22 -0
  510. package/src/hono/console/routes/api-keys.ts +721 -0
  511. package/src/hono/console/routes/clients.ts +447 -0
  512. package/src/hono/console/routes/commits.ts +1137 -0
  513. package/src/hono/console/routes/context.ts +956 -0
  514. package/src/hono/console/routes/events.ts +669 -0
  515. package/src/hono/console/routes/maintenance.ts +461 -0
  516. package/src/hono/console/routes/shared.ts +816 -0
  517. package/src/hono/console/routes/stats.ts +392 -0
  518. package/src/hono/console/routes/storage.ts +159 -0
  519. package/src/hono/console/routes.ts +146 -0
  520. package/src/hono/console/schema-errors.ts +23 -0
  521. package/src/hono/console/schemas.ts +914 -0
  522. package/src/hono/console/types.ts +223 -0
  523. package/src/hono/console/ui.ts +100 -0
  524. package/src/hono/create-server.ts +230 -0
  525. package/src/hono/errors.ts +50 -0
  526. package/src/hono/index.ts +54 -0
  527. package/src/hono/openapi.ts +139 -0
  528. package/src/hono/proxy/connection-manager.ts +340 -0
  529. package/src/hono/proxy/index.ts +8 -0
  530. package/src/hono/proxy/routes.ts +272 -0
  531. package/src/hono/rate-limit.ts +319 -0
  532. package/src/hono/realtime-sync-packs.ts +354 -0
  533. package/src/hono/routes/audit.ts +499 -0
  534. package/src/hono/routes/auth-leases.ts +119 -0
  535. package/src/hono/routes/combined.ts +583 -0
  536. package/src/hono/routes/context.ts +1629 -0
  537. package/src/hono/routes/health.ts +26 -0
  538. package/src/hono/routes/realtime.ts +808 -0
  539. package/src/hono/routes/shared.ts +1626 -0
  540. package/src/hono/routes/snapshots.ts +345 -0
  541. package/src/hono/routes.ts +68 -0
  542. package/src/hono/validation.ts +81 -0
  543. package/src/hono/websocket-origin.ts +131 -0
  544. package/src/hono/ws.ts +1134 -0
  545. package/src/index.ts +6 -0
  546. package/src/libsql.ts +51 -0
  547. package/src/neon.ts +28 -0
  548. package/src/notify.ts +224 -44
  549. package/src/pglite.ts +68 -0
  550. package/src/plugins/index.ts +1 -0
  551. package/src/plugins/types.ts +144 -0
  552. package/src/postgres/index.ts +1291 -0
  553. package/src/proxy/collection.ts +5 -27
  554. package/src/proxy/handler.ts +2 -2
  555. package/src/proxy/index.ts +0 -2
  556. package/src/proxy/oplog.ts +41 -10
  557. package/src/prune.ts +137 -36
  558. package/src/pull.ts +1504 -591
  559. package/src/push.ts +881 -443
  560. package/src/realtime/index.ts +2 -0
  561. package/src/realtime/types.ts +35 -0
  562. package/src/relay/bun-types.d.ts +50 -0
  563. package/src/relay/client-role/forward-engine.ts +355 -0
  564. package/src/relay/client-role/index.ts +9 -0
  565. package/src/relay/client-role/pull-engine.ts +329 -0
  566. package/src/relay/client-role/sequence-mapper.ts +201 -0
  567. package/src/relay/evaluation/relay-paths.ts +699 -0
  568. package/src/relay/evaluation/rust-boundary.ts +464 -0
  569. package/src/relay/index.ts +50 -0
  570. package/src/relay/migrate.ts +113 -0
  571. package/src/relay/mode-manager.ts +142 -0
  572. package/src/relay/realtime.ts +207 -0
  573. package/src/relay/relay.ts +431 -0
  574. package/src/relay/schema.ts +171 -0
  575. package/src/relay/server-role/index.ts +338 -0
  576. package/src/relay/server-role/pull.ts +43 -0
  577. package/src/relay/server-role/push.ts +164 -0
  578. package/src/s3/index.ts +346 -0
  579. package/src/schema.ts +141 -1
  580. package/src/service-worker/index.ts +773 -0
  581. package/src/snapshot-artifacts/sqlite-bun.ts +168 -0
  582. package/src/snapshot-artifacts.ts +896 -0
  583. package/src/snapshot-chunks/db-metadata.ts +131 -72
  584. package/src/snapshot-chunks/types.ts +2 -0
  585. package/src/snapshot-chunks.ts +194 -70
  586. package/src/sqlite/index.ts +1064 -0
  587. package/src/sqlite3.ts +137 -0
  588. package/src/stats.ts +76 -13
  589. package/src/subscriptions/cache.ts +58 -0
  590. package/src/subscriptions/resolve.ts +99 -58
  591. package/src/sync.ts +16 -6
  592. package/src/blobs/adapters/database.test.ts +0 -67
  593. package/src/notify.test.ts +0 -520
  594. package/src/proxy/handler.test.ts +0 -126
  595. package/src/proxy/mutation-detector.test.ts +0 -71
  596. package/src/snapshot-chunks/db-metadata.test.ts +0 -172
  597. package/src/subscriptions/resolve.test.ts +0 -180
@@ -1,8 +1,12 @@
1
1
  import type {
2
+ BinarySnapshotColumn,
3
+ BinarySnapshotRowsEncoder,
2
4
  ScopePattern,
3
5
  ScopeValues,
4
6
  ScopeValuesForKeys,
5
7
  StoredScopes,
8
+ SyncAuthLeaseProvenance,
9
+ SyncChange,
6
10
  SyncOp,
7
11
  SyncOperation,
8
12
  SyncOperationResult,
@@ -43,6 +47,11 @@ export interface ApplyOperationResult {
43
47
  emittedChanges: EmittedChange[];
44
48
  }
45
49
 
50
+ export interface BatchApplyOperationInput {
51
+ op: SyncOperation;
52
+ opIndex: number;
53
+ }
54
+
46
55
  /**
47
56
  * Context for server operations.
48
57
  */
@@ -74,6 +83,11 @@ export interface ServerSnapshotContext<
74
83
  cursor: string | null;
75
84
  /** Max rows to return */
76
85
  limit: number;
86
+ /**
87
+ * Client schema version targeted by this snapshot.
88
+ * Use this to emit the correct generated client row shape for older clients.
89
+ */
90
+ schemaVersion: number;
77
91
  }
78
92
 
79
93
  /**
@@ -94,6 +108,11 @@ export interface ServerApplyOperationContext<
94
108
  * Use this to transform payloads from older client versions.
95
109
  */
96
110
  schemaVersion: number;
111
+ /**
112
+ * Auth lease provenance captured when the client queued the commit.
113
+ * This is audit/replay context only; handlers must still use current auth.
114
+ */
115
+ authLease?: SyncAuthLeaseProvenance;
97
116
  }
98
117
 
99
118
  /**
@@ -200,6 +219,35 @@ export interface ServerHandlerOptions<
200
219
  */
201
220
  snapshotChunkTtlMs?: number;
202
221
 
222
+ /**
223
+ * Stable binary snapshot column metadata. Generators should provide this for
224
+ * Rust/native clients so the server does not need to infer column order and
225
+ * value types from every snapshot chunk at runtime.
226
+ */
227
+ snapshotBinaryColumns?: readonly BinarySnapshotColumn[];
228
+
229
+ /**
230
+ * Version-aware binary snapshot column metadata. Returning null intentionally
231
+ * disables fallback to current metadata.
232
+ */
233
+ snapshotBinaryColumnsForVersion?: (
234
+ schemaVersion: number
235
+ ) => readonly BinarySnapshotColumn[] | null | undefined;
236
+
237
+ /**
238
+ * Optional generated binary snapshot encoder. When present, binary bootstrap
239
+ * chunks use this instead of the generic object-row encoder.
240
+ */
241
+ snapshotBinaryEncoder?: BinarySnapshotRowsEncoder;
242
+
243
+ /**
244
+ * Version-aware generated binary snapshot encoder. Returning null
245
+ * intentionally disables fallback to the current encoder.
246
+ */
247
+ snapshotBinaryEncoderForVersion?: (
248
+ schemaVersion: number
249
+ ) => BinarySnapshotRowsEncoder | null | undefined;
250
+
203
251
  /**
204
252
  * Transform client payload → server row on writes.
205
253
  */
@@ -245,6 +293,9 @@ export interface ServerTableHandler<
245
293
  /** Table name */
246
294
  table: string;
247
295
 
296
+ /** Primary key column for row ids and artifact/import metadata. */
297
+ primaryKeyColumn?: string;
298
+
248
299
  /** Scope patterns used by this handler */
249
300
  scopePatterns: ScopePattern[];
250
301
 
@@ -258,6 +309,58 @@ export interface ServerTableHandler<
258
309
  */
259
310
  snapshotChunkTtlMs?: number;
260
311
 
312
+ /**
313
+ * Stable binary snapshot column metadata used by binary bootstrap chunks.
314
+ */
315
+ snapshotBinaryColumns?: readonly BinarySnapshotColumn[];
316
+
317
+ /**
318
+ * Version-aware binary snapshot column metadata. Generated handlers should
319
+ * use this when old client schema versions can have different row shapes.
320
+ * Returning null intentionally disables fallback to current metadata.
321
+ */
322
+ snapshotBinaryColumnsForVersion?: (
323
+ schemaVersion: number
324
+ ) => readonly BinarySnapshotColumn[] | null | undefined;
325
+
326
+ /**
327
+ * Optional generated binary snapshot encoder used by binary bootstrap chunks.
328
+ */
329
+ snapshotBinaryEncoder?: BinarySnapshotRowsEncoder;
330
+
331
+ /**
332
+ * Version-aware binary snapshot encoder. Returning null intentionally
333
+ * disables fallback to the current generated encoder.
334
+ */
335
+ snapshotBinaryEncoderForVersion?: (
336
+ schemaVersion: number
337
+ ) => BinarySnapshotRowsEncoder | null | undefined;
338
+
339
+ /**
340
+ * Project a persisted incremental change row to the requested client schema
341
+ * before pull plugins, wire integrity, and response encoding run.
342
+ *
343
+ * Generated divergent-schema handlers use this to keep the commit log in the
344
+ * current client row shape while serving older clients their targeted row
345
+ * shape.
346
+ */
347
+ projectChangeForVersion?: (
348
+ change: SyncChange,
349
+ schemaVersion: number
350
+ ) => SyncChange;
351
+
352
+ /**
353
+ * Hint for push engine savepoint optimization on single-op commits.
354
+ *
355
+ * When true, the handler guarantees that a rejected single operation
356
+ * does not leave durable writes behind before returning the rejection.
357
+ * This allows pushCommit() to skip SAVEPOINT overhead for single-op
358
+ * commits on savepoint-capable dialects.
359
+ *
360
+ * Omit or set false for custom handlers unless this guarantee holds.
361
+ */
362
+ canRejectSingleOperationWithoutSavepoint?: boolean;
363
+
261
364
  /**
262
365
  * Resolve allowed scope values for the current actor.
263
366
  */
@@ -284,4 +387,17 @@ export interface ServerTableHandler<
284
387
  op: SyncOperation,
285
388
  opIndex: number
286
389
  ): Promise<ApplyOperationResult>;
390
+
391
+ /**
392
+ * Apply multiple operations in order.
393
+ *
394
+ * Implementations may internally batch writes but must preserve the same
395
+ * observable semantics as sequential applyOperation calls:
396
+ * - results are returned in operation order
397
+ * - processing stops at the first non-applied result
398
+ */
399
+ applyOperationBatch?(
400
+ ctx: ServerApplyOperationContext<DB, Auth>,
401
+ operations: BatchApplyOperationInput[]
402
+ ): Promise<ApplyOperationResult[]>;
287
403
  }
@@ -7,4 +7,6 @@
7
7
  export * from './conflict';
8
8
  export * from './emitted-change';
9
9
  export * from './paginate';
10
+ export * from './scope-authorization';
11
+ export * from './scope-commit-index';
10
12
  export * from './scope-strings';
@@ -0,0 +1,27 @@
1
+ import type { ScopeValues, StoredScopes } from '@syncular/core';
2
+
3
+ function scopeValueAllows(
4
+ allowed: ScopeValues[string] | undefined,
5
+ rowValue: string
6
+ ): boolean {
7
+ if (allowed === undefined) return false;
8
+ const allowedValues = Array.isArray(allowed) ? allowed : [allowed];
9
+ return allowedValues.includes('*') || allowedValues.includes(rowValue);
10
+ }
11
+
12
+ export function rowScopesAllowed(args: {
13
+ rowScopes: StoredScopes;
14
+ allowedScopes: ScopeValues;
15
+ requiredScopeKeys: readonly string[];
16
+ }): boolean {
17
+ for (const key of args.requiredScopeKeys) {
18
+ const rowValue = args.rowScopes[key];
19
+ if (typeof rowValue !== 'string' || rowValue.length === 0) {
20
+ return false;
21
+ }
22
+ if (!scopeValueAllows(args.allowedScopes[key], rowValue)) {
23
+ return false;
24
+ }
25
+ }
26
+ return true;
27
+ }
@@ -0,0 +1,52 @@
1
+ import type { ScopeValues, StoredScopes } from '@syncular/core';
2
+
3
+ export interface ScopeCommitIndexChange {
4
+ table: string;
5
+ scopes: ScopeValues | StoredScopes;
6
+ }
7
+
8
+ export interface ScopeCommitIndexEntry {
9
+ table: string;
10
+ scopeKey: string;
11
+ }
12
+
13
+ export function scopeKeysFromScopeValues(
14
+ scopes: ScopeValues | StoredScopes | null | undefined
15
+ ): string[] {
16
+ if (!scopes || typeof scopes !== 'object') return [];
17
+ const keys = new Set<string>();
18
+
19
+ for (const [key, rawValue] of Object.entries(scopes)) {
20
+ const prefix = key.replace(/_id$/, '');
21
+ const values = Array.isArray(rawValue) ? rawValue : [rawValue];
22
+ for (const value of values) {
23
+ if (typeof value === 'string') {
24
+ if (value.length > 0) keys.add(`${prefix}:${value}`);
25
+ continue;
26
+ }
27
+ if (typeof value === 'number' || typeof value === 'bigint') {
28
+ keys.add(`${prefix}:${String(value)}`);
29
+ }
30
+ }
31
+ }
32
+
33
+ return Array.from(keys);
34
+ }
35
+
36
+ export function createScopeCommitIndexEntries(
37
+ changes: readonly ScopeCommitIndexChange[]
38
+ ): ScopeCommitIndexEntry[] {
39
+ const entries = new Map<string, ScopeCommitIndexEntry>();
40
+
41
+ for (const change of changes) {
42
+ if (!change.table) continue;
43
+ for (const scopeKey of scopeKeysFromScopeValues(change.scopes)) {
44
+ const key = `${change.table}\u0000${scopeKey}`;
45
+ if (!entries.has(key)) {
46
+ entries.set(key, { table: change.table, scopeKey });
47
+ }
48
+ }
49
+ }
50
+
51
+ return Array.from(entries.values());
52
+ }
@@ -0,0 +1,177 @@
1
+ /**
2
+ * @syncular/server/hono - API Key Authentication Helper
3
+ *
4
+ * Provides utilities for validating API keys in relay/proxy routes.
5
+ */
6
+
7
+ import { sha256Hex } from '@syncular/core';
8
+ import type { ServerSyncDialect } from '@syncular/server';
9
+ import type { Context } from 'hono';
10
+ import { type Kysely, sql } from 'kysely';
11
+ import { type ApiKeyType, ApiKeyTypeSchema } from './console/schemas';
12
+ import { syncError } from './errors';
13
+
14
+ interface SyncApiKeysTable {
15
+ key_id: string;
16
+ key_hash: string;
17
+ key_prefix: string;
18
+ name: string;
19
+ key_type: string;
20
+ scope_keys: unknown | null;
21
+ actor_id: string | null;
22
+ created_at: string;
23
+ expires_at: string | null;
24
+ last_used_at: string | null;
25
+ revoked_at: string | null;
26
+ }
27
+
28
+ type ApiKeyDb = {
29
+ sync_api_keys: SyncApiKeysTable;
30
+ };
31
+
32
+ interface ValidateApiKeyResult {
33
+ keyId: string;
34
+ keyType: ApiKeyType;
35
+ actorId: string | null;
36
+ scopeKeys: string[];
37
+ }
38
+
39
+ /**
40
+ * Validates an API key from Authorization header.
41
+ * Updates last_used_at on successful validation.
42
+ */
43
+ export async function validateApiKey<DB extends ApiKeyDb>(
44
+ db: Kysely<DB>,
45
+ dialect: ServerSyncDialect,
46
+ authHeader: string | undefined
47
+ ): Promise<ValidateApiKeyResult | null> {
48
+ if (!authHeader?.startsWith('Bearer ')) {
49
+ return null;
50
+ }
51
+
52
+ const secretKey = authHeader.slice(7);
53
+ if (!secretKey?.startsWith('sk_')) {
54
+ return null;
55
+ }
56
+
57
+ // Hash the provided key
58
+ const keyHash = await hashApiKey(secretKey);
59
+
60
+ // Look up key by hash
61
+ const rowResult = await sql<{
62
+ key_id: string;
63
+ key_type: string;
64
+ actor_id: string | null;
65
+ scope_keys: unknown | null;
66
+ expires_at: string | null;
67
+ revoked_at: string | null;
68
+ }>`
69
+ select key_id, key_type, actor_id, scope_keys, expires_at, revoked_at
70
+ from ${sql.table('sync_api_keys')}
71
+ where key_hash = ${keyHash}
72
+ limit 1
73
+ `.execute(db);
74
+ const row = rowResult.rows[0];
75
+
76
+ if (!row) {
77
+ return null;
78
+ }
79
+
80
+ const parsedKeyType = ApiKeyTypeSchema.safeParse(row.key_type);
81
+ if (!parsedKeyType.success) return null;
82
+
83
+ // Check if revoked
84
+ if (row.revoked_at) {
85
+ return null;
86
+ }
87
+
88
+ // Check if expired
89
+ if (row.expires_at) {
90
+ const expiresAt = new Date(row.expires_at);
91
+ if (expiresAt < new Date()) {
92
+ return null;
93
+ }
94
+ }
95
+
96
+ // Update last_used_at
97
+ const now = new Date().toISOString();
98
+ await sql`
99
+ update ${sql.table('sync_api_keys')}
100
+ set last_used_at = ${now}
101
+ where key_id = ${row.key_id}
102
+ `.execute(db);
103
+
104
+ // Parse scopes
105
+ const scopeKeys = dialect.dbToArray(row.scope_keys);
106
+
107
+ return {
108
+ keyId: row.key_id,
109
+ keyType: parsedKeyType.data,
110
+ actorId: row.actor_id,
111
+ scopeKeys,
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Creates an authenticator for relay/proxy routes.
117
+ * Returns actorId from the API key if valid and allowed.
118
+ */
119
+ export function createApiKeyAuthenticator<DB extends ApiKeyDb>(
120
+ db: Kysely<DB>,
121
+ dialect: ServerSyncDialect,
122
+ allowedTypes: ApiKeyType[]
123
+ ): (c: Context) => Promise<{ actorId: string } | null> {
124
+ return async (c: Context) => {
125
+ const authHeader = c.req.header('Authorization');
126
+ const result = await validateApiKey(db, dialect, authHeader);
127
+
128
+ if (!result) {
129
+ return null;
130
+ }
131
+
132
+ // Check if key type is allowed
133
+ if (!allowedTypes.includes(result.keyType)) {
134
+ return null;
135
+ }
136
+
137
+ // Return actorId (use key's actorId if set, otherwise use a default)
138
+ return {
139
+ actorId: result.actorId ?? `api-key:${result.keyId}`,
140
+ };
141
+ };
142
+ }
143
+
144
+ /**
145
+ * Middleware that validates API key and attaches result to context.
146
+ */
147
+ export function apiKeyAuthMiddleware<DB extends ApiKeyDb>(
148
+ db: Kysely<DB>,
149
+ dialect: ServerSyncDialect,
150
+ allowedTypes: ApiKeyType[]
151
+ ) {
152
+ return async (
153
+ c: Context,
154
+ next: () => Promise<void>
155
+ ): Promise<Response | undefined> => {
156
+ const authHeader = c.req.header('Authorization');
157
+ const result = await validateApiKey(db, dialect, authHeader);
158
+
159
+ if (!result) {
160
+ return syncError(c, 401, 'sync.auth_required');
161
+ }
162
+
163
+ if (!allowedTypes.includes(result.keyType)) {
164
+ return syncError(c, 403, 'sync.forbidden', 'Invalid key type');
165
+ }
166
+
167
+ // Attach to context for downstream handlers
168
+ c.set('apiKey', result);
169
+
170
+ await next();
171
+ };
172
+ }
173
+
174
+ // Hash function (same as in routes.ts)
175
+ async function hashApiKey(secretKey: string): Promise<string> {
176
+ return sha256Hex(secretKey);
177
+ }
@@ -0,0 +1,135 @@
1
+ import {
2
+ parseJsonValue,
3
+ SYNC_CRDT_CHECKPOINTS_TABLE,
4
+ SYNC_CRDT_UPDATES_TABLE,
5
+ } from '@syncular/server';
6
+
7
+ type AuditChangeKind =
8
+ | 'app_row'
9
+ | 'delete'
10
+ | 'blob_reference'
11
+ | 'encrypted_field_envelope'
12
+ | 'encrypted_crdt_update'
13
+ | 'encrypted_crdt_checkpoint';
14
+
15
+ interface AuditChangeRedaction {
16
+ payload: 'omitted';
17
+ reason: 'audit_redacted_by_default';
18
+ }
19
+
20
+ interface AuditChangeSummary {
21
+ changeKind: AuditChangeKind;
22
+ fields: string[];
23
+ scopeFields: string[];
24
+ sensitiveFields: string[];
25
+ redaction: AuditChangeRedaction;
26
+ }
27
+
28
+ export function summarizeAuditChange(args: {
29
+ table: string;
30
+ op: 'upsert' | 'delete';
31
+ rowJson: unknown | null;
32
+ scopes: unknown;
33
+ }): AuditChangeSummary {
34
+ const row = parseJsonRecord(args.rowJson);
35
+ const fields = Object.keys(row).sort();
36
+ const sensitiveFields = detectSensitiveFields(row);
37
+
38
+ return {
39
+ changeKind: classifyAuditChange({
40
+ table: args.table,
41
+ op: args.op,
42
+ row,
43
+ sensitiveFields,
44
+ }),
45
+ fields,
46
+ scopeFields: Object.keys(parseJsonRecord(args.scopes)).sort(),
47
+ sensitiveFields,
48
+ redaction: {
49
+ payload: 'omitted',
50
+ reason: 'audit_redacted_by_default',
51
+ },
52
+ };
53
+ }
54
+
55
+ function classifyAuditChange(args: {
56
+ table: string;
57
+ op: 'upsert' | 'delete';
58
+ row: Record<string, unknown>;
59
+ sensitiveFields: string[];
60
+ }): AuditChangeKind {
61
+ if (args.table === SYNC_CRDT_UPDATES_TABLE) {
62
+ return 'encrypted_crdt_update';
63
+ }
64
+ if (args.table === SYNC_CRDT_CHECKPOINTS_TABLE) {
65
+ return 'encrypted_crdt_checkpoint';
66
+ }
67
+ if (args.op === 'delete') {
68
+ return 'delete';
69
+ }
70
+ if (args.sensitiveFields.some((field) => isEncryptedFieldName(field))) {
71
+ return 'encrypted_field_envelope';
72
+ }
73
+ if (args.sensitiveFields.length > 0) {
74
+ return 'blob_reference';
75
+ }
76
+ return 'app_row';
77
+ }
78
+
79
+ function detectSensitiveFields(row: Record<string, unknown>): string[] {
80
+ const sensitive = new Set<string>();
81
+
82
+ for (const [field, value] of Object.entries(row)) {
83
+ const parsed = parseJsonValue(value);
84
+ if (isEncryptedFieldName(field) || isEncryptedEnvelope(parsed)) {
85
+ sensitive.add(field);
86
+ continue;
87
+ }
88
+ if (isBlobRef(parsed)) {
89
+ sensitive.add(field);
90
+ }
91
+ }
92
+
93
+ return Array.from(sensitive).sort();
94
+ }
95
+
96
+ function parseJsonRecord(value: unknown): Record<string, unknown> {
97
+ const parsed = parseJsonValue(value);
98
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
99
+ return {};
100
+ }
101
+ return parsed as Record<string, unknown>;
102
+ }
103
+
104
+ function isBlobRef(value: unknown): boolean {
105
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
106
+ return false;
107
+ }
108
+ const record = value as Record<string, unknown>;
109
+ return (
110
+ typeof record.hash === 'string' &&
111
+ record.hash.length > 0 &&
112
+ (typeof record.size === 'number' || typeof record.size === 'bigint')
113
+ );
114
+ }
115
+
116
+ function isEncryptedEnvelope(value: unknown): boolean {
117
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
118
+ return false;
119
+ }
120
+ const record = value as Record<string, unknown>;
121
+ return (
122
+ typeof record.ciphertext === 'string' &&
123
+ (typeof record.key_id === 'string' || typeof record.keyId === 'string')
124
+ );
125
+ }
126
+
127
+ function isEncryptedFieldName(field: string): boolean {
128
+ return (
129
+ field === 'ciphertext' ||
130
+ field === 'key_id' ||
131
+ field === 'keyId' ||
132
+ field.endsWith('_encrypted') ||
133
+ field.endsWith('_ciphertext')
134
+ );
135
+ }