@syncular/server 0.0.6-95 → 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
@@ -30,19 +30,66 @@ export interface BlobManagerOptions<
30
30
  defaultExpiresIn?: number;
31
31
  /** How long incomplete uploads are kept before cleanup. Default: 86400 (24 hours) */
32
32
  uploadTtlSeconds?: number;
33
+ /** Optional cleanup throughput tuning knobs. */
34
+ cleanupTuning?: BlobCleanupTuning;
33
35
  }
34
36
 
37
+ export interface BlobCleanupTuning {
38
+ /** Cleanup select/delete batch size. Default: 250 */
39
+ batchSize?: number;
40
+ /** Max concurrent storage deletes during cleanup. Default: 8 */
41
+ storageDeleteConcurrency?: number;
42
+ /** Max concurrent reference checks for completed uploads. Default: 16 */
43
+ referenceCheckConcurrency?: number;
44
+ }
45
+
46
+ export const BLOB_CLEANUP_TUNING_PRESETS = {
47
+ server: {
48
+ batchSize: 500,
49
+ storageDeleteConcurrency: 16,
50
+ referenceCheckConcurrency: 24,
51
+ },
52
+ edge: {
53
+ batchSize: 100,
54
+ storageDeleteConcurrency: 4,
55
+ referenceCheckConcurrency: 8,
56
+ },
57
+ } as const satisfies Record<'server' | 'edge', Required<BlobCleanupTuning>>;
58
+
35
59
  export interface InitiateUploadOptions {
36
60
  hash: string;
37
61
  size: number;
38
62
  mimeType: string;
39
63
  actorId: string;
64
+ partitionId?: string;
40
65
  }
41
66
 
42
67
  export interface GetDownloadUrlOptions {
43
68
  hash: string;
44
69
  /** Optional: verify actor has access to this blob via a scope check */
45
70
  actorId?: string;
71
+ partitionId?: string;
72
+ }
73
+
74
+ export interface CompleteUploadOptions {
75
+ /**
76
+ * Optional actor identity to authorize upload completion.
77
+ * When provided, only the initiating actor may mark an upload complete.
78
+ */
79
+ actorId?: string;
80
+ partitionId?: string;
81
+ }
82
+
83
+ export interface BlobUploadRecord {
84
+ partitionId: string;
85
+ hash: string;
86
+ size: number;
87
+ mimeType: string;
88
+ status: 'pending' | 'complete';
89
+ actorId: string;
90
+ createdAt: string;
91
+ expiresAt: string;
92
+ completedAt: string | null;
46
93
  }
47
94
 
48
95
  /**
@@ -56,8 +103,82 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
56
103
  adapter,
57
104
  defaultExpiresIn = 3600,
58
105
  uploadTtlSeconds = 86400,
106
+ cleanupTuning,
59
107
  } = options;
60
108
 
109
+ function positiveIntOrDefault(value: number | undefined, fallback: number) {
110
+ if (value === undefined) return fallback;
111
+ if (!Number.isFinite(value)) return fallback;
112
+ const normalized = Math.trunc(value);
113
+ return normalized > 0 ? normalized : fallback;
114
+ }
115
+
116
+ function resolvePartitionId(partitionId?: string): string {
117
+ return partitionId ?? 'default';
118
+ }
119
+
120
+ function normalizeBlobSizeValue(value: number | string): number {
121
+ return typeof value === 'number' ? value : Number(value);
122
+ }
123
+
124
+ function toStoragePartitionOptions(partitionId: string): {
125
+ partitionId?: string;
126
+ } {
127
+ if (partitionId === 'default') return {};
128
+ return { partitionId };
129
+ }
130
+
131
+ const CLEANUP_BATCH_SIZE = positiveIntOrDefault(
132
+ cleanupTuning?.batchSize,
133
+ 250
134
+ );
135
+ const STORAGE_DELETE_CONCURRENCY = positiveIntOrDefault(
136
+ cleanupTuning?.storageDeleteConcurrency,
137
+ 8
138
+ );
139
+ const REFERENCE_CHECK_CONCURRENCY = positiveIntOrDefault(
140
+ cleanupTuning?.referenceCheckConcurrency,
141
+ 16
142
+ );
143
+
144
+ async function runWithConcurrency<T>(
145
+ items: readonly T[],
146
+ concurrency: number,
147
+ worker: (item: T) => Promise<void>
148
+ ): Promise<void> {
149
+ if (items.length === 0) return;
150
+
151
+ const workerCount = Math.max(1, Math.min(concurrency, items.length));
152
+ let nextIndex = 0;
153
+
154
+ async function runWorker(): Promise<void> {
155
+ while (nextIndex < items.length) {
156
+ const index = nextIndex;
157
+ nextIndex += 1;
158
+ const item = items[index];
159
+ if (item === undefined) continue;
160
+ await worker(item);
161
+ }
162
+ }
163
+
164
+ await Promise.all(Array.from({ length: workerCount }, () => runWorker()));
165
+ }
166
+
167
+ async function deleteUploadRowsByHashes(
168
+ partitionId: string,
169
+ hashes: readonly string[]
170
+ ): Promise<number> {
171
+ if (hashes.length === 0) return 0;
172
+
173
+ const deletedResult = await sql`
174
+ delete from ${sql.table('sync_blob_uploads')}
175
+ where partition_id = ${partitionId}
176
+ and hash in (${sql.join(hashes)})
177
+ `.execute(db);
178
+
179
+ return Number(deletedResult.numAffectedRows ?? 0);
180
+ }
181
+
61
182
  return {
62
183
  /**
63
184
  * Initiate a blob upload.
@@ -68,6 +189,8 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
68
189
  opts: InitiateUploadOptions
69
190
  ): Promise<BlobUploadInitResponse> {
70
191
  const { hash, size, mimeType, actorId } = opts;
192
+ const partitionId = resolvePartitionId(opts.partitionId);
193
+ const storagePartitionOptions = toStoragePartitionOptions(partitionId);
71
194
 
72
195
  // Validate hash format
73
196
  if (!parseBlobHash(hash)) {
@@ -75,13 +198,15 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
75
198
  }
76
199
 
77
200
  // Check if blob already exists (deduplication)
78
- const exists = await adapter.exists(hash);
201
+ const exists = await adapter.exists(hash, storagePartitionOptions);
79
202
  if (exists) {
80
203
  // Also check if we have a complete upload record
81
204
  const existingResult = await sql<{ status: 'pending' | 'complete' }>`
82
205
  select status
83
206
  from ${sql.table('sync_blob_uploads')}
84
- where hash = ${hash} and status = 'complete'
207
+ where partition_id = ${partitionId}
208
+ and hash = ${hash}
209
+ and status = 'complete'
85
210
  limit 1
86
211
  `.execute(db);
87
212
  const existing = existingResult.rows[0];
@@ -98,6 +223,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
98
223
 
99
224
  await sql`
100
225
  insert into ${sql.table('sync_blob_uploads')} (
226
+ partition_id,
101
227
  hash,
102
228
  size,
103
229
  mime_type,
@@ -107,6 +233,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
107
233
  completed_at
108
234
  )
109
235
  values (
236
+ ${partitionId},
110
237
  ${hash},
111
238
  ${size},
112
239
  ${mimeType},
@@ -115,7 +242,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
115
242
  ${existsExpiresAt},
116
243
  ${existsCompletedAt}
117
244
  )
118
- on conflict (hash) do nothing
245
+ on conflict (partition_id, hash) do nothing
119
246
  `.execute(db);
120
247
 
121
248
  return { exists: true };
@@ -128,6 +255,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
128
255
 
129
256
  await sql`
130
257
  insert into ${sql.table('sync_blob_uploads')} (
258
+ partition_id,
131
259
  hash,
132
260
  size,
133
261
  mime_type,
@@ -137,6 +265,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
137
265
  completed_at
138
266
  )
139
267
  values (
268
+ ${partitionId},
140
269
  ${hash},
141
270
  ${size},
142
271
  ${mimeType},
@@ -145,7 +274,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
145
274
  ${expiresAt},
146
275
  ${null}
147
276
  )
148
- on conflict (hash)
277
+ on conflict (partition_id, hash)
149
278
  do update set
150
279
  size = ${size},
151
280
  mime_type = ${mimeType},
@@ -158,6 +287,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
158
287
  // Generate presigned upload URL
159
288
  const signed = await adapter.signUpload({
160
289
  hash,
290
+ partitionId: storagePartitionOptions.partitionId,
161
291
  size,
162
292
  mimeType,
163
293
  expiresIn: defaultExpiresIn,
@@ -177,38 +307,57 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
177
307
  *
178
308
  * Verifies the blob exists in storage and marks the upload as complete.
179
309
  */
180
- async completeUpload(hash: string): Promise<BlobUploadCompleteResponse> {
310
+ async completeUpload(
311
+ hash: string,
312
+ options?: CompleteUploadOptions
313
+ ): Promise<BlobUploadCompleteResponse> {
314
+ const partitionId = resolvePartitionId(options?.partitionId);
315
+ const storagePartitionOptions = toStoragePartitionOptions(partitionId);
316
+
181
317
  // Validate hash format
182
318
  if (!parseBlobHash(hash)) {
183
- return { ok: false, error: 'Invalid blob hash format' };
319
+ return {
320
+ ok: false,
321
+ error: 'Invalid blob hash format',
322
+ code: 'blob.invalid_request',
323
+ };
184
324
  }
185
325
 
186
326
  // Check upload record exists
187
327
  const uploadResult = await sql<{
188
328
  hash: string;
189
- size: number;
329
+ size: number | string;
190
330
  mime_type: string;
191
331
  status: 'pending' | 'complete';
332
+ actor_id: string;
192
333
  created_at: string;
193
334
  }>`
194
- select hash, size, mime_type, status, created_at
335
+ select hash, size, mime_type, status, actor_id, created_at
195
336
  from ${sql.table('sync_blob_uploads')}
196
- where hash = ${hash}
337
+ where partition_id = ${partitionId} and hash = ${hash}
197
338
  limit 1
198
339
  `.execute(db);
199
340
  const upload = uploadResult.rows[0];
200
341
 
201
342
  if (!upload) {
202
- return { ok: false, error: 'Upload not found' };
343
+ return { ok: false, error: 'Upload not found', code: 'blob.not_found' };
344
+ }
345
+
346
+ if (
347
+ options?.actorId !== undefined &&
348
+ upload.actor_id !== options.actorId
349
+ ) {
350
+ return { ok: false, error: 'Forbidden', code: 'blob.forbidden' };
203
351
  }
204
352
 
205
353
  if (upload.status === 'complete') {
354
+ const uploadSize = normalizeBlobSizeValue(upload.size);
206
355
  // Already complete - return metadata
207
356
  return {
208
357
  ok: true,
209
358
  metadata: {
210
359
  hash: upload.hash,
211
- size: upload.size,
360
+ size: uploadSize,
212
361
  mimeType: upload.mime_type,
213
362
  createdAt: upload.created_at,
214
363
  uploadComplete: true,
@@ -217,18 +366,24 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
217
366
  }
218
367
 
219
368
  // Verify blob exists in storage
220
- const exists = await adapter.exists(hash);
369
+ const exists = await adapter.exists(hash, storagePartitionOptions);
221
370
  if (!exists) {
222
- return { ok: false, error: 'Blob not found in storage' };
371
+ return {
372
+ ok: false,
373
+ error: 'Blob not found in storage',
374
+ code: 'blob.not_found',
375
+ };
223
376
  }
224
377
 
225
378
  // Optionally verify size matches
379
+ const uploadSize = normalizeBlobSizeValue(upload.size);
226
380
  if (adapter.getMetadata) {
227
- const meta = await adapter.getMetadata(hash);
228
- if (meta && meta.size !== upload.size) {
381
+ const meta = await adapter.getMetadata(hash, storagePartitionOptions);
382
+ if (meta && meta.size !== uploadSize) {
229
383
  return {
230
384
  ok: false,
231
- error: `Size mismatch: expected ${upload.size}, got ${meta.size}`,
385
+ error: `Size mismatch: expected ${uploadSize}, got ${meta.size}`,
386
+ code: 'blob.size_mismatch',
232
387
  };
233
388
  }
234
389
  }
@@ -238,14 +393,14 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
238
393
  await sql`
239
394
  update ${sql.table('sync_blob_uploads')}
240
395
  set status = 'complete', completed_at = ${completedAt}
241
- where hash = ${hash}
396
+ where partition_id = ${partitionId} and hash = ${hash}
242
397
  `.execute(db);
243
398
 
244
399
  return {
245
400
  ok: true,
246
401
  metadata: {
247
402
  hash: upload.hash,
248
- size: upload.size,
403
+ size: uploadSize,
249
404
  mimeType: upload.mime_type,
250
405
  createdAt: upload.created_at,
251
406
  uploadComplete: true,
@@ -260,6 +415,8 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
260
415
  opts: GetDownloadUrlOptions
261
416
  ): Promise<{ url: string; expiresAt: string; metadata: BlobMetadata }> {
262
417
  const { hash } = opts;
418
+ const partitionId = resolvePartitionId(opts.partitionId);
419
+ const storagePartitionOptions = toStoragePartitionOptions(partitionId);
263
420
 
264
421
  // Validate hash format
265
422
  if (!parseBlobHash(hash)) {
@@ -269,14 +426,16 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
269
426
  // Get upload record (must be complete)
270
427
  const uploadResult = await sql<{
271
428
  hash: string;
272
- size: number;
429
+ size: number | string;
273
430
  mime_type: string;
274
431
  status: 'pending' | 'complete';
275
432
  created_at: string;
276
433
  }>`
277
434
  select hash, size, mime_type, status, created_at
278
435
  from ${sql.table('sync_blob_uploads')}
279
- where hash = ${hash} and status = 'complete'
436
+ where partition_id = ${partitionId}
437
+ and hash = ${hash}
438
+ and status = 'complete'
280
439
  limit 1
281
440
  `.execute(db);
282
441
  const upload = uploadResult.rows[0];
@@ -288,6 +447,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
288
447
  // Generate presigned download URL
289
448
  const url = await adapter.signDownload({
290
449
  hash,
450
+ partitionId: storagePartitionOptions.partitionId,
291
451
  expiresIn: defaultExpiresIn,
292
452
  });
293
453
 
@@ -300,7 +460,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
300
460
  expiresAt,
301
461
  metadata: {
302
462
  hash: upload.hash,
303
- size: upload.size,
463
+ size: normalizeBlobSizeValue(upload.size),
304
464
  mimeType: upload.mime_type,
305
465
  createdAt: upload.created_at,
306
466
  uploadComplete: true,
@@ -308,10 +468,70 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
308
468
  };
309
469
  },
310
470
 
471
+ /**
472
+ * Get upload record for a blob hash, including pending uploads.
473
+ */
474
+ async getUploadRecord(
475
+ hash: string,
476
+ options?: { partitionId?: string }
477
+ ): Promise<BlobUploadRecord | null> {
478
+ const partitionId = resolvePartitionId(options?.partitionId);
479
+ if (!parseBlobHash(hash)) {
480
+ return null;
481
+ }
482
+
483
+ const uploadResult = await sql<{
484
+ partition_id: string;
485
+ hash: string;
486
+ size: number | string;
487
+ mime_type: string;
488
+ status: 'pending' | 'complete';
489
+ actor_id: string;
490
+ created_at: string;
491
+ expires_at: string;
492
+ completed_at: string | null;
493
+ }>`
494
+ select
495
+ partition_id,
496
+ hash,
497
+ size,
498
+ mime_type,
499
+ status,
500
+ actor_id,
501
+ created_at,
502
+ expires_at,
503
+ completed_at
504
+ from ${sql.table('sync_blob_uploads')}
505
+ where partition_id = ${partitionId} and hash = ${hash}
506
+ limit 1
507
+ `.execute(db);
508
+ const upload = uploadResult.rows[0];
509
+
510
+ if (!upload) {
511
+ return null;
512
+ }
513
+
514
+ return {
515
+ partitionId: upload.partition_id,
516
+ hash: upload.hash,
517
+ size: normalizeBlobSizeValue(upload.size),
518
+ mimeType: upload.mime_type,
519
+ status: upload.status,
520
+ actorId: upload.actor_id,
521
+ createdAt: upload.created_at,
522
+ expiresAt: upload.expires_at,
523
+ completedAt: upload.completed_at,
524
+ };
525
+ },
526
+
311
527
  /**
312
528
  * Get blob metadata without generating a download URL.
313
529
  */
314
- async getMetadata(hash: string): Promise<BlobMetadata | null> {
530
+ async getMetadata(
531
+ hash: string,
532
+ options?: { partitionId?: string }
533
+ ): Promise<BlobMetadata | null> {
534
+ const partitionId = resolvePartitionId(options?.partitionId);
315
535
  // Validate hash format
316
536
  if (!parseBlobHash(hash)) {
317
537
  return null;
@@ -319,14 +539,16 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
319
539
 
320
540
  const uploadResult = await sql<{
321
541
  hash: string;
322
- size: number;
542
+ size: number | string;
323
543
  mime_type: string;
324
544
  status: 'pending' | 'complete';
325
545
  created_at: string;
326
546
  }>`
327
547
  select hash, size, mime_type, status, created_at
328
548
  from ${sql.table('sync_blob_uploads')}
329
- where hash = ${hash} and status = 'complete'
549
+ where partition_id = ${partitionId}
550
+ and hash = ${hash}
551
+ and status = 'complete'
330
552
  limit 1
331
553
  `.execute(db);
332
554
  const upload = uploadResult.rows[0];
@@ -337,7 +559,7 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
337
559
 
338
560
  return {
339
561
  hash: upload.hash,
340
- size: upload.size,
562
+ size: normalizeBlobSizeValue(upload.size),
341
563
  mimeType: upload.mime_type,
342
564
  createdAt: upload.created_at,
343
565
  uploadComplete: true,
@@ -347,13 +569,19 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
347
569
  /**
348
570
  * Check if a blob exists and is complete.
349
571
  */
350
- async exists(hash: string): Promise<boolean> {
572
+ async exists(
573
+ hash: string,
574
+ options?: { partitionId?: string }
575
+ ): Promise<boolean> {
576
+ const partitionId = resolvePartitionId(options?.partitionId);
351
577
  if (!parseBlobHash(hash)) return false;
352
578
 
353
579
  const rowResult = await sql<{ hash: string }>`
354
580
  select hash
355
581
  from ${sql.table('sync_blob_uploads')}
356
- where hash = ${hash} and status = 'complete'
582
+ where partition_id = ${partitionId}
583
+ and hash = ${hash}
584
+ and status = 'complete'
357
585
  limit 1
358
586
  `.execute(db);
359
587
 
@@ -372,62 +600,131 @@ export function createBlobManager<DB extends SyncBlobUploadsDb>(
372
600
  isReferenced?: (hash: string) => Promise<boolean>;
373
601
  /** Delete from storage too (not just tracking table) */
374
602
  deleteFromStorage?: boolean;
603
+ /** Optional partition filter for cleanup */
604
+ partitionId?: string;
375
605
  }): Promise<{ deleted: number }> {
376
606
  const now = new Date().toISOString();
377
-
378
- // Find expired pending uploads
379
- const expiredResult = await sql<{ hash: string }>`
380
- select hash
381
- from ${sql.table('sync_blob_uploads')}
382
- where status = 'pending' and expires_at < ${now}
383
- `.execute(db);
384
- const expired = expiredResult.rows;
607
+ const partitionId = resolvePartitionId(options?.partitionId);
608
+ const storagePartitionOptions = toStoragePartitionOptions(partitionId);
385
609
 
386
610
  let deleted = 0;
387
611
 
388
- for (const row of expired) {
612
+ // Find and delete expired pending uploads in batches.
613
+ while (true) {
614
+ const expiredResult = await sql<{ hash: string }>`
615
+ select hash
616
+ from ${sql.table('sync_blob_uploads')}
617
+ where partition_id = ${partitionId}
618
+ and status = 'pending'
619
+ and expires_at < ${now}
620
+ order by expires_at asc
621
+ limit ${CLEANUP_BATCH_SIZE}
622
+ `.execute(db);
623
+ const expiredHashes = expiredResult.rows
624
+ .map((row) => row.hash)
625
+ .filter((hash): hash is string => typeof hash === 'string');
626
+
627
+ if (expiredHashes.length === 0) {
628
+ break;
629
+ }
630
+
389
631
  if (options?.deleteFromStorage) {
390
- try {
391
- await adapter.delete(row.hash);
392
- } catch {
393
- // Ignore storage errors during cleanup
394
- }
632
+ await runWithConcurrency(
633
+ expiredHashes,
634
+ STORAGE_DELETE_CONCURRENCY,
635
+ async (hash) => {
636
+ try {
637
+ await adapter.delete(hash, storagePartitionOptions);
638
+ } catch {
639
+ // Ignore storage errors during cleanup
640
+ }
641
+ }
642
+ );
395
643
  }
396
644
 
397
- await sql`
398
- delete from ${sql.table('sync_blob_uploads')}
399
- where hash = ${row.hash}
400
- `.execute(db);
645
+ deleted += await deleteUploadRowsByHashes(partitionId, expiredHashes);
401
646
 
402
- deleted++;
647
+ if (expiredHashes.length < CLEANUP_BATCH_SIZE) {
648
+ break;
649
+ }
403
650
  }
404
651
 
405
652
  // If reference check provided, also clean up unreferenced complete uploads
653
+ // in batches with bounded parallelism.
406
654
  if (options?.isReferenced) {
407
- const completeResult = await sql<{ hash: string }>`
408
- select hash
409
- from ${sql.table('sync_blob_uploads')}
410
- where status = 'complete'
411
- `.execute(db);
412
- const complete = completeResult.rows;
655
+ const isReferenced = options.isReferenced;
656
+ let afterHash: string | null = null;
657
+
658
+ while (true) {
659
+ let completeRows: Array<{ hash: string }>;
660
+ if (afterHash === null) {
661
+ const completeResult = await sql<{ hash: string }>`
662
+ select hash
663
+ from ${sql.table('sync_blob_uploads')}
664
+ where partition_id = ${partitionId}
665
+ and status = 'complete'
666
+ order by hash asc
667
+ limit ${CLEANUP_BATCH_SIZE}
668
+ `.execute(db);
669
+ completeRows = completeResult.rows;
670
+ } else {
671
+ const completeResult = await sql<{ hash: string }>`
672
+ select hash
673
+ from ${sql.table('sync_blob_uploads')}
674
+ where partition_id = ${partitionId}
675
+ and status = 'complete'
676
+ and hash > ${afterHash}
677
+ order by hash asc
678
+ limit ${CLEANUP_BATCH_SIZE}
679
+ `.execute(db);
680
+ completeRows = completeResult.rows;
681
+ }
413
682
 
414
- for (const row of complete) {
415
- const referenced = await options.isReferenced(row.hash);
416
- if (!referenced) {
417
- if (options?.deleteFromStorage) {
418
- try {
419
- await adapter.delete(row.hash);
420
- } catch {
421
- // Ignore storage errors during cleanup
683
+ const completeHashes = completeRows
684
+ .map((row) => row.hash)
685
+ .filter((hash): hash is string => typeof hash === 'string');
686
+
687
+ if (completeHashes.length === 0) {
688
+ break;
689
+ }
690
+
691
+ afterHash = completeHashes[completeHashes.length - 1] ?? afterHash;
692
+
693
+ const unreferencedHashes: string[] = [];
694
+ await runWithConcurrency(
695
+ completeHashes,
696
+ REFERENCE_CHECK_CONCURRENCY,
697
+ async (hash) => {
698
+ const referenced = await isReferenced(hash);
699
+ if (!referenced) {
700
+ unreferencedHashes.push(hash);
422
701
  }
423
702
  }
703
+ );
424
704
 
425
- await sql`
426
- delete from ${sql.table('sync_blob_uploads')}
427
- where hash = ${row.hash}
428
- `.execute(db);
705
+ if (unreferencedHashes.length > 0) {
706
+ if (options?.deleteFromStorage) {
707
+ await runWithConcurrency(
708
+ unreferencedHashes,
709
+ STORAGE_DELETE_CONCURRENCY,
710
+ async (hash) => {
711
+ try {
712
+ await adapter.delete(hash, storagePartitionOptions);
713
+ } catch {
714
+ // Ignore storage errors during cleanup
715
+ }
716
+ }
717
+ );
718
+ }
719
+
720
+ deleted += await deleteUploadRowsByHashes(
721
+ partitionId,
722
+ unreferencedHashes
723
+ );
724
+ }
429
725
 
430
- deleted++;
726
+ if (completeHashes.length < CLEANUP_BATCH_SIZE) {
727
+ break;
431
728
  }
432
729
  }
433
730
  }
@@ -455,6 +752,8 @@ export interface BlobCleanupSchedulerOptions {
455
752
  deleteFromStorage?: boolean;
456
753
  /** Optional: Check if a blob hash is referenced by any row */
457
754
  isReferenced?: (hash: string) => Promise<boolean>;
755
+ /** Optional partition to scope cleanup. Defaults to "default". */
756
+ partitionId?: string;
458
757
  /** Optional: Called after each cleanup run */
459
758
  onCleanup?: (result: { deleted: number; error?: Error }) => void;
460
759
  }
@@ -499,6 +798,7 @@ export function createBlobCleanupScheduler(
499
798
  intervalMs = 3600000, // 1 hour
500
799
  deleteFromStorage = true,
501
800
  isReferenced,
801
+ partitionId,
502
802
  onCleanup,
503
803
  } = options;
504
804
 
@@ -516,6 +816,7 @@ export function createBlobCleanupScheduler(
516
816
  const result = await blobManager.cleanup({
517
817
  deleteFromStorage,
518
818
  isReferenced,
819
+ partitionId,
519
820
  });
520
821
 
521
822
  onCleanup?.({ deleted: result.deleted });