@syncular/server 0.0.6-96 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/README.md +1 -2
  2. package/dist/auth-leases.d.ts +85 -0
  3. package/dist/auth-leases.d.ts.map +1 -0
  4. package/dist/auth-leases.js +368 -0
  5. package/dist/auth-leases.js.map +1 -0
  6. package/dist/better-sqlite3.d.ts +22 -0
  7. package/dist/better-sqlite3.d.ts.map +1 -0
  8. package/dist/better-sqlite3.js +16 -0
  9. package/dist/better-sqlite3.js.map +1 -0
  10. package/dist/blobs/access.d.ts +35 -0
  11. package/dist/blobs/access.d.ts.map +1 -0
  12. package/dist/blobs/access.js +149 -0
  13. package/dist/blobs/access.js.map +1 -0
  14. package/dist/blobs/adapters/database.d.ts +26 -9
  15. package/dist/blobs/adapters/database.d.ts.map +1 -1
  16. package/dist/blobs/adapters/database.js +68 -23
  17. package/dist/blobs/adapters/database.js.map +1 -1
  18. package/dist/blobs/index.d.ts +1 -0
  19. package/dist/blobs/index.d.ts.map +1 -1
  20. package/dist/blobs/index.js +5 -4
  21. package/dist/blobs/index.js.map +1 -1
  22. package/dist/blobs/manager.d.ts +69 -44
  23. package/dist/blobs/manager.d.ts.map +1 -1
  24. package/dist/blobs/manager.js +250 -65
  25. package/dist/blobs/manager.js.map +1 -1
  26. package/dist/blobs/migrate.d.ts.map +1 -1
  27. package/dist/blobs/migrate.js +16 -8
  28. package/dist/blobs/migrate.js.map +1 -1
  29. package/dist/blobs/types.d.ts +4 -0
  30. package/dist/blobs/types.d.ts.map +1 -1
  31. package/dist/bun-sqlite.d.ts +19 -0
  32. package/dist/bun-sqlite.d.ts.map +1 -0
  33. package/dist/bun-sqlite.js +19 -0
  34. package/dist/bun-sqlite.js.map +1 -0
  35. package/dist/clients.d.ts +1 -0
  36. package/dist/clients.d.ts.map +1 -1
  37. package/dist/clients.js.map +1 -1
  38. package/dist/cloudflare/durable-object.d.ts +93 -0
  39. package/dist/cloudflare/durable-object.d.ts.map +1 -0
  40. package/dist/cloudflare/durable-object.js +210 -0
  41. package/dist/cloudflare/durable-object.js.map +1 -0
  42. package/dist/cloudflare/index.d.ts +22 -0
  43. package/dist/cloudflare/index.d.ts.map +1 -0
  44. package/dist/cloudflare/index.js +22 -0
  45. package/dist/cloudflare/index.js.map +1 -0
  46. package/dist/cloudflare/r2.d.ts +180 -0
  47. package/dist/cloudflare/r2.d.ts.map +1 -0
  48. package/dist/cloudflare/r2.js +258 -0
  49. package/dist/cloudflare/r2.js.map +1 -0
  50. package/dist/cloudflare/scope-cache.d.ts +54 -0
  51. package/dist/cloudflare/scope-cache.d.ts.map +1 -0
  52. package/dist/cloudflare/scope-cache.js +223 -0
  53. package/dist/cloudflare/scope-cache.js.map +1 -0
  54. package/dist/cloudflare/sentry.d.ts +47 -0
  55. package/dist/cloudflare/sentry.d.ts.map +1 -0
  56. package/dist/cloudflare/sentry.js +163 -0
  57. package/dist/cloudflare/sentry.js.map +1 -0
  58. package/dist/cloudflare/worker.d.ts +46 -0
  59. package/dist/cloudflare/worker.d.ts.map +1 -0
  60. package/dist/cloudflare/worker.js +63 -0
  61. package/dist/cloudflare/worker.js.map +1 -0
  62. package/dist/commit-integrity.d.ts +38 -0
  63. package/dist/commit-integrity.d.ts.map +1 -0
  64. package/dist/commit-integrity.js +260 -0
  65. package/dist/commit-integrity.js.map +1 -0
  66. package/dist/compaction.js.map +1 -1
  67. package/dist/crdt-yjs/index.d.ts +99 -0
  68. package/dist/crdt-yjs/index.d.ts.map +1 -0
  69. package/dist/crdt-yjs/index.js +629 -0
  70. package/dist/crdt-yjs/index.js.map +1 -0
  71. package/dist/d1.d.ts +13 -0
  72. package/dist/d1.d.ts.map +1 -0
  73. package/dist/d1.js +14 -0
  74. package/dist/d1.js.map +1 -0
  75. package/dist/dialect/base.d.ts +11 -1
  76. package/dist/dialect/base.d.ts.map +1 -1
  77. package/dist/dialect/base.js +43 -6
  78. package/dist/dialect/base.js.map +1 -1
  79. package/dist/dialect/helpers.d.ts +6 -0
  80. package/dist/dialect/helpers.d.ts.map +1 -1
  81. package/dist/dialect/helpers.js +24 -0
  82. package/dist/dialect/helpers.js.map +1 -1
  83. package/dist/dialect/index.js +3 -3
  84. package/dist/dialect/types.d.ts +40 -0
  85. package/dist/dialect/types.d.ts.map +1 -1
  86. package/dist/encrypted-crdt.d.ts +67 -0
  87. package/dist/encrypted-crdt.d.ts.map +1 -0
  88. package/dist/encrypted-crdt.js +426 -0
  89. package/dist/encrypted-crdt.js.map +1 -0
  90. package/dist/errors.d.ts +10 -0
  91. package/dist/errors.d.ts.map +1 -0
  92. package/dist/errors.js +13 -0
  93. package/dist/errors.js.map +1 -0
  94. package/dist/filesystem/index.d.ts +44 -0
  95. package/dist/filesystem/index.d.ts.map +1 -0
  96. package/dist/filesystem/index.js +164 -0
  97. package/dist/filesystem/index.js.map +1 -0
  98. package/dist/handlers/collection.d.ts +11 -3
  99. package/dist/handlers/collection.d.ts.map +1 -1
  100. package/dist/handlers/collection.js +34 -56
  101. package/dist/handlers/collection.js.map +1 -1
  102. package/dist/handlers/create-handler.d.ts +31 -7
  103. package/dist/handlers/create-handler.d.ts.map +1 -1
  104. package/dist/handlers/create-handler.js +332 -115
  105. package/dist/handlers/create-handler.js.map +1 -1
  106. package/dist/handlers/index.js +3 -3
  107. package/dist/handlers/types.d.ts +86 -1
  108. package/dist/handlers/types.d.ts.map +1 -1
  109. package/dist/helpers/conflict.js.map +1 -1
  110. package/dist/helpers/emitted-change.js.map +1 -1
  111. package/dist/helpers/index.d.ts +2 -0
  112. package/dist/helpers/index.d.ts.map +1 -1
  113. package/dist/helpers/index.js +6 -4
  114. package/dist/helpers/index.js.map +1 -1
  115. package/dist/helpers/paginate.js.map +1 -1
  116. package/dist/helpers/scope-authorization.d.ts +7 -0
  117. package/dist/helpers/scope-authorization.d.ts.map +1 -0
  118. package/dist/helpers/scope-authorization.js +19 -0
  119. package/dist/helpers/scope-authorization.js.map +1 -0
  120. package/dist/helpers/scope-commit-index.d.ts +12 -0
  121. package/dist/helpers/scope-commit-index.d.ts.map +1 -0
  122. package/dist/helpers/scope-commit-index.js +35 -0
  123. package/dist/helpers/scope-commit-index.js.map +1 -0
  124. package/dist/helpers/scope-strings.js.map +1 -1
  125. package/dist/hono/api-key-auth.d.ts +49 -0
  126. package/dist/hono/api-key-auth.d.ts.map +1 -0
  127. package/dist/hono/api-key-auth.js +108 -0
  128. package/dist/hono/api-key-auth.js.map +1 -0
  129. package/dist/hono/audit-redaction.d.ts +20 -0
  130. package/dist/hono/audit-redaction.d.ts.map +1 -0
  131. package/dist/hono/audit-redaction.js +85 -0
  132. package/dist/hono/audit-redaction.js.map +1 -0
  133. package/dist/hono/blobs.d.ts +75 -0
  134. package/dist/hono/blobs.d.ts.map +1 -0
  135. package/dist/hono/blobs.js +586 -0
  136. package/dist/hono/blobs.js.map +1 -0
  137. package/dist/hono/console/gateway.d.ts +42 -0
  138. package/dist/hono/console/gateway.d.ts.map +1 -0
  139. package/dist/hono/console/gateway.js +2158 -0
  140. package/dist/hono/console/gateway.js.map +1 -0
  141. package/dist/hono/console/live-auth.d.ts +7 -0
  142. package/dist/hono/console/live-auth.d.ts.map +1 -0
  143. package/dist/hono/console/live-auth.js +39 -0
  144. package/dist/hono/console/live-auth.js.map +1 -0
  145. package/dist/hono/console/route-descriptor.d.ts +6 -0
  146. package/dist/hono/console/route-descriptor.d.ts.map +1 -0
  147. package/dist/hono/console/route-descriptor.js +16 -0
  148. package/dist/hono/console/route-descriptor.js.map +1 -0
  149. package/dist/hono/console/routes/api-keys.d.ts +8 -0
  150. package/dist/hono/console/routes/api-keys.d.ts.map +1 -0
  151. package/dist/hono/console/routes/api-keys.js +575 -0
  152. package/dist/hono/console/routes/api-keys.js.map +1 -0
  153. package/dist/hono/console/routes/clients.d.ts +8 -0
  154. package/dist/hono/console/routes/clients.d.ts.map +1 -0
  155. package/dist/hono/console/routes/clients.js +322 -0
  156. package/dist/hono/console/routes/clients.js.map +1 -0
  157. package/dist/hono/console/routes/commits.d.ts +8 -0
  158. package/dist/hono/console/routes/commits.d.ts.map +1 -0
  159. package/dist/hono/console/routes/commits.js +882 -0
  160. package/dist/hono/console/routes/commits.js.map +1 -0
  161. package/dist/hono/console/routes/context.d.ts +188 -0
  162. package/dist/hono/console/routes/context.d.ts.map +1 -0
  163. package/dist/hono/console/routes/context.js +633 -0
  164. package/dist/hono/console/routes/context.js.map +1 -0
  165. package/dist/hono/console/routes/events.d.ts +8 -0
  166. package/dist/hono/console/routes/events.d.ts.map +1 -0
  167. package/dist/hono/console/routes/events.js +501 -0
  168. package/dist/hono/console/routes/events.js.map +1 -0
  169. package/dist/hono/console/routes/maintenance.d.ts +8 -0
  170. package/dist/hono/console/routes/maintenance.d.ts.map +1 -0
  171. package/dist/hono/console/routes/maintenance.js +341 -0
  172. package/dist/hono/console/routes/maintenance.js.map +1 -0
  173. package/dist/hono/console/routes/shared.d.ts +174 -0
  174. package/dist/hono/console/routes/shared.d.ts.map +1 -0
  175. package/dist/hono/console/routes/shared.js +583 -0
  176. package/dist/hono/console/routes/shared.js.map +1 -0
  177. package/dist/hono/console/routes/stats.d.ts +8 -0
  178. package/dist/hono/console/routes/stats.d.ts.map +1 -0
  179. package/dist/hono/console/routes/stats.js +295 -0
  180. package/dist/hono/console/routes/stats.js.map +1 -0
  181. package/dist/hono/console/routes/storage.d.ts +8 -0
  182. package/dist/hono/console/routes/storage.d.ts.map +1 -0
  183. package/dist/hono/console/routes/storage.js +121 -0
  184. package/dist/hono/console/routes/storage.js.map +1 -0
  185. package/dist/hono/console/routes.d.ts +36 -0
  186. package/dist/hono/console/routes.d.ts.map +1 -0
  187. package/dist/hono/console/routes.js +112 -0
  188. package/dist/hono/console/routes.js.map +1 -0
  189. package/dist/hono/console/schema-errors.d.ts +2 -0
  190. package/dist/hono/console/schema-errors.d.ts.map +1 -0
  191. package/dist/hono/console/schema-errors.js +17 -0
  192. package/dist/hono/console/schema-errors.js.map +1 -0
  193. package/dist/hono/console/schemas.d.ts +1515 -0
  194. package/dist/hono/console/schemas.d.ts.map +1 -0
  195. package/dist/hono/console/schemas.js +661 -0
  196. package/dist/hono/console/schemas.js.map +1 -0
  197. package/dist/hono/console/types.d.ts +213 -0
  198. package/dist/hono/console/types.d.ts.map +1 -0
  199. package/dist/hono/console/types.js +2 -0
  200. package/dist/hono/console/types.js.map +1 -0
  201. package/dist/hono/console/ui.d.ts +38 -0
  202. package/dist/hono/console/ui.d.ts.map +1 -0
  203. package/dist/hono/console/ui.js +43 -0
  204. package/dist/hono/console/ui.js.map +1 -0
  205. package/dist/hono/create-server.d.ts +71 -0
  206. package/dist/hono/create-server.d.ts.map +1 -0
  207. package/dist/hono/create-server.js +121 -0
  208. package/dist/hono/create-server.js.map +1 -0
  209. package/dist/hono/errors.d.ts +13 -0
  210. package/dist/hono/errors.d.ts.map +1 -0
  211. package/dist/hono/errors.js +21 -0
  212. package/dist/hono/errors.js.map +1 -0
  213. package/dist/hono/index.d.ts +20 -0
  214. package/dist/hono/index.d.ts.map +1 -0
  215. package/dist/hono/index.js +31 -0
  216. package/dist/hono/index.js.map +1 -0
  217. package/dist/hono/openapi.d.ts +72 -0
  218. package/dist/hono/openapi.d.ts.map +1 -0
  219. package/dist/hono/openapi.js +99 -0
  220. package/dist/hono/openapi.js.map +1 -0
  221. package/dist/hono/proxy/connection-manager.d.ts +78 -0
  222. package/dist/hono/proxy/connection-manager.d.ts.map +1 -0
  223. package/dist/hono/proxy/connection-manager.js +251 -0
  224. package/dist/hono/proxy/connection-manager.js.map +1 -0
  225. package/dist/hono/proxy/index.d.ts +8 -0
  226. package/dist/hono/proxy/index.d.ts.map +1 -0
  227. package/dist/hono/proxy/index.js +8 -0
  228. package/dist/hono/proxy/index.js.map +1 -0
  229. package/dist/hono/proxy/routes.d.ts +86 -0
  230. package/dist/hono/proxy/routes.d.ts.map +1 -0
  231. package/dist/hono/proxy/routes.js +183 -0
  232. package/dist/hono/proxy/routes.js.map +1 -0
  233. package/dist/hono/rate-limit.d.ts +101 -0
  234. package/dist/hono/rate-limit.d.ts.map +1 -0
  235. package/dist/hono/rate-limit.js +184 -0
  236. package/dist/hono/rate-limit.js.map +1 -0
  237. package/dist/hono/realtime-sync-packs.d.ts +43 -0
  238. package/dist/hono/realtime-sync-packs.d.ts.map +1 -0
  239. package/dist/hono/realtime-sync-packs.js +219 -0
  240. package/dist/hono/realtime-sync-packs.js.map +1 -0
  241. package/dist/hono/routes/audit.d.ts +12 -0
  242. package/dist/hono/routes/audit.d.ts.map +1 -0
  243. package/dist/hono/routes/audit.js +385 -0
  244. package/dist/hono/routes/audit.js.map +1 -0
  245. package/dist/hono/routes/auth-leases.d.ts +8 -0
  246. package/dist/hono/routes/auth-leases.d.ts.map +1 -0
  247. package/dist/hono/routes/auth-leases.js +88 -0
  248. package/dist/hono/routes/auth-leases.js.map +1 -0
  249. package/dist/hono/routes/combined.d.ts +8 -0
  250. package/dist/hono/routes/combined.d.ts.map +1 -0
  251. package/dist/hono/routes/combined.js +392 -0
  252. package/dist/hono/routes/combined.js.map +1 -0
  253. package/dist/hono/routes/context.d.ts +314 -0
  254. package/dist/hono/routes/context.d.ts.map +1 -0
  255. package/dist/hono/routes/context.js +1147 -0
  256. package/dist/hono/routes/context.js.map +1 -0
  257. package/dist/hono/routes/health.d.ts +8 -0
  258. package/dist/hono/routes/health.d.ts.map +1 -0
  259. package/dist/hono/routes/health.js +16 -0
  260. package/dist/hono/routes/health.js.map +1 -0
  261. package/dist/hono/routes/realtime.d.ts +9 -0
  262. package/dist/hono/routes/realtime.d.ts.map +1 -0
  263. package/dist/hono/routes/realtime.js +626 -0
  264. package/dist/hono/routes/realtime.js.map +1 -0
  265. package/dist/hono/routes/shared.d.ts +689 -0
  266. package/dist/hono/routes/shared.d.ts.map +1 -0
  267. package/dist/hono/routes/shared.js +972 -0
  268. package/dist/hono/routes/shared.js.map +1 -0
  269. package/dist/hono/routes/snapshots.d.ts +10 -0
  270. package/dist/hono/routes/snapshots.d.ts.map +1 -0
  271. package/dist/hono/routes/snapshots.js +281 -0
  272. package/dist/hono/routes/snapshots.js.map +1 -0
  273. package/dist/hono/routes.d.ts +19 -0
  274. package/dist/hono/routes.d.ts.map +1 -0
  275. package/dist/hono/routes.js +37 -0
  276. package/dist/hono/routes.js.map +1 -0
  277. package/dist/hono/validation.d.ts +5 -0
  278. package/dist/hono/validation.d.ts.map +1 -0
  279. package/dist/hono/validation.js +47 -0
  280. package/dist/hono/validation.js.map +1 -0
  281. package/dist/hono/websocket-origin.d.ts +9 -0
  282. package/dist/hono/websocket-origin.d.ts.map +1 -0
  283. package/dist/hono/websocket-origin.js +96 -0
  284. package/dist/hono/websocket-origin.js.map +1 -0
  285. package/dist/hono/ws.d.ts +341 -0
  286. package/dist/hono/ws.d.ts.map +1 -0
  287. package/dist/hono/ws.js +711 -0
  288. package/dist/hono/ws.js.map +1 -0
  289. package/dist/index.d.ts +6 -0
  290. package/dist/index.d.ts.map +1 -1
  291. package/dist/index.js +24 -18
  292. package/dist/index.js.map +1 -1
  293. package/dist/libsql.d.ts +29 -0
  294. package/dist/libsql.d.ts.map +1 -0
  295. package/dist/libsql.js +25 -0
  296. package/dist/libsql.js.map +1 -0
  297. package/dist/migrate.js.map +1 -1
  298. package/dist/neon.d.ts +21 -0
  299. package/dist/neon.d.ts.map +1 -0
  300. package/dist/neon.js +22 -0
  301. package/dist/neon.js.map +1 -0
  302. package/dist/notify.d.ts +30 -0
  303. package/dist/notify.d.ts.map +1 -1
  304. package/dist/notify.js +160 -41
  305. package/dist/notify.js.map +1 -1
  306. package/dist/pglite.d.ts +37 -0
  307. package/dist/pglite.d.ts.map +1 -0
  308. package/dist/pglite.js +37 -0
  309. package/dist/pglite.js.map +1 -0
  310. package/dist/plugins/index.d.ts +2 -0
  311. package/dist/plugins/index.d.ts.map +1 -0
  312. package/dist/plugins/index.js +2 -0
  313. package/dist/plugins/index.js.map +1 -0
  314. package/dist/plugins/types.d.ts +73 -0
  315. package/dist/plugins/types.d.ts.map +1 -0
  316. package/dist/plugins/types.js +30 -0
  317. package/dist/plugins/types.js.map +1 -0
  318. package/dist/postgres/index.d.ts +68 -0
  319. package/dist/postgres/index.d.ts.map +1 -0
  320. package/dist/postgres/index.js +924 -0
  321. package/dist/postgres/index.js.map +1 -0
  322. package/dist/proxy/collection.d.ts +0 -2
  323. package/dist/proxy/collection.d.ts.map +1 -1
  324. package/dist/proxy/collection.js +2 -17
  325. package/dist/proxy/collection.js.map +1 -1
  326. package/dist/proxy/handler.d.ts +1 -1
  327. package/dist/proxy/handler.d.ts.map +1 -1
  328. package/dist/proxy/handler.js +3 -4
  329. package/dist/proxy/handler.js.map +1 -1
  330. package/dist/proxy/index.d.ts +1 -1
  331. package/dist/proxy/index.d.ts.map +1 -1
  332. package/dist/proxy/index.js +3 -3
  333. package/dist/proxy/index.js.map +1 -1
  334. package/dist/proxy/mutation-detector.js.map +1 -1
  335. package/dist/proxy/oplog.d.ts.map +1 -1
  336. package/dist/proxy/oplog.js +32 -8
  337. package/dist/proxy/oplog.js.map +1 -1
  338. package/dist/prune.d.ts +8 -1
  339. package/dist/prune.d.ts.map +1 -1
  340. package/dist/prune.js +68 -28
  341. package/dist/prune.js.map +1 -1
  342. package/dist/pull.d.ts +31 -0
  343. package/dist/pull.d.ts.map +1 -1
  344. package/dist/pull.js +1014 -474
  345. package/dist/pull.js.map +1 -1
  346. package/dist/push.d.ts +36 -2
  347. package/dist/push.d.ts.map +1 -1
  348. package/dist/push.js +603 -358
  349. package/dist/push.js.map +1 -1
  350. package/dist/realtime/in-memory.js.map +1 -1
  351. package/dist/realtime/index.d.ts +2 -1
  352. package/dist/realtime/index.d.ts.map +1 -1
  353. package/dist/realtime/index.js +2 -1
  354. package/dist/realtime/index.js.map +1 -1
  355. package/dist/realtime/types.d.ts +12 -0
  356. package/dist/realtime/types.d.ts.map +1 -1
  357. package/dist/realtime/types.js +13 -1
  358. package/dist/realtime/types.js.map +1 -1
  359. package/dist/relay/client-role/forward-engine.d.ts +63 -0
  360. package/dist/relay/client-role/forward-engine.d.ts.map +1 -0
  361. package/dist/relay/client-role/forward-engine.js +267 -0
  362. package/dist/relay/client-role/forward-engine.js.map +1 -0
  363. package/dist/relay/client-role/index.d.ts +9 -0
  364. package/dist/relay/client-role/index.d.ts.map +1 -0
  365. package/dist/relay/client-role/index.js +9 -0
  366. package/dist/relay/client-role/index.js.map +1 -0
  367. package/dist/relay/client-role/pull-engine.d.ts +72 -0
  368. package/dist/relay/client-role/pull-engine.d.ts.map +1 -0
  369. package/dist/relay/client-role/pull-engine.js +249 -0
  370. package/dist/relay/client-role/pull-engine.js.map +1 -0
  371. package/dist/relay/client-role/sequence-mapper.d.ts +65 -0
  372. package/dist/relay/client-role/sequence-mapper.d.ts.map +1 -0
  373. package/dist/relay/client-role/sequence-mapper.js +161 -0
  374. package/dist/relay/client-role/sequence-mapper.js.map +1 -0
  375. package/dist/relay/evaluation/relay-paths.d.ts +41 -0
  376. package/dist/relay/evaluation/relay-paths.d.ts.map +1 -0
  377. package/dist/relay/evaluation/relay-paths.js +504 -0
  378. package/dist/relay/evaluation/relay-paths.js.map +1 -0
  379. package/dist/relay/evaluation/rust-boundary.d.ts +47 -0
  380. package/dist/relay/evaluation/rust-boundary.d.ts.map +1 -0
  381. package/dist/relay/evaluation/rust-boundary.js +220 -0
  382. package/dist/relay/evaluation/rust-boundary.js.map +1 -0
  383. package/dist/relay/index.d.ts +37 -0
  384. package/dist/relay/index.d.ts.map +1 -0
  385. package/dist/relay/index.js +44 -0
  386. package/dist/relay/index.js.map +1 -0
  387. package/dist/relay/migrate.d.ts +18 -0
  388. package/dist/relay/migrate.d.ts.map +1 -0
  389. package/dist/relay/migrate.js +99 -0
  390. package/dist/relay/migrate.js.map +1 -0
  391. package/dist/relay/mode-manager.d.ts +60 -0
  392. package/dist/relay/mode-manager.d.ts.map +1 -0
  393. package/dist/relay/mode-manager.js +114 -0
  394. package/dist/relay/mode-manager.js.map +1 -0
  395. package/dist/relay/realtime.d.ts +90 -0
  396. package/dist/relay/realtime.d.ts.map +1 -0
  397. package/dist/relay/realtime.js +147 -0
  398. package/dist/relay/realtime.js.map +1 -0
  399. package/dist/relay/relay.d.ts +190 -0
  400. package/dist/relay/relay.d.ts.map +1 -0
  401. package/dist/relay/relay.js +320 -0
  402. package/dist/relay/relay.js.map +1 -0
  403. package/dist/relay/schema.d.ts +158 -0
  404. package/dist/relay/schema.d.ts.map +1 -0
  405. package/dist/relay/schema.js +7 -0
  406. package/dist/relay/schema.js.map +1 -0
  407. package/dist/relay/server-role/index.d.ts +56 -0
  408. package/dist/relay/server-role/index.d.ts.map +1 -0
  409. package/dist/relay/server-role/index.js +193 -0
  410. package/dist/relay/server-role/index.js.map +1 -0
  411. package/dist/relay/server-role/pull.d.ts +27 -0
  412. package/dist/relay/server-role/pull.d.ts.map +1 -0
  413. package/dist/relay/server-role/pull.js +24 -0
  414. package/dist/relay/server-role/pull.js.map +1 -0
  415. package/dist/relay/server-role/push.d.ts +29 -0
  416. package/dist/relay/server-role/push.d.ts.map +1 -0
  417. package/dist/relay/server-role/push.js +122 -0
  418. package/dist/relay/server-role/push.js.map +1 -0
  419. package/dist/s3/index.d.ts +83 -0
  420. package/dist/s3/index.d.ts.map +1 -0
  421. package/dist/s3/index.js +223 -0
  422. package/dist/s3/index.js.map +1 -0
  423. package/dist/schema.d.ts +137 -1
  424. package/dist/schema.d.ts.map +1 -1
  425. package/dist/schema.js +1 -0
  426. package/dist/schema.js.map +1 -1
  427. package/dist/service-worker/index.d.ts +114 -0
  428. package/dist/service-worker/index.d.ts.map +1 -0
  429. package/dist/service-worker/index.js +487 -0
  430. package/dist/service-worker/index.js.map +1 -0
  431. package/dist/snapshot-artifacts/sqlite-bun.d.ts +15 -0
  432. package/dist/snapshot-artifacts/sqlite-bun.d.ts.map +1 -0
  433. package/dist/snapshot-artifacts/sqlite-bun.js +128 -0
  434. package/dist/snapshot-artifacts/sqlite-bun.js.map +1 -0
  435. package/dist/snapshot-artifacts.d.ts +206 -0
  436. package/dist/snapshot-artifacts.d.ts.map +1 -0
  437. package/dist/snapshot-artifacts.js +545 -0
  438. package/dist/snapshot-artifacts.js.map +1 -0
  439. package/dist/snapshot-chunks/db-metadata.d.ts +18 -0
  440. package/dist/snapshot-chunks/db-metadata.d.ts.map +1 -1
  441. package/dist/snapshot-chunks/db-metadata.js +91 -63
  442. package/dist/snapshot-chunks/db-metadata.js.map +1 -1
  443. package/dist/snapshot-chunks/index.js +2 -2
  444. package/dist/snapshot-chunks/types.d.ts +2 -0
  445. package/dist/snapshot-chunks/types.d.ts.map +1 -1
  446. package/dist/snapshot-chunks.d.ts +33 -3
  447. package/dist/snapshot-chunks.d.ts.map +1 -1
  448. package/dist/snapshot-chunks.js +136 -55
  449. package/dist/snapshot-chunks.js.map +1 -1
  450. package/dist/sqlite/index.d.ts +53 -0
  451. package/dist/sqlite/index.d.ts.map +1 -0
  452. package/dist/sqlite/index.js +795 -0
  453. package/dist/sqlite/index.js.map +1 -0
  454. package/dist/sqlite3.d.ts +22 -0
  455. package/dist/sqlite3.d.ts.map +1 -0
  456. package/dist/sqlite3.js +99 -0
  457. package/dist/sqlite3.js.map +1 -0
  458. package/dist/stats.d.ts +8 -0
  459. package/dist/stats.d.ts.map +1 -1
  460. package/dist/stats.js +45 -13
  461. package/dist/stats.js.map +1 -1
  462. package/dist/subscriptions/cache.d.ts +3 -0
  463. package/dist/subscriptions/cache.d.ts.map +1 -1
  464. package/dist/subscriptions/cache.js +44 -0
  465. package/dist/subscriptions/cache.js.map +1 -1
  466. package/dist/subscriptions/index.js +2 -2
  467. package/dist/subscriptions/resolve.d.ts +3 -1
  468. package/dist/subscriptions/resolve.d.ts.map +1 -1
  469. package/dist/subscriptions/resolve.js +91 -52
  470. package/dist/subscriptions/resolve.js.map +1 -1
  471. package/dist/sync.d.ts +3 -0
  472. package/dist/sync.d.ts.map +1 -1
  473. package/dist/sync.js +9 -5
  474. package/dist/sync.js.map +1 -1
  475. package/package.json +297 -8
  476. package/src/auth-leases.ts +649 -0
  477. package/src/better-sqlite3.ts +35 -0
  478. package/src/blobs/access.ts +244 -0
  479. package/src/blobs/adapters/database.ts +125 -43
  480. package/src/blobs/index.ts +1 -0
  481. package/src/blobs/manager.ts +366 -65
  482. package/src/blobs/migrate.ts +16 -8
  483. package/src/blobs/types.ts +4 -0
  484. package/src/bun-sqlite-ambient.d.ts +19 -0
  485. package/src/bun-sqlite.ts +27 -0
  486. package/src/clients.ts +1 -0
  487. package/src/cloudflare/durable-object.ts +289 -0
  488. package/src/cloudflare/index.ts +22 -0
  489. package/src/cloudflare/r2.ts +526 -0
  490. package/src/cloudflare/scope-cache.ts +341 -0
  491. package/src/cloudflare/sentry.ts +230 -0
  492. package/src/cloudflare/worker.ts +77 -0
  493. package/src/commit-integrity.ts +371 -0
  494. package/src/crdt-yjs/index.ts +931 -0
  495. package/src/d1.ts +16 -0
  496. package/src/dialect/base.ts +71 -5
  497. package/src/dialect/helpers.ts +31 -0
  498. package/src/dialect/types.ts +47 -0
  499. package/src/encrypted-crdt.ts +786 -0
  500. package/src/errors.ts +22 -0
  501. package/src/filesystem/index.ts +262 -0
  502. package/src/handlers/collection.ts +78 -78
  503. package/src/handlers/create-handler.ts +540 -147
  504. package/src/handlers/types.ts +116 -0
  505. package/src/helpers/index.ts +2 -0
  506. package/src/helpers/scope-authorization.ts +27 -0
  507. package/src/helpers/scope-commit-index.ts +52 -0
  508. package/src/hono/api-key-auth.ts +177 -0
  509. package/src/hono/audit-redaction.ts +135 -0
  510. package/src/hono/blobs.ts +851 -0
  511. package/src/hono/console/gateway.ts +3046 -0
  512. package/src/hono/console/live-auth.ts +46 -0
  513. package/src/hono/console/route-descriptor.ts +22 -0
  514. package/src/hono/console/routes/api-keys.ts +721 -0
  515. package/src/hono/console/routes/clients.ts +447 -0
  516. package/src/hono/console/routes/commits.ts +1137 -0
  517. package/src/hono/console/routes/context.ts +956 -0
  518. package/src/hono/console/routes/events.ts +669 -0
  519. package/src/hono/console/routes/maintenance.ts +461 -0
  520. package/src/hono/console/routes/shared.ts +816 -0
  521. package/src/hono/console/routes/stats.ts +392 -0
  522. package/src/hono/console/routes/storage.ts +159 -0
  523. package/src/hono/console/routes.ts +146 -0
  524. package/src/hono/console/schema-errors.ts +23 -0
  525. package/src/hono/console/schemas.ts +914 -0
  526. package/src/hono/console/types.ts +223 -0
  527. package/src/hono/console/ui.ts +100 -0
  528. package/src/hono/create-server.ts +230 -0
  529. package/src/hono/errors.ts +50 -0
  530. package/src/hono/index.ts +54 -0
  531. package/src/hono/openapi.ts +139 -0
  532. package/src/hono/proxy/connection-manager.ts +340 -0
  533. package/src/hono/proxy/index.ts +8 -0
  534. package/src/hono/proxy/routes.ts +272 -0
  535. package/src/hono/rate-limit.ts +319 -0
  536. package/src/hono/realtime-sync-packs.ts +354 -0
  537. package/src/hono/routes/audit.ts +499 -0
  538. package/src/hono/routes/auth-leases.ts +119 -0
  539. package/src/hono/routes/combined.ts +583 -0
  540. package/src/hono/routes/context.ts +1629 -0
  541. package/src/hono/routes/health.ts +26 -0
  542. package/src/hono/routes/realtime.ts +808 -0
  543. package/src/hono/routes/shared.ts +1626 -0
  544. package/src/hono/routes/snapshots.ts +345 -0
  545. package/src/hono/routes.ts +68 -0
  546. package/src/hono/validation.ts +81 -0
  547. package/src/hono/websocket-origin.ts +131 -0
  548. package/src/hono/ws.ts +1134 -0
  549. package/src/index.ts +6 -0
  550. package/src/libsql.ts +51 -0
  551. package/src/neon.ts +28 -0
  552. package/src/notify.ts +224 -44
  553. package/src/pglite.ts +68 -0
  554. package/src/plugins/index.ts +1 -0
  555. package/src/plugins/types.ts +144 -0
  556. package/src/postgres/index.ts +1291 -0
  557. package/src/proxy/collection.ts +5 -27
  558. package/src/proxy/handler.ts +2 -2
  559. package/src/proxy/index.ts +0 -2
  560. package/src/proxy/oplog.ts +41 -10
  561. package/src/prune.ts +137 -36
  562. package/src/pull.ts +1504 -591
  563. package/src/push.ts +881 -443
  564. package/src/realtime/index.ts +2 -0
  565. package/src/realtime/types.ts +35 -0
  566. package/src/relay/bun-types.d.ts +50 -0
  567. package/src/relay/client-role/forward-engine.ts +355 -0
  568. package/src/relay/client-role/index.ts +9 -0
  569. package/src/relay/client-role/pull-engine.ts +329 -0
  570. package/src/relay/client-role/sequence-mapper.ts +201 -0
  571. package/src/relay/evaluation/relay-paths.ts +699 -0
  572. package/src/relay/evaluation/rust-boundary.ts +464 -0
  573. package/src/relay/index.ts +50 -0
  574. package/src/relay/migrate.ts +113 -0
  575. package/src/relay/mode-manager.ts +142 -0
  576. package/src/relay/realtime.ts +207 -0
  577. package/src/relay/relay.ts +431 -0
  578. package/src/relay/schema.ts +171 -0
  579. package/src/relay/server-role/index.ts +338 -0
  580. package/src/relay/server-role/pull.ts +43 -0
  581. package/src/relay/server-role/push.ts +164 -0
  582. package/src/s3/index.ts +346 -0
  583. package/src/schema.ts +141 -1
  584. package/src/service-worker/index.ts +773 -0
  585. package/src/snapshot-artifacts/sqlite-bun.ts +168 -0
  586. package/src/snapshot-artifacts.ts +896 -0
  587. package/src/snapshot-chunks/db-metadata.ts +131 -72
  588. package/src/snapshot-chunks/types.ts +2 -0
  589. package/src/snapshot-chunks.ts +194 -70
  590. package/src/sqlite/index.ts +1064 -0
  591. package/src/sqlite3.ts +137 -0
  592. package/src/stats.ts +76 -13
  593. package/src/subscriptions/cache.ts +58 -0
  594. package/src/subscriptions/resolve.ts +99 -58
  595. package/src/sync.ts +16 -6
  596. package/src/blobs/adapters/database.test.ts +0 -67
  597. package/src/notify.test.ts +0 -520
  598. package/src/proxy/handler.test.ts +0 -126
  599. package/src/proxy/mutation-detector.test.ts +0 -71
  600. package/src/snapshot-chunks/db-metadata.test.ts +0 -172
  601. package/src/subscriptions/resolve.test.ts +0 -180
package/dist/push.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { captureSyncException, countSyncMetric, distributionSyncMetric, startSyncSpan, } from '@syncular/core';
2
2
  import { sql } from 'kysely';
3
- import { getServerHandlerOrThrow, } from './handlers/collection.js';
3
+ import { finalizeCommitIntegrity } from './commit-integrity';
4
+ import { coerceNumber, parseJsonValue, toDialectJsonValue, } from './dialect/helpers';
5
+ import { createScopeCommitIndexEntries, scopeKeysFromScopeValues, } from './helpers/scope-commit-index';
6
+ import { sortServerPushPlugins, } from './plugins/types';
4
7
  class RejectCommitError extends Error {
5
8
  response;
6
9
  constructor(response) {
@@ -9,45 +12,23 @@ class RejectCommitError extends Error {
9
12
  this.name = 'RejectCommitError';
10
13
  }
11
14
  }
12
- function toDialectJsonValue(dialect, value) {
13
- if (value === null || value === undefined)
14
- return null;
15
- if (dialect.family === 'sqlite')
16
- return JSON.stringify(value);
17
- return value;
18
- }
19
- function parseJsonValue(value) {
20
- if (typeof value !== 'string')
21
- return value;
22
- try {
23
- return JSON.parse(value);
24
- }
25
- catch {
26
- return value;
27
- }
28
- }
29
- function coerceNumber(value) {
30
- if (value === null || value === undefined)
31
- return null;
32
- if (typeof value === 'number') {
33
- return Number.isFinite(value) ? value : null;
34
- }
35
- if (typeof value === 'bigint') {
36
- const coerced = Number(value);
37
- return Number.isFinite(coerced) ? coerced : null;
38
- }
39
- if (typeof value === 'string') {
40
- const coerced = Number(value);
41
- return Number.isFinite(coerced) ? coerced : null;
42
- }
43
- return null;
44
- }
45
15
  function isRecord(value) {
46
16
  return typeof value === 'object' && value !== null;
47
17
  }
48
18
  function isSyncPushResponse(value) {
49
19
  return (isRecord(value) && value.ok === true && typeof value.status === 'string');
50
20
  }
21
+ function assertOperationIdentityUnchanged(pluginName, before, after) {
22
+ if (before.table !== after.table) {
23
+ throw new Error(`Server push plugin "${pluginName}" cannot change op.table (${before.table} -> ${after.table})`);
24
+ }
25
+ if (before.row_id !== after.row_id) {
26
+ throw new Error(`Server push plugin "${pluginName}" cannot change op.row_id (${before.row_id} -> ${after.row_id})`);
27
+ }
28
+ if (before.op !== after.op) {
29
+ throw new Error(`Server push plugin "${pluginName}" cannot change op.op (${before.op} -> ${after.op})`);
30
+ }
31
+ }
51
32
  async function readCommitAffectedTables(db, dialect, commitSeq, partitionId) {
52
33
  try {
53
34
  const commitsQ = db.selectFrom('sync_commits');
@@ -68,11 +49,8 @@ async function readCommitAffectedTables(db, dialect, commitSeq, partitionId) {
68
49
  function scopeKeysFromEmitted(emitted) {
69
50
  const keys = new Set();
70
51
  for (const c of emitted) {
71
- for (const [key, value] of Object.entries(c.scopes)) {
72
- if (!value)
73
- continue;
74
- const prefix = key.replace(/_id$/, '');
75
- keys.add(`${prefix}:${value}`);
52
+ for (const scopeKey of scopeKeysFromScopeValues(c.scopes)) {
53
+ keys.add(scopeKey);
76
54
  }
77
55
  }
78
56
  return Array.from(keys);
@@ -96,15 +74,480 @@ function recordPushMetrics(args) {
96
74
  attributes: { status },
97
75
  });
98
76
  }
99
- export async function pushCommit(args) {
100
- const { db, dialect, handlers, request } = args;
77
+ function createRejectedPushResult(error) {
78
+ return {
79
+ response: {
80
+ ok: true,
81
+ status: 'rejected',
82
+ results: [error],
83
+ },
84
+ affectedTables: [],
85
+ scopeKeys: [],
86
+ emittedChanges: [],
87
+ commitActorId: null,
88
+ commitCreatedAt: null,
89
+ };
90
+ }
91
+ function createRejectedPushResponse(error, commitSeq) {
92
+ return {
93
+ ok: true,
94
+ status: 'rejected',
95
+ ...(commitSeq !== undefined ? { commitSeq } : {}),
96
+ results: [error],
97
+ };
98
+ }
99
+ function validatePushRequest(request) {
100
+ if (!request.clientId || !request.clientCommitId) {
101
+ return {
102
+ opIndex: 0,
103
+ status: 'error',
104
+ error: 'Invalid push request',
105
+ code: 'sync.invalid_request',
106
+ retriable: false,
107
+ };
108
+ }
109
+ const ops = request.operations ?? [];
110
+ if (!Array.isArray(ops) || ops.length === 0) {
111
+ return {
112
+ opIndex: 0,
113
+ status: 'error',
114
+ error: 'Empty commit',
115
+ code: 'sync.empty_commit',
116
+ retriable: false,
117
+ };
118
+ }
119
+ return null;
120
+ }
121
+ function shouldUseSavepoints(args) {
122
+ if (!args.dialect.supportsSavepoints) {
123
+ return false;
124
+ }
125
+ if ((args.operations?.length ?? 0) !== 1) {
126
+ return true;
127
+ }
128
+ const singleOp = args.operations?.[0];
129
+ if (!singleOp) {
130
+ return true;
131
+ }
132
+ const singleOpHandler = args.handlers.byTable.get(singleOp.table);
133
+ if (!singleOpHandler) {
134
+ throw new Error(`Unknown table: ${singleOp.table}`);
135
+ }
136
+ return !singleOpHandler.canRejectSingleOperationWithoutSavepoint;
137
+ }
138
+ async function persistEmittedChanges(args) {
139
+ if (args.emittedChanges.length === 0) {
140
+ return;
141
+ }
142
+ const syncTrx = args.trx;
143
+ const changeRows = args.emittedChanges.map((change) => ({
144
+ partition_id: args.partitionId,
145
+ commit_seq: args.commitSeq,
146
+ table: change.table,
147
+ row_id: change.row_id,
148
+ op: change.op,
149
+ row_json: toDialectJsonValue(args.dialect, change.row_json),
150
+ row_version: change.row_version,
151
+ scopes: args.dialect.scopesToDb(change.scopes),
152
+ }));
153
+ await syncTrx.insertInto('sync_changes').values(changeRows).execute();
154
+ const scopeEntries = createScopeCommitIndexEntries(args.emittedChanges);
155
+ if (scopeEntries.length > 0) {
156
+ await syncTrx
157
+ .insertInto('sync_scope_commits')
158
+ .values(scopeEntries.map((entry) => ({
159
+ partition_id: args.partitionId,
160
+ table: entry.table,
161
+ scope_key: entry.scopeKey,
162
+ commit_seq: args.commitSeq,
163
+ })))
164
+ .onConflict((oc) => oc
165
+ .columns(['partition_id', 'table', 'scope_key', 'commit_seq'])
166
+ .doNothing())
167
+ .execute();
168
+ }
169
+ }
170
+ async function persistCommitOutcome(args) {
171
+ const syncTrx = args.trx;
172
+ await syncTrx
173
+ .updateTable('sync_commits')
174
+ .set({
175
+ result_json: toDialectJsonValue(args.dialect, args.response),
176
+ change_count: args.emittedChangeCount,
177
+ affected_tables: args.dialect.arrayToDb(args.affectedTables),
178
+ })
179
+ .where('commit_seq', '=', args.commitSeq)
180
+ .execute();
181
+ if (args.affectedTables.length > 0) {
182
+ await syncTrx
183
+ .insertInto('sync_table_commits')
184
+ .values(args.affectedTables.map((table) => ({
185
+ partition_id: args.partitionId,
186
+ table,
187
+ commit_seq: args.commitSeq,
188
+ })))
189
+ .onConflict((oc) => oc.columns(['partition_id', 'table', 'commit_seq']).doNothing())
190
+ .execute();
191
+ }
192
+ await finalizeCommitIntegrity({
193
+ db: args.trx,
194
+ dialect: args.dialect,
195
+ partitionId: args.partitionId,
196
+ commitSeq: args.commitSeq,
197
+ });
198
+ }
199
+ async function loadExistingCommitResult(args) {
200
+ let query = args.syncTrx.selectFrom('sync_commits')
201
+ .selectAll()
202
+ .where('partition_id', '=', args.partitionId)
203
+ .where('client_id', '=', args.request.clientId)
204
+ .where('client_commit_id', '=', args.request.clientCommitId);
205
+ if (args.dialect.supportsForUpdate) {
206
+ query = query.forUpdate();
207
+ }
208
+ const existing = await query.executeTakeFirstOrThrow();
209
+ const parsedCached = parseJsonValue(existing.result_json);
210
+ if (!isSyncPushResponse(parsedCached)) {
211
+ return createRejectedPushResult({
212
+ opIndex: 0,
213
+ status: 'error',
214
+ error: 'Idempotency cache miss',
215
+ code: 'sync.idempotency_cache_miss',
216
+ retriable: true,
217
+ });
218
+ }
219
+ const base = {
220
+ ...parsedCached,
221
+ commitSeq: Number(existing.commit_seq),
222
+ };
223
+ if (parsedCached.status === 'applied') {
224
+ const tablesFromDb = args.dialect.dbToArray(existing.affected_tables);
225
+ return {
226
+ response: { ...base, status: 'cached' },
227
+ affectedTables: tablesFromDb.length > 0
228
+ ? tablesFromDb
229
+ : await readCommitAffectedTables(args.trx, args.dialect, Number(existing.commit_seq), args.partitionId),
230
+ scopeKeys: [],
231
+ emittedChanges: [],
232
+ commitActorId: typeof existing.actor_id === 'string' ? existing.actor_id : null,
233
+ commitCreatedAt: typeof existing.created_at === 'string' ? existing.created_at : null,
234
+ };
235
+ }
236
+ return {
237
+ response: base,
238
+ affectedTables: [],
239
+ scopeKeys: [],
240
+ emittedChanges: [],
241
+ commitActorId: typeof existing.actor_id === 'string' ? existing.actor_id : null,
242
+ commitCreatedAt: typeof existing.created_at === 'string' ? existing.created_at : null,
243
+ };
244
+ }
245
+ async function insertPendingCommit(args) {
246
+ if (args.dialect.supportsInsertReturning) {
247
+ const insertedCommit = await args.syncTrx
248
+ .insertInto('sync_commits')
249
+ .values(args.commitRow)
250
+ .onConflict((oc) => oc
251
+ .columns(['partition_id', 'client_id', 'client_commit_id'])
252
+ .doNothing())
253
+ .returning(['commit_seq'])
254
+ .executeTakeFirst();
255
+ if (!insertedCommit) {
256
+ return null;
257
+ }
258
+ return coerceNumber(insertedCommit.commit_seq) ?? 0;
259
+ }
260
+ const insertResult = await args.syncTrx
261
+ .insertInto('sync_commits')
262
+ .values(args.commitRow)
263
+ .onConflict((oc) => oc.columns(['partition_id', 'client_id', 'client_commit_id']).doNothing())
264
+ .executeTakeFirstOrThrow();
265
+ const insertedRows = Number(insertResult.numInsertedOrUpdatedRows ?? 0);
266
+ if (insertedRows === 0) {
267
+ return null;
268
+ }
269
+ return coerceNumber(insertResult.insertId) ?? 0;
270
+ }
271
+ async function applyCommitOperations(args) {
272
+ const ops = args.request.operations ?? [];
273
+ const allEmitted = [];
274
+ const results = [];
275
+ const affectedTablesSet = new Set();
276
+ for (let i = 0; i < ops.length;) {
277
+ const op = ops[i];
278
+ const handler = args.handlers.byTable.get(op.table);
279
+ if (!handler) {
280
+ throw new Error(`Unknown table: ${op.table}`);
281
+ }
282
+ const operationCtx = {
283
+ db: args.trx,
284
+ trx: args.trx,
285
+ actorId: args.actorId,
286
+ auth: args.auth,
287
+ clientId: args.request.clientId,
288
+ commitId: args.commitId,
289
+ schemaVersion: args.request.schemaVersion,
290
+ authLease: args.request.authLease,
291
+ };
292
+ let transformedOp = op;
293
+ for (const plugin of args.pushPlugins) {
294
+ if (!plugin.beforeApplyOperation)
295
+ continue;
296
+ const nextOp = await plugin.beforeApplyOperation({
297
+ ctx: operationCtx,
298
+ tableHandler: handler,
299
+ op: transformedOp,
300
+ opIndex: i,
301
+ });
302
+ assertOperationIdentityUnchanged(plugin.name, op, nextOp);
303
+ transformedOp = nextOp;
304
+ }
305
+ let appliedBatch = null;
306
+ let consumed = 1;
307
+ if (args.pushPlugins.length === 0 && handler.applyOperationBatch) {
308
+ const batchInput = [];
309
+ for (let j = i; j < ops.length; j++) {
310
+ const nextOp = ops[j];
311
+ if (nextOp.table !== op.table)
312
+ break;
313
+ batchInput.push({ op: nextOp, opIndex: j });
314
+ }
315
+ if (batchInput.length > 1) {
316
+ appliedBatch = await handler.applyOperationBatch(operationCtx, batchInput);
317
+ consumed = Math.max(1, appliedBatch.length);
318
+ }
319
+ }
320
+ if (!appliedBatch) {
321
+ let appliedSingle = await handler.applyOperation(operationCtx, transformedOp, i);
322
+ for (const plugin of args.pushPlugins) {
323
+ if (!plugin.afterApplyOperation)
324
+ continue;
325
+ appliedSingle = await plugin.afterApplyOperation({
326
+ ctx: operationCtx,
327
+ tableHandler: handler,
328
+ op: transformedOp,
329
+ opIndex: i,
330
+ applied: appliedSingle,
331
+ });
332
+ }
333
+ appliedBatch = [appliedSingle];
334
+ }
335
+ if (appliedBatch.length === 0) {
336
+ throw new Error(`Handler "${op.table}" returned no results from applyOperationBatch`);
337
+ }
338
+ for (const applied of appliedBatch) {
339
+ if (applied.result.status !== 'applied') {
340
+ results.push(applied.result);
341
+ throw new RejectCommitError(createRejectedPushResponse(applied.result, args.commitSeq));
342
+ }
343
+ for (const change of applied.emittedChanges ?? []) {
344
+ const scopes = change?.scopes;
345
+ if (!scopes || typeof scopes !== 'object') {
346
+ const error = {
347
+ opIndex: applied.result.opIndex,
348
+ status: 'error',
349
+ error: 'Missing scopes',
350
+ code: 'sync.missing_scopes',
351
+ retriable: false,
352
+ };
353
+ results.push(error);
354
+ throw new RejectCommitError(createRejectedPushResponse(error, args.commitSeq));
355
+ }
356
+ }
357
+ results.push(applied.result);
358
+ allEmitted.push(...applied.emittedChanges);
359
+ for (const change of applied.emittedChanges) {
360
+ affectedTablesSet.add(change.table);
361
+ }
362
+ }
363
+ i += consumed;
364
+ }
365
+ return {
366
+ results,
367
+ emittedChanges: allEmitted,
368
+ affectedTables: Array.from(affectedTablesSet).sort(),
369
+ };
370
+ }
371
+ async function executePushCommitInExecutor(args) {
372
+ const { trx, dialect, handlers, request, pushPlugins } = args;
101
373
  const actorId = args.auth.actorId;
102
374
  const partitionId = args.auth.partitionId ?? 'default';
375
+ const ops = request.operations ?? [];
376
+ const syncTrx = trx;
377
+ if (!dialect.supportsSavepoints) {
378
+ await syncTrx
379
+ .deleteFrom('sync_commits')
380
+ .where('partition_id', '=', partitionId)
381
+ .where('client_id', '=', request.clientId)
382
+ .where('client_commit_id', '=', request.clientCommitId)
383
+ .where('result_json', 'is', null)
384
+ .execute();
385
+ }
386
+ const commitCreatedAt = new Date().toISOString();
387
+ const commitRow = {
388
+ partition_id: partitionId,
389
+ actor_id: actorId,
390
+ client_id: request.clientId,
391
+ client_commit_id: request.clientCommitId,
392
+ created_at: commitCreatedAt,
393
+ meta: request.authLease
394
+ ? toDialectJsonValue(dialect, {
395
+ authLease: request.authLease,
396
+ })
397
+ : null,
398
+ result_json: null,
399
+ };
400
+ let commitSeq = (await insertPendingCommit({
401
+ syncTrx,
402
+ dialect,
403
+ commitRow,
404
+ })) ?? 0;
405
+ if (commitSeq === 0) {
406
+ return loadExistingCommitResult({
407
+ trx,
408
+ syncTrx,
409
+ dialect,
410
+ request,
411
+ partitionId,
412
+ });
413
+ }
414
+ if (commitSeq <= 0) {
415
+ const insertedCommitRow = await syncTrx.selectFrom('sync_commits')
416
+ .selectAll()
417
+ .where('partition_id', '=', partitionId)
418
+ .where('client_id', '=', request.clientId)
419
+ .where('client_commit_id', '=', request.clientCommitId)
420
+ .executeTakeFirstOrThrow();
421
+ commitSeq = Number(insertedCommitRow.commit_seq);
422
+ }
423
+ const commitId = `${request.clientId}:${request.clientCommitId}`;
424
+ const validationResult = await args.validateCommit?.({
425
+ trx,
426
+ dialect,
427
+ auth: args.auth,
428
+ request,
429
+ partitionId,
430
+ actorId,
431
+ commitSeq,
432
+ });
433
+ if (validationResult) {
434
+ const response = createRejectedPushResponse(validationResult, commitSeq);
435
+ await persistCommitOutcome({
436
+ trx,
437
+ dialect,
438
+ partitionId,
439
+ commitSeq,
440
+ response,
441
+ affectedTables: [],
442
+ emittedChangeCount: 0,
443
+ });
444
+ return {
445
+ response,
446
+ affectedTables: [],
447
+ scopeKeys: [],
448
+ emittedChanges: [],
449
+ commitActorId: actorId,
450
+ commitCreatedAt,
451
+ };
452
+ }
453
+ const savepointName = `sync_apply_${commitSeq}`;
454
+ const useSavepoints = shouldUseSavepoints({
455
+ dialect,
456
+ handlers,
457
+ operations: ops,
458
+ });
459
+ let savepointCreated = false;
460
+ try {
461
+ if (useSavepoints) {
462
+ await sql.raw(`SAVEPOINT ${savepointName}`).execute(trx);
463
+ savepointCreated = true;
464
+ }
465
+ const applied = await applyCommitOperations({
466
+ trx,
467
+ handlers,
468
+ pushPlugins,
469
+ auth: args.auth,
470
+ request,
471
+ actorId,
472
+ commitId,
473
+ commitSeq,
474
+ });
475
+ const appliedResponse = {
476
+ ok: true,
477
+ status: 'applied',
478
+ commitSeq,
479
+ results: applied.results,
480
+ };
481
+ await persistEmittedChanges({
482
+ trx,
483
+ dialect,
484
+ partitionId,
485
+ commitSeq,
486
+ emittedChanges: applied.emittedChanges,
487
+ });
488
+ await persistCommitOutcome({
489
+ trx,
490
+ dialect,
491
+ partitionId,
492
+ commitSeq,
493
+ response: appliedResponse,
494
+ affectedTables: applied.affectedTables,
495
+ emittedChangeCount: applied.emittedChanges.length,
496
+ });
497
+ if (useSavepoints) {
498
+ await sql.raw(`RELEASE SAVEPOINT ${savepointName}`).execute(trx);
499
+ }
500
+ return {
501
+ response: appliedResponse,
502
+ affectedTables: applied.affectedTables,
503
+ scopeKeys: scopeKeysFromEmitted(applied.emittedChanges),
504
+ emittedChanges: applied.emittedChanges,
505
+ commitActorId: actorId,
506
+ commitCreatedAt,
507
+ };
508
+ }
509
+ catch (error) {
510
+ if (savepointCreated) {
511
+ try {
512
+ await sql.raw(`ROLLBACK TO SAVEPOINT ${savepointName}`).execute(trx);
513
+ await sql.raw(`RELEASE SAVEPOINT ${savepointName}`).execute(trx);
514
+ }
515
+ catch (savepointError) {
516
+ console.error('[pushCommit] Savepoint rollback failed:', savepointError);
517
+ throw savepointError;
518
+ }
519
+ }
520
+ if (!(error instanceof RejectCommitError)) {
521
+ throw error;
522
+ }
523
+ await persistCommitOutcome({
524
+ trx,
525
+ dialect,
526
+ partitionId,
527
+ commitSeq,
528
+ response: error.response,
529
+ affectedTables: [],
530
+ emittedChangeCount: 0,
531
+ });
532
+ return {
533
+ response: error.response,
534
+ affectedTables: [],
535
+ scopeKeys: [],
536
+ emittedChanges: [],
537
+ commitActorId: actorId,
538
+ commitCreatedAt,
539
+ };
540
+ }
541
+ }
542
+ export async function pushCommit(args) {
543
+ const { db, dialect, handlers, request } = args;
544
+ const pushPlugins = sortServerPushPlugins(args.plugins);
103
545
  const requestedOps = Array.isArray(request.operations)
104
546
  ? request.operations
105
547
  : [];
106
548
  const operationCount = requestedOps.length;
107
549
  const startedAtMs = Date.now();
550
+ const suppressTelemetry = args.suppressTelemetry === true;
108
551
  return startSyncSpan({
109
552
  name: 'sync.server.push',
110
553
  op: 'sync.push',
@@ -120,337 +563,139 @@ export async function pushCommit(args) {
120
563
  span.setAttribute('emitted_change_count', result.emittedChanges.length);
121
564
  span.setAttribute('affected_table_count', result.affectedTables.length);
122
565
  span.setStatus('ok');
123
- recordPushMetrics({
124
- status,
125
- durationMs,
126
- operationCount,
127
- emittedChangeCount: result.emittedChanges.length,
128
- affectedTableCount: result.affectedTables.length,
129
- });
566
+ if (!suppressTelemetry) {
567
+ recordPushMetrics({
568
+ status,
569
+ durationMs,
570
+ operationCount,
571
+ emittedChangeCount: result.emittedChanges.length,
572
+ affectedTableCount: result.affectedTables.length,
573
+ });
574
+ }
130
575
  return result;
131
576
  };
132
577
  try {
133
- if (!request.clientId || !request.clientCommitId) {
134
- return finalizeResult({
135
- response: {
136
- ok: true,
137
- status: 'rejected',
138
- results: [
139
- {
140
- opIndex: 0,
141
- status: 'error',
142
- error: 'INVALID_REQUEST',
143
- code: 'INVALID_REQUEST',
144
- retriable: false,
145
- },
146
- ],
147
- },
148
- affectedTables: [],
149
- scopeKeys: [],
150
- emittedChanges: [],
151
- });
578
+ const validationError = validatePushRequest(request);
579
+ if (validationError) {
580
+ return finalizeResult(createRejectedPushResult(validationError));
152
581
  }
153
- const ops = request.operations ?? [];
154
- if (!Array.isArray(ops) || ops.length === 0) {
155
- return finalizeResult({
156
- response: {
157
- ok: true,
158
- status: 'rejected',
159
- results: [
160
- {
161
- opIndex: 0,
162
- status: 'error',
163
- error: 'EMPTY_COMMIT',
164
- code: 'EMPTY_COMMIT',
165
- retriable: false,
166
- },
167
- ],
168
- },
169
- affectedTables: [],
170
- scopeKeys: [],
171
- emittedChanges: [],
582
+ return finalizeResult(await dialect.executeInTransaction(db, async (trx) => executePushCommitInExecutor({
583
+ trx,
584
+ dialect,
585
+ handlers,
586
+ pushPlugins,
587
+ auth: args.auth,
588
+ request,
589
+ validateCommit: args.validateCommit,
590
+ })));
591
+ }
592
+ catch (error) {
593
+ const durationMs = Math.max(0, Date.now() - startedAtMs);
594
+ span.setAttribute('status', 'error');
595
+ span.setAttribute('duration_ms', durationMs);
596
+ span.setStatus('error');
597
+ if (!suppressTelemetry) {
598
+ recordPushMetrics({
599
+ status: 'error',
600
+ durationMs,
601
+ operationCount,
602
+ emittedChangeCount: 0,
603
+ affectedTableCount: 0,
604
+ });
605
+ captureSyncException(error, {
606
+ event: 'sync.server.push',
607
+ operationCount,
172
608
  });
173
609
  }
174
- return finalizeResult(await dialect.executeInTransaction(db, async (trx) => {
175
- const syncTrx = trx;
176
- // Clean up any stale commit row with null result_json.
177
- // This can happen when a previous push inserted the commit row but crashed
178
- // before writing the result (e.g., on D1 without transaction support).
179
- if (!dialect.supportsSavepoints) {
180
- await syncTrx
181
- .deleteFrom('sync_commits')
182
- .where('partition_id', '=', partitionId)
183
- .where('client_id', '=', request.clientId)
184
- .where('client_commit_id', '=', request.clientCommitId)
185
- .where('result_json', 'is', null)
186
- .execute();
187
- }
188
- // Insert commit row (idempotency key)
189
- const commitRow = {
190
- partition_id: partitionId,
191
- actor_id: actorId,
192
- client_id: request.clientId,
193
- client_commit_id: request.clientCommitId,
194
- meta: null,
195
- result_json: null,
196
- };
197
- const insertResult = await syncTrx
198
- .insertInto('sync_commits')
199
- .values(commitRow)
200
- .onConflict((oc) => oc
201
- .columns(['partition_id', 'client_id', 'client_commit_id'])
202
- .doNothing())
203
- .executeTakeFirstOrThrow();
204
- const insertedRows = Number(insertResult.numInsertedOrUpdatedRows ?? 0);
205
- if (insertedRows === 0) {
206
- // Existing commit: return cached response (applied or rejected)
207
- // Use forUpdate() for row locking on databases that support it
208
- let query = syncTrx.selectFrom('sync_commits')
209
- .selectAll()
210
- .where('partition_id', '=', partitionId)
211
- .where('client_id', '=', request.clientId)
212
- .where('client_commit_id', '=', request.clientCommitId);
213
- if (dialect.supportsForUpdate) {
214
- query = query.forUpdate();
215
- }
216
- const existing = await query.executeTakeFirstOrThrow();
217
- const parsedCached = parseJsonValue(existing.result_json);
218
- if (!isSyncPushResponse(parsedCached)) {
219
- return {
220
- response: {
221
- ok: true,
222
- status: 'rejected',
223
- results: [
224
- {
225
- opIndex: 0,
226
- status: 'error',
227
- error: 'IDEMPOTENCY_CACHE_MISS',
228
- code: 'INTERNAL',
229
- retriable: true,
230
- },
231
- ],
232
- },
233
- affectedTables: [],
234
- scopeKeys: [],
235
- emittedChanges: [],
236
- };
237
- }
238
- const base = {
239
- ...parsedCached,
240
- commitSeq: Number(existing.commit_seq),
241
- };
242
- if (parsedCached.status === 'applied') {
243
- const tablesFromDb = dialect.dbToArray(existing.affected_tables);
244
- return {
245
- response: { ...base, status: 'cached' },
246
- affectedTables: tablesFromDb.length > 0
247
- ? tablesFromDb
248
- : await readCommitAffectedTables(trx, dialect, Number(existing.commit_seq), partitionId),
249
- scopeKeys: [],
250
- emittedChanges: [],
251
- };
252
- }
253
- return {
254
- response: base,
255
- affectedTables: [],
256
- scopeKeys: [],
257
- emittedChanges: [],
258
- };
259
- }
260
- let commitSeq = coerceNumber(insertResult.insertId) ?? 0;
261
- if (commitSeq <= 0) {
262
- const insertedCommit = await syncTrx.selectFrom('sync_commits')
263
- .selectAll()
264
- .where('partition_id', '=', partitionId)
265
- .where('client_id', '=', request.clientId)
266
- .where('client_commit_id', '=', request.clientCommitId)
267
- .executeTakeFirstOrThrow();
268
- commitSeq = Number(insertedCommit.commit_seq);
269
- }
270
- const commitId = `${request.clientId}:${request.clientCommitId}`;
271
- const savepointName = 'sync_apply';
272
- const useSavepoints = dialect.supportsSavepoints;
273
- let savepointCreated = false;
274
- try {
275
- // Apply the commit under a savepoint so we can roll back app writes on conflict
276
- // while still persisting the commit-level cached response.
277
- if (useSavepoints) {
278
- await sql.raw(`SAVEPOINT ${savepointName}`).execute(trx);
279
- savepointCreated = true;
280
- }
281
- const allEmitted = [];
282
- const results = [];
283
- const affectedTablesSet = new Set();
284
- for (let i = 0; i < ops.length; i++) {
285
- const op = ops[i];
286
- const handler = getServerHandlerOrThrow(handlers, op.table);
287
- const applied = await handler.applyOperation({
288
- db: trx,
289
- trx,
290
- actorId,
291
- auth: args.auth,
292
- clientId: request.clientId,
293
- commitId,
294
- schemaVersion: request.schemaVersion,
295
- }, op, i);
296
- if (applied.result.status !== 'applied') {
297
- results.push(applied.result);
298
- throw new RejectCommitError({
299
- ok: true,
300
- status: 'rejected',
301
- commitSeq,
302
- results,
303
- });
304
- }
305
- // Framework-level enforcement: emitted changes must have scopes
306
- for (const c of applied.emittedChanges ?? []) {
307
- const scopes = c?.scopes;
308
- if (!scopes || typeof scopes !== 'object') {
309
- results.push({
310
- opIndex: i,
311
- status: 'error',
312
- error: 'MISSING_SCOPES',
313
- code: 'INVALID_SCOPE',
314
- retriable: false,
315
- });
316
- throw new RejectCommitError({
317
- ok: true,
318
- status: 'rejected',
319
- commitSeq,
320
- results,
321
- });
322
- }
323
- }
324
- results.push(applied.result);
325
- allEmitted.push(...applied.emittedChanges);
326
- for (const c of applied.emittedChanges) {
327
- affectedTablesSet.add(c.table);
328
- }
329
- }
330
- if (allEmitted.length > 0) {
331
- const changeRows = allEmitted.map((c) => ({
332
- partition_id: partitionId,
333
- commit_seq: commitSeq,
334
- table: c.table,
335
- row_id: c.row_id,
336
- op: c.op,
337
- row_json: toDialectJsonValue(dialect, c.row_json),
338
- row_version: c.row_version,
339
- scopes: dialect.scopesToDb(c.scopes),
340
- }));
341
- await syncTrx
342
- .insertInto('sync_changes')
343
- .values(changeRows)
344
- .execute();
345
- }
346
- const appliedResponse = {
347
- ok: true,
348
- status: 'applied',
349
- commitSeq,
350
- results,
351
- };
352
- const affectedTables = Array.from(affectedTablesSet).sort();
353
- const appliedCommitUpdate = {
354
- result_json: toDialectJsonValue(dialect, appliedResponse),
355
- change_count: allEmitted.length,
356
- affected_tables: dialect.arrayToDb(affectedTables),
357
- };
358
- await syncTrx
359
- .updateTable('sync_commits')
360
- .set(appliedCommitUpdate)
361
- .where('commit_seq', '=', commitSeq)
362
- .execute();
363
- // Insert table commits for subscription filtering
364
- if (affectedTables.length > 0) {
365
- const tableCommits = affectedTables.map((table) => ({
366
- partition_id: partitionId,
367
- table,
368
- commit_seq: commitSeq,
369
- }));
370
- await syncTrx
371
- .insertInto('sync_table_commits')
372
- .values(tableCommits)
373
- .onConflict((oc) => oc
374
- .columns(['partition_id', 'table', 'commit_seq'])
375
- .doNothing())
376
- .execute();
377
- }
378
- if (useSavepoints) {
379
- await sql
380
- .raw(`RELEASE SAVEPOINT ${savepointName}`)
381
- .execute(trx);
382
- }
383
- return {
384
- response: appliedResponse,
385
- affectedTables,
386
- scopeKeys: scopeKeysFromEmitted(allEmitted),
387
- emittedChanges: allEmitted.map((c) => ({
388
- table: c.table,
389
- row_id: c.row_id,
390
- op: c.op,
391
- row_json: c.row_json,
392
- row_version: c.row_version,
393
- scopes: c.scopes,
394
- })),
395
- };
396
- }
397
- catch (err) {
398
- // Roll back app writes but keep the commit row.
399
- if (savepointCreated) {
400
- try {
401
- await sql
402
- .raw(`ROLLBACK TO SAVEPOINT ${savepointName}`)
403
- .execute(trx);
404
- await sql
405
- .raw(`RELEASE SAVEPOINT ${savepointName}`)
406
- .execute(trx);
407
- }
408
- catch (savepointErr) {
409
- // If savepoint rollback fails, the transaction may be in an
410
- // inconsistent state. Log and rethrow to fail the entire commit
411
- // rather than risk data corruption.
412
- console.error('[pushCommit] Savepoint rollback failed:', savepointErr);
413
- throw savepointErr;
414
- }
610
+ throw error;
611
+ }
612
+ });
613
+ }
614
+ export async function pushCommitBatch(args) {
615
+ const { db, dialect, handlers, requests } = args;
616
+ const pushPlugins = sortServerPushPlugins(args.plugins);
617
+ const startedAtMs = Date.now();
618
+ const suppressTelemetry = args.suppressTelemetry === true;
619
+ const totalOperationCount = requests.reduce((count, request) => {
620
+ const operations = Array.isArray(request.operations)
621
+ ? request.operations
622
+ : [];
623
+ return count + operations.length;
624
+ }, 0);
625
+ return startSyncSpan({
626
+ name: 'sync.server.push_batch',
627
+ op: 'sync.push.batch',
628
+ attributes: {
629
+ commit_count: requests.length,
630
+ operation_count: totalOperationCount,
631
+ },
632
+ }, async (span) => {
633
+ try {
634
+ const results = await dialect.executeInTransaction(db, async (trx) => {
635
+ const executed = [];
636
+ for (const request of requests) {
637
+ const validationError = validatePushRequest(request);
638
+ if (validationError) {
639
+ executed.push(createRejectedPushResult(validationError));
640
+ continue;
415
641
  }
416
- if (!(err instanceof RejectCommitError))
417
- throw err;
418
- const rejectedCommitUpdate = {
419
- result_json: toDialectJsonValue(dialect, err.response),
420
- change_count: 0,
421
- affected_tables: dialect.arrayToDb([]),
422
- };
423
- // Persist the rejected response for commit-level idempotency.
424
- await syncTrx
425
- .updateTable('sync_commits')
426
- .set(rejectedCommitUpdate)
427
- .where('commit_seq', '=', commitSeq)
428
- .execute();
429
- return {
430
- response: err.response,
431
- affectedTables: [],
432
- scopeKeys: [],
433
- emittedChanges: [],
434
- };
642
+ executed.push(await executePushCommitInExecutor({
643
+ trx,
644
+ dialect,
645
+ handlers,
646
+ pushPlugins,
647
+ auth: args.auth,
648
+ request,
649
+ validateCommit: args.validateCommit,
650
+ }));
435
651
  }
436
- }));
652
+ return executed;
653
+ });
654
+ const durationMs = Math.max(0, Date.now() - startedAtMs);
655
+ const emittedChangeCount = results.reduce((count, result) => count + result.emittedChanges.length, 0);
656
+ const affectedTableCount = results.reduce((count, result) => count + result.affectedTables.length, 0);
657
+ const status = results.every((result) => result.response.status === 'cached')
658
+ ? 'cached'
659
+ : results.every((result) => result.response.status === 'applied' ||
660
+ result.response.status === 'cached')
661
+ ? 'applied'
662
+ : 'rejected';
663
+ span.setAttribute('status', status);
664
+ span.setAttribute('duration_ms', durationMs);
665
+ span.setAttribute('commit_count', results.length);
666
+ span.setAttribute('emitted_change_count', emittedChangeCount);
667
+ span.setAttribute('affected_table_count', affectedTableCount);
668
+ span.setStatus('ok');
669
+ if (!suppressTelemetry) {
670
+ recordPushMetrics({
671
+ status,
672
+ durationMs,
673
+ operationCount: totalOperationCount,
674
+ emittedChangeCount,
675
+ affectedTableCount,
676
+ });
677
+ }
678
+ return results;
437
679
  }
438
680
  catch (error) {
439
681
  const durationMs = Math.max(0, Date.now() - startedAtMs);
440
682
  span.setAttribute('status', 'error');
441
683
  span.setAttribute('duration_ms', durationMs);
442
684
  span.setStatus('error');
443
- recordPushMetrics({
444
- status: 'error',
445
- durationMs,
446
- operationCount,
447
- emittedChangeCount: 0,
448
- affectedTableCount: 0,
449
- });
450
- captureSyncException(error, {
451
- event: 'sync.server.push',
452
- operationCount,
453
- });
685
+ if (!suppressTelemetry) {
686
+ recordPushMetrics({
687
+ status: 'error',
688
+ durationMs,
689
+ operationCount: totalOperationCount,
690
+ emittedChangeCount: 0,
691
+ affectedTableCount: 0,
692
+ });
693
+ captureSyncException(error, {
694
+ event: 'sync.server.push_batch',
695
+ commitCount: requests.length,
696
+ operationCount: totalOperationCount,
697
+ });
698
+ }
454
699
  throw error;
455
700
  }
456
701
  });