@syncular/server 0.1.2 → 0.2.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 (758) hide show
  1. package/README.md +773 -13
  2. package/dist/admin.d.ts +136 -0
  3. package/dist/admin.js +168 -0
  4. package/dist/blob-handlers.d.ts +69 -0
  5. package/dist/blob-handlers.js +245 -0
  6. package/dist/blob-store.d.ts +111 -0
  7. package/dist/blob-store.js +0 -0
  8. package/dist/content-encoding.d.ts +27 -0
  9. package/dist/content-encoding.js +69 -0
  10. package/dist/context.d.ts +151 -0
  11. package/dist/context.js +21 -0
  12. package/dist/crdt-merger.d.ts +28 -0
  13. package/dist/crdt-merger.js +11 -0
  14. package/dist/d1-storage.d.ts +50 -0
  15. package/dist/d1-storage.js +0 -0
  16. package/dist/errors.d.ts +35 -9
  17. package/dist/errors.js +220 -11
  18. package/dist/events-ring.d.ts +55 -0
  19. package/dist/events-ring.js +96 -0
  20. package/dist/events.d.ts +231 -0
  21. package/dist/events.js +22 -0
  22. package/dist/frame-bytes.d.ts +20 -0
  23. package/dist/frame-bytes.js +75 -0
  24. package/dist/handler.d.ts +9 -0
  25. package/dist/handler.js +490 -0
  26. package/dist/index.d.ts +42 -33
  27. package/dist/index.js +45 -27
  28. package/dist/lease-store.d.ts +50 -0
  29. package/dist/lease-store.js +0 -0
  30. package/dist/pg-executor-pglite.d.ts +27 -0
  31. package/dist/pg-executor-pglite.js +33 -0
  32. package/dist/pg-executor.d.ts +67 -0
  33. package/dist/pg-executor.js +56 -0
  34. package/dist/postgres-fanout.d.ts +83 -0
  35. package/dist/postgres-fanout.js +71 -0
  36. package/dist/postgres-storage.d.ts +69 -0
  37. package/dist/postgres-storage.js +766 -0
  38. package/dist/prune.d.ts +24 -39
  39. package/dist/prune.js +44 -146
  40. package/dist/pull.d.ts +42 -67
  41. package/dist/pull.js +387 -1187
  42. package/dist/push.d.ts +31 -66
  43. package/dist/push.js +406 -655
  44. package/dist/realtime.d.ts +197 -0
  45. package/dist/realtime.js +848 -0
  46. package/dist/relational-rows.d.ts +229 -0
  47. package/dist/relational-rows.js +514 -0
  48. package/dist/s3-blob-store.d.ts +142 -0
  49. package/dist/s3-blob-store.js +458 -0
  50. package/dist/s3-segment-store.d.ts +95 -0
  51. package/dist/s3-segment-store.js +380 -0
  52. package/dist/schema.d.ts +82 -286
  53. package/dist/schema.js +133 -9
  54. package/dist/scopes.d.ts +48 -0
  55. package/dist/scopes.js +98 -0
  56. package/dist/segment-download.d.ts +14 -0
  57. package/dist/segment-download.js +125 -0
  58. package/dist/segment-store.d.ts +81 -0
  59. package/dist/segment-store.js +63 -0
  60. package/dist/signed-url.d.ts +139 -0
  61. package/dist/signed-url.js +143 -0
  62. package/dist/sigv4.d.ts +97 -0
  63. package/dist/sigv4.js +161 -0
  64. package/dist/sqlite-blob-store.d.ts +22 -0
  65. package/dist/sqlite-blob-store.js +86 -0
  66. package/dist/sqlite-dialect.d.ts +101 -0
  67. package/dist/sqlite-dialect.js +250 -0
  68. package/dist/sqlite-image.d.ts +27 -0
  69. package/dist/sqlite-image.js +83 -0
  70. package/dist/sqlite-lease-store.d.ts +21 -0
  71. package/dist/sqlite-lease-store.js +94 -0
  72. package/dist/sqlite-segment-store.d.ts +25 -0
  73. package/dist/sqlite-segment-store.js +115 -0
  74. package/dist/sqlite-storage.d.ts +47 -0
  75. package/dist/sqlite-storage.js +477 -0
  76. package/dist/storage.d.ts +252 -0
  77. package/dist/storage.js +1 -0
  78. package/dist/validate.d.ts +83 -0
  79. package/dist/validate.js +44 -0
  80. package/package.json +17 -325
  81. package/src/admin.ts +312 -0
  82. package/src/blob-handlers.ts +340 -0
  83. package/src/blob-store.ts +0 -0
  84. package/src/content-encoding.ts +94 -0
  85. package/src/context.ts +176 -0
  86. package/src/crdt-merger.ts +33 -0
  87. package/src/d1-storage.ts +0 -0
  88. package/src/errors.ts +241 -19
  89. package/src/events-ring.ts +116 -0
  90. package/src/events.ts +291 -0
  91. package/src/frame-bytes.ts +94 -0
  92. package/src/handler.ts +678 -0
  93. package/src/index.ts +44 -27
  94. package/src/lease-store.ts +0 -0
  95. package/src/pg-executor-pglite.ts +63 -0
  96. package/src/pg-executor.ts +87 -0
  97. package/src/postgres-fanout.ts +143 -0
  98. package/src/postgres-storage.ts +1182 -0
  99. package/src/prune.ts +63 -289
  100. package/src/pull.ts +505 -1805
  101. package/src/push.ts +623 -1006
  102. package/src/realtime.ts +1082 -0
  103. package/src/relational-rows.ts +633 -0
  104. package/src/s3-blob-store.ts +616 -0
  105. package/src/s3-segment-store.ts +519 -0
  106. package/src/schema.ts +242 -281
  107. package/src/scopes.ts +127 -0
  108. package/src/segment-download.ts +169 -0
  109. package/src/segment-store.ts +154 -0
  110. package/src/signed-url.ts +308 -0
  111. package/src/sigv4.ts +267 -0
  112. package/src/sqlite-blob-store.ts +125 -0
  113. package/src/sqlite-dialect.ts +337 -0
  114. package/src/sqlite-image.ts +124 -0
  115. package/src/sqlite-lease-store.ts +144 -0
  116. package/src/sqlite-segment-store.ts +204 -0
  117. package/src/sqlite-storage.ts +792 -0
  118. package/src/storage.ts +316 -0
  119. package/src/validate.ts +123 -0
  120. package/dist/auth-leases.d.ts +0 -85
  121. package/dist/auth-leases.d.ts.map +0 -1
  122. package/dist/auth-leases.js +0 -368
  123. package/dist/auth-leases.js.map +0 -1
  124. package/dist/better-sqlite3.d.ts +0 -22
  125. package/dist/better-sqlite3.d.ts.map +0 -1
  126. package/dist/better-sqlite3.js +0 -16
  127. package/dist/better-sqlite3.js.map +0 -1
  128. package/dist/blobs/access.d.ts +0 -35
  129. package/dist/blobs/access.d.ts.map +0 -1
  130. package/dist/blobs/access.js +0 -149
  131. package/dist/blobs/access.js.map +0 -1
  132. package/dist/blobs/adapters/database.d.ts +0 -100
  133. package/dist/blobs/adapters/database.d.ts.map +0 -1
  134. package/dist/blobs/adapters/database.js +0 -247
  135. package/dist/blobs/adapters/database.js.map +0 -1
  136. package/dist/blobs/index.d.ts +0 -9
  137. package/dist/blobs/index.d.ts.map +0 -1
  138. package/dist/blobs/index.js +0 -9
  139. package/dist/blobs/index.js.map +0 -1
  140. package/dist/blobs/manager.d.ts +0 -220
  141. package/dist/blobs/manager.d.ts.map +0 -1
  142. package/dist/blobs/manager.js +0 -625
  143. package/dist/blobs/manager.js.map +0 -1
  144. package/dist/blobs/migrate.d.ts +0 -27
  145. package/dist/blobs/migrate.d.ts.map +0 -1
  146. package/dist/blobs/migrate.js +0 -127
  147. package/dist/blobs/migrate.js.map +0 -1
  148. package/dist/blobs/types.d.ts +0 -58
  149. package/dist/blobs/types.d.ts.map +0 -1
  150. package/dist/blobs/types.js +0 -5
  151. package/dist/blobs/types.js.map +0 -1
  152. package/dist/bun-sqlite.d.ts +0 -19
  153. package/dist/bun-sqlite.d.ts.map +0 -1
  154. package/dist/bun-sqlite.js +0 -19
  155. package/dist/bun-sqlite.js.map +0 -1
  156. package/dist/clients.d.ts +0 -15
  157. package/dist/clients.d.ts.map +0 -1
  158. package/dist/clients.js +0 -7
  159. package/dist/clients.js.map +0 -1
  160. package/dist/cloudflare/durable-object.d.ts +0 -93
  161. package/dist/cloudflare/durable-object.d.ts.map +0 -1
  162. package/dist/cloudflare/durable-object.js +0 -210
  163. package/dist/cloudflare/durable-object.js.map +0 -1
  164. package/dist/cloudflare/index.d.ts +0 -22
  165. package/dist/cloudflare/index.d.ts.map +0 -1
  166. package/dist/cloudflare/index.js +0 -22
  167. package/dist/cloudflare/index.js.map +0 -1
  168. package/dist/cloudflare/r2.d.ts +0 -180
  169. package/dist/cloudflare/r2.d.ts.map +0 -1
  170. package/dist/cloudflare/r2.js +0 -258
  171. package/dist/cloudflare/r2.js.map +0 -1
  172. package/dist/cloudflare/scope-cache.d.ts +0 -54
  173. package/dist/cloudflare/scope-cache.d.ts.map +0 -1
  174. package/dist/cloudflare/scope-cache.js +0 -223
  175. package/dist/cloudflare/scope-cache.js.map +0 -1
  176. package/dist/cloudflare/sentry.d.ts +0 -47
  177. package/dist/cloudflare/sentry.d.ts.map +0 -1
  178. package/dist/cloudflare/sentry.js +0 -163
  179. package/dist/cloudflare/sentry.js.map +0 -1
  180. package/dist/cloudflare/worker.d.ts +0 -46
  181. package/dist/cloudflare/worker.d.ts.map +0 -1
  182. package/dist/cloudflare/worker.js +0 -63
  183. package/dist/cloudflare/worker.js.map +0 -1
  184. package/dist/commit-integrity.d.ts +0 -38
  185. package/dist/commit-integrity.d.ts.map +0 -1
  186. package/dist/commit-integrity.js +0 -260
  187. package/dist/commit-integrity.js.map +0 -1
  188. package/dist/compaction.d.ts +0 -27
  189. package/dist/compaction.d.ts.map +0 -1
  190. package/dist/compaction.js +0 -49
  191. package/dist/compaction.js.map +0 -1
  192. package/dist/crdt-yjs/index.d.ts +0 -99
  193. package/dist/crdt-yjs/index.d.ts.map +0 -1
  194. package/dist/crdt-yjs/index.js +0 -629
  195. package/dist/crdt-yjs/index.js.map +0 -1
  196. package/dist/d1.d.ts +0 -13
  197. package/dist/d1.d.ts.map +0 -1
  198. package/dist/d1.js +0 -14
  199. package/dist/d1.js.map +0 -1
  200. package/dist/dialect/base.d.ts +0 -93
  201. package/dist/dialect/base.d.ts.map +0 -1
  202. package/dist/dialect/base.js +0 -181
  203. package/dist/dialect/base.js.map +0 -1
  204. package/dist/dialect/helpers.d.ts +0 -16
  205. package/dist/dialect/helpers.d.ts.map +0 -1
  206. package/dist/dialect/helpers.js +0 -83
  207. package/dist/dialect/helpers.js.map +0 -1
  208. package/dist/dialect/index.d.ts +0 -7
  209. package/dist/dialect/index.d.ts.map +0 -1
  210. package/dist/dialect/index.js +0 -7
  211. package/dist/dialect/index.js.map +0 -1
  212. package/dist/dialect/types.d.ts +0 -187
  213. package/dist/dialect/types.d.ts.map +0 -1
  214. package/dist/dialect/types.js +0 -8
  215. package/dist/dialect/types.js.map +0 -1
  216. package/dist/encrypted-crdt.d.ts +0 -67
  217. package/dist/encrypted-crdt.d.ts.map +0 -1
  218. package/dist/encrypted-crdt.js +0 -426
  219. package/dist/encrypted-crdt.js.map +0 -1
  220. package/dist/errors.d.ts.map +0 -1
  221. package/dist/errors.js.map +0 -1
  222. package/dist/filesystem/index.d.ts +0 -44
  223. package/dist/filesystem/index.d.ts.map +0 -1
  224. package/dist/filesystem/index.js +0 -164
  225. package/dist/filesystem/index.js.map +0 -1
  226. package/dist/handlers/collection.d.ts +0 -20
  227. package/dist/handlers/collection.d.ts.map +0 -1
  228. package/dist/handlers/collection.js +0 -42
  229. package/dist/handlers/collection.js.map +0 -1
  230. package/dist/handlers/create-handler.d.ts +0 -156
  231. package/dist/handlers/create-handler.d.ts.map +0 -1
  232. package/dist/handlers/create-handler.js +0 -626
  233. package/dist/handlers/create-handler.js.map +0 -1
  234. package/dist/handlers/index.d.ts +0 -4
  235. package/dist/handlers/index.d.ts.map +0 -1
  236. package/dist/handlers/index.js +0 -4
  237. package/dist/handlers/index.js.map +0 -1
  238. package/dist/handlers/types.d.ts +0 -295
  239. package/dist/handlers/types.d.ts.map +0 -1
  240. package/dist/handlers/types.js +0 -2
  241. package/dist/handlers/types.js.map +0 -1
  242. package/dist/helpers/conflict.d.ts +0 -52
  243. package/dist/helpers/conflict.d.ts.map +0 -1
  244. package/dist/helpers/conflict.js +0 -49
  245. package/dist/helpers/conflict.js.map +0 -1
  246. package/dist/helpers/emitted-change.d.ts +0 -56
  247. package/dist/helpers/emitted-change.d.ts.map +0 -1
  248. package/dist/helpers/emitted-change.js +0 -46
  249. package/dist/helpers/emitted-change.js.map +0 -1
  250. package/dist/helpers/index.d.ts +0 -12
  251. package/dist/helpers/index.d.ts.map +0 -1
  252. package/dist/helpers/index.js +0 -12
  253. package/dist/helpers/index.js.map +0 -1
  254. package/dist/helpers/paginate.d.ts +0 -49
  255. package/dist/helpers/paginate.d.ts.map +0 -1
  256. package/dist/helpers/paginate.js +0 -54
  257. package/dist/helpers/paginate.js.map +0 -1
  258. package/dist/helpers/scope-authorization.d.ts +0 -7
  259. package/dist/helpers/scope-authorization.d.ts.map +0 -1
  260. package/dist/helpers/scope-authorization.js +0 -19
  261. package/dist/helpers/scope-authorization.js.map +0 -1
  262. package/dist/helpers/scope-commit-index.d.ts +0 -12
  263. package/dist/helpers/scope-commit-index.d.ts.map +0 -1
  264. package/dist/helpers/scope-commit-index.js +0 -35
  265. package/dist/helpers/scope-commit-index.js.map +0 -1
  266. package/dist/helpers/scope-strings.d.ts +0 -74
  267. package/dist/helpers/scope-strings.d.ts.map +0 -1
  268. package/dist/helpers/scope-strings.js +0 -82
  269. package/dist/helpers/scope-strings.js.map +0 -1
  270. package/dist/hono/api-key-auth.d.ts +0 -49
  271. package/dist/hono/api-key-auth.d.ts.map +0 -1
  272. package/dist/hono/api-key-auth.js +0 -108
  273. package/dist/hono/api-key-auth.js.map +0 -1
  274. package/dist/hono/audit-redaction.d.ts +0 -20
  275. package/dist/hono/audit-redaction.d.ts.map +0 -1
  276. package/dist/hono/audit-redaction.js +0 -85
  277. package/dist/hono/audit-redaction.js.map +0 -1
  278. package/dist/hono/blobs.d.ts +0 -75
  279. package/dist/hono/blobs.d.ts.map +0 -1
  280. package/dist/hono/blobs.js +0 -586
  281. package/dist/hono/blobs.js.map +0 -1
  282. package/dist/hono/console/gateway.d.ts +0 -42
  283. package/dist/hono/console/gateway.d.ts.map +0 -1
  284. package/dist/hono/console/gateway.js +0 -2158
  285. package/dist/hono/console/gateway.js.map +0 -1
  286. package/dist/hono/console/live-auth.d.ts +0 -7
  287. package/dist/hono/console/live-auth.d.ts.map +0 -1
  288. package/dist/hono/console/live-auth.js +0 -39
  289. package/dist/hono/console/live-auth.js.map +0 -1
  290. package/dist/hono/console/route-descriptor.d.ts +0 -6
  291. package/dist/hono/console/route-descriptor.d.ts.map +0 -1
  292. package/dist/hono/console/route-descriptor.js +0 -16
  293. package/dist/hono/console/route-descriptor.js.map +0 -1
  294. package/dist/hono/console/routes/api-keys.d.ts +0 -8
  295. package/dist/hono/console/routes/api-keys.d.ts.map +0 -1
  296. package/dist/hono/console/routes/api-keys.js +0 -575
  297. package/dist/hono/console/routes/api-keys.js.map +0 -1
  298. package/dist/hono/console/routes/clients.d.ts +0 -8
  299. package/dist/hono/console/routes/clients.d.ts.map +0 -1
  300. package/dist/hono/console/routes/clients.js +0 -322
  301. package/dist/hono/console/routes/clients.js.map +0 -1
  302. package/dist/hono/console/routes/commits.d.ts +0 -8
  303. package/dist/hono/console/routes/commits.d.ts.map +0 -1
  304. package/dist/hono/console/routes/commits.js +0 -882
  305. package/dist/hono/console/routes/commits.js.map +0 -1
  306. package/dist/hono/console/routes/context.d.ts +0 -188
  307. package/dist/hono/console/routes/context.d.ts.map +0 -1
  308. package/dist/hono/console/routes/context.js +0 -633
  309. package/dist/hono/console/routes/context.js.map +0 -1
  310. package/dist/hono/console/routes/events.d.ts +0 -8
  311. package/dist/hono/console/routes/events.d.ts.map +0 -1
  312. package/dist/hono/console/routes/events.js +0 -501
  313. package/dist/hono/console/routes/events.js.map +0 -1
  314. package/dist/hono/console/routes/maintenance.d.ts +0 -8
  315. package/dist/hono/console/routes/maintenance.d.ts.map +0 -1
  316. package/dist/hono/console/routes/maintenance.js +0 -341
  317. package/dist/hono/console/routes/maintenance.js.map +0 -1
  318. package/dist/hono/console/routes/shared.d.ts +0 -174
  319. package/dist/hono/console/routes/shared.d.ts.map +0 -1
  320. package/dist/hono/console/routes/shared.js +0 -583
  321. package/dist/hono/console/routes/shared.js.map +0 -1
  322. package/dist/hono/console/routes/stats.d.ts +0 -8
  323. package/dist/hono/console/routes/stats.d.ts.map +0 -1
  324. package/dist/hono/console/routes/stats.js +0 -295
  325. package/dist/hono/console/routes/stats.js.map +0 -1
  326. package/dist/hono/console/routes/storage.d.ts +0 -8
  327. package/dist/hono/console/routes/storage.d.ts.map +0 -1
  328. package/dist/hono/console/routes/storage.js +0 -121
  329. package/dist/hono/console/routes/storage.js.map +0 -1
  330. package/dist/hono/console/routes.d.ts +0 -36
  331. package/dist/hono/console/routes.d.ts.map +0 -1
  332. package/dist/hono/console/routes.js +0 -112
  333. package/dist/hono/console/routes.js.map +0 -1
  334. package/dist/hono/console/schema-errors.d.ts +0 -2
  335. package/dist/hono/console/schema-errors.d.ts.map +0 -1
  336. package/dist/hono/console/schema-errors.js +0 -17
  337. package/dist/hono/console/schema-errors.js.map +0 -1
  338. package/dist/hono/console/schemas.d.ts +0 -1515
  339. package/dist/hono/console/schemas.d.ts.map +0 -1
  340. package/dist/hono/console/schemas.js +0 -661
  341. package/dist/hono/console/schemas.js.map +0 -1
  342. package/dist/hono/console/types.d.ts +0 -213
  343. package/dist/hono/console/types.d.ts.map +0 -1
  344. package/dist/hono/console/types.js +0 -2
  345. package/dist/hono/console/types.js.map +0 -1
  346. package/dist/hono/console/ui.d.ts +0 -38
  347. package/dist/hono/console/ui.d.ts.map +0 -1
  348. package/dist/hono/console/ui.js +0 -43
  349. package/dist/hono/console/ui.js.map +0 -1
  350. package/dist/hono/create-server.d.ts +0 -71
  351. package/dist/hono/create-server.d.ts.map +0 -1
  352. package/dist/hono/create-server.js +0 -121
  353. package/dist/hono/create-server.js.map +0 -1
  354. package/dist/hono/errors.d.ts +0 -13
  355. package/dist/hono/errors.d.ts.map +0 -1
  356. package/dist/hono/errors.js +0 -21
  357. package/dist/hono/errors.js.map +0 -1
  358. package/dist/hono/index.d.ts +0 -20
  359. package/dist/hono/index.d.ts.map +0 -1
  360. package/dist/hono/index.js +0 -31
  361. package/dist/hono/index.js.map +0 -1
  362. package/dist/hono/openapi.d.ts +0 -72
  363. package/dist/hono/openapi.d.ts.map +0 -1
  364. package/dist/hono/openapi.js +0 -99
  365. package/dist/hono/openapi.js.map +0 -1
  366. package/dist/hono/proxy/connection-manager.d.ts +0 -78
  367. package/dist/hono/proxy/connection-manager.d.ts.map +0 -1
  368. package/dist/hono/proxy/connection-manager.js +0 -251
  369. package/dist/hono/proxy/connection-manager.js.map +0 -1
  370. package/dist/hono/proxy/index.d.ts +0 -8
  371. package/dist/hono/proxy/index.d.ts.map +0 -1
  372. package/dist/hono/proxy/index.js +0 -8
  373. package/dist/hono/proxy/index.js.map +0 -1
  374. package/dist/hono/proxy/routes.d.ts +0 -86
  375. package/dist/hono/proxy/routes.d.ts.map +0 -1
  376. package/dist/hono/proxy/routes.js +0 -183
  377. package/dist/hono/proxy/routes.js.map +0 -1
  378. package/dist/hono/rate-limit.d.ts +0 -101
  379. package/dist/hono/rate-limit.d.ts.map +0 -1
  380. package/dist/hono/rate-limit.js +0 -184
  381. package/dist/hono/rate-limit.js.map +0 -1
  382. package/dist/hono/realtime-sync-packs.d.ts +0 -43
  383. package/dist/hono/realtime-sync-packs.d.ts.map +0 -1
  384. package/dist/hono/realtime-sync-packs.js +0 -219
  385. package/dist/hono/realtime-sync-packs.js.map +0 -1
  386. package/dist/hono/routes/audit.d.ts +0 -12
  387. package/dist/hono/routes/audit.d.ts.map +0 -1
  388. package/dist/hono/routes/audit.js +0 -385
  389. package/dist/hono/routes/audit.js.map +0 -1
  390. package/dist/hono/routes/auth-leases.d.ts +0 -8
  391. package/dist/hono/routes/auth-leases.d.ts.map +0 -1
  392. package/dist/hono/routes/auth-leases.js +0 -88
  393. package/dist/hono/routes/auth-leases.js.map +0 -1
  394. package/dist/hono/routes/combined.d.ts +0 -8
  395. package/dist/hono/routes/combined.d.ts.map +0 -1
  396. package/dist/hono/routes/combined.js +0 -392
  397. package/dist/hono/routes/combined.js.map +0 -1
  398. package/dist/hono/routes/context.d.ts +0 -314
  399. package/dist/hono/routes/context.d.ts.map +0 -1
  400. package/dist/hono/routes/context.js +0 -1147
  401. package/dist/hono/routes/context.js.map +0 -1
  402. package/dist/hono/routes/health.d.ts +0 -8
  403. package/dist/hono/routes/health.d.ts.map +0 -1
  404. package/dist/hono/routes/health.js +0 -16
  405. package/dist/hono/routes/health.js.map +0 -1
  406. package/dist/hono/routes/realtime.d.ts +0 -9
  407. package/dist/hono/routes/realtime.d.ts.map +0 -1
  408. package/dist/hono/routes/realtime.js +0 -626
  409. package/dist/hono/routes/realtime.js.map +0 -1
  410. package/dist/hono/routes/shared.d.ts +0 -689
  411. package/dist/hono/routes/shared.d.ts.map +0 -1
  412. package/dist/hono/routes/shared.js +0 -972
  413. package/dist/hono/routes/shared.js.map +0 -1
  414. package/dist/hono/routes/snapshots.d.ts +0 -10
  415. package/dist/hono/routes/snapshots.d.ts.map +0 -1
  416. package/dist/hono/routes/snapshots.js +0 -281
  417. package/dist/hono/routes/snapshots.js.map +0 -1
  418. package/dist/hono/routes.d.ts +0 -19
  419. package/dist/hono/routes.d.ts.map +0 -1
  420. package/dist/hono/routes.js +0 -37
  421. package/dist/hono/routes.js.map +0 -1
  422. package/dist/hono/validation.d.ts +0 -5
  423. package/dist/hono/validation.d.ts.map +0 -1
  424. package/dist/hono/validation.js +0 -47
  425. package/dist/hono/validation.js.map +0 -1
  426. package/dist/hono/websocket-origin.d.ts +0 -9
  427. package/dist/hono/websocket-origin.d.ts.map +0 -1
  428. package/dist/hono/websocket-origin.js +0 -96
  429. package/dist/hono/websocket-origin.js.map +0 -1
  430. package/dist/hono/ws.d.ts +0 -341
  431. package/dist/hono/ws.d.ts.map +0 -1
  432. package/dist/hono/ws.js +0 -711
  433. package/dist/hono/ws.js.map +0 -1
  434. package/dist/index.d.ts.map +0 -1
  435. package/dist/index.js.map +0 -1
  436. package/dist/libsql.d.ts +0 -29
  437. package/dist/libsql.d.ts.map +0 -1
  438. package/dist/libsql.js +0 -25
  439. package/dist/libsql.js.map +0 -1
  440. package/dist/migrate.d.ts +0 -14
  441. package/dist/migrate.d.ts.map +0 -1
  442. package/dist/migrate.js +0 -13
  443. package/dist/migrate.js.map +0 -1
  444. package/dist/neon.d.ts +0 -21
  445. package/dist/neon.d.ts.map +0 -1
  446. package/dist/neon.js +0 -22
  447. package/dist/neon.js.map +0 -1
  448. package/dist/notify.d.ts +0 -77
  449. package/dist/notify.d.ts.map +0 -1
  450. package/dist/notify.js +0 -233
  451. package/dist/notify.js.map +0 -1
  452. package/dist/pglite.d.ts +0 -37
  453. package/dist/pglite.d.ts.map +0 -1
  454. package/dist/pglite.js +0 -37
  455. package/dist/pglite.js.map +0 -1
  456. package/dist/plugins/index.d.ts +0 -2
  457. package/dist/plugins/index.d.ts.map +0 -1
  458. package/dist/plugins/index.js +0 -2
  459. package/dist/plugins/index.js.map +0 -1
  460. package/dist/plugins/types.d.ts +0 -73
  461. package/dist/plugins/types.d.ts.map +0 -1
  462. package/dist/plugins/types.js +0 -30
  463. package/dist/plugins/types.js.map +0 -1
  464. package/dist/postgres/index.d.ts +0 -68
  465. package/dist/postgres/index.d.ts.map +0 -1
  466. package/dist/postgres/index.js +0 -924
  467. package/dist/postgres/index.js.map +0 -1
  468. package/dist/proxy/collection.d.ts +0 -7
  469. package/dist/proxy/collection.d.ts.map +0 -1
  470. package/dist/proxy/collection.js +0 -6
  471. package/dist/proxy/collection.js.map +0 -1
  472. package/dist/proxy/handler.d.ts +0 -42
  473. package/dist/proxy/handler.d.ts.map +0 -1
  474. package/dist/proxy/handler.js +0 -102
  475. package/dist/proxy/handler.js.map +0 -1
  476. package/dist/proxy/index.d.ts +0 -9
  477. package/dist/proxy/index.d.ts.map +0 -1
  478. package/dist/proxy/index.js +0 -14
  479. package/dist/proxy/index.js.map +0 -1
  480. package/dist/proxy/mutation-detector.d.ts +0 -35
  481. package/dist/proxy/mutation-detector.d.ts.map +0 -1
  482. package/dist/proxy/mutation-detector.js +0 -246
  483. package/dist/proxy/mutation-detector.js.map +0 -1
  484. package/dist/proxy/oplog.d.ts +0 -30
  485. package/dist/proxy/oplog.d.ts.map +0 -1
  486. package/dist/proxy/oplog.js +0 -137
  487. package/dist/proxy/oplog.js.map +0 -1
  488. package/dist/proxy/types.d.ts +0 -44
  489. package/dist/proxy/types.d.ts.map +0 -1
  490. package/dist/proxy/types.js +0 -7
  491. package/dist/proxy/types.js.map +0 -1
  492. package/dist/prune.d.ts.map +0 -1
  493. package/dist/prune.js.map +0 -1
  494. package/dist/pull.d.ts.map +0 -1
  495. package/dist/pull.js.map +0 -1
  496. package/dist/push.d.ts.map +0 -1
  497. package/dist/push.js.map +0 -1
  498. package/dist/realtime/in-memory.d.ts +0 -13
  499. package/dist/realtime/in-memory.d.ts.map +0 -1
  500. package/dist/realtime/in-memory.js +0 -28
  501. package/dist/realtime/in-memory.js.map +0 -1
  502. package/dist/realtime/index.d.ts +0 -4
  503. package/dist/realtime/index.d.ts.map +0 -1
  504. package/dist/realtime/index.js +0 -3
  505. package/dist/realtime/index.js.map +0 -1
  506. package/dist/realtime/types.d.ts +0 -62
  507. package/dist/realtime/types.d.ts.map +0 -1
  508. package/dist/realtime/types.js +0 -19
  509. package/dist/realtime/types.js.map +0 -1
  510. package/dist/relay/client-role/forward-engine.d.ts +0 -63
  511. package/dist/relay/client-role/forward-engine.d.ts.map +0 -1
  512. package/dist/relay/client-role/forward-engine.js +0 -267
  513. package/dist/relay/client-role/forward-engine.js.map +0 -1
  514. package/dist/relay/client-role/index.d.ts +0 -9
  515. package/dist/relay/client-role/index.d.ts.map +0 -1
  516. package/dist/relay/client-role/index.js +0 -9
  517. package/dist/relay/client-role/index.js.map +0 -1
  518. package/dist/relay/client-role/pull-engine.d.ts +0 -72
  519. package/dist/relay/client-role/pull-engine.d.ts.map +0 -1
  520. package/dist/relay/client-role/pull-engine.js +0 -249
  521. package/dist/relay/client-role/pull-engine.js.map +0 -1
  522. package/dist/relay/client-role/sequence-mapper.d.ts +0 -65
  523. package/dist/relay/client-role/sequence-mapper.d.ts.map +0 -1
  524. package/dist/relay/client-role/sequence-mapper.js +0 -161
  525. package/dist/relay/client-role/sequence-mapper.js.map +0 -1
  526. package/dist/relay/evaluation/relay-paths.d.ts +0 -41
  527. package/dist/relay/evaluation/relay-paths.d.ts.map +0 -1
  528. package/dist/relay/evaluation/relay-paths.js +0 -504
  529. package/dist/relay/evaluation/relay-paths.js.map +0 -1
  530. package/dist/relay/evaluation/rust-boundary.d.ts +0 -47
  531. package/dist/relay/evaluation/rust-boundary.d.ts.map +0 -1
  532. package/dist/relay/evaluation/rust-boundary.js +0 -220
  533. package/dist/relay/evaluation/rust-boundary.js.map +0 -1
  534. package/dist/relay/index.d.ts +0 -37
  535. package/dist/relay/index.d.ts.map +0 -1
  536. package/dist/relay/index.js +0 -44
  537. package/dist/relay/index.js.map +0 -1
  538. package/dist/relay/migrate.d.ts +0 -18
  539. package/dist/relay/migrate.d.ts.map +0 -1
  540. package/dist/relay/migrate.js +0 -99
  541. package/dist/relay/migrate.js.map +0 -1
  542. package/dist/relay/mode-manager.d.ts +0 -60
  543. package/dist/relay/mode-manager.d.ts.map +0 -1
  544. package/dist/relay/mode-manager.js +0 -114
  545. package/dist/relay/mode-manager.js.map +0 -1
  546. package/dist/relay/realtime.d.ts +0 -90
  547. package/dist/relay/realtime.d.ts.map +0 -1
  548. package/dist/relay/realtime.js +0 -147
  549. package/dist/relay/realtime.js.map +0 -1
  550. package/dist/relay/relay.d.ts +0 -190
  551. package/dist/relay/relay.d.ts.map +0 -1
  552. package/dist/relay/relay.js +0 -320
  553. package/dist/relay/relay.js.map +0 -1
  554. package/dist/relay/schema.d.ts +0 -158
  555. package/dist/relay/schema.d.ts.map +0 -1
  556. package/dist/relay/schema.js +0 -7
  557. package/dist/relay/schema.js.map +0 -1
  558. package/dist/relay/server-role/index.d.ts +0 -56
  559. package/dist/relay/server-role/index.d.ts.map +0 -1
  560. package/dist/relay/server-role/index.js +0 -193
  561. package/dist/relay/server-role/index.js.map +0 -1
  562. package/dist/relay/server-role/pull.d.ts +0 -27
  563. package/dist/relay/server-role/pull.d.ts.map +0 -1
  564. package/dist/relay/server-role/pull.js +0 -24
  565. package/dist/relay/server-role/pull.js.map +0 -1
  566. package/dist/relay/server-role/push.d.ts +0 -29
  567. package/dist/relay/server-role/push.d.ts.map +0 -1
  568. package/dist/relay/server-role/push.js +0 -122
  569. package/dist/relay/server-role/push.js.map +0 -1
  570. package/dist/s3/index.d.ts +0 -83
  571. package/dist/s3/index.d.ts.map +0 -1
  572. package/dist/s3/index.js +0 -223
  573. package/dist/s3/index.js.map +0 -1
  574. package/dist/schema.d.ts.map +0 -1
  575. package/dist/schema.js.map +0 -1
  576. package/dist/service-worker/index.d.ts +0 -114
  577. package/dist/service-worker/index.d.ts.map +0 -1
  578. package/dist/service-worker/index.js +0 -487
  579. package/dist/service-worker/index.js.map +0 -1
  580. package/dist/snapshot-artifacts/sqlite-bun.d.ts +0 -15
  581. package/dist/snapshot-artifacts/sqlite-bun.d.ts.map +0 -1
  582. package/dist/snapshot-artifacts/sqlite-bun.js +0 -128
  583. package/dist/snapshot-artifacts/sqlite-bun.js.map +0 -1
  584. package/dist/snapshot-artifacts.d.ts +0 -206
  585. package/dist/snapshot-artifacts.d.ts.map +0 -1
  586. package/dist/snapshot-artifacts.js +0 -545
  587. package/dist/snapshot-artifacts.js.map +0 -1
  588. package/dist/snapshot-chunks/db-metadata.d.ts +0 -56
  589. package/dist/snapshot-chunks/db-metadata.d.ts.map +0 -1
  590. package/dist/snapshot-chunks/db-metadata.js +0 -360
  591. package/dist/snapshot-chunks/db-metadata.js.map +0 -1
  592. package/dist/snapshot-chunks/index.d.ts +0 -8
  593. package/dist/snapshot-chunks/index.d.ts.map +0 -1
  594. package/dist/snapshot-chunks/index.js +0 -8
  595. package/dist/snapshot-chunks/index.js.map +0 -1
  596. package/dist/snapshot-chunks/types.d.ts +0 -80
  597. package/dist/snapshot-chunks/types.d.ts.map +0 -1
  598. package/dist/snapshot-chunks/types.js +0 -8
  599. package/dist/snapshot-chunks/types.js.map +0 -1
  600. package/dist/snapshot-chunks.d.ts +0 -90
  601. package/dist/snapshot-chunks.d.ts.map +0 -1
  602. package/dist/snapshot-chunks.js +0 -304
  603. package/dist/snapshot-chunks.js.map +0 -1
  604. package/dist/sqlite/index.d.ts +0 -53
  605. package/dist/sqlite/index.d.ts.map +0 -1
  606. package/dist/sqlite/index.js +0 -795
  607. package/dist/sqlite/index.js.map +0 -1
  608. package/dist/sqlite3.d.ts +0 -22
  609. package/dist/sqlite3.d.ts.map +0 -1
  610. package/dist/sqlite3.js +0 -99
  611. package/dist/sqlite3.js.map +0 -1
  612. package/dist/stats.d.ts +0 -28
  613. package/dist/stats.d.ts.map +0 -1
  614. package/dist/stats.js +0 -93
  615. package/dist/stats.js.map +0 -1
  616. package/dist/subscriptions/cache.d.ts +0 -58
  617. package/dist/subscriptions/cache.d.ts.map +0 -1
  618. package/dist/subscriptions/cache.js +0 -250
  619. package/dist/subscriptions/cache.js.map +0 -1
  620. package/dist/subscriptions/index.d.ts +0 -3
  621. package/dist/subscriptions/index.d.ts.map +0 -1
  622. package/dist/subscriptions/index.js +0 -3
  623. package/dist/subscriptions/index.js.map +0 -1
  624. package/dist/subscriptions/resolve.d.ts +0 -40
  625. package/dist/subscriptions/resolve.d.ts.map +0 -1
  626. package/dist/subscriptions/resolve.js +0 -275
  627. package/dist/subscriptions/resolve.js.map +0 -1
  628. package/dist/sync.d.ts +0 -24
  629. package/dist/sync.d.ts.map +0 -1
  630. package/dist/sync.js +0 -27
  631. package/dist/sync.js.map +0 -1
  632. package/src/auth-leases.ts +0 -649
  633. package/src/better-sqlite3.ts +0 -35
  634. package/src/blobs/access.ts +0 -244
  635. package/src/blobs/adapters/database.ts +0 -397
  636. package/src/blobs/index.ts +0 -9
  637. package/src/blobs/manager.ts +0 -901
  638. package/src/blobs/migrate.ts +0 -158
  639. package/src/blobs/types.ts +0 -74
  640. package/src/bun-sqlite-ambient.d.ts +0 -19
  641. package/src/bun-sqlite.ts +0 -27
  642. package/src/clients.ts +0 -22
  643. package/src/cloudflare/durable-object.ts +0 -289
  644. package/src/cloudflare/index.ts +0 -22
  645. package/src/cloudflare/r2.ts +0 -526
  646. package/src/cloudflare/scope-cache.ts +0 -341
  647. package/src/cloudflare/sentry.ts +0 -230
  648. package/src/cloudflare/worker.ts +0 -77
  649. package/src/commit-integrity.ts +0 -371
  650. package/src/compaction.ts +0 -77
  651. package/src/crdt-yjs/index.ts +0 -931
  652. package/src/d1.ts +0 -16
  653. package/src/dialect/base.ts +0 -360
  654. package/src/dialect/helpers.ts +0 -92
  655. package/src/dialect/index.ts +0 -7
  656. package/src/dialect/types.ts +0 -247
  657. package/src/encrypted-crdt.ts +0 -786
  658. package/src/filesystem/index.ts +0 -262
  659. package/src/handlers/collection.ts +0 -121
  660. package/src/handlers/create-handler.ts +0 -1134
  661. package/src/handlers/index.ts +0 -3
  662. package/src/handlers/types.ts +0 -403
  663. package/src/helpers/conflict.ts +0 -64
  664. package/src/helpers/emitted-change.ts +0 -69
  665. package/src/helpers/index.ts +0 -12
  666. package/src/helpers/paginate.ts +0 -82
  667. package/src/helpers/scope-authorization.ts +0 -27
  668. package/src/helpers/scope-commit-index.ts +0 -52
  669. package/src/helpers/scope-strings.ts +0 -101
  670. package/src/hono/api-key-auth.ts +0 -177
  671. package/src/hono/audit-redaction.ts +0 -135
  672. package/src/hono/blobs.ts +0 -851
  673. package/src/hono/console/gateway.ts +0 -3046
  674. package/src/hono/console/live-auth.ts +0 -46
  675. package/src/hono/console/route-descriptor.ts +0 -22
  676. package/src/hono/console/routes/api-keys.ts +0 -721
  677. package/src/hono/console/routes/clients.ts +0 -447
  678. package/src/hono/console/routes/commits.ts +0 -1137
  679. package/src/hono/console/routes/context.ts +0 -956
  680. package/src/hono/console/routes/events.ts +0 -669
  681. package/src/hono/console/routes/maintenance.ts +0 -461
  682. package/src/hono/console/routes/shared.ts +0 -816
  683. package/src/hono/console/routes/stats.ts +0 -392
  684. package/src/hono/console/routes/storage.ts +0 -159
  685. package/src/hono/console/routes.ts +0 -146
  686. package/src/hono/console/schema-errors.ts +0 -23
  687. package/src/hono/console/schemas.ts +0 -914
  688. package/src/hono/console/types.ts +0 -223
  689. package/src/hono/console/ui.ts +0 -100
  690. package/src/hono/create-server.ts +0 -230
  691. package/src/hono/errors.ts +0 -50
  692. package/src/hono/index.ts +0 -54
  693. package/src/hono/openapi.ts +0 -139
  694. package/src/hono/proxy/connection-manager.ts +0 -340
  695. package/src/hono/proxy/index.ts +0 -8
  696. package/src/hono/proxy/routes.ts +0 -272
  697. package/src/hono/rate-limit.ts +0 -319
  698. package/src/hono/realtime-sync-packs.ts +0 -354
  699. package/src/hono/routes/audit.ts +0 -499
  700. package/src/hono/routes/auth-leases.ts +0 -119
  701. package/src/hono/routes/combined.ts +0 -583
  702. package/src/hono/routes/context.ts +0 -1629
  703. package/src/hono/routes/health.ts +0 -26
  704. package/src/hono/routes/realtime.ts +0 -808
  705. package/src/hono/routes/shared.ts +0 -1626
  706. package/src/hono/routes/snapshots.ts +0 -345
  707. package/src/hono/routes.ts +0 -68
  708. package/src/hono/validation.ts +0 -81
  709. package/src/hono/websocket-origin.ts +0 -131
  710. package/src/hono/ws.ts +0 -1134
  711. package/src/libsql.ts +0 -51
  712. package/src/migrate.ts +0 -20
  713. package/src/neon.ts +0 -28
  714. package/src/notify.ts +0 -341
  715. package/src/pglite.ts +0 -68
  716. package/src/plugins/index.ts +0 -1
  717. package/src/plugins/types.ts +0 -144
  718. package/src/postgres/index.ts +0 -1291
  719. package/src/proxy/collection.ts +0 -17
  720. package/src/proxy/handler.ts +0 -159
  721. package/src/proxy/index.ts +0 -21
  722. package/src/proxy/mutation-detector.ts +0 -281
  723. package/src/proxy/oplog.ts +0 -181
  724. package/src/proxy/types.ts +0 -46
  725. package/src/realtime/in-memory.ts +0 -33
  726. package/src/realtime/index.ts +0 -7
  727. package/src/realtime/types.ts +0 -90
  728. package/src/relay/bun-types.d.ts +0 -50
  729. package/src/relay/client-role/forward-engine.ts +0 -355
  730. package/src/relay/client-role/index.ts +0 -9
  731. package/src/relay/client-role/pull-engine.ts +0 -329
  732. package/src/relay/client-role/sequence-mapper.ts +0 -201
  733. package/src/relay/evaluation/relay-paths.ts +0 -699
  734. package/src/relay/evaluation/rust-boundary.ts +0 -464
  735. package/src/relay/index.ts +0 -50
  736. package/src/relay/migrate.ts +0 -113
  737. package/src/relay/mode-manager.ts +0 -142
  738. package/src/relay/realtime.ts +0 -207
  739. package/src/relay/relay.ts +0 -431
  740. package/src/relay/schema.ts +0 -171
  741. package/src/relay/server-role/index.ts +0 -338
  742. package/src/relay/server-role/pull.ts +0 -43
  743. package/src/relay/server-role/push.ts +0 -164
  744. package/src/s3/index.ts +0 -346
  745. package/src/service-worker/index.ts +0 -773
  746. package/src/snapshot-artifacts/sqlite-bun.ts +0 -168
  747. package/src/snapshot-artifacts.ts +0 -896
  748. package/src/snapshot-chunks/db-metadata.ts +0 -537
  749. package/src/snapshot-chunks/index.ts +0 -8
  750. package/src/snapshot-chunks/types.ts +0 -105
  751. package/src/snapshot-chunks.ts +0 -453
  752. package/src/sqlite/index.ts +0 -1064
  753. package/src/sqlite3.ts +0 -137
  754. package/src/stats.ts +0 -180
  755. package/src/subscriptions/cache.ts +0 -376
  756. package/src/subscriptions/index.ts +0 -2
  757. package/src/subscriptions/resolve.ts +0 -357
  758. package/src/sync.ts +0 -111
@@ -1,1064 +0,0 @@
1
- /**
2
- * @syncular/server/sqlite - SQLite Server Sync Dialect
3
- *
4
- * SQLite adaptation of the commit-log based sync system.
5
- * Works with SQLite-compatible Kysely dialects such as bun:sqlite, better-sqlite3, and sqlite3.
6
- *
7
- * Key differences from Postgres:
8
- * - No bigserial → INTEGER PRIMARY KEY AUTOINCREMENT
9
- * - No JSONB → JSON stored as TEXT (with json_extract for filtering)
10
- * - No array && overlap → JSON object key matching
11
- * - No timestamptz → TEXT with ISO format
12
- * - No GIN index → regular index + manual filtering
13
- * - REPEATABLE READ → no-op (SQLite uses serializable by default)
14
- */
15
-
16
- import type { ScopeValues, StoredScopes, SyncOp } from '@syncular/core';
17
- import type { DbExecutor } from '@syncular/server';
18
- import {
19
- type AuditRowHistoryArgs,
20
- type AuditRowHistoryRow,
21
- BaseServerSyncDialect,
22
- coerceIsoString,
23
- coerceNumber,
24
- createSavepointName,
25
- type IncrementalPullRow,
26
- type IncrementalPullRowsArgs,
27
- isActiveTransaction,
28
- parseScopes,
29
- } from '@syncular/server';
30
- import type { SyncChangeRow, SyncCoreDb } from '@syncular/server/schema';
31
- import type { Kysely, RawBuilder } from 'kysely';
32
- import { sql } from 'kysely';
33
-
34
- function parseJsonValue(value: unknown): unknown {
35
- if (value === null || value === undefined) return null;
36
- if (typeof value === 'object') return value;
37
- if (typeof value === 'string') {
38
- try {
39
- return JSON.parse(value);
40
- } catch {
41
- return value;
42
- }
43
- }
44
- return value;
45
- }
46
-
47
- function toStringArray(value: unknown): string[] {
48
- if (Array.isArray(value)) {
49
- return value.filter((k: unknown): k is string => typeof k === 'string');
50
- }
51
- if (typeof value === 'string') {
52
- try {
53
- const parsed = JSON.parse(value);
54
- if (Array.isArray(parsed)) {
55
- return parsed.filter(
56
- (k: unknown): k is string => typeof k === 'string'
57
- );
58
- }
59
- } catch {
60
- // ignore
61
- }
62
- }
63
- return [];
64
- }
65
-
66
- /**
67
- * Build a safe SQLite JSON path for a scope key.
68
- */
69
- function toSqliteJsonPath(scopeKey: string): string {
70
- if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(scopeKey)) {
71
- return `$.${scopeKey}`;
72
- }
73
- const escaped = scopeKey
74
- .replaceAll('\\', '\\\\')
75
- .replaceAll('"', '\\"')
76
- .replaceAll("'", "\\'");
77
- return `$."${escaped}"`;
78
- }
79
-
80
- /**
81
- * Build scope filter SQL for a JSON scopes column.
82
- * Returns `0 = 1` when a requested array scope is empty.
83
- */
84
- function buildScopeFilterSql(
85
- scopes: ScopeValues,
86
- scopeColumnSql: string
87
- ): ReturnType<typeof sql> {
88
- const conditions: ReturnType<typeof sql>[] = [];
89
-
90
- for (const [scopeKey, requested] of Object.entries(scopes)) {
91
- const jsonPath = toSqliteJsonPath(scopeKey);
92
- if (Array.isArray(requested)) {
93
- const values = requested.filter(
94
- (value): value is string => typeof value === 'string'
95
- );
96
- if (values.length === 0) {
97
- return sql`0 = 1`;
98
- }
99
- const valuesSql = sql.join(
100
- values.map((value) => sql`${value}`),
101
- sql`, `
102
- );
103
- conditions.push(
104
- sql`json_extract(${sql.raw(scopeColumnSql)}, ${jsonPath}) IN (${valuesSql})`
105
- );
106
- continue;
107
- }
108
-
109
- conditions.push(
110
- sql`json_extract(${sql.raw(scopeColumnSql)}, ${jsonPath}) = ${requested}`
111
- );
112
- }
113
-
114
- if (conditions.length === 0) {
115
- return sql`1 = 1`;
116
- }
117
-
118
- return sql.join(conditions, sql` AND `);
119
- }
120
-
121
- async function ensurePartitionColumn<DB extends SyncCoreDb>(
122
- db: Kysely<DB>,
123
- table: string
124
- ): Promise<void> {
125
- try {
126
- await sql
127
- .raw(
128
- `ALTER TABLE ${table} ADD COLUMN partition_id TEXT NOT NULL DEFAULT 'default'`
129
- )
130
- .execute(db);
131
- } catch {
132
- // Ignore when column already exists (or table is immutable in the current backend).
133
- }
134
- }
135
-
136
- async function ensureCommitVerificationColumns<DB extends SyncCoreDb>(
137
- db: Kysely<DB>
138
- ): Promise<void> {
139
- const alterStatements = [
140
- 'ALTER TABLE sync_commits ADD COLUMN commit_digest TEXT',
141
- 'ALTER TABLE sync_commits ADD COLUMN commit_chain_root TEXT',
142
- ];
143
-
144
- for (const statement of alterStatements) {
145
- try {
146
- await sql.raw(statement).execute(db);
147
- } catch {
148
- // Ignore when column already exists.
149
- }
150
- }
151
- }
152
-
153
- async function ensureConsoleEventColumns<DB extends SyncCoreDb>(
154
- db: Kysely<DB>
155
- ): Promise<void> {
156
- const alterStatements = [
157
- "ALTER TABLE sync_request_events ADD COLUMN partition_id TEXT NOT NULL DEFAULT 'default'",
158
- 'ALTER TABLE sync_request_events ADD COLUMN request_id TEXT',
159
- 'ALTER TABLE sync_request_events ADD COLUMN trace_id TEXT',
160
- 'ALTER TABLE sync_request_events ADD COLUMN span_id TEXT',
161
- "ALTER TABLE sync_request_events ADD COLUMN transport_path TEXT NOT NULL DEFAULT 'direct'",
162
- "ALTER TABLE sync_request_events ADD COLUMN sync_path TEXT NOT NULL DEFAULT 'http-combined'",
163
- "ALTER TABLE sync_request_events ADD COLUMN response_status TEXT NOT NULL DEFAULT 'unknown'",
164
- 'ALTER TABLE sync_request_events ADD COLUMN error_code TEXT',
165
- 'ALTER TABLE sync_request_events ADD COLUMN subscription_count INTEGER',
166
- 'ALTER TABLE sync_request_events ADD COLUMN scopes_summary TEXT',
167
- 'ALTER TABLE sync_request_events ADD COLUMN response_summary TEXT',
168
- 'ALTER TABLE sync_request_events ADD COLUMN payload_ref TEXT',
169
- ];
170
-
171
- for (const statement of alterStatements) {
172
- try {
173
- await sql.raw(statement).execute(db);
174
- } catch {
175
- // Ignore when column already exists (or table is immutable in the current backend).
176
- }
177
- }
178
- }
179
-
180
- async function ensureSnapshotChunkContinuationColumns<DB extends SyncCoreDb>(
181
- db: Kysely<DB>
182
- ): Promise<void> {
183
- const alterStatements = [
184
- 'ALTER TABLE sync_snapshot_chunks ADD COLUMN next_row_cursor TEXT',
185
- 'ALTER TABLE sync_snapshot_chunks ADD COLUMN is_last_page INTEGER NOT NULL DEFAULT 0',
186
- ];
187
-
188
- for (const statement of alterStatements) {
189
- try {
190
- await sql.raw(statement).execute(db);
191
- } catch {
192
- // Ignore when column already exists.
193
- }
194
- }
195
- }
196
-
197
- export class SqliteServerSyncDialect extends BaseServerSyncDialect<'sqlite'> {
198
- readonly family = 'sqlite' as const;
199
- readonly supportsForUpdate = false;
200
- readonly supportsSavepoints: boolean;
201
- readonly supportsInsertReturning = false;
202
- private readonly _supportsTransactions: boolean;
203
-
204
- constructor(options?: { supportsTransactions?: boolean }) {
205
- super();
206
- this._supportsTransactions = options?.supportsTransactions ?? true;
207
- this.supportsSavepoints = this._supportsTransactions;
208
- }
209
-
210
- // ===========================================================================
211
- // SQL Fragment Hooks
212
- // ===========================================================================
213
-
214
- protected buildNumberListFilter(values: number[]): RawBuilder<unknown> {
215
- const list = sql.join(
216
- values.map((v) => sql`${v}`),
217
- sql`, `
218
- );
219
- return sql`IN (${list})`;
220
- }
221
-
222
- protected buildStringListFilter(values: string[]): RawBuilder<unknown> {
223
- const list = sql.join(
224
- values.map((v) => sql`${v}`),
225
- sql`, `
226
- );
227
- return sql`IN (${list})`;
228
- }
229
-
230
- // ===========================================================================
231
- // Schema Setup
232
- // ===========================================================================
233
-
234
- async ensureSyncSchema<DB extends SyncCoreDb>(db: Kysely<DB>): Promise<void> {
235
- await sql`PRAGMA foreign_keys = ON`.execute(db);
236
-
237
- const nowIso = sql`(strftime('%Y-%m-%dT%H:%M:%fZ','now'))`;
238
-
239
- // sync_commits table
240
- await db.schema
241
- .createTable('sync_commits')
242
- .ifNotExists()
243
- .addColumn('commit_seq', 'integer', (col) =>
244
- col.primaryKey().autoIncrement()
245
- )
246
- .addColumn('partition_id', 'text', (col) =>
247
- col.notNull().defaultTo('default')
248
- )
249
- .addColumn('actor_id', 'text', (col) => col.notNull())
250
- .addColumn('client_id', 'text', (col) => col.notNull())
251
- .addColumn('client_commit_id', 'text', (col) => col.notNull())
252
- .addColumn('created_at', 'text', (col) => col.notNull().defaultTo(nowIso))
253
- .addColumn('meta', 'json')
254
- .addColumn('result_json', 'json')
255
- .addColumn('change_count', 'integer', (col) => col.notNull().defaultTo(0))
256
- .addColumn('commit_digest', 'text')
257
- .addColumn('commit_chain_root', 'text')
258
- .addColumn('affected_tables', 'text', (col) =>
259
- col.notNull().defaultTo('[]')
260
- )
261
- .execute();
262
- await ensurePartitionColumn(db, 'sync_commits');
263
- await ensureCommitVerificationColumns(db);
264
-
265
- await sql`DROP INDEX IF EXISTS idx_sync_commits_client_commit`.execute(db);
266
- await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_sync_commits_client_commit
267
- ON sync_commits(partition_id, client_id, client_commit_id)`.execute(db);
268
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_commits_partition_client_commit_seq
269
- ON sync_commits(partition_id, client_id, commit_seq)`.execute(db);
270
-
271
- // sync_table_commits table (index of which commits affect which tables)
272
- await db.schema
273
- .createTable('sync_table_commits')
274
- .ifNotExists()
275
- .addColumn('partition_id', 'text', (col) =>
276
- col.notNull().defaultTo('default')
277
- )
278
- .addColumn('table', 'text', (col) => col.notNull())
279
- .addColumn('commit_seq', 'integer', (col) =>
280
- col.notNull().references('sync_commits.commit_seq').onDelete('cascade')
281
- )
282
- .addPrimaryKeyConstraint('sync_table_commits_pk', [
283
- 'partition_id',
284
- 'table',
285
- 'commit_seq',
286
- ])
287
- .execute();
288
- await ensurePartitionColumn(db, 'sync_table_commits');
289
-
290
- // Ensure unique index matches ON CONFLICT clause in push.ts
291
- // (needed when migrating from old schema where PK was only (table, commit_seq))
292
- await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_sync_table_commits_partition_pk
293
- ON sync_table_commits(partition_id, "table", commit_seq)`.execute(db);
294
-
295
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_table_commits_commit_seq
296
- ON sync_table_commits(partition_id, commit_seq)`.execute(db);
297
-
298
- // sync_scope_commits table (index of which commits affect table/scope routes)
299
- await db.schema
300
- .createTable('sync_scope_commits')
301
- .ifNotExists()
302
- .addColumn('partition_id', 'text', (col) =>
303
- col.notNull().defaultTo('default')
304
- )
305
- .addColumn('table', 'text', (col) => col.notNull())
306
- .addColumn('scope_key', 'text', (col) => col.notNull())
307
- .addColumn('commit_seq', 'integer', (col) =>
308
- col.notNull().references('sync_commits.commit_seq').onDelete('cascade')
309
- )
310
- .addPrimaryKeyConstraint('sync_scope_commits_pk', [
311
- 'partition_id',
312
- 'table',
313
- 'scope_key',
314
- 'commit_seq',
315
- ])
316
- .execute();
317
- await ensurePartitionColumn(db, 'sync_scope_commits');
318
-
319
- await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_sync_scope_commits_partition_pk
320
- ON sync_scope_commits(partition_id, "table", scope_key, commit_seq)`.execute(
321
- db
322
- );
323
-
324
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_scope_commits_commit_seq
325
- ON sync_scope_commits(partition_id, commit_seq)`.execute(db);
326
-
327
- // sync_changes table - uses JSON for scopes
328
- await db.schema
329
- .createTable('sync_changes')
330
- .ifNotExists()
331
- .addColumn('change_id', 'integer', (col) =>
332
- col.primaryKey().autoIncrement()
333
- )
334
- .addColumn('partition_id', 'text', (col) =>
335
- col.notNull().defaultTo('default')
336
- )
337
- .addColumn('commit_seq', 'integer', (col) =>
338
- col.notNull().references('sync_commits.commit_seq').onDelete('cascade')
339
- )
340
- .addColumn('table', 'text', (col) => col.notNull())
341
- .addColumn('row_id', 'text', (col) => col.notNull())
342
- .addColumn('op', 'text', (col) => col.notNull())
343
- .addColumn('row_json', 'json')
344
- .addColumn('row_version', 'integer')
345
- .addColumn('scopes', 'json', (col) => col.notNull())
346
- .execute();
347
- await ensurePartitionColumn(db, 'sync_changes');
348
-
349
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_changes_commit_seq
350
- ON sync_changes(partition_id, commit_seq)`.execute(db);
351
-
352
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_changes_table
353
- ON sync_changes(partition_id, "table")`.execute(db);
354
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_changes_table_commit_seq_change_id
355
- ON sync_changes(partition_id, "table", commit_seq, change_id)`.execute(
356
- db
357
- );
358
-
359
- // sync_client_cursors table
360
- await db.schema
361
- .createTable('sync_client_cursors')
362
- .ifNotExists()
363
- .addColumn('partition_id', 'text', (col) =>
364
- col.notNull().defaultTo('default')
365
- )
366
- .addColumn('client_id', 'text', (col) => col.notNull())
367
- .addColumn('actor_id', 'text', (col) => col.notNull())
368
- .addColumn('cursor', 'integer', (col) => col.notNull().defaultTo(0))
369
- .addColumn('effective_scopes', 'json', (col) =>
370
- col.notNull().defaultTo('{}')
371
- )
372
- .addColumn('realtime_subscriptions', 'json')
373
- .addColumn('updated_at', 'text', (col) => col.notNull().defaultTo(nowIso))
374
- .addPrimaryKeyConstraint('sync_client_cursors_pk', [
375
- 'partition_id',
376
- 'client_id',
377
- ])
378
- .execute();
379
- await ensurePartitionColumn(db, 'sync_client_cursors');
380
- try {
381
- await sql`ALTER TABLE sync_client_cursors ADD COLUMN realtime_subscriptions json`.execute(
382
- db
383
- );
384
- } catch {
385
- // Ignore when column already exists.
386
- }
387
-
388
- // Ensure unique index matches ON CONFLICT clause in recordClientCursor
389
- // (needed when migrating from old schema where PK was only (client_id))
390
- await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_sync_client_cursors_partition_pk
391
- ON sync_client_cursors(partition_id, client_id)`.execute(db);
392
-
393
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_client_cursors_updated_at
394
- ON sync_client_cursors(updated_at)`.execute(db);
395
-
396
- // sync_snapshot_chunks table
397
- await db.schema
398
- .createTable('sync_snapshot_chunks')
399
- .ifNotExists()
400
- .addColumn('chunk_id', 'text', (col) => col.primaryKey())
401
- .addColumn('partition_id', 'text', (col) =>
402
- col.notNull().defaultTo('default')
403
- )
404
- .addColumn('scope_key', 'text', (col) => col.notNull())
405
- .addColumn('scope', 'text', (col) => col.notNull())
406
- .addColumn('as_of_commit_seq', 'integer', (col) => col.notNull())
407
- .addColumn('row_cursor', 'text', (col) => col.notNull().defaultTo(''))
408
- .addColumn('row_limit', 'integer', (col) => col.notNull())
409
- .addColumn('next_row_cursor', 'text')
410
- .addColumn('is_last_page', 'integer', (col) => col.notNull().defaultTo(0))
411
- .addColumn('encoding', 'text', (col) => col.notNull())
412
- .addColumn('compression', 'text', (col) => col.notNull())
413
- .addColumn('sha256', 'text', (col) => col.notNull())
414
- .addColumn('byte_length', 'integer', (col) => col.notNull())
415
- .addColumn('blob_hash', 'text', (col) => col.notNull().defaultTo(''))
416
- .addColumn('body', 'blob') // Deprecated: use blob storage
417
- .addColumn('created_at', 'text', (col) => col.notNull().defaultTo(nowIso))
418
- .addColumn('expires_at', 'text', (col) => col.notNull())
419
- .execute();
420
- await ensurePartitionColumn(db, 'sync_snapshot_chunks');
421
- await ensureSnapshotChunkContinuationColumns(db);
422
-
423
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_snapshot_chunks_expires_at
424
- ON sync_snapshot_chunks(expires_at)`.execute(db);
425
-
426
- await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_sync_snapshot_chunks_page_key
427
- ON sync_snapshot_chunks(partition_id, scope_key, scope, as_of_commit_seq, row_cursor, row_limit, encoding, compression)`.execute(
428
- db
429
- );
430
-
431
- // sync_snapshot_artifacts table. Artifact bodies live in object storage;
432
- // this table owns scoped eligibility and manifest metadata.
433
- await db.schema
434
- .createTable('sync_snapshot_artifacts')
435
- .ifNotExists()
436
- .addColumn('artifact_id', 'text', (col) => col.primaryKey())
437
- .addColumn('partition_id', 'text', (col) =>
438
- col.notNull().defaultTo('default')
439
- )
440
- .addColumn('scope_key', 'text', (col) => col.notNull())
441
- .addColumn('subscription_id', 'text', (col) => col.notNull())
442
- .addColumn('table', 'text', (col) => col.notNull())
443
- .addColumn('artifact_kind', 'text', (col) => col.notNull())
444
- .addColumn('schema_version', 'text', (col) => col.notNull())
445
- .addColumn('as_of_commit_seq', 'integer', (col) => col.notNull())
446
- .addColumn('row_cursor', 'text', (col) => col.notNull().defaultTo(''))
447
- .addColumn('row_limit', 'integer', (col) => col.notNull())
448
- .addColumn('row_count', 'integer', (col) => col.notNull())
449
- .addColumn('next_row_cursor', 'text')
450
- .addColumn('is_first_page', 'integer', (col) =>
451
- col.notNull().defaultTo(0)
452
- )
453
- .addColumn('is_last_page', 'integer', (col) => col.notNull().defaultTo(0))
454
- .addColumn('compression', 'text', (col) => col.notNull())
455
- .addColumn('sha256', 'text', (col) => col.notNull())
456
- .addColumn('byte_length', 'integer', (col) => col.notNull())
457
- .addColumn('manifest_digest', 'text', (col) => col.notNull())
458
- .addColumn('feature_set_json', 'text', (col) => col.notNull())
459
- .addColumn('manifest_json', 'text', (col) => col.notNull())
460
- .addColumn('blob_hash', 'text', (col) => col.notNull())
461
- .addColumn('created_at', 'text', (col) => col.notNull().defaultTo(nowIso))
462
- .addColumn('expires_at', 'text', (col) => col.notNull())
463
- .execute();
464
-
465
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_snapshot_artifacts_expires_at
466
- ON sync_snapshot_artifacts(expires_at)`.execute(db);
467
-
468
- await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_sync_snapshot_artifacts_page_key
469
- ON sync_snapshot_artifacts(partition_id, scope_key, subscription_id, "table", as_of_commit_seq, row_cursor, row_limit, artifact_kind, schema_version, compression)`.execute(
470
- db
471
- );
472
-
473
- // Encrypted CRDT system tables. These are shared by all encrypted CRDT
474
- // fields and are exposed through hidden handlers, not app query builders.
475
- await db.schema
476
- .createTable('sync_crdt_updates')
477
- .ifNotExists()
478
- .addColumn('seq', 'integer', (col) => col.primaryKey().autoIncrement())
479
- .addColumn('partition_id', 'text', (col) =>
480
- col.notNull().defaultTo('default')
481
- )
482
- .addColumn('stream_id', 'text', (col) => col.notNull())
483
- .addColumn('app_table', 'text', (col) => col.notNull())
484
- .addColumn('row_id', 'text', (col) => col.notNull())
485
- .addColumn('field_name', 'text', (col) => col.notNull())
486
- .addColumn('update_id', 'text', (col) => col.notNull())
487
- .addColumn('actor_id', 'text')
488
- .addColumn('client_id', 'text')
489
- .addColumn('key_id', 'text', (col) => col.notNull())
490
- .addColumn('ciphertext', 'text', (col) => col.notNull())
491
- .addColumn('scopes', 'json', (col) => col.notNull().defaultTo('{}'))
492
- .addColumn('created_at', 'text', (col) => col.notNull().defaultTo(nowIso))
493
- .execute();
494
- await ensurePartitionColumn(db, 'sync_crdt_updates');
495
- await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_sync_crdt_updates_update_id
496
- ON sync_crdt_updates(partition_id, update_id)`.execute(db);
497
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_crdt_updates_stream_seq
498
- ON sync_crdt_updates(partition_id, stream_id, seq)`.execute(db);
499
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_crdt_updates_scope_table
500
- ON sync_crdt_updates(partition_id, app_table, row_id, field_name)`.execute(
501
- db
502
- );
503
-
504
- await db.schema
505
- .createTable('sync_crdt_checkpoints')
506
- .ifNotExists()
507
- .addColumn('seq', 'integer', (col) => col.primaryKey().autoIncrement())
508
- .addColumn('partition_id', 'text', (col) =>
509
- col.notNull().defaultTo('default')
510
- )
511
- .addColumn('stream_id', 'text', (col) => col.notNull())
512
- .addColumn('app_table', 'text', (col) => col.notNull())
513
- .addColumn('row_id', 'text', (col) => col.notNull())
514
- .addColumn('field_name', 'text', (col) => col.notNull())
515
- .addColumn('checkpoint_id', 'text', (col) => col.notNull())
516
- .addColumn('covers_seq', 'integer', (col) => col.notNull())
517
- .addColumn('actor_id', 'text')
518
- .addColumn('client_id', 'text')
519
- .addColumn('key_id', 'text', (col) => col.notNull())
520
- .addColumn('ciphertext', 'text', (col) => col.notNull())
521
- .addColumn('scopes', 'json', (col) => col.notNull().defaultTo('{}'))
522
- .addColumn('created_at', 'text', (col) => col.notNull().defaultTo(nowIso))
523
- .execute();
524
- await ensurePartitionColumn(db, 'sync_crdt_checkpoints');
525
- await sql`CREATE UNIQUE INDEX IF NOT EXISTS idx_sync_crdt_checkpoints_checkpoint_id
526
- ON sync_crdt_checkpoints(partition_id, checkpoint_id)`.execute(db);
527
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_crdt_checkpoints_stream_covers
528
- ON sync_crdt_checkpoints(partition_id, stream_id, covers_seq)`.execute(
529
- db
530
- );
531
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_crdt_checkpoints_scope_table
532
- ON sync_crdt_checkpoints(partition_id, app_table, row_id, field_name)`.execute(
533
- db
534
- );
535
-
536
- // Cleanup orphaned rows
537
- await sql`
538
- DELETE FROM sync_table_commits
539
- WHERE commit_seq NOT IN (SELECT commit_seq FROM sync_commits)
540
- `.execute(db);
541
- await sql`
542
- DELETE FROM sync_changes
543
- WHERE commit_seq NOT IN (SELECT commit_seq FROM sync_commits)
544
- `.execute(db);
545
- }
546
-
547
- // ===========================================================================
548
- // Transaction Control
549
- // ===========================================================================
550
-
551
- async executeInTransaction<DB extends SyncCoreDb, T>(
552
- db: Kysely<DB>,
553
- fn: (executor: DbExecutor<DB>) => Promise<T>
554
- ): Promise<T> {
555
- if (isActiveTransaction(db)) {
556
- if (!this._supportsTransactions) {
557
- return fn(db);
558
- }
559
- const savepoint = createSavepointName();
560
- await sql.raw(`SAVEPOINT ${savepoint}`).execute(db);
561
- try {
562
- const result = await fn(db);
563
- await sql.raw(`RELEASE SAVEPOINT ${savepoint}`).execute(db);
564
- return result;
565
- } catch (error) {
566
- await sql.raw(`ROLLBACK TO SAVEPOINT ${savepoint}`).execute(db);
567
- await sql.raw(`RELEASE SAVEPOINT ${savepoint}`).execute(db);
568
- throw error;
569
- }
570
- }
571
- if (this._supportsTransactions) {
572
- return db.transaction().execute(fn);
573
- }
574
- return fn(db);
575
- }
576
-
577
- async setRepeatableRead<DB extends SyncCoreDb>(
578
- _trx: DbExecutor<DB>
579
- ): Promise<void> {
580
- // SQLite uses serializable isolation by default in WAL mode.
581
- }
582
-
583
- // ===========================================================================
584
- // Commit/Change Log Queries (dialect-specific)
585
- // ===========================================================================
586
-
587
- async readChangesForCommits<DB extends SyncCoreDb>(
588
- db: DbExecutor<DB>,
589
- args: {
590
- commitSeqs: number[];
591
- table: string;
592
- scopes: ScopeValues;
593
- partitionId?: string;
594
- }
595
- ): Promise<SyncChangeRow[]> {
596
- const partitionId = args.partitionId ?? 'default';
597
- if (args.commitSeqs.length === 0) return [];
598
- const scopeFilter = buildScopeFilterSql(args.scopes, 'scopes');
599
-
600
- const commitSeqsIn = sql.join(
601
- args.commitSeqs.map((seq) => sql`${seq}`),
602
- sql`, `
603
- );
604
-
605
- // Fetch all changes for the table and commit sequences
606
- const res = await sql<{
607
- commit_seq: unknown;
608
- table: string;
609
- row_id: string;
610
- op: string;
611
- row_json: unknown | null;
612
- row_version: unknown | null;
613
- scopes: unknown;
614
- }>`
615
- SELECT commit_seq, "table", row_id, op, row_json, row_version, scopes
616
- FROM sync_changes
617
- WHERE commit_seq IN (${commitSeqsIn})
618
- AND partition_id = ${partitionId}
619
- AND "table" = ${args.table}
620
- AND (${scopeFilter})
621
- ORDER BY commit_seq ASC, change_id ASC
622
- `.execute(db);
623
-
624
- return res.rows.map((row) => ({
625
- commit_seq: coerceNumber(row.commit_seq) ?? 0,
626
- table: row.table,
627
- row_id: row.row_id,
628
- op: row.op as SyncOp,
629
- row_json: parseJsonValue(row.row_json),
630
- row_version: coerceNumber(row.row_version),
631
- scopes: parseScopes(row.scopes),
632
- }));
633
- }
634
-
635
- async readAuditRowHistory<DB extends SyncCoreDb>(
636
- db: DbExecutor<DB>,
637
- args: AuditRowHistoryArgs
638
- ): Promise<AuditRowHistoryRow[]> {
639
- const partitionId = args.partitionId ?? 'default';
640
- const scopeFilter = buildScopeFilterSql(args.scopes, 'c.scopes');
641
- const limit = Math.max(1, Math.min(200, args.limit));
642
- const whereClauses = [
643
- sql`c.partition_id = ${partitionId}`,
644
- sql`cm.partition_id = ${partitionId}`,
645
- sql`c."table" = ${args.table}`,
646
- sql`c.row_id = ${args.rowId}`,
647
- sql`(${scopeFilter})`,
648
- ];
649
-
650
- if (args.beforeCommitSeq !== undefined) {
651
- whereClauses.push(sql`c.commit_seq < ${args.beforeCommitSeq}`);
652
- }
653
- if (args.afterCommitSeq !== undefined) {
654
- whereClauses.push(sql`c.commit_seq >= ${args.afterCommitSeq}`);
655
- }
656
-
657
- const res = await sql<{
658
- commit_seq: unknown;
659
- actor_id: string;
660
- client_id: string;
661
- client_commit_id: string;
662
- created_at: unknown;
663
- change_id: unknown;
664
- table: string;
665
- row_id: string;
666
- op: string;
667
- row_json: unknown | null;
668
- row_version: unknown | null;
669
- scopes: unknown;
670
- }>`
671
- SELECT
672
- c.commit_seq,
673
- cm.actor_id,
674
- cm.client_id,
675
- cm.client_commit_id,
676
- cm.created_at,
677
- c.change_id,
678
- c."table",
679
- c.row_id,
680
- c.op,
681
- c.row_json,
682
- c.row_version,
683
- c.scopes
684
- FROM sync_changes c
685
- JOIN sync_commits cm
686
- ON cm.partition_id = c.partition_id
687
- AND cm.commit_seq = c.commit_seq
688
- WHERE ${sql.join(whereClauses, sql` AND `)}
689
- ORDER BY c.commit_seq DESC, c.change_id DESC
690
- LIMIT ${limit + 1}
691
- `.execute(db);
692
-
693
- return res.rows.map((row) => ({
694
- commit_seq: coerceNumber(row.commit_seq) ?? 0,
695
- actor_id: row.actor_id,
696
- client_id: row.client_id,
697
- client_commit_id: row.client_commit_id,
698
- created_at: coerceIsoString(row.created_at),
699
- change_id: coerceNumber(row.change_id) ?? 0,
700
- table: row.table,
701
- row_id: row.row_id,
702
- op: row.op as SyncOp,
703
- row_json: parseJsonValue(row.row_json),
704
- row_version: coerceNumber(row.row_version),
705
- scopes: parseScopes(row.scopes),
706
- }));
707
- }
708
-
709
- protected override async readIncrementalPullRowsBatch<DB extends SyncCoreDb>(
710
- db: DbExecutor<DB>,
711
- args: Omit<IncrementalPullRowsArgs, 'batchSize'>
712
- ): Promise<IncrementalPullRow[]> {
713
- const partitionId = args.partitionId ?? 'default';
714
- const limitCommits = Math.max(1, Math.min(1000, args.limitCommits));
715
- const scopeFilter = buildScopeFilterSql(args.scopes, 'c.scopes');
716
-
717
- const commitSeqs = await this.readScopeIndexedCommitSeqsForPull(db, {
718
- partitionId,
719
- table: args.table,
720
- scopes: args.scopes,
721
- cursor: args.cursor,
722
- limitCommits,
723
- });
724
-
725
- if (commitSeqs.length === 0) return [];
726
- const scannedMaxCommitSeq =
727
- commitSeqs[commitSeqs.length - 1] ?? args.cursor;
728
-
729
- const commitSeqsIn = sql.join(
730
- commitSeqs.map((seq) => sql`${seq}`),
731
- sql`, `
732
- );
733
-
734
- // Get commits and changes for these commit_seqs
735
- const changesRes = await sql<{
736
- commit_seq: unknown;
737
- actor_id: string;
738
- created_at: unknown;
739
- commit_digest: string | null;
740
- commit_chain_root: string | null;
741
- change_id: unknown;
742
- table: string;
743
- row_id: string;
744
- op: string;
745
- row_json: unknown | null;
746
- row_version: unknown | null;
747
- scopes: unknown;
748
- }>`
749
- SELECT
750
- cm.commit_seq,
751
- cm.actor_id,
752
- cm.created_at,
753
- cm.commit_digest,
754
- cm.commit_chain_root,
755
- c.change_id,
756
- c."table",
757
- c.row_id,
758
- c.op,
759
- c.row_json,
760
- c.row_version,
761
- c.scopes
762
- FROM sync_commits cm
763
- JOIN sync_changes c ON c.commit_seq = cm.commit_seq
764
- WHERE cm.commit_seq IN (${commitSeqsIn})
765
- AND cm.partition_id = ${partitionId}
766
- AND c.partition_id = ${partitionId}
767
- AND c."table" = ${args.table}
768
- AND (${scopeFilter})
769
- ORDER BY cm.commit_seq ASC, c.change_id ASC
770
- `.execute(db);
771
-
772
- return changesRes.rows.map((row) => ({
773
- commit_seq: coerceNumber(row.commit_seq) ?? 0,
774
- scanned_max_commit_seq: scannedMaxCommitSeq,
775
- actor_id: row.actor_id,
776
- created_at: coerceIsoString(row.created_at),
777
- commit_digest: row.commit_digest ?? null,
778
- commit_chain_root: row.commit_chain_root ?? null,
779
- change_id: coerceNumber(row.change_id) ?? 0,
780
- table: row.table,
781
- row_id: row.row_id,
782
- op: row.op as SyncOp,
783
- row_json: parseJsonValue(row.row_json),
784
- row_version: coerceNumber(row.row_version),
785
- scopes: parseScopes(row.scopes),
786
- }));
787
- }
788
-
789
- async compactChanges<DB extends SyncCoreDb>(
790
- db: DbExecutor<DB>,
791
- args: { fullHistoryHours: number }
792
- ): Promise<number> {
793
- const cutoffIso = new Date(
794
- Date.now() - args.fullHistoryHours * 60 * 60 * 1000
795
- ).toISOString();
796
-
797
- const res = await sql`
798
- WITH ranked AS (
799
- SELECT
800
- c.change_id,
801
- row_number() OVER (
802
- PARTITION BY c.partition_id, c."table", c.row_id, c.scopes
803
- ORDER BY c.commit_seq DESC, c.change_id DESC
804
- ) AS rn
805
- FROM sync_changes c
806
- JOIN sync_commits cm ON cm.commit_seq = c.commit_seq
807
- WHERE cm.created_at < ${cutoffIso}
808
- )
809
- DELETE FROM sync_changes
810
- WHERE change_id IN (SELECT change_id FROM ranked WHERE rn > 1)
811
- `.execute(db);
812
- const deleted = Number(res.numAffectedRows ?? 0);
813
-
814
- // Remove routing index entries that no longer have any remaining changes
815
- await sql`
816
- DELETE FROM sync_scope_commits
817
- WHERE commit_seq IN (
818
- SELECT commit_seq
819
- FROM sync_commits
820
- WHERE created_at < ${cutoffIso}
821
- AND partition_id = sync_scope_commits.partition_id
822
- )
823
- AND NOT EXISTS (
824
- SELECT 1
825
- FROM sync_changes c
826
- WHERE c.commit_seq = sync_scope_commits.commit_seq
827
- AND c.partition_id = sync_scope_commits.partition_id
828
- AND c."table" = sync_scope_commits."table"
829
- )
830
- `.execute(db);
831
-
832
- await sql`
833
- DELETE FROM sync_table_commits
834
- WHERE commit_seq IN (
835
- SELECT commit_seq
836
- FROM sync_commits
837
- WHERE created_at < ${cutoffIso}
838
- AND partition_id = sync_table_commits.partition_id
839
- )
840
- AND NOT EXISTS (
841
- SELECT 1
842
- FROM sync_changes c
843
- WHERE c.commit_seq = sync_table_commits.commit_seq
844
- AND c.partition_id = sync_table_commits.partition_id
845
- AND c."table" = sync_table_commits."table"
846
- )
847
- `.execute(db);
848
-
849
- return deleted;
850
- }
851
-
852
- // ===========================================================================
853
- // Scope Conversion Helpers
854
- // ===========================================================================
855
-
856
- scopesToDb(scopes: StoredScopes): string {
857
- return JSON.stringify(scopes);
858
- }
859
-
860
- dbToArray(value: unknown): string[] {
861
- return toStringArray(value);
862
- }
863
-
864
- arrayToDb(values: string[]): string {
865
- return JSON.stringify(values.filter((v) => v.length > 0));
866
- }
867
-
868
- // ===========================================================================
869
- // Console Schema (Request Events)
870
- // ===========================================================================
871
-
872
- async ensureConsoleSchema<DB extends SyncCoreDb>(
873
- db: Kysely<DB>
874
- ): Promise<void> {
875
- const nowIso = sql`(strftime('%Y-%m-%dT%H:%M:%fZ','now'))`;
876
-
877
- await db.schema
878
- .createTable('sync_request_events')
879
- .ifNotExists()
880
- .addColumn('event_id', 'integer', (col) =>
881
- col.primaryKey().autoIncrement()
882
- )
883
- .addColumn('partition_id', 'text', (col) =>
884
- col.notNull().defaultTo('default')
885
- )
886
- .addColumn('request_id', 'text')
887
- .addColumn('trace_id', 'text')
888
- .addColumn('span_id', 'text')
889
- .addColumn('event_type', 'text', (col) => col.notNull())
890
- .addColumn('actor_id', 'text', (col) => col.notNull())
891
- .addColumn('client_id', 'text', (col) => col.notNull())
892
- .addColumn('transport_path', 'text', (col) =>
893
- col.notNull().defaultTo('direct')
894
- )
895
- .addColumn('sync_path', 'text', (col) =>
896
- col.notNull().defaultTo('http-combined')
897
- )
898
- .addColumn('status_code', 'integer', (col) => col.notNull())
899
- .addColumn('outcome', 'text', (col) => col.notNull())
900
- .addColumn('response_status', 'text', (col) =>
901
- col.notNull().defaultTo('unknown')
902
- )
903
- .addColumn('error_code', 'text')
904
- .addColumn('duration_ms', 'integer', (col) => col.notNull())
905
- .addColumn('commit_seq', 'integer')
906
- .addColumn('operation_count', 'integer')
907
- .addColumn('row_count', 'integer')
908
- .addColumn('subscription_count', 'integer')
909
- .addColumn('scopes_summary', 'text')
910
- .addColumn('response_summary', 'text')
911
- .addColumn('tables', 'text', (col) => col.notNull().defaultTo('[]'))
912
- .addColumn('error_message', 'text')
913
- .addColumn('payload_ref', 'text')
914
- .addColumn('created_at', 'text', (col) => col.notNull().defaultTo(nowIso))
915
- .execute();
916
- await ensureConsoleEventColumns(db);
917
-
918
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_request_events_created_at
919
- ON sync_request_events(created_at DESC)`.execute(db);
920
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_request_events_event_type
921
- ON sync_request_events(event_type)`.execute(db);
922
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_request_events_client_id
923
- ON sync_request_events(client_id)`.execute(db);
924
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_request_events_request_id
925
- ON sync_request_events(request_id)`.execute(db);
926
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_request_events_trace_id
927
- ON sync_request_events(trace_id)`.execute(db);
928
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_request_events_partition_created_at
929
- ON sync_request_events(partition_id, created_at DESC)`.execute(db);
930
-
931
- await db.schema
932
- .createTable('sync_request_payloads')
933
- .ifNotExists()
934
- .addColumn('payload_ref', 'text', (col) => col.primaryKey())
935
- .addColumn('partition_id', 'text', (col) =>
936
- col.notNull().defaultTo('default')
937
- )
938
- .addColumn('request_payload', 'text', (col) => col.notNull())
939
- .addColumn('response_payload', 'text')
940
- .addColumn('created_at', 'text', (col) => col.notNull().defaultTo(nowIso))
941
- .execute();
942
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_request_payloads_created_at
943
- ON sync_request_payloads(created_at DESC)`.execute(db);
944
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_request_payloads_partition_created_at
945
- ON sync_request_payloads(partition_id, created_at DESC)`.execute(db);
946
-
947
- await db.schema
948
- .createTable('sync_operation_events')
949
- .ifNotExists()
950
- .addColumn('operation_id', 'integer', (col) =>
951
- col.primaryKey().autoIncrement()
952
- )
953
- .addColumn('operation_type', 'text', (col) => col.notNull())
954
- .addColumn('console_user_id', 'text')
955
- .addColumn('partition_id', 'text')
956
- .addColumn('target_client_id', 'text')
957
- .addColumn('request_payload', 'text')
958
- .addColumn('result_payload', 'text')
959
- .addColumn('created_at', 'text', (col) => col.notNull().defaultTo(nowIso))
960
- .execute();
961
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_operation_events_created_at
962
- ON sync_operation_events(created_at DESC)`.execute(db);
963
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_operation_events_type
964
- ON sync_operation_events(operation_type)`.execute(db);
965
-
966
- await db.schema
967
- .createTable('sync_realtime_events')
968
- .ifNotExists()
969
- .addColumn('event_id', 'integer', (col) =>
970
- col.primaryKey().autoIncrement()
971
- )
972
- .addColumn('partition_id', 'text', (col) =>
973
- col.notNull().defaultTo('default')
974
- )
975
- .addColumn('actor_id', 'text', (col) => col.notNull())
976
- .addColumn('client_id', 'text', (col) => col.notNull())
977
- .addColumn('transport_path', 'text', (col) =>
978
- col.notNull().defaultTo('direct')
979
- )
980
- .addColumn('event_type', 'text', (col) => col.notNull())
981
- .addColumn('reason', 'text')
982
- .addColumn('cursor', 'integer')
983
- .addColumn('latest_cursor', 'integer')
984
- .addColumn('commit_seq', 'integer')
985
- .addColumn('scope_count', 'integer')
986
- .addColumn('skipped_count', 'integer')
987
- .addColumn('sync_pack_encoding', 'text')
988
- .addColumn('created_at', 'text', (col) => col.notNull().defaultTo(nowIso))
989
- .execute();
990
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_realtime_events_created_at
991
- ON sync_realtime_events(created_at DESC)`.execute(db);
992
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_realtime_events_partition_client_created_at
993
- ON sync_realtime_events(partition_id, client_id, created_at DESC)`.execute(
994
- db
995
- );
996
-
997
- await db.schema
998
- .createTable('sync_client_diagnostic_snapshots')
999
- .ifNotExists()
1000
- .addColumn('snapshot_id', 'integer', (col) =>
1001
- col.primaryKey().autoIncrement()
1002
- )
1003
- .addColumn('partition_id', 'text', (col) =>
1004
- col.notNull().defaultTo('default')
1005
- )
1006
- .addColumn('client_id', 'text', (col) => col.notNull())
1007
- .addColumn('actor_id', 'text')
1008
- .addColumn('runtime_kind', 'text')
1009
- .addColumn('runtime_version', 'text')
1010
- .addColumn('schema_version', 'integer')
1011
- .addColumn('reported_at', 'text', (col) => col.notNull())
1012
- .addColumn('received_at', 'text', (col) =>
1013
- col.notNull().defaultTo(nowIso)
1014
- )
1015
- .addColumn('lifecycle_phase', 'text')
1016
- .addColumn('connection_state', 'text')
1017
- .addColumn('freshness_state', 'text', (col) => col.notNull())
1018
- .addColumn('health_max_severity', 'text')
1019
- .addColumn('diagnostic_codes_summary', 'text')
1020
- .addColumn('queue_summary', 'text')
1021
- .addColumn('timing_summary', 'text')
1022
- .addColumn('redaction_summary', 'text')
1023
- .addColumn('snapshot_json', 'text', (col) => col.notNull())
1024
- .execute();
1025
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_client_diagnostic_snapshots_received_at
1026
- ON sync_client_diagnostic_snapshots(received_at DESC)`.execute(db);
1027
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_client_diagnostic_snapshots_latest
1028
- ON sync_client_diagnostic_snapshots(partition_id, client_id, received_at DESC)`.execute(
1029
- db
1030
- );
1031
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_client_diagnostic_snapshots_health
1032
- ON sync_client_diagnostic_snapshots(partition_id, health_max_severity, received_at DESC)`.execute(
1033
- db
1034
- );
1035
-
1036
- // API Keys table
1037
- await db.schema
1038
- .createTable('sync_api_keys')
1039
- .ifNotExists()
1040
- .addColumn('key_id', 'text', (col) => col.primaryKey())
1041
- .addColumn('key_hash', 'text', (col) => col.notNull())
1042
- .addColumn('key_prefix', 'text', (col) => col.notNull())
1043
- .addColumn('name', 'text', (col) => col.notNull())
1044
- .addColumn('key_type', 'text', (col) => col.notNull())
1045
- .addColumn('scope_keys', 'text', (col) => col.defaultTo('[]'))
1046
- .addColumn('actor_id', 'text')
1047
- .addColumn('created_at', 'text', (col) => col.notNull().defaultTo(nowIso))
1048
- .addColumn('expires_at', 'text')
1049
- .addColumn('last_used_at', 'text')
1050
- .addColumn('revoked_at', 'text')
1051
- .execute();
1052
-
1053
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_api_keys_key_hash
1054
- ON sync_api_keys(key_hash)`.execute(db);
1055
- await sql`CREATE INDEX IF NOT EXISTS idx_sync_api_keys_key_type
1056
- ON sync_api_keys(key_type)`.execute(db);
1057
- }
1058
- }
1059
-
1060
- export function createSqliteServerDialect(options?: {
1061
- supportsTransactions?: boolean;
1062
- }): SqliteServerSyncDialect {
1063
- return new SqliteServerSyncDialect(options);
1064
- }