@syncular/server 0.1.3 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
@@ -0,0 +1,340 @@
1
+ /**
2
+ * Blob upload + download handlers (SPEC.md §5.9.3, §5.9.5).
3
+ *
4
+ * Upload verifies the content address (§5.9.3); download re-authorizes on
5
+ * every request against the rows that reference the blob (§5.9.5) — a
6
+ * `blobId` is never a bearer capability. Framework-free; the hono/runtime
7
+ * adapters map these onto `PUT/GET <mount>/blobs/{blobId}`.
8
+ */
9
+ import { blobIdFor, isBlobId } from './blob-store';
10
+ import type { SyncRequestContext } from './context';
11
+ import { clockOf, RESOLVER_OUTAGE } from './context';
12
+ import { SyncError, syncError } from './errors';
13
+ import { emitEvent } from './events';
14
+ import { compileSchema } from './schema';
15
+ import { authorizeWrite, type ResolvedScopes } from './scopes';
16
+ import { issueBlobUploadUrl, issueBlobUrl } from './signed-url';
17
+
18
+ const DEFAULT_MAX_BLOB_BYTES = 64 * 1024 * 1024;
19
+
20
+ export interface BlobUploadRequest {
21
+ readonly blobId: string;
22
+ readonly bytes: Uint8Array;
23
+ /** Advisory MIME type from the upload `Content-Type`, if any. */
24
+ readonly mediaType?: string;
25
+ }
26
+
27
+ export interface BlobDownloadResult {
28
+ /**
29
+ * The blob bytes, when served inline. **Absent** when the host configured
30
+ * `blobSignedUrls` and a `url` was issued: the sync server exits the egress
31
+ * path and the client fetches `url` directly (§5.9.5 always-issue).
32
+ */
33
+ readonly bytes?: Uint8Array;
34
+ readonly headers: Record<string, string>;
35
+ /**
36
+ * §5.9.5 delegated presign (always-issue): a provider-signed GET URL for
37
+ * the bytes, issued only after the row-derived authorization check passed.
38
+ * Present iff the host configured `blobSignedUrls`; when present, `bytes` is
39
+ * absent and the client MUST fetch the URL directly (no host auth), verify
40
+ * the content address, and on failure re-request this endpoint — never fall
41
+ * through (§5.9.5 recovery rule).
42
+ */
43
+ readonly url?: string;
44
+ readonly urlExpiresAtMs?: number;
45
+ }
46
+
47
+ /** `POST <mount>/blobs/{blobId}/upload-grant` request body (§5.9.3). */
48
+ export interface BlobUploadGrantRequest {
49
+ readonly blobId: string;
50
+ /** Declared uncompressed size — the size-cap check runs against this. */
51
+ readonly byteLength: number;
52
+ /** Advisory MIME type, if any. */
53
+ readonly mediaType?: string;
54
+ }
55
+
56
+ /**
57
+ * `POST <mount>/blobs/{blobId}/upload-grant` result (§5.9.3). Exactly one of:
58
+ * `{url, urlExpiresAtMs}` — a presigned PUT the client uses direct-to-storage;
59
+ * or `{present: true}` — the blob already exists (idempotent §5.9.3), so the
60
+ * client skips the PUT; or `{}` (no fields) — the host has no presigned-upload
61
+ * store configured, so the client streams through the direct PUT endpoint
62
+ * (§5.9.3 capability, not fallback).
63
+ */
64
+ export interface BlobUploadGrantResult {
65
+ readonly url?: string;
66
+ readonly urlExpiresAtMs?: number;
67
+ readonly present?: boolean;
68
+ }
69
+
70
+ /** `PUT <mount>/blobs/{blobId}` (§5.9.3). Host auth is the adapter's job. */
71
+ export async function handleBlobUpload(
72
+ ctx: SyncRequestContext,
73
+ request: BlobUploadRequest,
74
+ ): Promise<void> {
75
+ const store = ctx.blobs;
76
+ if (store === undefined) {
77
+ throw syncError('blob.not_found', 'this server has no blob store (§5.9)');
78
+ }
79
+ if (!isBlobId(request.blobId)) {
80
+ throw syncError(
81
+ 'blob.hash_mismatch',
82
+ 'blobId path is not "sha256:<64 hex>" (§5.9.1)',
83
+ );
84
+ }
85
+ const maxBytes = ctx.maxBlobBytes ?? DEFAULT_MAX_BLOB_BYTES;
86
+ if (request.bytes.length > maxBytes) {
87
+ throw syncError(
88
+ 'blob.too_large',
89
+ `blob exceeds the ${maxBytes}-byte cap (§5.9.3)`,
90
+ );
91
+ }
92
+ const computed = await blobIdFor(request.bytes);
93
+ if (computed !== request.blobId) {
94
+ throw syncError(
95
+ 'blob.hash_mismatch',
96
+ 'uploaded bytes do not hash to the blobId path (§5.9.3)',
97
+ );
98
+ }
99
+ const clock = clockOf(ctx);
100
+ await store.put(
101
+ ctx.partition,
102
+ request.blobId,
103
+ request.bytes,
104
+ clock(),
105
+ request.mediaType,
106
+ );
107
+ if (ctx.events !== undefined) {
108
+ emitEvent(ctx.events, {
109
+ type: 'blob.uploaded',
110
+ atMs: clock(),
111
+ partition: ctx.partition,
112
+ actorId: ctx.actorId,
113
+ blobId: request.blobId,
114
+ bytes: request.bytes.length,
115
+ });
116
+ }
117
+ }
118
+
119
+ /**
120
+ * `GET <mount>/blobs/{blobId}` (§5.9.5). Authorization derives from the
121
+ * referencing rows: the actor may download iff at least one row in the
122
+ * reference index passes the §3.4 scope check for the actor.
123
+ */
124
+ export async function handleBlobDownload(
125
+ ctx: SyncRequestContext,
126
+ blobId: string,
127
+ ): Promise<BlobDownloadResult> {
128
+ const events = ctx.events;
129
+ if (events === undefined) return downloadBlob(ctx, blobId);
130
+ const clock = clockOf(ctx);
131
+ const startedAtMs = clock();
132
+ try {
133
+ const result = await downloadBlob(ctx, blobId);
134
+ emitEvent(events, {
135
+ type: 'blob.downloaded',
136
+ atMs: clock(),
137
+ partition: ctx.partition,
138
+ actorId: ctx.actorId,
139
+ blobId,
140
+ outcome: 'ok',
141
+ // Presigned delivery carries no inline bytes (§5.9.5 always-issue); the
142
+ // byte count is unknown to the sync server, which exited the egress path.
143
+ bytes: result.bytes?.length ?? 0,
144
+ durationMs: clock() - startedAtMs,
145
+ });
146
+ return result;
147
+ } catch (error) {
148
+ emitEvent(events, {
149
+ type: 'blob.downloaded',
150
+ atMs: clock(),
151
+ partition: ctx.partition,
152
+ actorId: ctx.actorId,
153
+ blobId,
154
+ outcome: 'error',
155
+ errorCode: error instanceof SyncError ? error.code : 'internal',
156
+ durationMs: clock() - startedAtMs,
157
+ });
158
+ throw error;
159
+ }
160
+ }
161
+
162
+ async function downloadBlob(
163
+ ctx: SyncRequestContext,
164
+ blobId: string,
165
+ ): Promise<BlobDownloadResult> {
166
+ const store = ctx.blobs;
167
+ if (store === undefined) {
168
+ throw syncError('blob.not_found', 'this server has no blob store (§5.9)');
169
+ }
170
+ if (!isBlobId(blobId)) {
171
+ throw syncError('blob.not_found', 'malformed blobId (§5.9.1)');
172
+ }
173
+ // §5.9.5 always-issue: when presign is configured the server exits the
174
+ // egress path — it only needs to know the object EXISTS (a HEAD/`has`), not
175
+ // the bytes. Inline delivery loads the bytes; presigned delivery does not.
176
+ const presignConfigured = ctx.blobSignedUrls !== undefined;
177
+ let entry: { record: { mediaType?: string }; bytes: Uint8Array } | undefined;
178
+ let mediaType: string | undefined;
179
+ if (presignConfigured) {
180
+ if (!(await store.has(ctx.partition, blobId))) {
181
+ throw syncError('blob.not_found', 'unknown blob (§5.9.5)');
182
+ }
183
+ } else {
184
+ entry = await store.get(ctx.partition, blobId);
185
+ if (entry === undefined) {
186
+ throw syncError('blob.not_found', 'unknown blob (§5.9.5)');
187
+ }
188
+ mediaType = entry.record.mediaType;
189
+ }
190
+
191
+ // §5.9.5 authorization: resolve once, then test referencing rows.
192
+ const listRows = ctx.storage.listRowsReferencingBlob;
193
+ if (listRows === undefined) {
194
+ // Storage without the reference index cannot authorize a download —
195
+ // fail closed (never serve bytes we cannot authorize).
196
+ throw syncError(
197
+ 'blob.forbidden',
198
+ 'storage has no blob reference index (§5.9.4)',
199
+ );
200
+ }
201
+ let resolved: ResolvedScopes;
202
+ try {
203
+ const allowed = await ctx.resolveScopes({
204
+ partition: ctx.partition,
205
+ actorId: ctx.actorId,
206
+ });
207
+ // §7.3.3: leases never authorize a blob download — an outage denies.
208
+ resolved =
209
+ allowed === RESOLVER_OUTAGE ? { ok: false } : { ok: true, allowed };
210
+ } catch (error) {
211
+ if (ctx.events !== undefined) {
212
+ emitEvent(ctx.events, {
213
+ type: 'scopes.resolve_failed',
214
+ atMs: clockOf(ctx)(),
215
+ partition: ctx.partition,
216
+ actorId: ctx.actorId,
217
+ phase: 'blob-download',
218
+ message: error instanceof Error ? error.message : String(error),
219
+ });
220
+ }
221
+ resolved = { ok: false };
222
+ }
223
+ if (!resolved.ok) {
224
+ throw syncError('blob.forbidden', 'scope resolution failed (§5.9.5)');
225
+ }
226
+
227
+ const schema = compileSchema(ctx.schema);
228
+ // A blob download can hit a fresh storage instance before any sync
229
+ // request has run (Workers): make sure the row tables exist first.
230
+ await ctx.storage.ensureSchema(schema);
231
+ const rows = await listRows.call(ctx.storage, ctx.partition, blobId);
232
+ let authorized = false;
233
+ for (const row of rows) {
234
+ const table = schema.tables.get(row.table);
235
+ if (table === undefined) continue;
236
+ if (authorizeWrite(table, row.scopes, resolved)) {
237
+ authorized = true;
238
+ break;
239
+ }
240
+ }
241
+ if (!authorized) {
242
+ // Never 404 here: existence-vs-authorization must not leak (§5.9.5).
243
+ throw syncError(
244
+ 'blob.forbidden',
245
+ 'no referencing row authorizes this actor (§5.9.5)',
246
+ );
247
+ }
248
+
249
+ // §5.9.5 delegated presign (always-issue): authorization has passed above,
250
+ // so a signed URL is now a short-TTL bearer grant to exactly these immutable
251
+ // bytes. When configured, issue it and return NO bytes — the client fetches
252
+ // the URL directly. Never before the check, never a capability from the id.
253
+ if (ctx.blobSignedUrls !== undefined) {
254
+ const issued = await issueBlobUrl(ctx.blobSignedUrls, {
255
+ partition: ctx.partition,
256
+ blobId,
257
+ nowMs: clockOf(ctx)(),
258
+ });
259
+ return {
260
+ headers: {
261
+ ETag: `"${blobId}"`,
262
+ 'Cache-Control': 'private, max-age=0',
263
+ Vary: 'Authorization, Accept-Encoding',
264
+ },
265
+ url: issued.url,
266
+ urlExpiresAtMs: issued.urlExpiresAtMs,
267
+ };
268
+ }
269
+
270
+ // Inline delivery (no presign store configured): the bytes were loaded.
271
+ const bytes = entry?.bytes;
272
+ if (bytes === undefined) {
273
+ // Unreachable: presign not configured ⇒ `entry` was loaded above.
274
+ throw syncError('blob.not_found', 'blob bytes unavailable (§5.9.5)');
275
+ }
276
+ return {
277
+ bytes,
278
+ headers: {
279
+ 'Content-Type': mediaType ?? 'application/octet-stream',
280
+ ETag: `"${blobId}"`,
281
+ 'Cache-Control': 'private, max-age=0',
282
+ Vary: 'Authorization, Accept-Encoding',
283
+ },
284
+ };
285
+ }
286
+
287
+ /**
288
+ * `POST <mount>/blobs/{blobId}/upload-grant` (§5.9.3 presigned upload). Host
289
+ * auth is the adapter's job — uploading is host-auth-only, not scope-bearing,
290
+ * so any authenticated actor may obtain a grant within the size cap (§5.9.3).
291
+ *
292
+ * The size cap is enforced HERE, up front, against the declared `byteLength`
293
+ * (the object-store hop cannot re-check the streamed byte count). Integrity is
294
+ * NOT checked here: the object store places bytes at the content-addressed key,
295
+ * and the address is verified at reference time (§5.9.6 push existence) and on
296
+ * every download (§5.9.5/§5.1). Returns a presigned single PUT, or a
297
+ * `present` marker if the blob already exists (idempotent §5.9.3), or an empty
298
+ * result when no presigned-upload store is configured (client streams direct).
299
+ */
300
+ export async function handleBlobUploadGrant(
301
+ ctx: SyncRequestContext,
302
+ request: BlobUploadGrantRequest,
303
+ ): Promise<BlobUploadGrantResult> {
304
+ const store = ctx.blobs;
305
+ if (store === undefined) {
306
+ throw syncError('blob.not_found', 'this server has no blob store (§5.9)');
307
+ }
308
+ if (!isBlobId(request.blobId)) {
309
+ throw syncError(
310
+ 'blob.hash_mismatch',
311
+ 'blobId path is not "sha256:<64 hex>" (§5.9.1)',
312
+ );
313
+ }
314
+ const maxBytes = ctx.maxBlobBytes ?? DEFAULT_MAX_BLOB_BYTES;
315
+ if (
316
+ !Number.isInteger(request.byteLength) ||
317
+ request.byteLength < 0 ||
318
+ request.byteLength > maxBytes
319
+ ) {
320
+ // §5.9.3: cap enforced at grant issuance, before any URL is minted.
321
+ throw syncError(
322
+ 'blob.too_large',
323
+ `blob byteLength exceeds the ${maxBytes}-byte cap (§5.9.3)`,
324
+ );
325
+ }
326
+ // §5.9.3 no presigned-upload store: report no grant; the client streams
327
+ // through the direct PUT endpoint (capability, not fallback).
328
+ if (ctx.blobUploadUrls === undefined) return {};
329
+ // Idempotent §5.9.3: an already-present blob needs no PUT.
330
+ if (await store.has(ctx.partition, request.blobId)) {
331
+ return { present: true };
332
+ }
333
+ const issued = await issueBlobUploadUrl(ctx.blobUploadUrls, {
334
+ partition: ctx.partition,
335
+ blobId: request.blobId,
336
+ byteLength: request.byteLength,
337
+ nowMs: clockOf(ctx)(),
338
+ });
339
+ return { url: issued.url, urlExpiresAtMs: issued.urlExpiresAtMs };
340
+ }
Binary file
@@ -0,0 +1,94 @@
1
+ /**
2
+ * §5.8 shipped compression posture for the direct segment endpoint:
3
+ * negotiate `Content-Encoding` from the request's `Accept-Encoding`
4
+ * (zstd preferred, gzip fallback, identity when the client offers
5
+ * neither), feature-detecting the runtime's codecs — zero dependencies.
6
+ *
7
+ * Segment bytes are stored and content-addressed UNCOMPRESSED (§5.1);
8
+ * this is a per-response serving concern only. It is never applied to
9
+ * stored objects or the signed-URL path (§5.8: presigned GETs serve the
10
+ * addressed bytes verbatim; edge compression is a deployment concern).
11
+ *
12
+ * Decision data (2026-07-03, 100k-row bench table, Bun 1.3): rows
13
+ * segments 6.2× in 8 ms (zstd) / 7.7× in 42 ms (gzip); sqlite images
14
+ * 3.4× in 14 ms (zstd) / 51 ms (gzip); client decompression ≤ 8 ms.
15
+ */
16
+
17
+ export type SegmentContentEncoding = 'zstd' | 'gzip';
18
+
19
+ interface Codec {
20
+ readonly encoding: SegmentContentEncoding;
21
+ readonly compress: (bytes: Uint8Array) => Uint8Array;
22
+ }
23
+
24
+ interface BunCompressors {
25
+ readonly zstdCompressSync?: (bytes: Uint8Array) => Uint8Array;
26
+ readonly gzipSync?: (bytes: Uint8Array) => Uint8Array;
27
+ }
28
+
29
+ /** Preference order is zstd, gzip (§5.8). Non-Bun runtimes without these
30
+ * codecs serve identity — negotiation, never a hard requirement here. */
31
+ function detectCodecs(): readonly Codec[] {
32
+ const bun = (globalThis as { Bun?: BunCompressors }).Bun;
33
+ const codecs: Codec[] = [];
34
+ const zstd = bun?.zstdCompressSync;
35
+ if (typeof zstd === 'function') {
36
+ codecs.push({ encoding: 'zstd', compress: (bytes) => zstd(bytes) });
37
+ }
38
+ const gzip = bun?.gzipSync;
39
+ if (typeof gzip === 'function') {
40
+ codecs.push({ encoding: 'gzip', compress: (bytes) => gzip(bytes) });
41
+ }
42
+ return codecs;
43
+ }
44
+
45
+ const CODECS = detectCodecs();
46
+
47
+ /** Bodies below this size are served identity (headers outweigh gains). */
48
+ const MIN_COMPRESS_BYTES = 1024;
49
+
50
+ /** Does the `Accept-Encoding` header value accept `encoding` (q > 0)? */
51
+ function accepts(header: string, encoding: SegmentContentEncoding): boolean {
52
+ for (const entry of header.split(',')) {
53
+ const [rawName, ...params] = entry.trim().split(';');
54
+ const name = rawName?.trim().toLowerCase();
55
+ if (name !== encoding) continue;
56
+ for (const param of params) {
57
+ const [key, value] = param.trim().split('=');
58
+ if (key?.trim().toLowerCase() === 'q' && Number(value) === 0) {
59
+ return false;
60
+ }
61
+ }
62
+ return true;
63
+ }
64
+ return false;
65
+ }
66
+
67
+ export interface EncodedSegmentBody {
68
+ readonly bytes: Uint8Array;
69
+ /** Absent ⇒ identity (no `Content-Encoding` header). */
70
+ readonly contentEncoding?: SegmentContentEncoding;
71
+ }
72
+
73
+ /**
74
+ * Compress a buffered segment body per §5.8. Returns the original bytes
75
+ * (identity) when the client offered no supported encoding, the body is
76
+ * tiny, or the runtime has no codec.
77
+ */
78
+ export function encodeSegmentBody(
79
+ bytes: Uint8Array,
80
+ acceptEncoding: string | undefined,
81
+ ): EncodedSegmentBody {
82
+ if (acceptEncoding === undefined || bytes.length < MIN_COMPRESS_BYTES) {
83
+ return { bytes };
84
+ }
85
+ for (const codec of CODECS) {
86
+ if (accepts(acceptEncoding, codec.encoding)) {
87
+ return {
88
+ bytes: codec.compress(bytes),
89
+ contentEncoding: codec.encoding,
90
+ };
91
+ }
92
+ }
93
+ return { bytes };
94
+ }
package/src/context.ts ADDED
@@ -0,0 +1,176 @@
1
+ /**
2
+ * The host context for `handleSyncRequest` (REVISE B2): storage, the
3
+ * `resolveScopes` host callback (runs in the host process — the moat),
4
+ * clock, and a segment store. Framework-free; adapters supply `partition`
5
+ * and `actorId` from host authentication (§1.1).
6
+ */
7
+ import type { ScopeMap } from '@syncular/core';
8
+ import type { BlobStore } from './blob-store';
9
+ import type { CrdtMergerRegistry } from './crdt-merger';
10
+ import type { SyncularServerEvents } from './events';
11
+ import type { LeaseStore } from './lease-store';
12
+ import type { ServerSchema } from './schema';
13
+ import type { SegmentStore } from './segment-store';
14
+ import type {
15
+ BlobPresignConfig,
16
+ BlobUploadPresignConfig,
17
+ SegmentUrlConfig,
18
+ } from './signed-url';
19
+ import type { SqliteImageBuilder } from './sqlite-image';
20
+ import type { ServerStorage, StoredCommit } from './storage';
21
+ import type { ValidatorRegistry } from './validate';
22
+
23
+ /** SSP2 body content type (§1.1). */
24
+ export const SSP2_CONTENT_TYPE = 'application/vnd.syncular.sync.v2';
25
+
26
+ export interface ResolveScopesArgs {
27
+ readonly partition: string;
28
+ readonly actorId: string;
29
+ /**
30
+ * The requesting client (§1.5). Present on sync rounds (the lease key,
31
+ * §7.3.3); absent on segment/blob downloads, which re-authorize by
32
+ * actor + scopes only (§5.5, §5.9.5) and never consult a lease.
33
+ */
34
+ readonly clientId?: string;
35
+ }
36
+
37
+ /**
38
+ * Sentinel a resolver returns to signal a **live-authorization outage**
39
+ * (§7.3.3): the live authority is unreachable, so the server SHOULD
40
+ * authorize this request against the actor's stored lease instead of
41
+ * throwing. Distinct from throwing (§3.2 rule 5, which still fails loud
42
+ * and revokes). Only meaningful when `leases` is configured; without a
43
+ * lease store an outage degrades to `sync.auth_lease_required`.
44
+ */
45
+ export const RESOLVER_OUTAGE = Symbol.for('syncular.resolver_outage');
46
+ export type ResolverOutage = typeof RESOLVER_OUTAGE;
47
+
48
+ /**
49
+ * Host callback: actor → allowed scopes (§3.2 step 3). Resolved at most
50
+ * once per request and memoized (§3.4 step 1). `'*'` means "any value for
51
+ * this variable". A throwing resolver revokes subscriptions and rejects
52
+ * writes with `sync.forbidden` — fail loud, never leak. Returning
53
+ * `RESOLVER_OUTAGE` instead opts the request into lease authorization
54
+ * (§7.3.3) — a deliberate outage signal, not a failure.
55
+ */
56
+ export type ResolveScopes = (
57
+ args: ResolveScopesArgs,
58
+ ) => ScopeMap | ResolverOutage | Promise<ScopeMap | ResolverOutage>;
59
+
60
+ /** §7.3: auth-lease feature config. Absent ⇒ leases off (zero cost). */
61
+ export interface LeaseConfig {
62
+ /** Lease TTL in ms — the sliding window width (§7.3.3). */
63
+ readonly ttlMs: number;
64
+ /** The lease store (§7.3.1); host-owned, optional like blobs. */
65
+ readonly store: LeaseStore;
66
+ }
67
+
68
+ export interface ServerLimits {
69
+ /** Operation cap per request (§6.1 `sync.too_many_operations`). */
70
+ readonly maxOperationsPerRequest: number;
71
+ /** Inline rows segments up to this size (§5.7 SHOULD: 256 KiB). */
72
+ readonly inlineSegmentMaxBytes: number;
73
+ }
74
+
75
+ export const DEFAULT_LIMITS: ServerLimits = {
76
+ maxOperationsPerRequest: 500,
77
+ inlineSegmentMaxBytes: 256 * 1024,
78
+ };
79
+
80
+ /** Receives applied commits for realtime fanout (§8.2). */
81
+ export interface RealtimeNotifier {
82
+ notifyCommit(partition: string, commit: StoredCommit): void | Promise<void>;
83
+ }
84
+
85
+ export interface SyncServerConfig {
86
+ readonly schema: ServerSchema;
87
+ readonly storage: ServerStorage;
88
+ readonly segments: SegmentStore;
89
+ /**
90
+ * Blob store (§5.9). Absent ⇒ blobs unsupported: a table with a
91
+ * `blob_ref` column may still sync (the ref is just a string), but the
92
+ * push existence check (§6.6) and the `/blobs` endpoints require it.
93
+ */
94
+ readonly blobs?: BlobStore;
95
+ /** Max upload size for `/blobs` (§5.9.3 `blob.too_large`); default 64 MiB. */
96
+ readonly maxBlobBytes?: number;
97
+ /**
98
+ * CRDT merger registry (§5.10.2), `crdtType` → merge fn. Absent ⇒ no
99
+ * column can CRDT-merge: a push touching a `crdt` column then fails
100
+ * `sync.crdt_merge_failed` (§5.10.6). Kept out of core — the reference
101
+ * `yjs-doc` merger ships in `@syncular/crdt-yjs` (the blob-store rule).
102
+ */
103
+ readonly crdtMergers?: CrdtMergerRegistry;
104
+ /**
105
+ * §6.7 per-table write-validation hooks (`table` → validator). Absent ⇒
106
+ * the feature is off: the push path pays only an `undefined` check and
107
+ * builds no validator context — zero cost. Present ⇒ each push operation
108
+ * on a listed table runs its validator after decode + §3.4 scope
109
+ * authorization, inside the commit transaction; a throw rejects the
110
+ * whole commit atomically (§6.4) with the host code (§6.3). Kept a host
111
+ * callback (like `resolveScopes`) — business rules live in the host
112
+ * process, never on the wire.
113
+ */
114
+ readonly validators?: ValidatorRegistry;
115
+ readonly resolveScopes: ResolveScopes;
116
+ /**
117
+ * §7.3 auth leases. Absent ⇒ the feature is off: no `LEASE` frame is
118
+ * ever emitted and a `RESOLVER_OUTAGE` signal degrades to
119
+ * `sync.auth_lease_required`. Present ⇒ successful authorized rounds
120
+ * issue/refresh a lease and outages authorize against it.
121
+ */
122
+ readonly leases?: LeaseConfig;
123
+ /** Epoch-ms clock; defaults to `Date.now`. */
124
+ readonly clock?: () => number;
125
+ readonly limits?: Partial<ServerLimits>;
126
+ /** §5.4 signed-URL delivery: native HMAC tokens or delegated presign. */
127
+ readonly signedUrls?: SegmentUrlConfig;
128
+ /**
129
+ * §5.9.5 signed-URL delivery for BLOB downloads (delegated presign,
130
+ * always-issue). When set, `handleBlobDownload` issues a provider-presigned
131
+ * GET URL AFTER the row-derived authorization check and returns
132
+ * `url`/`urlExpiresAtMs` on `BlobDownloadResult` WITHOUT loading the bytes
133
+ * (the sync server exits the download egress path). The reference client
134
+ * fetches the URL directly (§5.9.5 recovery rule: failure ⇒ re-request,
135
+ * never fall-through). Absent ⇒ blobs are served inline (the shipped
136
+ * default).
137
+ */
138
+ readonly blobSignedUrls?: BlobPresignConfig;
139
+ /**
140
+ * §5.9.3 presigned-upload (direct-to-storage) delivery. When set,
141
+ * `handleBlobUploadGrant` issues a single provider-presigned PUT URL AFTER
142
+ * host authentication + the size-cap check, and the client PUTs bytes
143
+ * straight to the object store (the sync server exits the upload egress
144
+ * path). Absent ⇒ the `/upload-grant` route reports no grant and clients
145
+ * stream through the direct `PUT /blobs/{blobId}` endpoint (§5.9.3 —
146
+ * capability, not fallback). Never a multipart/chunk protocol (single PUT).
147
+ */
148
+ readonly blobUploadUrls?: BlobUploadPresignConfig;
149
+ /**
150
+ * §5.3 sqlite-image builder (TODO §4.2), injected so the pull path never
151
+ * statically imports `bun:sqlite`. Absent ⇒ the sqlite-image lane is off
152
+ * (bit-2 clients are served the rows lane) — the Workers/edge posture. A
153
+ * Bun/Node host wires `buildSqliteImage` from `@syncular/server`.
154
+ */
155
+ readonly sqliteImageBuilder?: SqliteImageBuilder;
156
+ readonly realtime?: RealtimeNotifier;
157
+ /**
158
+ * Optional structured-events sink (ops seam). Absent ⇒ zero cost: no
159
+ * event objects are built. A throwing sink never affects processing.
160
+ */
161
+ readonly events?: SyncularServerEvents;
162
+ }
163
+
164
+ /** Per-request context: the config plus host-authenticated identity. */
165
+ export interface SyncRequestContext extends SyncServerConfig {
166
+ readonly partition: string;
167
+ readonly actorId: string;
168
+ }
169
+
170
+ export function clockOf(ctx: SyncServerConfig): () => number {
171
+ return ctx.clock ?? Date.now;
172
+ }
173
+
174
+ export function limitsOf(ctx: SyncServerConfig): ServerLimits {
175
+ return { ...DEFAULT_LIMITS, ...ctx.limits };
176
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * CRDT column merge registry (SPEC.md §5.10.2) — the pluggability seam.
3
+ *
4
+ * The server core NEVER depends on a CRDT library. A `crdt` column (§2.4
5
+ * tag 8) is merged server-side on push (§5.10.3) by a host-supplied
6
+ * `CrdtMerger`, selected per column by its schema-IR `crdtType` (§5.10.1).
7
+ * The reference `yjs-doc` merger lives in `@syncular/crdt-yjs`, keeping
8
+ * Yjs out of core/server (the blob-store placement rule, §5.9.2, applied to
9
+ * CRDT).
10
+ */
11
+
12
+ /**
13
+ * Merge a `crdt` column's stored value with an incoming push value,
14
+ * returning the new stored bytes (§5.10.2). `stored` is `null` when the row
15
+ * is new or the column was NULL. Implementations MUST be commutative,
16
+ * associative, and idempotent over the updates they consume — the CRDT
17
+ * contract that makes concurrent-order-independent convergence and
18
+ * idempotent replay hold (§5.10.3).
19
+ *
20
+ * A synchronous return is fine; async is allowed so a native/WASM merger can
21
+ * cross an FFI boundary.
22
+ */
23
+ export type CrdtMerger = (
24
+ stored: Uint8Array | null,
25
+ incoming: Uint8Array,
26
+ ) => Uint8Array | Promise<Uint8Array>;
27
+
28
+ /**
29
+ * `crdtType` (§5.10.1) → merger. Supplied through `SyncServerConfig`
30
+ * (§ context). Absent ⇒ no column can CRDT-merge: a push touching a `crdt`
31
+ * column then fails `sync.crdt_merge_failed` (§5.10.2, §5.10.6).
32
+ */
33
+ export type CrdtMergerRegistry = Readonly<Record<string, CrdtMerger>>;
Binary file