@syncular/server 0.0.6-96 → 0.1.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 (601) 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 +5 -4
  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 +43 -6
  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/index.js +3 -3
  84. package/dist/dialect/types.d.ts +40 -0
  85. package/dist/dialect/types.d.ts.map +1 -1
  86. package/dist/encrypted-crdt.d.ts +67 -0
  87. package/dist/encrypted-crdt.d.ts.map +1 -0
  88. package/dist/encrypted-crdt.js +426 -0
  89. package/dist/encrypted-crdt.js.map +1 -0
  90. package/dist/errors.d.ts +10 -0
  91. package/dist/errors.d.ts.map +1 -0
  92. package/dist/errors.js +13 -0
  93. package/dist/errors.js.map +1 -0
  94. package/dist/filesystem/index.d.ts +44 -0
  95. package/dist/filesystem/index.d.ts.map +1 -0
  96. package/dist/filesystem/index.js +164 -0
  97. package/dist/filesystem/index.js.map +1 -0
  98. package/dist/handlers/collection.d.ts +11 -3
  99. package/dist/handlers/collection.d.ts.map +1 -1
  100. package/dist/handlers/collection.js +34 -56
  101. package/dist/handlers/collection.js.map +1 -1
  102. package/dist/handlers/create-handler.d.ts +31 -7
  103. package/dist/handlers/create-handler.d.ts.map +1 -1
  104. package/dist/handlers/create-handler.js +332 -115
  105. package/dist/handlers/create-handler.js.map +1 -1
  106. package/dist/handlers/index.js +3 -3
  107. package/dist/handlers/types.d.ts +86 -1
  108. package/dist/handlers/types.d.ts.map +1 -1
  109. package/dist/helpers/conflict.js.map +1 -1
  110. package/dist/helpers/emitted-change.js.map +1 -1
  111. package/dist/helpers/index.d.ts +2 -0
  112. package/dist/helpers/index.d.ts.map +1 -1
  113. package/dist/helpers/index.js +6 -4
  114. package/dist/helpers/index.js.map +1 -1
  115. package/dist/helpers/paginate.js.map +1 -1
  116. package/dist/helpers/scope-authorization.d.ts +7 -0
  117. package/dist/helpers/scope-authorization.d.ts.map +1 -0
  118. package/dist/helpers/scope-authorization.js +19 -0
  119. package/dist/helpers/scope-authorization.js.map +1 -0
  120. package/dist/helpers/scope-commit-index.d.ts +12 -0
  121. package/dist/helpers/scope-commit-index.d.ts.map +1 -0
  122. package/dist/helpers/scope-commit-index.js +35 -0
  123. package/dist/helpers/scope-commit-index.js.map +1 -0
  124. package/dist/helpers/scope-strings.js.map +1 -1
  125. package/dist/hono/api-key-auth.d.ts +49 -0
  126. package/dist/hono/api-key-auth.d.ts.map +1 -0
  127. package/dist/hono/api-key-auth.js +108 -0
  128. package/dist/hono/api-key-auth.js.map +1 -0
  129. package/dist/hono/audit-redaction.d.ts +20 -0
  130. package/dist/hono/audit-redaction.d.ts.map +1 -0
  131. package/dist/hono/audit-redaction.js +85 -0
  132. package/dist/hono/audit-redaction.js.map +1 -0
  133. package/dist/hono/blobs.d.ts +75 -0
  134. package/dist/hono/blobs.d.ts.map +1 -0
  135. package/dist/hono/blobs.js +586 -0
  136. package/dist/hono/blobs.js.map +1 -0
  137. package/dist/hono/console/gateway.d.ts +42 -0
  138. package/dist/hono/console/gateway.d.ts.map +1 -0
  139. package/dist/hono/console/gateway.js +2158 -0
  140. package/dist/hono/console/gateway.js.map +1 -0
  141. package/dist/hono/console/live-auth.d.ts +7 -0
  142. package/dist/hono/console/live-auth.d.ts.map +1 -0
  143. package/dist/hono/console/live-auth.js +39 -0
  144. package/dist/hono/console/live-auth.js.map +1 -0
  145. package/dist/hono/console/route-descriptor.d.ts +6 -0
  146. package/dist/hono/console/route-descriptor.d.ts.map +1 -0
  147. package/dist/hono/console/route-descriptor.js +16 -0
  148. package/dist/hono/console/route-descriptor.js.map +1 -0
  149. package/dist/hono/console/routes/api-keys.d.ts +8 -0
  150. package/dist/hono/console/routes/api-keys.d.ts.map +1 -0
  151. package/dist/hono/console/routes/api-keys.js +575 -0
  152. package/dist/hono/console/routes/api-keys.js.map +1 -0
  153. package/dist/hono/console/routes/clients.d.ts +8 -0
  154. package/dist/hono/console/routes/clients.d.ts.map +1 -0
  155. package/dist/hono/console/routes/clients.js +322 -0
  156. package/dist/hono/console/routes/clients.js.map +1 -0
  157. package/dist/hono/console/routes/commits.d.ts +8 -0
  158. package/dist/hono/console/routes/commits.d.ts.map +1 -0
  159. package/dist/hono/console/routes/commits.js +882 -0
  160. package/dist/hono/console/routes/commits.js.map +1 -0
  161. package/dist/hono/console/routes/context.d.ts +188 -0
  162. package/dist/hono/console/routes/context.d.ts.map +1 -0
  163. package/dist/hono/console/routes/context.js +633 -0
  164. package/dist/hono/console/routes/context.js.map +1 -0
  165. package/dist/hono/console/routes/events.d.ts +8 -0
  166. package/dist/hono/console/routes/events.d.ts.map +1 -0
  167. package/dist/hono/console/routes/events.js +501 -0
  168. package/dist/hono/console/routes/events.js.map +1 -0
  169. package/dist/hono/console/routes/maintenance.d.ts +8 -0
  170. package/dist/hono/console/routes/maintenance.d.ts.map +1 -0
  171. package/dist/hono/console/routes/maintenance.js +341 -0
  172. package/dist/hono/console/routes/maintenance.js.map +1 -0
  173. package/dist/hono/console/routes/shared.d.ts +174 -0
  174. package/dist/hono/console/routes/shared.d.ts.map +1 -0
  175. package/dist/hono/console/routes/shared.js +583 -0
  176. package/dist/hono/console/routes/shared.js.map +1 -0
  177. package/dist/hono/console/routes/stats.d.ts +8 -0
  178. package/dist/hono/console/routes/stats.d.ts.map +1 -0
  179. package/dist/hono/console/routes/stats.js +295 -0
  180. package/dist/hono/console/routes/stats.js.map +1 -0
  181. package/dist/hono/console/routes/storage.d.ts +8 -0
  182. package/dist/hono/console/routes/storage.d.ts.map +1 -0
  183. package/dist/hono/console/routes/storage.js +121 -0
  184. package/dist/hono/console/routes/storage.js.map +1 -0
  185. package/dist/hono/console/routes.d.ts +36 -0
  186. package/dist/hono/console/routes.d.ts.map +1 -0
  187. package/dist/hono/console/routes.js +112 -0
  188. package/dist/hono/console/routes.js.map +1 -0
  189. package/dist/hono/console/schema-errors.d.ts +2 -0
  190. package/dist/hono/console/schema-errors.d.ts.map +1 -0
  191. package/dist/hono/console/schema-errors.js +17 -0
  192. package/dist/hono/console/schema-errors.js.map +1 -0
  193. package/dist/hono/console/schemas.d.ts +1515 -0
  194. package/dist/hono/console/schemas.d.ts.map +1 -0
  195. package/dist/hono/console/schemas.js +661 -0
  196. package/dist/hono/console/schemas.js.map +1 -0
  197. package/dist/hono/console/types.d.ts +213 -0
  198. package/dist/hono/console/types.d.ts.map +1 -0
  199. package/dist/hono/console/types.js +2 -0
  200. package/dist/hono/console/types.js.map +1 -0
  201. package/dist/hono/console/ui.d.ts +38 -0
  202. package/dist/hono/console/ui.d.ts.map +1 -0
  203. package/dist/hono/console/ui.js +43 -0
  204. package/dist/hono/console/ui.js.map +1 -0
  205. package/dist/hono/create-server.d.ts +71 -0
  206. package/dist/hono/create-server.d.ts.map +1 -0
  207. package/dist/hono/create-server.js +121 -0
  208. package/dist/hono/create-server.js.map +1 -0
  209. package/dist/hono/errors.d.ts +13 -0
  210. package/dist/hono/errors.d.ts.map +1 -0
  211. package/dist/hono/errors.js +21 -0
  212. package/dist/hono/errors.js.map +1 -0
  213. package/dist/hono/index.d.ts +20 -0
  214. package/dist/hono/index.d.ts.map +1 -0
  215. package/dist/hono/index.js +31 -0
  216. package/dist/hono/index.js.map +1 -0
  217. package/dist/hono/openapi.d.ts +72 -0
  218. package/dist/hono/openapi.d.ts.map +1 -0
  219. package/dist/hono/openapi.js +99 -0
  220. package/dist/hono/openapi.js.map +1 -0
  221. package/dist/hono/proxy/connection-manager.d.ts +78 -0
  222. package/dist/hono/proxy/connection-manager.d.ts.map +1 -0
  223. package/dist/hono/proxy/connection-manager.js +251 -0
  224. package/dist/hono/proxy/connection-manager.js.map +1 -0
  225. package/dist/hono/proxy/index.d.ts +8 -0
  226. package/dist/hono/proxy/index.d.ts.map +1 -0
  227. package/dist/hono/proxy/index.js +8 -0
  228. package/dist/hono/proxy/index.js.map +1 -0
  229. package/dist/hono/proxy/routes.d.ts +86 -0
  230. package/dist/hono/proxy/routes.d.ts.map +1 -0
  231. package/dist/hono/proxy/routes.js +183 -0
  232. package/dist/hono/proxy/routes.js.map +1 -0
  233. package/dist/hono/rate-limit.d.ts +101 -0
  234. package/dist/hono/rate-limit.d.ts.map +1 -0
  235. package/dist/hono/rate-limit.js +184 -0
  236. package/dist/hono/rate-limit.js.map +1 -0
  237. package/dist/hono/realtime-sync-packs.d.ts +43 -0
  238. package/dist/hono/realtime-sync-packs.d.ts.map +1 -0
  239. package/dist/hono/realtime-sync-packs.js +219 -0
  240. package/dist/hono/realtime-sync-packs.js.map +1 -0
  241. package/dist/hono/routes/audit.d.ts +12 -0
  242. package/dist/hono/routes/audit.d.ts.map +1 -0
  243. package/dist/hono/routes/audit.js +385 -0
  244. package/dist/hono/routes/audit.js.map +1 -0
  245. package/dist/hono/routes/auth-leases.d.ts +8 -0
  246. package/dist/hono/routes/auth-leases.d.ts.map +1 -0
  247. package/dist/hono/routes/auth-leases.js +88 -0
  248. package/dist/hono/routes/auth-leases.js.map +1 -0
  249. package/dist/hono/routes/combined.d.ts +8 -0
  250. package/dist/hono/routes/combined.d.ts.map +1 -0
  251. package/dist/hono/routes/combined.js +392 -0
  252. package/dist/hono/routes/combined.js.map +1 -0
  253. package/dist/hono/routes/context.d.ts +314 -0
  254. package/dist/hono/routes/context.d.ts.map +1 -0
  255. package/dist/hono/routes/context.js +1147 -0
  256. package/dist/hono/routes/context.js.map +1 -0
  257. package/dist/hono/routes/health.d.ts +8 -0
  258. package/dist/hono/routes/health.d.ts.map +1 -0
  259. package/dist/hono/routes/health.js +16 -0
  260. package/dist/hono/routes/health.js.map +1 -0
  261. package/dist/hono/routes/realtime.d.ts +9 -0
  262. package/dist/hono/routes/realtime.d.ts.map +1 -0
  263. package/dist/hono/routes/realtime.js +626 -0
  264. package/dist/hono/routes/realtime.js.map +1 -0
  265. package/dist/hono/routes/shared.d.ts +689 -0
  266. package/dist/hono/routes/shared.d.ts.map +1 -0
  267. package/dist/hono/routes/shared.js +972 -0
  268. package/dist/hono/routes/shared.js.map +1 -0
  269. package/dist/hono/routes/snapshots.d.ts +10 -0
  270. package/dist/hono/routes/snapshots.d.ts.map +1 -0
  271. package/dist/hono/routes/snapshots.js +281 -0
  272. package/dist/hono/routes/snapshots.js.map +1 -0
  273. package/dist/hono/routes.d.ts +19 -0
  274. package/dist/hono/routes.d.ts.map +1 -0
  275. package/dist/hono/routes.js +37 -0
  276. package/dist/hono/routes.js.map +1 -0
  277. package/dist/hono/validation.d.ts +5 -0
  278. package/dist/hono/validation.d.ts.map +1 -0
  279. package/dist/hono/validation.js +47 -0
  280. package/dist/hono/validation.js.map +1 -0
  281. package/dist/hono/websocket-origin.d.ts +9 -0
  282. package/dist/hono/websocket-origin.d.ts.map +1 -0
  283. package/dist/hono/websocket-origin.js +96 -0
  284. package/dist/hono/websocket-origin.js.map +1 -0
  285. package/dist/hono/ws.d.ts +341 -0
  286. package/dist/hono/ws.d.ts.map +1 -0
  287. package/dist/hono/ws.js +711 -0
  288. package/dist/hono/ws.js.map +1 -0
  289. package/dist/index.d.ts +6 -0
  290. package/dist/index.d.ts.map +1 -1
  291. package/dist/index.js +24 -18
  292. package/dist/index.js.map +1 -1
  293. package/dist/libsql.d.ts +29 -0
  294. package/dist/libsql.d.ts.map +1 -0
  295. package/dist/libsql.js +25 -0
  296. package/dist/libsql.js.map +1 -0
  297. package/dist/migrate.js.map +1 -1
  298. package/dist/neon.d.ts +21 -0
  299. package/dist/neon.d.ts.map +1 -0
  300. package/dist/neon.js +22 -0
  301. package/dist/neon.js.map +1 -0
  302. package/dist/notify.d.ts +30 -0
  303. package/dist/notify.d.ts.map +1 -1
  304. package/dist/notify.js +160 -41
  305. package/dist/notify.js.map +1 -1
  306. package/dist/pglite.d.ts +37 -0
  307. package/dist/pglite.d.ts.map +1 -0
  308. package/dist/pglite.js +37 -0
  309. package/dist/pglite.js.map +1 -0
  310. package/dist/plugins/index.d.ts +2 -0
  311. package/dist/plugins/index.d.ts.map +1 -0
  312. package/dist/plugins/index.js +2 -0
  313. package/dist/plugins/index.js.map +1 -0
  314. package/dist/plugins/types.d.ts +73 -0
  315. package/dist/plugins/types.d.ts.map +1 -0
  316. package/dist/plugins/types.js +30 -0
  317. package/dist/plugins/types.js.map +1 -0
  318. package/dist/postgres/index.d.ts +68 -0
  319. package/dist/postgres/index.d.ts.map +1 -0
  320. package/dist/postgres/index.js +924 -0
  321. package/dist/postgres/index.js.map +1 -0
  322. package/dist/proxy/collection.d.ts +0 -2
  323. package/dist/proxy/collection.d.ts.map +1 -1
  324. package/dist/proxy/collection.js +2 -17
  325. package/dist/proxy/collection.js.map +1 -1
  326. package/dist/proxy/handler.d.ts +1 -1
  327. package/dist/proxy/handler.d.ts.map +1 -1
  328. package/dist/proxy/handler.js +3 -4
  329. package/dist/proxy/handler.js.map +1 -1
  330. package/dist/proxy/index.d.ts +1 -1
  331. package/dist/proxy/index.d.ts.map +1 -1
  332. package/dist/proxy/index.js +3 -3
  333. package/dist/proxy/index.js.map +1 -1
  334. package/dist/proxy/mutation-detector.js.map +1 -1
  335. package/dist/proxy/oplog.d.ts.map +1 -1
  336. package/dist/proxy/oplog.js +32 -8
  337. package/dist/proxy/oplog.js.map +1 -1
  338. package/dist/prune.d.ts +8 -1
  339. package/dist/prune.d.ts.map +1 -1
  340. package/dist/prune.js +68 -28
  341. package/dist/prune.js.map +1 -1
  342. package/dist/pull.d.ts +31 -0
  343. package/dist/pull.d.ts.map +1 -1
  344. package/dist/pull.js +1014 -474
  345. package/dist/pull.js.map +1 -1
  346. package/dist/push.d.ts +36 -2
  347. package/dist/push.d.ts.map +1 -1
  348. package/dist/push.js +603 -358
  349. package/dist/push.js.map +1 -1
  350. package/dist/realtime/in-memory.js.map +1 -1
  351. package/dist/realtime/index.d.ts +2 -1
  352. package/dist/realtime/index.d.ts.map +1 -1
  353. package/dist/realtime/index.js +2 -1
  354. package/dist/realtime/index.js.map +1 -1
  355. package/dist/realtime/types.d.ts +12 -0
  356. package/dist/realtime/types.d.ts.map +1 -1
  357. package/dist/realtime/types.js +13 -1
  358. package/dist/realtime/types.js.map +1 -1
  359. package/dist/relay/client-role/forward-engine.d.ts +63 -0
  360. package/dist/relay/client-role/forward-engine.d.ts.map +1 -0
  361. package/dist/relay/client-role/forward-engine.js +267 -0
  362. package/dist/relay/client-role/forward-engine.js.map +1 -0
  363. package/dist/relay/client-role/index.d.ts +9 -0
  364. package/dist/relay/client-role/index.d.ts.map +1 -0
  365. package/dist/relay/client-role/index.js +9 -0
  366. package/dist/relay/client-role/index.js.map +1 -0
  367. package/dist/relay/client-role/pull-engine.d.ts +72 -0
  368. package/dist/relay/client-role/pull-engine.d.ts.map +1 -0
  369. package/dist/relay/client-role/pull-engine.js +249 -0
  370. package/dist/relay/client-role/pull-engine.js.map +1 -0
  371. package/dist/relay/client-role/sequence-mapper.d.ts +65 -0
  372. package/dist/relay/client-role/sequence-mapper.d.ts.map +1 -0
  373. package/dist/relay/client-role/sequence-mapper.js +161 -0
  374. package/dist/relay/client-role/sequence-mapper.js.map +1 -0
  375. package/dist/relay/evaluation/relay-paths.d.ts +41 -0
  376. package/dist/relay/evaluation/relay-paths.d.ts.map +1 -0
  377. package/dist/relay/evaluation/relay-paths.js +504 -0
  378. package/dist/relay/evaluation/relay-paths.js.map +1 -0
  379. package/dist/relay/evaluation/rust-boundary.d.ts +47 -0
  380. package/dist/relay/evaluation/rust-boundary.d.ts.map +1 -0
  381. package/dist/relay/evaluation/rust-boundary.js +220 -0
  382. package/dist/relay/evaluation/rust-boundary.js.map +1 -0
  383. package/dist/relay/index.d.ts +37 -0
  384. package/dist/relay/index.d.ts.map +1 -0
  385. package/dist/relay/index.js +44 -0
  386. package/dist/relay/index.js.map +1 -0
  387. package/dist/relay/migrate.d.ts +18 -0
  388. package/dist/relay/migrate.d.ts.map +1 -0
  389. package/dist/relay/migrate.js +99 -0
  390. package/dist/relay/migrate.js.map +1 -0
  391. package/dist/relay/mode-manager.d.ts +60 -0
  392. package/dist/relay/mode-manager.d.ts.map +1 -0
  393. package/dist/relay/mode-manager.js +114 -0
  394. package/dist/relay/mode-manager.js.map +1 -0
  395. package/dist/relay/realtime.d.ts +90 -0
  396. package/dist/relay/realtime.d.ts.map +1 -0
  397. package/dist/relay/realtime.js +147 -0
  398. package/dist/relay/realtime.js.map +1 -0
  399. package/dist/relay/relay.d.ts +190 -0
  400. package/dist/relay/relay.d.ts.map +1 -0
  401. package/dist/relay/relay.js +320 -0
  402. package/dist/relay/relay.js.map +1 -0
  403. package/dist/relay/schema.d.ts +158 -0
  404. package/dist/relay/schema.d.ts.map +1 -0
  405. package/dist/relay/schema.js +7 -0
  406. package/dist/relay/schema.js.map +1 -0
  407. package/dist/relay/server-role/index.d.ts +56 -0
  408. package/dist/relay/server-role/index.d.ts.map +1 -0
  409. package/dist/relay/server-role/index.js +193 -0
  410. package/dist/relay/server-role/index.js.map +1 -0
  411. package/dist/relay/server-role/pull.d.ts +27 -0
  412. package/dist/relay/server-role/pull.d.ts.map +1 -0
  413. package/dist/relay/server-role/pull.js +24 -0
  414. package/dist/relay/server-role/pull.js.map +1 -0
  415. package/dist/relay/server-role/push.d.ts +29 -0
  416. package/dist/relay/server-role/push.d.ts.map +1 -0
  417. package/dist/relay/server-role/push.js +122 -0
  418. package/dist/relay/server-role/push.js.map +1 -0
  419. package/dist/s3/index.d.ts +83 -0
  420. package/dist/s3/index.d.ts.map +1 -0
  421. package/dist/s3/index.js +223 -0
  422. package/dist/s3/index.js.map +1 -0
  423. package/dist/schema.d.ts +137 -1
  424. package/dist/schema.d.ts.map +1 -1
  425. package/dist/schema.js +1 -0
  426. package/dist/schema.js.map +1 -1
  427. package/dist/service-worker/index.d.ts +114 -0
  428. package/dist/service-worker/index.d.ts.map +1 -0
  429. package/dist/service-worker/index.js +487 -0
  430. package/dist/service-worker/index.js.map +1 -0
  431. package/dist/snapshot-artifacts/sqlite-bun.d.ts +15 -0
  432. package/dist/snapshot-artifacts/sqlite-bun.d.ts.map +1 -0
  433. package/dist/snapshot-artifacts/sqlite-bun.js +128 -0
  434. package/dist/snapshot-artifacts/sqlite-bun.js.map +1 -0
  435. package/dist/snapshot-artifacts.d.ts +206 -0
  436. package/dist/snapshot-artifacts.d.ts.map +1 -0
  437. package/dist/snapshot-artifacts.js +545 -0
  438. package/dist/snapshot-artifacts.js.map +1 -0
  439. package/dist/snapshot-chunks/db-metadata.d.ts +18 -0
  440. package/dist/snapshot-chunks/db-metadata.d.ts.map +1 -1
  441. package/dist/snapshot-chunks/db-metadata.js +91 -63
  442. package/dist/snapshot-chunks/db-metadata.js.map +1 -1
  443. package/dist/snapshot-chunks/index.js +2 -2
  444. package/dist/snapshot-chunks/types.d.ts +2 -0
  445. package/dist/snapshot-chunks/types.d.ts.map +1 -1
  446. package/dist/snapshot-chunks.d.ts +33 -3
  447. package/dist/snapshot-chunks.d.ts.map +1 -1
  448. package/dist/snapshot-chunks.js +136 -55
  449. package/dist/snapshot-chunks.js.map +1 -1
  450. package/dist/sqlite/index.d.ts +53 -0
  451. package/dist/sqlite/index.d.ts.map +1 -0
  452. package/dist/sqlite/index.js +795 -0
  453. package/dist/sqlite/index.js.map +1 -0
  454. package/dist/sqlite3.d.ts +22 -0
  455. package/dist/sqlite3.d.ts.map +1 -0
  456. package/dist/sqlite3.js +99 -0
  457. package/dist/sqlite3.js.map +1 -0
  458. package/dist/stats.d.ts +8 -0
  459. package/dist/stats.d.ts.map +1 -1
  460. package/dist/stats.js +45 -13
  461. package/dist/stats.js.map +1 -1
  462. package/dist/subscriptions/cache.d.ts +3 -0
  463. package/dist/subscriptions/cache.d.ts.map +1 -1
  464. package/dist/subscriptions/cache.js +44 -0
  465. package/dist/subscriptions/cache.js.map +1 -1
  466. package/dist/subscriptions/index.js +2 -2
  467. package/dist/subscriptions/resolve.d.ts +3 -1
  468. package/dist/subscriptions/resolve.d.ts.map +1 -1
  469. package/dist/subscriptions/resolve.js +91 -52
  470. package/dist/subscriptions/resolve.js.map +1 -1
  471. package/dist/sync.d.ts +3 -0
  472. package/dist/sync.d.ts.map +1 -1
  473. package/dist/sync.js +9 -5
  474. package/dist/sync.js.map +1 -1
  475. package/package.json +297 -8
  476. package/src/auth-leases.ts +649 -0
  477. package/src/better-sqlite3.ts +35 -0
  478. package/src/blobs/access.ts +244 -0
  479. package/src/blobs/adapters/database.ts +125 -43
  480. package/src/blobs/index.ts +1 -0
  481. package/src/blobs/manager.ts +366 -65
  482. package/src/blobs/migrate.ts +16 -8
  483. package/src/blobs/types.ts +4 -0
  484. package/src/bun-sqlite-ambient.d.ts +19 -0
  485. package/src/bun-sqlite.ts +27 -0
  486. package/src/clients.ts +1 -0
  487. package/src/cloudflare/durable-object.ts +289 -0
  488. package/src/cloudflare/index.ts +22 -0
  489. package/src/cloudflare/r2.ts +526 -0
  490. package/src/cloudflare/scope-cache.ts +341 -0
  491. package/src/cloudflare/sentry.ts +230 -0
  492. package/src/cloudflare/worker.ts +77 -0
  493. package/src/commit-integrity.ts +371 -0
  494. package/src/crdt-yjs/index.ts +931 -0
  495. package/src/d1.ts +16 -0
  496. package/src/dialect/base.ts +71 -5
  497. package/src/dialect/helpers.ts +31 -0
  498. package/src/dialect/types.ts +47 -0
  499. package/src/encrypted-crdt.ts +786 -0
  500. package/src/errors.ts +22 -0
  501. package/src/filesystem/index.ts +262 -0
  502. package/src/handlers/collection.ts +78 -78
  503. package/src/handlers/create-handler.ts +540 -147
  504. package/src/handlers/types.ts +116 -0
  505. package/src/helpers/index.ts +2 -0
  506. package/src/helpers/scope-authorization.ts +27 -0
  507. package/src/helpers/scope-commit-index.ts +52 -0
  508. package/src/hono/api-key-auth.ts +177 -0
  509. package/src/hono/audit-redaction.ts +135 -0
  510. package/src/hono/blobs.ts +851 -0
  511. package/src/hono/console/gateway.ts +3046 -0
  512. package/src/hono/console/live-auth.ts +46 -0
  513. package/src/hono/console/route-descriptor.ts +22 -0
  514. package/src/hono/console/routes/api-keys.ts +721 -0
  515. package/src/hono/console/routes/clients.ts +447 -0
  516. package/src/hono/console/routes/commits.ts +1137 -0
  517. package/src/hono/console/routes/context.ts +956 -0
  518. package/src/hono/console/routes/events.ts +669 -0
  519. package/src/hono/console/routes/maintenance.ts +461 -0
  520. package/src/hono/console/routes/shared.ts +816 -0
  521. package/src/hono/console/routes/stats.ts +392 -0
  522. package/src/hono/console/routes/storage.ts +159 -0
  523. package/src/hono/console/routes.ts +146 -0
  524. package/src/hono/console/schema-errors.ts +23 -0
  525. package/src/hono/console/schemas.ts +914 -0
  526. package/src/hono/console/types.ts +223 -0
  527. package/src/hono/console/ui.ts +100 -0
  528. package/src/hono/create-server.ts +230 -0
  529. package/src/hono/errors.ts +50 -0
  530. package/src/hono/index.ts +54 -0
  531. package/src/hono/openapi.ts +139 -0
  532. package/src/hono/proxy/connection-manager.ts +340 -0
  533. package/src/hono/proxy/index.ts +8 -0
  534. package/src/hono/proxy/routes.ts +272 -0
  535. package/src/hono/rate-limit.ts +319 -0
  536. package/src/hono/realtime-sync-packs.ts +354 -0
  537. package/src/hono/routes/audit.ts +499 -0
  538. package/src/hono/routes/auth-leases.ts +119 -0
  539. package/src/hono/routes/combined.ts +583 -0
  540. package/src/hono/routes/context.ts +1629 -0
  541. package/src/hono/routes/health.ts +26 -0
  542. package/src/hono/routes/realtime.ts +808 -0
  543. package/src/hono/routes/shared.ts +1626 -0
  544. package/src/hono/routes/snapshots.ts +345 -0
  545. package/src/hono/routes.ts +68 -0
  546. package/src/hono/validation.ts +81 -0
  547. package/src/hono/websocket-origin.ts +131 -0
  548. package/src/hono/ws.ts +1134 -0
  549. package/src/index.ts +6 -0
  550. package/src/libsql.ts +51 -0
  551. package/src/neon.ts +28 -0
  552. package/src/notify.ts +224 -44
  553. package/src/pglite.ts +68 -0
  554. package/src/plugins/index.ts +1 -0
  555. package/src/plugins/types.ts +144 -0
  556. package/src/postgres/index.ts +1291 -0
  557. package/src/proxy/collection.ts +5 -27
  558. package/src/proxy/handler.ts +2 -2
  559. package/src/proxy/index.ts +0 -2
  560. package/src/proxy/oplog.ts +41 -10
  561. package/src/prune.ts +137 -36
  562. package/src/pull.ts +1504 -591
  563. package/src/push.ts +881 -443
  564. package/src/realtime/index.ts +2 -0
  565. package/src/realtime/types.ts +35 -0
  566. package/src/relay/bun-types.d.ts +50 -0
  567. package/src/relay/client-role/forward-engine.ts +355 -0
  568. package/src/relay/client-role/index.ts +9 -0
  569. package/src/relay/client-role/pull-engine.ts +329 -0
  570. package/src/relay/client-role/sequence-mapper.ts +201 -0
  571. package/src/relay/evaluation/relay-paths.ts +699 -0
  572. package/src/relay/evaluation/rust-boundary.ts +464 -0
  573. package/src/relay/index.ts +50 -0
  574. package/src/relay/migrate.ts +113 -0
  575. package/src/relay/mode-manager.ts +142 -0
  576. package/src/relay/realtime.ts +207 -0
  577. package/src/relay/relay.ts +431 -0
  578. package/src/relay/schema.ts +171 -0
  579. package/src/relay/server-role/index.ts +338 -0
  580. package/src/relay/server-role/pull.ts +43 -0
  581. package/src/relay/server-role/push.ts +164 -0
  582. package/src/s3/index.ts +346 -0
  583. package/src/schema.ts +141 -1
  584. package/src/service-worker/index.ts +773 -0
  585. package/src/snapshot-artifacts/sqlite-bun.ts +168 -0
  586. package/src/snapshot-artifacts.ts +896 -0
  587. package/src/snapshot-chunks/db-metadata.ts +131 -72
  588. package/src/snapshot-chunks/types.ts +2 -0
  589. package/src/snapshot-chunks.ts +194 -70
  590. package/src/sqlite/index.ts +1064 -0
  591. package/src/sqlite3.ts +137 -0
  592. package/src/stats.ts +76 -13
  593. package/src/subscriptions/cache.ts +58 -0
  594. package/src/subscriptions/resolve.ts +99 -58
  595. package/src/sync.ts +16 -6
  596. package/src/blobs/adapters/database.test.ts +0 -67
  597. package/src/notify.test.ts +0 -520
  598. package/src/proxy/handler.test.ts +0 -126
  599. package/src/proxy/mutation-detector.test.ts +0 -71
  600. package/src/snapshot-chunks/db-metadata.test.ts +0 -172
  601. package/src/subscriptions/resolve.test.ts +0 -180
@@ -0,0 +1,649 @@
1
+ import {
2
+ collectScopeVars,
3
+ type ScopeValues,
4
+ type StoredScopes,
5
+ SYNC_AUTH_LEASE_ALG_ES256,
6
+ SYNC_AUTH_LEASE_CODE_EXPIRED,
7
+ SYNC_AUTH_LEASE_CODE_INVALID,
8
+ SYNC_AUTH_LEASE_CODE_SCHEMA_MISMATCH,
9
+ SYNC_AUTH_LEASE_CODE_SCOPE_MISMATCH,
10
+ SYNC_AUTH_LEASE_CODE_SCOPE_REVOKED,
11
+ SYNC_AUTH_LEASE_PROTOCOL_VERSION,
12
+ SYNC_AUTH_LEASE_TYP,
13
+ SYNC_AUTH_LEASE_VERSION,
14
+ type SyncAuthLeaseCapabilities,
15
+ type SyncAuthLeaseIssueRequest,
16
+ type SyncAuthLeaseIssueResponse,
17
+ type SyncAuthLeasePayload,
18
+ SyncAuthLeasePayloadSchema,
19
+ type SyncAuthLeaseProtectedHeader,
20
+ type SyncOperation,
21
+ type SyncOperationResult,
22
+ } from '@syncular/core';
23
+ import { type Kysely, sql } from 'kysely';
24
+ import type { DbExecutor } from './dialect/types';
25
+ import type { ServerHandlerCollection } from './handlers';
26
+ import type { ServerTableHandler, SyncServerAuth } from './handlers/types';
27
+ import type { SyncCoreDb } from './schema';
28
+ import { resolveEffectiveScopesForSubscriptions } from './subscriptions';
29
+ import type { ScopeCacheBackend } from './subscriptions/cache';
30
+
31
+ const textEncoder = new TextEncoder();
32
+ const textDecoder = new TextDecoder();
33
+
34
+ export interface AuthLeaseSignedToken {
35
+ ok: true;
36
+ token: string;
37
+ protectedHeader: SyncAuthLeaseProtectedHeader;
38
+ payload: SyncAuthLeasePayload;
39
+ }
40
+
41
+ export interface AuthLeaseSigningInput {
42
+ protectedHeader: SyncAuthLeaseProtectedHeader;
43
+ payload: SyncAuthLeasePayload;
44
+ signingInput: string;
45
+ }
46
+
47
+ export type AuthLeaseSigner = (
48
+ input: AuthLeaseSigningInput
49
+ ) => Promise<Uint8Array>;
50
+
51
+ export interface AuthLeaseIssueOptions<
52
+ DB extends SyncCoreDb,
53
+ Auth extends SyncServerAuth,
54
+ > {
55
+ db: Kysely<DB>;
56
+ auth: Auth;
57
+ handlers: ServerHandlerCollection<DB, Auth>;
58
+ request: SyncAuthLeaseIssueRequest;
59
+ issuer: string;
60
+ audience: string;
61
+ kid: string;
62
+ signer: AuthLeaseSigner;
63
+ capabilities?: SyncAuthLeaseCapabilities;
64
+ maxClockSkewMs?: number;
65
+ defaultTtlMs?: number;
66
+ maxTtlMs?: number;
67
+ nowMs?: () => number;
68
+ leaseId?: () => string;
69
+ scopeCache?: ScopeCacheBackend;
70
+ subject?: (
71
+ auth: Auth
72
+ ) => Record<string, unknown> | Promise<Record<string, unknown>>;
73
+ }
74
+
75
+ export interface AuthLeaseVerificationSuccess {
76
+ ok: true;
77
+ protectedHeader: SyncAuthLeaseProtectedHeader;
78
+ payload: SyncAuthLeasePayload;
79
+ }
80
+
81
+ export interface AuthLeaseVerificationFailure {
82
+ ok: false;
83
+ code: string;
84
+ message: string;
85
+ leaseId?: string;
86
+ kid?: string;
87
+ expiresAtMs?: number;
88
+ }
89
+
90
+ export type AuthLeaseVerificationResult =
91
+ | AuthLeaseVerificationSuccess
92
+ | AuthLeaseVerificationFailure;
93
+
94
+ export interface VerifyAuthLeaseTokenOptions {
95
+ token: string;
96
+ publicKey: CryptoKey;
97
+ nowMs?: number;
98
+ expectedIssuer?: string;
99
+ expectedAudience?: string;
100
+ expectedSchemaVersion?: number;
101
+ }
102
+
103
+ export interface ValidateAuthLeaseOperationOptions<
104
+ DB extends SyncCoreDb,
105
+ Auth extends SyncServerAuth,
106
+ > {
107
+ db: DbExecutor<DB>;
108
+ auth: Auth;
109
+ handler: ServerTableHandler<DB, Auth>;
110
+ payload: SyncAuthLeasePayload;
111
+ operation: SyncOperation;
112
+ opIndex: number;
113
+ }
114
+
115
+ export async function issueAuthLease<
116
+ DB extends SyncCoreDb,
117
+ Auth extends SyncServerAuth,
118
+ >(
119
+ options: AuthLeaseIssueOptions<DB, Auth>
120
+ ): Promise<SyncAuthLeaseIssueResponse | null> {
121
+ const nowMs = options.nowMs?.() ?? Date.now();
122
+ const defaultTtlMs = positiveIntegerOrDefault(
123
+ options.defaultTtlMs,
124
+ 15 * 60 * 1000
125
+ );
126
+ const maxTtlMs = positiveIntegerOrDefault(options.maxTtlMs, defaultTtlMs);
127
+ const requestedTtlMs = positiveIntegerOrDefault(
128
+ options.request.ttlMs,
129
+ defaultTtlMs
130
+ );
131
+ const ttlMs = Math.min(requestedTtlMs, maxTtlMs);
132
+ const requestedSubscriptions = options.request.scopes.map((scope) => ({
133
+ id: scope.subscriptionId,
134
+ table: scope.table,
135
+ scopes: scope.values,
136
+ params: {},
137
+ cursor: -1,
138
+ crdtStateVectors: [],
139
+ }));
140
+ const resolved = await resolveEffectiveScopesForSubscriptions({
141
+ db: options.db,
142
+ auth: options.auth,
143
+ handlers: options.handlers,
144
+ scopeCache: options.scopeCache,
145
+ subscriptions: requestedSubscriptions,
146
+ });
147
+ const scopes = resolved
148
+ .filter((subscription) => subscription.status === 'active')
149
+ .map((subscription) => {
150
+ const requested = options.request.scopes.find(
151
+ (scope) => scope.subscriptionId === subscription.id
152
+ );
153
+ return {
154
+ subscriptionId: subscription.id,
155
+ table: subscription.table,
156
+ values: subscription.scopes,
157
+ operations: requested?.operations ?? [],
158
+ };
159
+ })
160
+ .filter((scope) => scope.operations.length > 0);
161
+
162
+ if (scopes.length === 0) {
163
+ return null;
164
+ }
165
+
166
+ const payload: SyncAuthLeasePayload = {
167
+ version: SYNC_AUTH_LEASE_VERSION,
168
+ leaseId: options.leaseId?.() ?? randomLeaseId(),
169
+ issuer: options.issuer,
170
+ audience: options.audience,
171
+ actorId: options.auth.actorId,
172
+ subject: (await options.subject?.(options.auth)) ?? {},
173
+ schemaVersion: options.request.schemaVersion,
174
+ protocolVersion: SYNC_AUTH_LEASE_PROTOCOL_VERSION,
175
+ issuedAtMs: nowMs,
176
+ notBeforeMs: nowMs,
177
+ expiresAtMs: nowMs + ttlMs,
178
+ maxClockSkewMs: Math.max(0, options.maxClockSkewMs ?? 30_000),
179
+ scopes,
180
+ capabilities: options.capabilities ?? {
181
+ allowBlobs: false,
182
+ allowCrdt: false,
183
+ allowEncryptedFields: false,
184
+ },
185
+ };
186
+
187
+ return signAuthLeaseToken({
188
+ kid: options.kid,
189
+ payload,
190
+ signer: options.signer,
191
+ });
192
+ }
193
+
194
+ export async function signAuthLeaseToken(args: {
195
+ kid: string;
196
+ payload: SyncAuthLeasePayload;
197
+ signer: AuthLeaseSigner;
198
+ }): Promise<AuthLeaseSignedToken> {
199
+ const protectedHeader: SyncAuthLeaseProtectedHeader = {
200
+ alg: SYNC_AUTH_LEASE_ALG_ES256,
201
+ kid: args.kid,
202
+ typ: SYNC_AUTH_LEASE_TYP,
203
+ };
204
+ const payload = SyncAuthLeasePayloadSchema.parse(args.payload);
205
+ const signingInput = `${encodeJsonSegment(protectedHeader)}.${encodeJsonSegment(
206
+ payload
207
+ )}`;
208
+ const signature = await args.signer({
209
+ protectedHeader,
210
+ payload,
211
+ signingInput,
212
+ });
213
+ return {
214
+ ok: true,
215
+ token: `${signingInput}.${base64UrlEncode(signature)}`,
216
+ protectedHeader,
217
+ payload,
218
+ };
219
+ }
220
+
221
+ export function createWebCryptoEs256AuthLeaseSigner(args: {
222
+ privateKey: CryptoKey;
223
+ }): AuthLeaseSigner {
224
+ return async ({ signingInput }) =>
225
+ new Uint8Array(
226
+ await crypto.subtle.sign(
227
+ { name: 'ECDSA', hash: 'SHA-256' },
228
+ args.privateKey,
229
+ textEncoder.encode(signingInput)
230
+ )
231
+ );
232
+ }
233
+
234
+ export async function verifyAuthLeaseToken(
235
+ options: VerifyAuthLeaseTokenOptions
236
+ ): Promise<AuthLeaseVerificationResult> {
237
+ const parts = options.token.split('.');
238
+ if (parts.length !== 3) {
239
+ return rejected(
240
+ SYNC_AUTH_LEASE_CODE_INVALID,
241
+ 'auth lease token must have three JWS segments'
242
+ );
243
+ }
244
+
245
+ const protectedHeader = decodeJsonSegment<SyncAuthLeaseProtectedHeader>(
246
+ parts[0]!
247
+ );
248
+ if (
249
+ !protectedHeader ||
250
+ protectedHeader.alg !== SYNC_AUTH_LEASE_ALG_ES256 ||
251
+ protectedHeader.typ !== SYNC_AUTH_LEASE_TYP
252
+ ) {
253
+ return rejected(
254
+ SYNC_AUTH_LEASE_CODE_INVALID,
255
+ 'auth lease token has unsupported protected header'
256
+ );
257
+ }
258
+
259
+ const signature = base64UrlDecode(parts[2]!);
260
+ if (!signature) {
261
+ return rejected(
262
+ SYNC_AUTH_LEASE_CODE_INVALID,
263
+ 'auth lease signature segment is invalid'
264
+ );
265
+ }
266
+
267
+ const signingInput = `${parts[0]}.${parts[1]}`;
268
+ const verified = await crypto.subtle.verify(
269
+ { name: 'ECDSA', hash: 'SHA-256' },
270
+ options.publicKey,
271
+ toBufferSource(signature),
272
+ textEncoder.encode(signingInput)
273
+ );
274
+ if (!verified) {
275
+ return rejected(
276
+ SYNC_AUTH_LEASE_CODE_INVALID,
277
+ 'auth lease signature verification failed',
278
+ { kid: protectedHeader.kid }
279
+ );
280
+ }
281
+
282
+ const rawPayload = decodeJsonSegment<unknown>(parts[1]!);
283
+ const parsedPayload = SyncAuthLeasePayloadSchema.safeParse(rawPayload);
284
+ if (!parsedPayload.success) {
285
+ return rejected(
286
+ SYNC_AUTH_LEASE_CODE_INVALID,
287
+ 'auth lease payload is invalid',
288
+ {
289
+ kid: protectedHeader.kid,
290
+ }
291
+ );
292
+ }
293
+ const payload = parsedPayload.data;
294
+ if (
295
+ options.expectedIssuer !== undefined &&
296
+ payload.issuer !== options.expectedIssuer
297
+ ) {
298
+ return rejected(
299
+ SYNC_AUTH_LEASE_CODE_INVALID,
300
+ 'auth lease issuer mismatch',
301
+ {
302
+ leaseId: payload.leaseId,
303
+ kid: protectedHeader.kid,
304
+ }
305
+ );
306
+ }
307
+ if (
308
+ options.expectedAudience !== undefined &&
309
+ payload.audience !== options.expectedAudience
310
+ ) {
311
+ return rejected(
312
+ SYNC_AUTH_LEASE_CODE_INVALID,
313
+ 'auth lease audience mismatch',
314
+ {
315
+ leaseId: payload.leaseId,
316
+ kid: protectedHeader.kid,
317
+ }
318
+ );
319
+ }
320
+ if (
321
+ options.expectedSchemaVersion !== undefined &&
322
+ payload.schemaVersion !== options.expectedSchemaVersion
323
+ ) {
324
+ return rejected(
325
+ SYNC_AUTH_LEASE_CODE_SCHEMA_MISMATCH,
326
+ 'auth lease schema version mismatch',
327
+ { leaseId: payload.leaseId, kid: protectedHeader.kid }
328
+ );
329
+ }
330
+
331
+ const nowMs = options.nowMs ?? Date.now();
332
+ const skewMs = Math.max(0, payload.maxClockSkewMs);
333
+ if (nowMs + skewMs < payload.notBeforeMs) {
334
+ return rejected(
335
+ SYNC_AUTH_LEASE_CODE_INVALID,
336
+ 'auth lease is not valid yet',
337
+ {
338
+ leaseId: payload.leaseId,
339
+ kid: protectedHeader.kid,
340
+ }
341
+ );
342
+ }
343
+ if (nowMs - skewMs > payload.expiresAtMs) {
344
+ return rejected(SYNC_AUTH_LEASE_CODE_EXPIRED, 'auth lease is expired', {
345
+ leaseId: payload.leaseId,
346
+ kid: protectedHeader.kid,
347
+ expiresAtMs: payload.expiresAtMs,
348
+ });
349
+ }
350
+
351
+ return { ok: true, protectedHeader, payload };
352
+ }
353
+
354
+ export function authLeaseCoversOperation(args: {
355
+ payload: SyncAuthLeasePayload;
356
+ table: string;
357
+ op: string;
358
+ scopes: ScopeValues;
359
+ }): AuthLeaseVerificationFailure | null {
360
+ const leaseScope = args.payload.scopes.find(
361
+ (scope) =>
362
+ scope.table === args.table &&
363
+ scope.operations.some((operation) => operation === args.op)
364
+ );
365
+ if (!leaseScope) {
366
+ return rejected(
367
+ SYNC_AUTH_LEASE_CODE_SCOPE_MISMATCH,
368
+ 'auth lease does not cover operation table or type',
369
+ { leaseId: args.payload.leaseId }
370
+ );
371
+ }
372
+ for (const [key, value] of Object.entries(args.scopes)) {
373
+ if (!scopeValueCovers(leaseScope.values[key], value)) {
374
+ return rejected(
375
+ SYNC_AUTH_LEASE_CODE_SCOPE_MISMATCH,
376
+ 'auth lease does not cover scope',
377
+ {
378
+ leaseId: args.payload.leaseId,
379
+ }
380
+ );
381
+ }
382
+ }
383
+ return null;
384
+ }
385
+
386
+ export async function validateAuthLeaseOperation<
387
+ DB extends SyncCoreDb,
388
+ Auth extends SyncServerAuth,
389
+ >(
390
+ options: ValidateAuthLeaseOperationOptions<DB, Auth>
391
+ ): Promise<SyncOperationResult | null> {
392
+ const requiredScopeKeys = Array.from(
393
+ collectScopeVars(options.handler.scopePatterns)
394
+ );
395
+ const extracted = await extractOperationScopes({
396
+ db: options.db,
397
+ handler: options.handler,
398
+ operation: options.operation,
399
+ });
400
+ const requiresScopeValues =
401
+ requiredScopeKeys.length > 0 && extracted.rowExistsOrWillBeWritten;
402
+ if (
403
+ requiresScopeValues &&
404
+ requiredScopeKeys.some(
405
+ (key) =>
406
+ typeof extracted.scopes[key] !== 'string' ||
407
+ extracted.scopes[key].length === 0
408
+ )
409
+ ) {
410
+ return authLeaseOperationError({
411
+ opIndex: options.opIndex,
412
+ code: SYNC_AUTH_LEASE_CODE_SCOPE_MISMATCH,
413
+ error: 'Auth lease operation scopes could not be extracted',
414
+ });
415
+ }
416
+
417
+ const leaseCoverage = authLeaseCoversOperation({
418
+ payload: options.payload,
419
+ table: options.operation.table,
420
+ op: options.operation.op,
421
+ scopes: extracted.scopes,
422
+ });
423
+ if (leaseCoverage) {
424
+ return authLeaseOperationError({
425
+ opIndex: options.opIndex,
426
+ code: leaseCoverage.code,
427
+ error: leaseCoverage.message,
428
+ });
429
+ }
430
+
431
+ if (requiresScopeValues) {
432
+ let currentScopes: ScopeValues;
433
+ try {
434
+ currentScopes = await options.handler.resolveScopes({
435
+ db: options.db,
436
+ actorId: options.auth.actorId,
437
+ auth: options.auth,
438
+ });
439
+ } catch {
440
+ return authLeaseOperationError({
441
+ opIndex: options.opIndex,
442
+ code: SYNC_AUTH_LEASE_CODE_SCOPE_REVOKED,
443
+ error: 'Auth lease scopes could not be resolved for replay',
444
+ });
445
+ }
446
+
447
+ if (
448
+ !storedScopesCoveredByScopeValues({
449
+ storedScopes: extracted.scopes,
450
+ allowedScopes: currentScopes,
451
+ requiredScopeKeys,
452
+ })
453
+ ) {
454
+ return authLeaseOperationError({
455
+ opIndex: options.opIndex,
456
+ code: SYNC_AUTH_LEASE_CODE_SCOPE_REVOKED,
457
+ error: 'Auth lease scope is no longer authorized',
458
+ });
459
+ }
460
+ }
461
+
462
+ return null;
463
+ }
464
+
465
+ async function extractOperationScopes<
466
+ DB extends SyncCoreDb,
467
+ Auth extends SyncServerAuth,
468
+ >(args: {
469
+ db: DbExecutor<DB>;
470
+ handler: ServerTableHandler<DB, Auth>;
471
+ operation: SyncOperation;
472
+ }): Promise<{ scopes: StoredScopes; rowExistsOrWillBeWritten: boolean }> {
473
+ const existingRow = await readExistingRow({
474
+ db: args.db,
475
+ table: args.operation.table,
476
+ primaryKeyColumn: args.handler.primaryKeyColumn ?? 'id',
477
+ rowId: args.operation.row_id,
478
+ });
479
+
480
+ if (existingRow) {
481
+ return {
482
+ scopes: args.handler.extractScopes(existingRow),
483
+ rowExistsOrWillBeWritten: true,
484
+ };
485
+ }
486
+
487
+ if (args.operation.op === 'delete') {
488
+ return { scopes: {}, rowExistsOrWillBeWritten: false };
489
+ }
490
+
491
+ const payloadRecord =
492
+ args.operation.payload &&
493
+ typeof args.operation.payload === 'object' &&
494
+ !Array.isArray(args.operation.payload)
495
+ ? args.operation.payload
496
+ : {};
497
+ return {
498
+ scopes: args.handler.extractScopes({
499
+ ...payloadRecord,
500
+ [args.handler.primaryKeyColumn ?? 'id']: args.operation.row_id,
501
+ }),
502
+ rowExistsOrWillBeWritten: true,
503
+ };
504
+ }
505
+
506
+ async function readExistingRow<DB extends SyncCoreDb>(args: {
507
+ db: DbExecutor<DB>;
508
+ table: string;
509
+ primaryKeyColumn: string;
510
+ rowId: string;
511
+ }): Promise<Record<string, unknown> | null> {
512
+ const result = await sql<Record<string, unknown>>`
513
+ SELECT *
514
+ FROM ${sql.table(args.table)}
515
+ WHERE ${sql.ref(args.primaryKeyColumn)} = ${args.rowId}
516
+ LIMIT 1
517
+ `.execute(args.db);
518
+ return result.rows[0] ?? null;
519
+ }
520
+
521
+ function storedScopesCoveredByScopeValues(args: {
522
+ storedScopes: StoredScopes;
523
+ allowedScopes: ScopeValues;
524
+ requiredScopeKeys: readonly string[];
525
+ }): boolean {
526
+ for (const key of args.requiredScopeKeys) {
527
+ const storedValue = args.storedScopes[key];
528
+ if (typeof storedValue !== 'string' || storedValue.length === 0) {
529
+ return false;
530
+ }
531
+ if (!scopeValueCovers(args.allowedScopes[key], storedValue)) {
532
+ return false;
533
+ }
534
+ }
535
+ return true;
536
+ }
537
+
538
+ function authLeaseOperationError(args: {
539
+ opIndex: number;
540
+ code: string;
541
+ error: string;
542
+ }): SyncOperationResult {
543
+ return {
544
+ opIndex: args.opIndex,
545
+ status: 'error',
546
+ error: args.error,
547
+ code: args.code,
548
+ retriable: false,
549
+ };
550
+ }
551
+
552
+ function scopeValueCovers(
553
+ leaseValue: ScopeValues[string] | undefined,
554
+ requestedValue: ScopeValues[string]
555
+ ): boolean {
556
+ if (leaseValue === undefined) return false;
557
+ const leaseValues = Array.isArray(leaseValue) ? leaseValue : [leaseValue];
558
+ const requestedValues = Array.isArray(requestedValue)
559
+ ? requestedValue
560
+ : [requestedValue];
561
+ if (leaseValues.includes('*')) return true;
562
+ return requestedValues.every((value) => leaseValues.includes(value));
563
+ }
564
+
565
+ function positiveIntegerOrDefault(
566
+ value: number | undefined,
567
+ defaultValue: number
568
+ ): number {
569
+ return typeof value === 'number' && Number.isInteger(value) && value > 0
570
+ ? value
571
+ : defaultValue;
572
+ }
573
+
574
+ function randomLeaseId(): string {
575
+ if (
576
+ typeof crypto !== 'undefined' &&
577
+ typeof crypto.randomUUID === 'function'
578
+ ) {
579
+ return `lease_${crypto.randomUUID()}`;
580
+ }
581
+ return `lease_${Date.now().toString(36)}_${Math.random()
582
+ .toString(36)
583
+ .slice(2)}`;
584
+ }
585
+
586
+ function encodeJsonSegment(value: unknown): string {
587
+ return base64UrlEncode(textEncoder.encode(JSON.stringify(value)));
588
+ }
589
+
590
+ function decodeJsonSegment<T>(segment: string): T | null {
591
+ const bytes = base64UrlDecode(segment);
592
+ if (!bytes) return null;
593
+ try {
594
+ return JSON.parse(textDecoder.decode(bytes)) as T;
595
+ } catch {
596
+ return null;
597
+ }
598
+ }
599
+
600
+ function base64UrlEncode(bytes: Uint8Array): string {
601
+ let binary = '';
602
+ for (const byte of bytes) {
603
+ binary += String.fromCharCode(byte);
604
+ }
605
+ return btoa(binary)
606
+ .replaceAll('+', '-')
607
+ .replaceAll('/', '_')
608
+ .replaceAll('=', '');
609
+ }
610
+
611
+ function base64UrlDecode(value: string): Uint8Array | null {
612
+ const normalized = value.replaceAll('-', '+').replaceAll('_', '/');
613
+ const padded = normalized.padEnd(
614
+ normalized.length + ((4 - (normalized.length % 4)) % 4),
615
+ '='
616
+ );
617
+ try {
618
+ const binary = atob(padded);
619
+ const bytes = new Uint8Array(binary.length);
620
+ for (let index = 0; index < binary.length; index += 1) {
621
+ bytes[index] = binary.charCodeAt(index);
622
+ }
623
+ return bytes;
624
+ } catch {
625
+ return null;
626
+ }
627
+ }
628
+
629
+ function toBufferSource(bytes: Uint8Array): Uint8Array<ArrayBuffer> {
630
+ if (bytes.buffer instanceof ArrayBuffer) {
631
+ return new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
632
+ }
633
+ const owned = new Uint8Array(bytes.byteLength);
634
+ owned.set(bytes);
635
+ return owned;
636
+ }
637
+
638
+ function rejected(
639
+ code: string,
640
+ message: string,
641
+ details: Omit<AuthLeaseVerificationFailure, 'ok' | 'code' | 'message'> = {}
642
+ ): AuthLeaseVerificationFailure {
643
+ return {
644
+ ok: false,
645
+ code,
646
+ message,
647
+ ...details,
648
+ };
649
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @syncular/server/better-sqlite3 - better-sqlite3 dialect for sync
3
+ *
4
+ * Provides a Kysely dialect for better-sqlite3 (Node.js).
5
+ * SQLite-compatible — use with @syncular/server/sqlite.
6
+ */
7
+
8
+ import type { Database as BetterSqlite3Database } from 'better-sqlite3';
9
+ import Database from 'better-sqlite3';
10
+ import { SqliteDialect } from 'kysely';
11
+
12
+ export interface BetterSqlite3PathOptions {
13
+ /** Path to SQLite database file, or ':memory:' for in-memory */
14
+ path: string;
15
+ }
16
+
17
+ export interface BetterSqlite3InstanceOptions {
18
+ /** An existing better-sqlite3 Database instance */
19
+ database: BetterSqlite3Database;
20
+ }
21
+
22
+ export type BetterSqlite3Options =
23
+ | BetterSqlite3PathOptions
24
+ | BetterSqlite3InstanceOptions;
25
+
26
+ /**
27
+ * Create the better-sqlite3 dialect directly.
28
+ */
29
+ export function createBetterSqlite3Dialect(
30
+ options: BetterSqlite3Options
31
+ ): SqliteDialect {
32
+ const database =
33
+ 'database' in options ? options.database : new Database(options.path);
34
+ return new SqliteDialect({ database });
35
+ }