@livestore/common 0.4.0-dev.9 → 0.4.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 (513) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ClientSessionLeaderThreadProxy.d.ts +27 -12
  3. package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
  4. package/dist/ClientSessionLeaderThreadProxy.js.map +1 -1
  5. package/dist/WorkerTransportError.d.ts +11 -0
  6. package/dist/WorkerTransportError.d.ts.map +1 -0
  7. package/dist/WorkerTransportError.js +11 -0
  8. package/dist/WorkerTransportError.js.map +1 -0
  9. package/dist/adapter-types.d.ts +37 -7
  10. package/dist/adapter-types.d.ts.map +1 -1
  11. package/dist/adapter-types.js +27 -1
  12. package/dist/adapter-types.js.map +1 -1
  13. package/dist/bounded-collections.d.ts.map +1 -1
  14. package/dist/bounded-collections.js +6 -4
  15. package/dist/bounded-collections.js.map +1 -1
  16. package/dist/debug-info.d.ts.map +1 -1
  17. package/dist/debug-info.js +33 -6
  18. package/dist/debug-info.js.map +1 -1
  19. package/dist/devtools/devtools-compatibility.test.d.ts +2 -0
  20. package/dist/devtools/devtools-compatibility.test.d.ts.map +1 -0
  21. package/dist/devtools/devtools-compatibility.test.js +15 -0
  22. package/dist/devtools/devtools-compatibility.test.js.map +1 -0
  23. package/dist/devtools/devtools-messages-client-session.d.ts +55 -24
  24. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
  25. package/dist/devtools/devtools-messages-client-session.js +22 -5
  26. package/dist/devtools/devtools-messages-client-session.js.map +1 -1
  27. package/dist/devtools/devtools-messages-common.d.ts +11 -14
  28. package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
  29. package/dist/devtools/devtools-messages-common.js +7 -9
  30. package/dist/devtools/devtools-messages-common.js.map +1 -1
  31. package/dist/devtools/devtools-messages-leader.d.ts +65 -30
  32. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
  33. package/dist/devtools/devtools-messages-leader.js +29 -11
  34. package/dist/devtools/devtools-messages-leader.js.map +1 -1
  35. package/dist/devtools/devtools-sessioninfo.d.ts +14 -2
  36. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
  37. package/dist/devtools/devtools-sessioninfo.js +7 -4
  38. package/dist/devtools/devtools-sessioninfo.js.map +1 -1
  39. package/dist/devtools/mod.d.ts +13 -2
  40. package/dist/devtools/mod.d.ts.map +1 -1
  41. package/dist/devtools/mod.js +10 -3
  42. package/dist/devtools/mod.js.map +1 -1
  43. package/dist/errors.d.ts +48 -18
  44. package/dist/errors.d.ts.map +1 -1
  45. package/dist/errors.js +20 -12
  46. package/dist/errors.js.map +1 -1
  47. package/dist/index.d.ts +4 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +4 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/leader-thread/LeaderSyncProcessor.d.ts +53 -6
  52. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  53. package/dist/leader-thread/LeaderSyncProcessor.js +325 -257
  54. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  55. package/dist/leader-thread/RejectedPushError.d.ts +107 -0
  56. package/dist/leader-thread/RejectedPushError.d.ts.map +1 -0
  57. package/dist/leader-thread/RejectedPushError.js +78 -0
  58. package/dist/leader-thread/RejectedPushError.js.map +1 -0
  59. package/dist/leader-thread/connection.js +1 -1
  60. package/dist/leader-thread/connection.js.map +1 -1
  61. package/dist/leader-thread/eventlog.d.ts +19 -14
  62. package/dist/leader-thread/eventlog.d.ts.map +1 -1
  63. package/dist/leader-thread/eventlog.js +78 -18
  64. package/dist/leader-thread/eventlog.js.map +1 -1
  65. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -2
  66. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  67. package/dist/leader-thread/leader-worker-devtools.js +90 -58
  68. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  69. package/dist/leader-thread/make-leader-thread-layer.d.ts +15 -7
  70. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  71. package/dist/leader-thread/make-leader-thread-layer.js +49 -17
  72. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  73. package/dist/leader-thread/make-leader-thread-layer.test.d.ts +2 -0
  74. package/dist/leader-thread/make-leader-thread-layer.test.d.ts.map +1 -0
  75. package/dist/leader-thread/make-leader-thread-layer.test.js +32 -0
  76. package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -0
  77. package/dist/leader-thread/materialize-event.d.ts +1 -1
  78. package/dist/leader-thread/materialize-event.d.ts.map +1 -1
  79. package/dist/leader-thread/materialize-event.js +28 -9
  80. package/dist/leader-thread/materialize-event.js.map +1 -1
  81. package/dist/leader-thread/mod.d.ts +1 -0
  82. package/dist/leader-thread/mod.d.ts.map +1 -1
  83. package/dist/leader-thread/mod.js +1 -0
  84. package/dist/leader-thread/mod.js.map +1 -1
  85. package/dist/leader-thread/recreate-db.d.ts +2 -2
  86. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  87. package/dist/leader-thread/recreate-db.js +6 -6
  88. package/dist/leader-thread/recreate-db.js.map +1 -1
  89. package/dist/leader-thread/shutdown-channel.d.ts +2 -2
  90. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  91. package/dist/leader-thread/shutdown-channel.js +2 -2
  92. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  93. package/dist/leader-thread/stream-events.d.ts +56 -0
  94. package/dist/leader-thread/stream-events.d.ts.map +1 -0
  95. package/dist/leader-thread/stream-events.js +167 -0
  96. package/dist/leader-thread/stream-events.js.map +1 -0
  97. package/dist/leader-thread/types.d.ts +95 -17
  98. package/dist/leader-thread/types.d.ts.map +1 -1
  99. package/dist/leader-thread/types.js +13 -0
  100. package/dist/leader-thread/types.js.map +1 -1
  101. package/dist/logging.d.ts +40 -0
  102. package/dist/logging.d.ts.map +1 -0
  103. package/dist/logging.js +33 -0
  104. package/dist/logging.js.map +1 -0
  105. package/dist/make-client-session.d.ts +5 -3
  106. package/dist/make-client-session.d.ts.map +1 -1
  107. package/dist/make-client-session.js +7 -4
  108. package/dist/make-client-session.js.map +1 -1
  109. package/dist/materializer-helper.d.ts +6 -6
  110. package/dist/materializer-helper.d.ts.map +1 -1
  111. package/dist/materializer-helper.js +18 -8
  112. package/dist/materializer-helper.js.map +1 -1
  113. package/dist/otel.d.ts +2 -1
  114. package/dist/otel.d.ts.map +1 -1
  115. package/dist/otel.js +7 -2
  116. package/dist/otel.js.map +1 -1
  117. package/dist/rematerialize-from-eventlog.d.ts +3 -3
  118. package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
  119. package/dist/rematerialize-from-eventlog.js +40 -29
  120. package/dist/rematerialize-from-eventlog.js.map +1 -1
  121. package/dist/schema/EventDef/define.d.ts +161 -0
  122. package/dist/schema/EventDef/define.d.ts.map +1 -0
  123. package/dist/schema/EventDef/define.js +140 -0
  124. package/dist/schema/EventDef/define.js.map +1 -0
  125. package/dist/schema/EventDef/deprecated.d.ts +99 -0
  126. package/dist/schema/EventDef/deprecated.d.ts.map +1 -0
  127. package/dist/schema/EventDef/deprecated.js +144 -0
  128. package/dist/schema/EventDef/deprecated.js.map +1 -0
  129. package/dist/schema/EventDef/deprecated.test.d.ts +2 -0
  130. package/dist/schema/EventDef/deprecated.test.d.ts.map +1 -0
  131. package/dist/schema/EventDef/deprecated.test.js +95 -0
  132. package/dist/schema/EventDef/deprecated.test.js.map +1 -0
  133. package/dist/schema/EventDef/event-def.d.ts +110 -0
  134. package/dist/schema/EventDef/event-def.d.ts.map +1 -0
  135. package/dist/schema/EventDef/event-def.js +2 -0
  136. package/dist/schema/EventDef/event-def.js.map +1 -0
  137. package/dist/schema/EventDef/facts.d.ts +118 -0
  138. package/dist/schema/EventDef/facts.d.ts.map +1 -0
  139. package/dist/schema/EventDef/facts.js +53 -0
  140. package/dist/schema/EventDef/facts.js.map +1 -0
  141. package/dist/schema/EventDef/materializer.d.ts +155 -0
  142. package/dist/schema/EventDef/materializer.d.ts.map +1 -0
  143. package/dist/schema/EventDef/materializer.js +83 -0
  144. package/dist/schema/EventDef/materializer.js.map +1 -0
  145. package/dist/schema/EventDef/mod.d.ts +6 -0
  146. package/dist/schema/EventDef/mod.d.ts.map +1 -0
  147. package/dist/schema/EventDef/mod.js +6 -0
  148. package/dist/schema/EventDef/mod.js.map +1 -0
  149. package/dist/schema/EventSequenceNumber/client.d.ts +136 -0
  150. package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -0
  151. package/dist/schema/EventSequenceNumber/client.js +193 -0
  152. package/dist/schema/EventSequenceNumber/client.js.map +1 -0
  153. package/dist/schema/EventSequenceNumber/global.d.ts +15 -0
  154. package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -0
  155. package/dist/schema/EventSequenceNumber/global.js +14 -0
  156. package/dist/schema/EventSequenceNumber/global.js.map +1 -0
  157. package/dist/schema/EventSequenceNumber/mod.d.ts +37 -0
  158. package/dist/schema/EventSequenceNumber/mod.d.ts.map +1 -0
  159. package/dist/schema/EventSequenceNumber/mod.js +37 -0
  160. package/dist/schema/EventSequenceNumber/mod.js.map +1 -0
  161. package/dist/schema/EventSequenceNumber.test.js +44 -44
  162. package/dist/schema/EventSequenceNumber.test.js.map +1 -1
  163. package/dist/schema/{LiveStoreEvent.d.ts → LiveStoreEvent/client.d.ts} +102 -111
  164. package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -0
  165. package/dist/schema/LiveStoreEvent/client.js +176 -0
  166. package/dist/schema/LiveStoreEvent/client.js.map +1 -0
  167. package/dist/schema/LiveStoreEvent/client.test.d.ts +2 -0
  168. package/dist/schema/LiveStoreEvent/client.test.d.ts.map +1 -0
  169. package/dist/schema/LiveStoreEvent/client.test.js +111 -0
  170. package/dist/schema/LiveStoreEvent/client.test.js.map +1 -0
  171. package/dist/schema/LiveStoreEvent/for-event-def.d.ts +52 -0
  172. package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -0
  173. package/dist/schema/LiveStoreEvent/for-event-def.js +2 -0
  174. package/dist/schema/LiveStoreEvent/for-event-def.js.map +1 -0
  175. package/dist/schema/LiveStoreEvent/global.d.ts +36 -0
  176. package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -0
  177. package/dist/schema/LiveStoreEvent/global.js +31 -0
  178. package/dist/schema/LiveStoreEvent/global.js.map +1 -0
  179. package/dist/schema/LiveStoreEvent/input.d.ts +46 -0
  180. package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -0
  181. package/dist/schema/LiveStoreEvent/input.js +26 -0
  182. package/dist/schema/LiveStoreEvent/input.js.map +1 -0
  183. package/dist/schema/LiveStoreEvent/mod.d.ts +5 -0
  184. package/dist/schema/LiveStoreEvent/mod.d.ts.map +1 -0
  185. package/dist/schema/LiveStoreEvent/mod.js +5 -0
  186. package/dist/schema/LiveStoreEvent/mod.js.map +1 -0
  187. package/dist/schema/events.d.ts +1 -1
  188. package/dist/schema/events.d.ts.map +1 -1
  189. package/dist/schema/events.js +1 -1
  190. package/dist/schema/events.js.map +1 -1
  191. package/dist/schema/mod.d.ts +6 -4
  192. package/dist/schema/mod.d.ts.map +1 -1
  193. package/dist/schema/mod.js +5 -4
  194. package/dist/schema/mod.js.map +1 -1
  195. package/dist/schema/schema.d.ts +16 -1
  196. package/dist/schema/schema.d.ts.map +1 -1
  197. package/dist/schema/schema.js +32 -4
  198. package/dist/schema/schema.js.map +1 -1
  199. package/dist/schema/state/sqlite/client-document-def.d.ts +2 -1
  200. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  201. package/dist/schema/state/sqlite/client-document-def.js +36 -15
  202. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  203. package/dist/schema/state/sqlite/client-document-def.test.js +121 -2
  204. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
  205. package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
  206. package/dist/schema/state/sqlite/column-annotations.js +1 -1
  207. package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
  208. package/dist/schema/state/sqlite/column-annotations.test.js +2 -2
  209. package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
  210. package/dist/schema/state/sqlite/column-def.d.ts.map +1 -1
  211. package/dist/schema/state/sqlite/column-def.js +96 -47
  212. package/dist/schema/state/sqlite/column-def.js.map +1 -1
  213. package/dist/schema/state/sqlite/column-def.test.js +51 -12
  214. package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
  215. package/dist/schema/state/sqlite/column-spec.d.ts.map +1 -1
  216. package/dist/schema/state/sqlite/column-spec.js +30 -12
  217. package/dist/schema/state/sqlite/column-spec.js.map +1 -1
  218. package/dist/schema/state/sqlite/column-spec.test.js +24 -15
  219. package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
  220. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +2 -2
  221. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
  222. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +16 -10
  223. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
  224. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +15 -4
  225. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
  226. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +1 -1
  227. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -1
  228. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +1 -1
  229. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
  230. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +1 -1
  231. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
  232. package/dist/schema/state/sqlite/mod.d.ts +2 -2
  233. package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
  234. package/dist/schema/state/sqlite/mod.js +5 -7
  235. package/dist/schema/state/sqlite/mod.js.map +1 -1
  236. package/dist/schema/state/sqlite/query-builder/api.d.ts +51 -22
  237. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
  238. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
  239. package/dist/schema/state/sqlite/query-builder/astToSql.js +99 -22
  240. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
  241. package/dist/schema/state/sqlite/query-builder/impl.d.ts +1 -1
  242. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
  243. package/dist/schema/state/sqlite/query-builder/impl.js +28 -15
  244. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
  245. package/dist/schema/state/sqlite/query-builder/impl.test.js +231 -93
  246. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  247. package/dist/schema/state/sqlite/schema-helpers.d.ts +2 -2
  248. package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -1
  249. package/dist/schema/state/sqlite/schema-helpers.js +24 -14
  250. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
  251. package/dist/schema/state/sqlite/schema-helpers.test.d.ts +2 -0
  252. package/dist/schema/state/sqlite/schema-helpers.test.d.ts.map +1 -0
  253. package/dist/schema/state/sqlite/schema-helpers.test.js +36 -0
  254. package/dist/schema/state/sqlite/schema-helpers.test.js.map +1 -0
  255. package/dist/schema/state/sqlite/{system-tables.d.ts → system-tables/eventlog-tables.d.ts} +21 -450
  256. package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts.map +1 -0
  257. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +54 -0
  258. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -0
  259. package/dist/schema/state/sqlite/system-tables/mod.d.ts +3 -0
  260. package/dist/schema/state/sqlite/system-tables/mod.d.ts.map +1 -0
  261. package/dist/schema/state/sqlite/system-tables/mod.js +3 -0
  262. package/dist/schema/state/sqlite/system-tables/mod.js.map +1 -0
  263. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +456 -0
  264. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -0
  265. package/dist/schema/state/sqlite/system-tables/state-tables.js +55 -0
  266. package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -0
  267. package/dist/schema/state/sqlite/table-def.d.ts +5 -3
  268. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  269. package/dist/schema/state/sqlite/table-def.js +1 -1
  270. package/dist/schema/state/sqlite/table-def.js.map +1 -1
  271. package/dist/schema/state/sqlite/table-def.test.js +92 -3
  272. package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
  273. package/dist/schema/unknown-events.d.ts +47 -0
  274. package/dist/schema/unknown-events.d.ts.map +1 -0
  275. package/dist/schema/unknown-events.js +69 -0
  276. package/dist/schema/unknown-events.js.map +1 -0
  277. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts +2 -0
  278. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts.map +1 -0
  279. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +73 -0
  280. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -0
  281. package/dist/schema-management/common.js +2 -2
  282. package/dist/schema-management/common.js.map +1 -1
  283. package/dist/schema-management/migrations.d.ts +32 -2
  284. package/dist/schema-management/migrations.d.ts.map +1 -1
  285. package/dist/schema-management/migrations.js +38 -6
  286. package/dist/schema-management/migrations.js.map +1 -1
  287. package/dist/schema-management/validate-schema.d.ts +3 -3
  288. package/dist/schema-management/validate-schema.d.ts.map +1 -1
  289. package/dist/schema-management/validate-schema.js +2 -2
  290. package/dist/schema-management/validate-schema.js.map +1 -1
  291. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  292. package/dist/sql-queries/sql-queries.js +18 -6
  293. package/dist/sql-queries/sql-queries.js.map +1 -1
  294. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  295. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  296. package/dist/sqlite-db-helper.js +3 -3
  297. package/dist/sqlite-db-helper.js.map +1 -1
  298. package/dist/sqlite-types.d.ts +5 -5
  299. package/dist/sqlite-types.d.ts.map +1 -1
  300. package/dist/sqlite-types.js.map +1 -1
  301. package/dist/sync/ClientSessionSyncProcessor.d.ts +12 -12
  302. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  303. package/dist/sync/ClientSessionSyncProcessor.js +99 -114
  304. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  305. package/dist/sync/errors.d.ts +0 -33
  306. package/dist/sync/errors.d.ts.map +1 -1
  307. package/dist/sync/errors.js +5 -22
  308. package/dist/sync/errors.js.map +1 -1
  309. package/dist/sync/index.d.ts +2 -0
  310. package/dist/sync/index.d.ts.map +1 -1
  311. package/dist/sync/index.js +2 -0
  312. package/dist/sync/index.js.map +1 -1
  313. package/dist/sync/mock-sync-backend.d.ts +10 -8
  314. package/dist/sync/mock-sync-backend.d.ts.map +1 -1
  315. package/dist/sync/mock-sync-backend.js +71 -69
  316. package/dist/sync/mock-sync-backend.js.map +1 -1
  317. package/dist/sync/next/compact-events.d.ts.map +1 -1
  318. package/dist/sync/next/compact-events.js +11 -12
  319. package/dist/sync/next/compact-events.js.map +1 -1
  320. package/dist/sync/next/facts.d.ts +5 -5
  321. package/dist/sync/next/facts.d.ts.map +1 -1
  322. package/dist/sync/next/facts.js +7 -8
  323. package/dist/sync/next/facts.js.map +1 -1
  324. package/dist/sync/next/history-dag-common.d.ts +54 -15
  325. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  326. package/dist/sync/next/history-dag-common.js +198 -9
  327. package/dist/sync/next/history-dag-common.js.map +1 -1
  328. package/dist/sync/next/history-dag.d.ts.map +1 -1
  329. package/dist/sync/next/history-dag.js +11 -11
  330. package/dist/sync/next/history-dag.js.map +1 -1
  331. package/dist/sync/next/rebase-events.d.ts +5 -5
  332. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  333. package/dist/sync/next/rebase-events.js +6 -6
  334. package/dist/sync/next/rebase-events.js.map +1 -1
  335. package/dist/sync/next/test/compact-events.calculator.test.js +2 -2
  336. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  337. package/dist/sync/next/test/compact-events.test.d.ts.map +1 -1
  338. package/dist/sync/next/test/compact-events.test.js +2 -2
  339. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  340. package/dist/sync/next/test/event-fixtures.d.ts +2 -2
  341. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
  342. package/dist/sync/next/test/event-fixtures.js +11 -11
  343. package/dist/sync/next/test/event-fixtures.js.map +1 -1
  344. package/dist/sync/sync-backend-kv.d.ts +3 -3
  345. package/dist/sync/sync-backend-kv.d.ts.map +1 -1
  346. package/dist/sync/sync-backend-kv.js +3 -3
  347. package/dist/sync/sync-backend-kv.js.map +1 -1
  348. package/dist/sync/sync-backend.d.ts +33 -13
  349. package/dist/sync/sync-backend.d.ts.map +1 -1
  350. package/dist/sync/sync-backend.js +38 -1
  351. package/dist/sync/sync-backend.js.map +1 -1
  352. package/dist/sync/sync.d.ts +23 -2
  353. package/dist/sync/sync.d.ts.map +1 -1
  354. package/dist/sync/syncstate.d.ts +55 -55
  355. package/dist/sync/syncstate.d.ts.map +1 -1
  356. package/dist/sync/syncstate.js +80 -98
  357. package/dist/sync/syncstate.js.map +1 -1
  358. package/dist/sync/syncstate.test.js +221 -132
  359. package/dist/sync/syncstate.test.js.map +1 -1
  360. package/dist/sync/transport-chunking.d.ts +36 -0
  361. package/dist/sync/transport-chunking.d.ts.map +1 -0
  362. package/dist/sync/transport-chunking.js +56 -0
  363. package/dist/sync/transport-chunking.js.map +1 -0
  364. package/dist/sync/validate-push-payload.d.ts +2 -2
  365. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  366. package/dist/sync/validate-push-payload.js +4 -6
  367. package/dist/sync/validate-push-payload.js.map +1 -1
  368. package/dist/testing/event-factory.d.ts +3 -3
  369. package/dist/testing/event-factory.d.ts.map +1 -1
  370. package/dist/testing/event-factory.js +5 -7
  371. package/dist/testing/event-factory.js.map +1 -1
  372. package/dist/util.js +2 -2
  373. package/dist/util.js.map +1 -1
  374. package/dist/version.d.ts +24 -5
  375. package/dist/version.d.ts.map +1 -1
  376. package/dist/version.js +25 -8
  377. package/dist/version.js.map +1 -1
  378. package/package.json +67 -15
  379. package/src/ClientSessionLeaderThreadProxy.ts +27 -12
  380. package/src/WorkerTransportError.ts +12 -0
  381. package/src/adapter-types.ts +50 -7
  382. package/src/bounded-collections.ts +6 -5
  383. package/src/debug-info.ts +37 -6
  384. package/src/devtools/devtools-compatibility.test.ts +18 -0
  385. package/src/devtools/devtools-messages-client-session.ts +22 -4
  386. package/src/devtools/devtools-messages-common.ts +7 -12
  387. package/src/devtools/devtools-messages-leader.ts +29 -10
  388. package/src/devtools/devtools-sessioninfo.ts +8 -5
  389. package/src/devtools/mod.ts +11 -2
  390. package/src/errors.ts +32 -24
  391. package/src/index.ts +4 -1
  392. package/src/leader-thread/LeaderSyncProcessor.ts +523 -373
  393. package/src/leader-thread/RejectedPushError.ts +106 -0
  394. package/src/leader-thread/connection.ts +1 -1
  395. package/src/leader-thread/eventlog.ts +112 -39
  396. package/src/leader-thread/leader-worker-devtools.ts +201 -120
  397. package/src/leader-thread/make-leader-thread-layer.test.ts +44 -0
  398. package/src/leader-thread/make-leader-thread-layer.ts +125 -40
  399. package/src/leader-thread/materialize-event.ts +40 -10
  400. package/src/leader-thread/mod.ts +1 -0
  401. package/src/leader-thread/recreate-db.ts +7 -7
  402. package/src/leader-thread/shutdown-channel.ts +4 -8
  403. package/src/leader-thread/stream-events.ts +206 -0
  404. package/src/leader-thread/types.ts +68 -18
  405. package/src/logging.ts +62 -0
  406. package/src/make-client-session.ts +11 -5
  407. package/src/materializer-helper.ts +27 -16
  408. package/src/otel.ts +13 -2
  409. package/src/rematerialize-from-eventlog.ts +61 -51
  410. package/src/schema/EventDef/define.ts +217 -0
  411. package/src/schema/EventDef/deprecated.test.ts +129 -0
  412. package/src/schema/EventDef/deprecated.ts +175 -0
  413. package/src/schema/EventDef/event-def.ts +125 -0
  414. package/src/schema/EventDef/facts.ts +135 -0
  415. package/src/schema/EventDef/materializer.ts +172 -0
  416. package/src/schema/EventDef/mod.ts +5 -0
  417. package/src/schema/EventSequenceNumber/client.ts +257 -0
  418. package/src/schema/EventSequenceNumber/global.ts +19 -0
  419. package/src/schema/EventSequenceNumber/mod.ts +37 -0
  420. package/src/schema/EventSequenceNumber.test.ts +72 -53
  421. package/src/schema/LiveStoreEvent/client.test.ts +129 -0
  422. package/src/schema/LiveStoreEvent/client.ts +235 -0
  423. package/src/schema/LiveStoreEvent/for-event-def.ts +60 -0
  424. package/src/schema/LiveStoreEvent/global.ts +45 -0
  425. package/src/schema/LiveStoreEvent/input.ts +63 -0
  426. package/src/schema/LiveStoreEvent/mod.ts +4 -0
  427. package/src/schema/events.ts +1 -1
  428. package/src/schema/mod.ts +6 -4
  429. package/src/schema/schema.ts +46 -5
  430. package/src/schema/state/sqlite/client-document-def.test.ts +144 -5
  431. package/src/schema/state/sqlite/client-document-def.ts +47 -34
  432. package/src/schema/state/sqlite/column-annotations.test.ts +3 -2
  433. package/src/schema/state/sqlite/column-annotations.ts +2 -1
  434. package/src/schema/state/sqlite/column-def.test.ts +66 -12
  435. package/src/schema/state/sqlite/column-def.ts +119 -47
  436. package/src/schema/state/sqlite/column-spec.test.ts +32 -17
  437. package/src/schema/state/sqlite/column-spec.ts +37 -11
  438. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +2 -2
  439. package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +2 -1
  440. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +41 -15
  441. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +13 -19
  442. package/src/schema/state/sqlite/mod.ts +7 -8
  443. package/src/schema/state/sqlite/query-builder/api.ts +55 -17
  444. package/src/schema/state/sqlite/query-builder/astToSql.ts +110 -21
  445. package/src/schema/state/sqlite/query-builder/impl.test.ts +267 -93
  446. package/src/schema/state/sqlite/query-builder/impl.ts +26 -13
  447. package/src/schema/state/sqlite/schema-helpers.test.ts +44 -0
  448. package/src/schema/state/sqlite/schema-helpers.ts +30 -22
  449. package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +64 -0
  450. package/src/schema/state/sqlite/system-tables/mod.ts +2 -0
  451. package/src/schema/state/sqlite/system-tables/state-tables.ts +69 -0
  452. package/src/schema/state/sqlite/table-def.test.ts +114 -3
  453. package/src/schema/state/sqlite/table-def.ts +16 -22
  454. package/src/schema/unknown-events.ts +131 -0
  455. package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +88 -0
  456. package/src/schema-management/common.ts +2 -2
  457. package/src/schema-management/migrations.ts +42 -9
  458. package/src/schema-management/validate-schema.ts +3 -3
  459. package/src/sql-queries/sql-queries.ts +18 -6
  460. package/src/sql-queries/sql-query-builder.ts +1 -0
  461. package/src/sqlite-db-helper.ts +3 -3
  462. package/src/sqlite-types.ts +6 -5
  463. package/src/sync/ClientSessionSyncProcessor.ts +152 -142
  464. package/src/sync/errors.ts +12 -24
  465. package/src/sync/index.ts +2 -0
  466. package/src/sync/mock-sync-backend.ts +146 -104
  467. package/src/sync/next/compact-events.ts +10 -11
  468. package/src/sync/next/facts.ts +13 -14
  469. package/src/sync/next/history-dag-common.ts +280 -26
  470. package/src/sync/next/history-dag.ts +17 -13
  471. package/src/sync/next/rebase-events.ts +12 -12
  472. package/src/sync/next/test/compact-events.calculator.test.ts +3 -2
  473. package/src/sync/next/test/compact-events.test.ts +4 -3
  474. package/src/sync/next/test/event-fixtures.ts +13 -13
  475. package/src/sync/sync-backend-kv.ts +4 -3
  476. package/src/sync/sync-backend.ts +66 -17
  477. package/src/sync/sync.ts +24 -2
  478. package/src/sync/syncstate.test.ts +583 -419
  479. package/src/sync/syncstate.ts +127 -122
  480. package/src/sync/transport-chunking.ts +90 -0
  481. package/src/sync/validate-push-payload.ts +6 -8
  482. package/src/testing/event-factory.ts +10 -12
  483. package/src/util.ts +2 -2
  484. package/src/version.ts +33 -8
  485. package/dist/schema/EventDef.d.ts +0 -126
  486. package/dist/schema/EventDef.d.ts.map +0 -1
  487. package/dist/schema/EventDef.js +0 -46
  488. package/dist/schema/EventDef.js.map +0 -1
  489. package/dist/schema/EventSequenceNumber.d.ts +0 -80
  490. package/dist/schema/EventSequenceNumber.d.ts.map +0 -1
  491. package/dist/schema/EventSequenceNumber.js +0 -139
  492. package/dist/schema/EventSequenceNumber.js.map +0 -1
  493. package/dist/schema/LiveStoreEvent.d.ts.map +0 -1
  494. package/dist/schema/LiveStoreEvent.js +0 -147
  495. package/dist/schema/LiveStoreEvent.js.map +0 -1
  496. package/dist/schema/state/sqlite/system-tables.d.ts.map +0 -1
  497. package/dist/schema/state/sqlite/system-tables.js +0 -81
  498. package/dist/schema/state/sqlite/system-tables.js.map +0 -1
  499. package/dist/sync/next/graphology.d.ts +0 -8
  500. package/dist/sync/next/graphology.d.ts.map +0 -1
  501. package/dist/sync/next/graphology.js +0 -30
  502. package/dist/sync/next/graphology.js.map +0 -1
  503. package/dist/sync/next/graphology_.d.ts +0 -3
  504. package/dist/sync/next/graphology_.d.ts.map +0 -1
  505. package/dist/sync/next/graphology_.js +0 -3
  506. package/dist/sync/next/graphology_.js.map +0 -1
  507. package/src/schema/EventDef.ts +0 -222
  508. package/src/schema/EventSequenceNumber.ts +0 -199
  509. package/src/schema/LiveStoreEvent.ts +0 -286
  510. package/src/schema/state/sqlite/system-tables.ts +0 -106
  511. package/src/sync/next/ambient.d.ts +0 -3
  512. package/src/sync/next/graphology.ts +0 -41
  513. package/src/sync/next/graphology_.ts +0 -2
@@ -1,31 +1,35 @@
1
- import { describe, expect, it } from 'vitest'
1
+ import { Vitest } from '@livestore/utils-dev/node-vitest'
2
+ import { Cause, Effect, Exit, Schema } from '@livestore/utils/effect'
3
+ import { assert, expect } from 'vitest'
2
4
 
3
- import * as EventSequenceNumber from '../schema/EventSequenceNumber.ts'
4
- import * as LiveStoreEvent from '../schema/LiveStoreEvent.ts'
5
+ import * as EventSequenceNumber from '../schema/EventSequenceNumber/mod.ts'
6
+ import * as LiveStoreEvent from '../schema/LiveStoreEvent/mod.ts'
5
7
  import * as SyncState from './syncstate.ts'
6
8
 
7
- class TestEvent extends LiveStoreEvent.EncodedWithMeta {
8
- public readonly payload: string
9
- public readonly isClient: boolean
10
- constructor(
11
- seqNum: EventSequenceNumber.EventSequenceNumberInput,
12
- parentSeqNum: EventSequenceNumber.EventSequenceNumberInput,
9
+ class TestEvent extends LiveStoreEvent.Client.EncodedWithMeta {
10
+ public payload = 'uninitialized'
11
+ public isClient = false
12
+
13
+ static new = (
14
+ seqNum: EventSequenceNumber.Client.CompositeInput,
15
+ parentSeqNum: EventSequenceNumber.Client.CompositeInput,
13
16
  payload: string,
14
17
  isClient: boolean,
15
- ) {
16
- super({
17
- seqNum: EventSequenceNumber.make(seqNum),
18
- parentSeqNum: EventSequenceNumber.make(parentSeqNum),
18
+ ) => {
19
+ const event = new TestEvent({
20
+ seqNum: EventSequenceNumber.Client.Composite.make(seqNum),
21
+ parentSeqNum: EventSequenceNumber.Client.Composite.make(parentSeqNum),
19
22
  name: 'a',
20
23
  args: payload,
21
24
  clientId: 'static-local-id',
22
25
  sessionId: 'static-session-id',
23
26
  })
24
- this.payload = payload
25
- this.isClient = isClient
27
+ event.payload = payload
28
+ event.isClient = isClient
29
+ return event
26
30
  }
27
31
 
28
- rebase_ = (parentSeqNum: EventSequenceNumber.EventSequenceNumber, rebaseGeneration: number) => {
32
+ rebase_ = (parentSeqNum: EventSequenceNumber.Client.Composite, rebaseGeneration: number) => {
29
33
  return this.rebase({ parentSeqNum, isClient: this.isClient, rebaseGeneration })
30
34
  }
31
35
 
@@ -34,20 +38,20 @@ class TestEvent extends LiveStoreEvent.EncodedWithMeta {
34
38
  // toString = () => this.toJSON()
35
39
  }
36
40
 
37
- const e0_1 = new TestEvent({ global: 0, client: 1 }, EventSequenceNumber.ROOT, 'a', true)
38
- const e1_0 = new TestEvent({ global: 1, client: 0 }, EventSequenceNumber.ROOT, 'a', false)
39
- const e1_1 = new TestEvent({ global: 1, client: 1 }, e1_0.seqNum, 'a', true)
40
- const e1_2 = new TestEvent({ global: 1, client: 2 }, e1_1.seqNum, 'a', true)
41
- const e1_3 = new TestEvent({ global: 1, client: 3 }, e1_2.seqNum, 'a', true)
42
- const e2_0 = new TestEvent({ global: 2, client: 0 }, e1_0.seqNum, 'a', false)
43
- const e2_1 = new TestEvent({ global: 2, client: 1 }, e2_0.seqNum, 'a', true)
41
+ const e0_1 = TestEvent.new({ global: 0, client: 1 }, EventSequenceNumber.Client.ROOT, 'a', true)
42
+ const e1_0 = TestEvent.new({ global: 1, client: 0 }, EventSequenceNumber.Client.ROOT, 'a', false)
43
+ const e1_1 = TestEvent.new({ global: 1, client: 1 }, e1_0.seqNum, 'a', true)
44
+ const e1_2 = TestEvent.new({ global: 1, client: 2 }, e1_1.seqNum, 'a', true)
45
+ const e1_3 = TestEvent.new({ global: 1, client: 3 }, e1_2.seqNum, 'a', true)
46
+ const e2_0 = TestEvent.new({ global: 2, client: 0 }, e1_0.seqNum, 'a', false)
47
+ const e2_1 = TestEvent.new({ global: 2, client: 1 }, e2_0.seqNum, 'a', true)
44
48
 
45
- const isEqualEvent = LiveStoreEvent.isEqualEncoded
49
+ const isEqualEvent = LiveStoreEvent.Client.isEqualEncoded
46
50
 
47
- const isClientEvent = (event: LiveStoreEvent.EncodedWithMeta) => (event as TestEvent).isClient
51
+ const isClientEvent = (event: LiveStoreEvent.Client.EncodedWithMeta) => (event as TestEvent).isClient
48
52
 
49
- describe('syncstate', () => {
50
- describe('merge', () => {
53
+ Vitest.describe('syncstate', () => {
54
+ Vitest.describe('merge', () => {
51
55
  const merge = ({
52
56
  syncState,
53
57
  payload,
@@ -58,404 +62,564 @@ describe('syncstate', () => {
58
62
  ignoreClientEvents?: boolean
59
63
  }) => SyncState.merge({ syncState, payload, isClientEvent, isEqualEvent, ignoreClientEvents })
60
64
 
61
- describe('upstream-rebase', () => {
62
- it('should rollback until start', () => {
63
- const syncState = new SyncState.SyncState({
64
- pending: [e2_0],
65
- upstreamHead: EventSequenceNumber.ROOT,
66
- localHead: e2_0.seqNum,
67
- })
68
- const e1_0_e2_0 = e1_0.rebase_(e2_0.seqNum, 0)
69
- const e1_1_e2_1 = e1_1.rebase_(e1_0_e2_0.seqNum, 0)
70
- const result = merge({
71
- syncState,
72
- payload: SyncState.PayloadUpstreamRebase.make({
73
- rollbackEvents: [e1_0, e1_1],
74
- newEvents: [e1_0_e2_0, e1_1_e2_1],
75
- }),
76
- })
77
- const e2_0_e3_0 = e2_0.rebase_(e1_0_e2_0.seqNum, 1)
78
- expectRebase(result)
79
- expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
80
- expect(result.newSyncState.upstreamHead).toMatchObject(e1_1_e2_1.seqNum)
81
- expect(result.newSyncState.localHead).toMatchObject(e2_0_e3_0.seqNum)
82
- expectEventArraysEqual(result.newEvents, [e1_0_e2_0, e1_1_e2_1, e2_0_e3_0])
83
- expectEventArraysEqual(result.rollbackEvents, [e1_0, e1_1, e2_0])
84
- })
85
-
86
- it('should rollback only to specified point', () => {
87
- const syncState = new SyncState.SyncState({
88
- pending: [e2_0],
89
- upstreamHead: EventSequenceNumber.ROOT,
90
- localHead: e2_0.seqNum,
91
- })
92
- const e1_1_e2_0 = e1_1.rebase_(e1_0.seqNum, 0)
93
- const result = merge({
94
- syncState,
95
- payload: SyncState.PayloadUpstreamRebase.make({
96
- newEvents: [e1_1_e2_0],
97
- rollbackEvents: [e1_1],
98
- }),
99
- })
100
- const e2_0_e3_0 = e2_0.rebase_(e1_1_e2_0.seqNum, 1)
101
- expectRebase(result)
102
- expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
103
- expect(result.newSyncState.upstreamHead).toMatchObject(e1_1_e2_0.seqNum)
104
- expect(result.newSyncState.localHead).toMatchObject(e2_0_e3_0.seqNum)
105
- expectEventArraysEqual(result.newEvents, [e1_1_e2_0, e2_0_e3_0])
106
- expectEventArraysEqual(result.rollbackEvents, [e1_1, e2_0])
107
- })
108
-
109
- it('should work for empty pending', () => {
110
- const syncState = new SyncState.SyncState({
111
- pending: [],
112
- upstreamHead: EventSequenceNumber.ROOT,
113
- localHead: e1_0.seqNum,
114
- })
115
- const result = merge({
116
- syncState,
117
- payload: SyncState.PayloadUpstreamRebase.make({ rollbackEvents: [e1_0], newEvents: [e2_0] }),
118
- })
119
- expectRebase(result)
120
- expectEventArraysEqual(result.newSyncState.pending, [])
121
- expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
122
- expect(result.newSyncState.localHead).toMatchObject(e2_0.seqNum)
123
- expect(result.newEvents).toStrictEqual([e2_0])
124
- })
65
+ Vitest.describe('upstream-rebase', () => {
66
+ Vitest.it.effect('should rollback until start', () =>
67
+ Effect.gen(function* () {
68
+ const syncState = new SyncState.SyncState({
69
+ pending: [e2_0],
70
+ upstreamHead: EventSequenceNumber.Client.ROOT,
71
+ localHead: e2_0.seqNum,
72
+ })
73
+ const e1_0_e2_0 = e1_0.rebase_(e2_0.seqNum, 0)
74
+ const e1_1_e2_1 = e1_1.rebase_(e1_0_e2_0.seqNum, 0)
75
+ const result = yield* merge({
76
+ syncState,
77
+ payload: SyncState.PayloadUpstreamRebase.make({
78
+ rollbackEvents: [e1_0, e1_1],
79
+ newEvents: [e1_0_e2_0, e1_1_e2_1],
80
+ }),
81
+ })
82
+ const e2_0_e3_0 = e2_0.rebase_(e1_0_e2_0.seqNum, 1)
83
+ expectRebase(result)
84
+ expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
85
+ expect(result.newSyncState.upstreamHead).toMatchObject(e1_1_e2_1.seqNum)
86
+ expect(result.newSyncState.localHead).toMatchObject(e2_0_e3_0.seqNum)
87
+ expectEventArraysEqual(result.newEvents, [e1_0_e2_0, e1_1_e2_1, e2_0_e3_0])
88
+ expectEventArraysEqual(result.rollbackEvents, [e1_0, e1_1, e2_0])
89
+ }),
90
+ )
91
+
92
+ Vitest.it.effect('should rollback only to specified point', () =>
93
+ Effect.gen(function* () {
94
+ const syncState = new SyncState.SyncState({
95
+ pending: [e2_0],
96
+ upstreamHead: EventSequenceNumber.Client.ROOT,
97
+ localHead: e2_0.seqNum,
98
+ })
99
+ const e1_1_e2_0 = e1_1.rebase_(e1_0.seqNum, 0)
100
+ const result = yield* merge({
101
+ syncState,
102
+ payload: SyncState.PayloadUpstreamRebase.make({
103
+ newEvents: [e1_1_e2_0],
104
+ rollbackEvents: [e1_1],
105
+ }),
106
+ })
107
+ const e2_0_e3_0 = e2_0.rebase_(e1_1_e2_0.seqNum, 1)
108
+ expectRebase(result)
109
+ expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
110
+ expect(result.newSyncState.upstreamHead).toMatchObject(e1_1_e2_0.seqNum)
111
+ expect(result.newSyncState.localHead).toMatchObject(e2_0_e3_0.seqNum)
112
+ expectEventArraysEqual(result.newEvents, [e1_1_e2_0, e2_0_e3_0])
113
+ expectEventArraysEqual(result.rollbackEvents, [e1_1, e2_0])
114
+ }),
115
+ )
116
+
117
+ Vitest.it.effect('should work for empty pending', () =>
118
+ Effect.gen(function* () {
119
+ const syncState = new SyncState.SyncState({
120
+ pending: [],
121
+ upstreamHead: EventSequenceNumber.Client.ROOT,
122
+ localHead: e1_0.seqNum,
123
+ })
124
+ const result = yield* merge({
125
+ syncState,
126
+ payload: SyncState.PayloadUpstreamRebase.make({ rollbackEvents: [e1_0], newEvents: [e2_0] }),
127
+ })
128
+ expectRebase(result)
129
+ expectEventArraysEqual(result.newSyncState.pending, [])
130
+ expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
131
+ expect(result.newSyncState.localHead).toMatchObject(e2_0.seqNum)
132
+ expect(result.newEvents).toStrictEqual([e2_0])
133
+ }),
134
+ )
125
135
  })
126
136
 
127
- describe('upstream-advance: advance', () => {
128
- it('should throw error if newEvents are not sorted in ascending order by event number (client)', () => {
129
- const syncState = new SyncState.SyncState({
130
- pending: [e1_0],
131
- upstreamHead: EventSequenceNumber.ROOT,
132
- localHead: e1_0.seqNum,
133
- })
134
- const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_1, e1_0] } })
135
- expect(result).toMatchObject({ _tag: 'unexpected-error' })
136
- })
137
-
138
- it('should throw error if newEvents are not sorted in ascending order by event number (global)', () => {
139
- const syncState = new SyncState.SyncState({
140
- pending: [e1_0],
141
- upstreamHead: EventSequenceNumber.ROOT,
142
- localHead: e1_0.seqNum,
143
- })
144
- const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e2_0, e1_0] } })
145
- expect(result).toMatchObject({ _tag: 'unexpected-error' })
146
- })
147
-
148
- it('should throw error if incoming event is < expected upstream head', () => {
149
- const syncState = new SyncState.SyncState({
150
- pending: [],
151
- upstreamHead: e2_0.seqNum,
152
- localHead: e2_0.seqNum,
153
- })
154
- const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
155
- expect(result).toMatchObject({ _tag: 'unexpected-error' })
156
- })
157
-
158
- it('should throw error if incoming event is = expected upstream head', () => {
159
- const syncState = new SyncState.SyncState({
160
- pending: [],
161
- upstreamHead: e2_0.seqNum,
162
- localHead: e2_0.seqNum,
163
- })
164
- const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e2_0] } })
165
- expect(result).toMatchObject({ _tag: 'unexpected-error' })
166
- })
167
-
168
- it('should confirm pending event when receiving matching event', () => {
169
- const syncState = new SyncState.SyncState({
170
- pending: [e1_0],
171
- upstreamHead: EventSequenceNumber.ROOT,
172
- localHead: e1_0.seqNum,
173
- })
174
- const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
175
-
176
- expectAdvance(result)
177
- expectEventArraysEqual(result.newSyncState.pending, [])
178
- expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.seqNum)
179
- expect(result.newSyncState.localHead).toMatchObject(e1_0.seqNum)
180
- expectEventArraysEqual(result.newEvents, [])
181
- expectEventArraysEqual(result.confirmedEvents, [e1_0])
182
- })
183
-
184
- it('should confirm partial pending event when receiving matching event', () => {
185
- const syncState = new SyncState.SyncState({
186
- pending: [e1_0, e2_0],
187
- upstreamHead: EventSequenceNumber.ROOT,
188
- localHead: e2_0.seqNum,
189
- })
190
- const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
191
-
192
- expectAdvance(result)
193
- expectEventArraysEqual(result.newSyncState.pending, [e2_0])
194
- expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.seqNum)
195
- expect(result.newSyncState.localHead).toMatchObject(e2_0.seqNum)
196
- expectEventArraysEqual(result.newEvents, [])
197
- expectEventArraysEqual(result.confirmedEvents, [e1_0])
198
- })
199
-
200
- it('should confirm pending event and add new event', () => {
201
- const syncState = new SyncState.SyncState({
202
- pending: [e1_0],
203
- upstreamHead: EventSequenceNumber.ROOT,
204
- localHead: e1_0.seqNum,
205
- })
206
- const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0, e1_1] } })
207
-
208
- expectAdvance(result)
209
- expectEventArraysEqual(result.newSyncState.pending, [])
210
- expect(result.newSyncState.upstreamHead).toMatchObject(e1_1.seqNum)
211
- expect(result.newSyncState.localHead).toMatchObject(e1_1.seqNum)
212
- expect(result.newEvents).toStrictEqual([e1_1])
213
- expectEventArraysEqual(result.confirmedEvents, [e1_0])
214
- })
215
-
216
- it('should confirm pending event and add multiple new events', () => {
217
- const syncState = new SyncState.SyncState({
218
- pending: [e1_1],
219
- upstreamHead: e1_0.seqNum,
220
- localHead: e1_1.seqNum,
221
- })
222
- const result = merge({
223
- syncState,
224
- payload: { _tag: 'upstream-advance', newEvents: [e1_1, e1_2, e1_3, e2_0, e2_1] },
225
- })
226
-
227
- expectAdvance(result)
228
- expectEventArraysEqual(result.newSyncState.pending, [])
229
- expect(result.newSyncState.upstreamHead).toMatchObject(e2_1.seqNum)
230
- expect(result.newSyncState.localHead).toMatchObject(e2_1.seqNum)
231
- expect(result.newEvents).toStrictEqual([e1_2, e1_3, e2_0, e2_1])
232
- expectEventArraysEqual(result.confirmedEvents, [e1_1])
233
- })
234
-
235
- it('should confirm pending global event while keep pending client events', () => {
236
- const syncState = new SyncState.SyncState({
237
- pending: [e1_0, e1_1],
238
- upstreamHead: EventSequenceNumber.ROOT,
239
- localHead: e1_1.seqNum,
240
- })
241
- const result = merge({
242
- syncState,
243
- payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
244
- })
137
+ Vitest.describe('upstream-advance: advance', () => {
138
+ Vitest.it.effect('should die if newEvents are not sorted in ascending order by event number (client)', () =>
139
+ Effect.gen(function* () {
140
+ const syncState = new SyncState.SyncState({
141
+ pending: [e1_0],
142
+ upstreamHead: EventSequenceNumber.Client.ROOT,
143
+ localHead: e1_0.seqNum,
144
+ })
145
+ const exit = yield* merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_1, e1_0] } }).pipe(
146
+ Effect.exit,
147
+ )
148
+ assert(Exit.isFailure(exit))
149
+ expect(Cause.isDie(exit.cause)).toBe(true)
150
+ }),
151
+ )
152
+
153
+ Vitest.it.effect('should die if newEvents are not sorted in ascending order by event number (global)', () =>
154
+ Effect.gen(function* () {
155
+ const syncState = new SyncState.SyncState({
156
+ pending: [e1_0],
157
+ upstreamHead: EventSequenceNumber.Client.ROOT,
158
+ localHead: e1_0.seqNum,
159
+ })
160
+ const exit = yield* merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e2_0, e1_0] } }).pipe(
161
+ Effect.exit,
162
+ )
163
+ assert(Exit.isFailure(exit))
164
+ expect(Cause.isDie(exit.cause)).toBe(true)
165
+ }),
166
+ )
167
+
168
+ Vitest.it.effect('should die if incoming event is < expected upstream head', () =>
169
+ Effect.gen(function* () {
170
+ const syncState = new SyncState.SyncState({
171
+ pending: [],
172
+ upstreamHead: e2_0.seqNum,
173
+ localHead: e2_0.seqNum,
174
+ })
175
+ const exit = yield* merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } }).pipe(
176
+ Effect.exit,
177
+ )
178
+ assert(Exit.isFailure(exit))
179
+ expect(Cause.isDie(exit.cause)).toBe(true)
180
+ }),
181
+ )
182
+
183
+ Vitest.it.effect('should die if incoming event is = expected upstream head', () =>
184
+ Effect.gen(function* () {
185
+ const syncState = new SyncState.SyncState({
186
+ pending: [],
187
+ upstreamHead: e2_0.seqNum,
188
+ localHead: e2_0.seqNum,
189
+ })
190
+ const exit = yield* merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e2_0] } }).pipe(
191
+ Effect.exit,
192
+ )
193
+ assert(Exit.isFailure(exit))
194
+ expect(Cause.isDie(exit.cause)).toBe(true)
195
+ }),
196
+ )
197
+
198
+ Vitest.it.effect('should confirm pending event when receiving matching event', () =>
199
+ Effect.gen(function* () {
200
+ const syncState = new SyncState.SyncState({
201
+ pending: [e1_0],
202
+ upstreamHead: EventSequenceNumber.Client.ROOT,
203
+ localHead: e1_0.seqNum,
204
+ })
205
+ const result = yield* merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
206
+
207
+ expectAdvance(result)
208
+ expectEventArraysEqual(result.newSyncState.pending, [])
209
+ expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.seqNum)
210
+ expect(result.newSyncState.localHead).toMatchObject(e1_0.seqNum)
211
+ expectEventArraysEqual(result.newEvents, [])
212
+ expectEventArraysEqual(result.confirmedEvents, [e1_0])
213
+ }),
214
+ )
215
+
216
+ Vitest.it.effect('should confirm partial pending event when receiving matching event', () =>
217
+ Effect.gen(function* () {
218
+ const syncState = new SyncState.SyncState({
219
+ pending: [e1_0, e2_0],
220
+ upstreamHead: EventSequenceNumber.Client.ROOT,
221
+ localHead: e2_0.seqNum,
222
+ })
223
+ const result = yield* merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
224
+
225
+ expectAdvance(result)
226
+ expectEventArraysEqual(result.newSyncState.pending, [e2_0])
227
+ expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.seqNum)
228
+ expect(result.newSyncState.localHead).toMatchObject(e2_0.seqNum)
229
+ expectEventArraysEqual(result.newEvents, [])
230
+ expectEventArraysEqual(result.confirmedEvents, [e1_0])
231
+ }),
232
+ )
233
+
234
+ Vitest.it.effect('should confirm pending event and add new event', () =>
235
+ Effect.gen(function* () {
236
+ const syncState = new SyncState.SyncState({
237
+ pending: [e1_0],
238
+ upstreamHead: EventSequenceNumber.Client.ROOT,
239
+ localHead: e1_0.seqNum,
240
+ })
241
+ const result = yield* merge({
242
+ syncState,
243
+ payload: { _tag: 'upstream-advance', newEvents: [e1_0, e1_1] },
244
+ })
245
245
 
246
- expectAdvance(result)
247
- expectEventArraysEqual(result.newSyncState.pending, [e1_1])
248
- expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.seqNum)
249
- expect(result.newSyncState.localHead).toMatchObject(e1_1.seqNum)
250
- expectEventArraysEqual(result.newEvents, [])
251
- expectEventArraysEqual(result.confirmedEvents, [e1_0])
252
- })
246
+ expectAdvance(result)
247
+ expectEventArraysEqual(result.newSyncState.pending, [])
248
+ expect(result.newSyncState.upstreamHead).toMatchObject(e1_1.seqNum)
249
+ expect(result.newSyncState.localHead).toMatchObject(e1_1.seqNum)
250
+ expect(result.newEvents).toStrictEqual([e1_1])
251
+ expectEventArraysEqual(result.confirmedEvents, [e1_0])
252
+ }),
253
+ )
254
+
255
+ Vitest.it.effect('should confirm pending event and add multiple new events', () =>
256
+ Effect.gen(function* () {
257
+ const syncState = new SyncState.SyncState({
258
+ pending: [e1_1],
259
+ upstreamHead: e1_0.seqNum,
260
+ localHead: e1_1.seqNum,
261
+ })
262
+ const result = yield* merge({
263
+ syncState,
264
+ payload: { _tag: 'upstream-advance', newEvents: [e1_1, e1_2, e1_3, e2_0, e2_1] },
265
+ })
253
266
 
254
- it('should ignore client events (incoming is subset of pending)', () => {
255
- const syncState = new SyncState.SyncState({
256
- pending: [e0_1, e1_0],
257
- upstreamHead: EventSequenceNumber.ROOT,
258
- localHead: e1_0.seqNum,
259
- })
260
- const result = merge({
261
- syncState,
262
- payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
263
- ignoreClientEvents: true,
264
- })
265
- expectAdvance(result)
266
- expectEventArraysEqual(result.newSyncState.pending, [])
267
- expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.seqNum)
268
- expect(result.newSyncState.localHead).toMatchObject(e1_0.seqNum)
269
- expectEventArraysEqual(result.newEvents, [])
270
- expectEventArraysEqual(result.confirmedEvents, [e0_1, e1_0])
271
- })
267
+ expectAdvance(result)
268
+ expectEventArraysEqual(result.newSyncState.pending, [])
269
+ expect(result.newSyncState.upstreamHead).toMatchObject(e2_1.seqNum)
270
+ expect(result.newSyncState.localHead).toMatchObject(e2_1.seqNum)
271
+ expect(result.newEvents).toStrictEqual([e1_2, e1_3, e2_0, e2_1])
272
+ expectEventArraysEqual(result.confirmedEvents, [e1_1])
273
+ }),
274
+ )
275
+
276
+ Vitest.it.effect('should confirm pending global event while keep pending client events', () =>
277
+ Effect.gen(function* () {
278
+ const syncState = new SyncState.SyncState({
279
+ pending: [e1_0, e1_1],
280
+ upstreamHead: EventSequenceNumber.Client.ROOT,
281
+ localHead: e1_1.seqNum,
282
+ })
283
+ const result = yield* merge({
284
+ syncState,
285
+ payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
286
+ })
272
287
 
273
- it('should ignore client events (incoming is subset of pending case 2)', () => {
274
- const syncState = new SyncState.SyncState({
275
- pending: [e0_1, e1_0, e2_0],
276
- upstreamHead: EventSequenceNumber.ROOT,
277
- localHead: e1_0.seqNum,
278
- })
279
- const result = merge({
280
- syncState,
281
- payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
282
- ignoreClientEvents: true,
283
- })
284
- expectAdvance(result)
285
- expectEventArraysEqual(result.newSyncState.pending, [e2_0])
286
- expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.seqNum)
287
- expect(result.newSyncState.localHead).toMatchObject(e2_0.seqNum)
288
- expectEventArraysEqual(result.newEvents, [])
289
- expectEventArraysEqual(result.confirmedEvents, [e0_1, e1_0])
290
- })
288
+ expectAdvance(result)
289
+ expectEventArraysEqual(result.newSyncState.pending, [e1_1])
290
+ expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.seqNum)
291
+ expect(result.newSyncState.localHead).toMatchObject(e1_1.seqNum)
292
+ expectEventArraysEqual(result.newEvents, [])
293
+ expectEventArraysEqual(result.confirmedEvents, [e1_0])
294
+ }),
295
+ )
296
+
297
+ Vitest.it.effect('should ignore client events (incoming is subset of pending)', () =>
298
+ Effect.gen(function* () {
299
+ const syncState = new SyncState.SyncState({
300
+ pending: [e0_1, e1_0],
301
+ upstreamHead: EventSequenceNumber.Client.ROOT,
302
+ localHead: e1_0.seqNum,
303
+ })
304
+ const result = yield* merge({
305
+ syncState,
306
+ payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
307
+ ignoreClientEvents: true,
308
+ })
309
+ expectAdvance(result)
310
+ expectEventArraysEqual(result.newSyncState.pending, [])
311
+ expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.seqNum)
312
+ expect(result.newSyncState.localHead).toMatchObject(e1_0.seqNum)
313
+ expectEventArraysEqual(result.newEvents, [])
314
+ expectEventArraysEqual(result.confirmedEvents, [e0_1, e1_0])
315
+ }),
316
+ )
317
+
318
+ Vitest.it.effect('should ignore client events (incoming is subset of pending case 2)', () =>
319
+ Effect.gen(function* () {
320
+ const syncState = new SyncState.SyncState({
321
+ pending: [e0_1, e1_0, e2_0],
322
+ upstreamHead: EventSequenceNumber.Client.ROOT,
323
+ localHead: e1_0.seqNum,
324
+ })
325
+ const result = yield* merge({
326
+ syncState,
327
+ payload: { _tag: 'upstream-advance', newEvents: [e1_0] },
328
+ ignoreClientEvents: true,
329
+ })
330
+ expectAdvance(result)
331
+ expectEventArraysEqual(result.newSyncState.pending, [e2_0])
332
+ expect(result.newSyncState.upstreamHead).toMatchObject(e1_0.seqNum)
333
+ expect(result.newSyncState.localHead).toMatchObject(e2_0.seqNum)
334
+ expectEventArraysEqual(result.newEvents, [])
335
+ expectEventArraysEqual(result.confirmedEvents, [e0_1, e1_0])
336
+ }),
337
+ )
338
+
339
+ Vitest.it.effect('should ignore client events (incoming goes beyond pending)', () =>
340
+ Effect.gen(function* () {
341
+ const syncState = new SyncState.SyncState({
342
+ pending: [e0_1, e1_0, e1_1],
343
+ upstreamHead: EventSequenceNumber.Client.ROOT,
344
+ localHead: e1_1.seqNum,
345
+ })
346
+ const result = yield* merge({
347
+ syncState,
348
+ payload: { _tag: 'upstream-advance', newEvents: [e1_0, e2_0] },
349
+ ignoreClientEvents: true,
350
+ })
291
351
 
292
- it('should ignore client events (incoming goes beyond pending)', () => {
293
- const syncState = new SyncState.SyncState({
294
- pending: [e0_1, e1_0, e1_1],
295
- upstreamHead: EventSequenceNumber.ROOT,
296
- localHead: e1_1.seqNum,
297
- })
298
- const result = merge({
299
- syncState,
300
- payload: { _tag: 'upstream-advance', newEvents: [e1_0, e2_0] },
301
- ignoreClientEvents: true,
302
- })
352
+ expectAdvance(result)
353
+ expectEventArraysEqual(result.newSyncState.pending, [])
354
+ expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
355
+ expect(result.newSyncState.localHead).toMatchObject(e2_0.seqNum)
356
+ expect(result.newEvents).toStrictEqual([e2_0])
357
+ expectEventArraysEqual(result.confirmedEvents, [e0_1, e1_0, e1_1])
358
+ }),
359
+ )
360
+
361
+ Vitest.it.effect('should die if incoming event is ≤ local head', () =>
362
+ Effect.gen(function* () {
363
+ const syncState = new SyncState.SyncState({
364
+ pending: [],
365
+ upstreamHead: e2_0.seqNum,
366
+ localHead: e2_0.seqNum,
367
+ })
368
+ const exit = yield* merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } }).pipe(
369
+ Effect.exit,
370
+ )
371
+ assert(Exit.isFailure(exit))
372
+ expect(Cause.isDie(exit.cause)).toBe(true)
373
+ }),
374
+ )
375
+
376
+ Vitest.it.effect('should advance (not rebase) when pending event has undefined-valued key dropped by JSON wire round-trip', () =>
377
+ Effect.gen(function* () {
378
+ const argsSchema = Schema.Struct({
379
+ id: Schema.String,
380
+ flag: Schema.UndefinedOr(Schema.Boolean),
381
+ })
382
+ const localArgs = Schema.encodeUnknownSync(argsSchema)({ id: 'abc' } as any)
383
+ const wireArgs = JSON.parse(JSON.stringify(localArgs))
384
+
385
+ const localPending = new TestEvent({
386
+ seqNum: e1_0.seqNum,
387
+ parentSeqNum: e1_0.parentSeqNum,
388
+ name: e1_0.name,
389
+ args: localArgs,
390
+ clientId: e1_0.clientId,
391
+ sessionId: e1_0.sessionId,
392
+ })
393
+ const fromUpstream = new TestEvent({
394
+ seqNum: e1_0.seqNum,
395
+ parentSeqNum: e1_0.parentSeqNum,
396
+ name: e1_0.name,
397
+ args: wireArgs,
398
+ clientId: e1_0.clientId,
399
+ sessionId: e1_0.sessionId,
400
+ })
303
401
 
304
- expectAdvance(result)
305
- expectEventArraysEqual(result.newSyncState.pending, [])
306
- expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
307
- expect(result.newSyncState.localHead).toMatchObject(e2_0.seqNum)
308
- expect(result.newEvents).toStrictEqual([e2_0])
309
- expectEventArraysEqual(result.confirmedEvents, [e0_1, e1_0, e1_1])
310
- })
402
+ const syncState = new SyncState.SyncState({
403
+ pending: [localPending],
404
+ upstreamHead: EventSequenceNumber.Client.ROOT,
405
+ localHead: localPending.seqNum,
406
+ })
407
+ const result = yield* merge({
408
+ syncState,
409
+ payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [fromUpstream] }),
410
+ })
311
411
 
312
- it('should fail if incoming event is ≤ local head', () => {
313
- const syncState = new SyncState.SyncState({
314
- pending: [],
315
- upstreamHead: e2_0.seqNum,
316
- localHead: e2_0.seqNum,
317
- })
318
- const result = merge({ syncState, payload: { _tag: 'upstream-advance', newEvents: [e1_0] } })
319
- expect(result).toMatchObject({ _tag: 'unexpected-error' })
320
- })
412
+ expectAdvance(result)
413
+ expect(result.confirmedEvents).toHaveLength(1)
414
+ expect(result.newSyncState.pending).toHaveLength(0)
415
+ }),
416
+ )
321
417
  })
322
418
 
323
- describe('upstream-advance: rebase', () => {
324
- it('should rebase single client event to end', () => {
325
- const syncState = new SyncState.SyncState({
326
- pending: [e1_0],
327
- upstreamHead: EventSequenceNumber.ROOT,
328
- localHead: e1_0.seqNum,
329
- })
330
- const result = merge({ syncState, payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1] }) })
331
-
332
- const e1_0_e1_2 = e1_0.rebase_(e1_1.seqNum, 1)
333
-
334
- expectRebase(result)
335
- expectEventArraysEqual(result.newSyncState.pending, [e1_0_e1_2])
336
- expect(result.newSyncState.upstreamHead).toMatchObject(e1_1.seqNum)
337
- expect(result.newSyncState.localHead).toMatchObject(e1_0_e1_2.seqNum)
338
- expectEventArraysEqual(result.rollbackEvents, [e1_0])
339
- expectEventArraysEqual(result.newEvents, [e1_1, e1_0_e1_2])
340
- })
341
-
342
- it('should rebase different event with same id', () => {
343
- const e2_0_b = new TestEvent({ global: 1, client: 0 }, e1_0.seqNum, '1_0_b', false)
344
- const syncState = new SyncState.SyncState({
345
- pending: [e2_0_b],
346
- upstreamHead: EventSequenceNumber.ROOT,
347
- localHead: e2_0_b.seqNum,
348
- })
349
- const result = merge({ syncState, payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e2_0] }) })
350
- const e2_0_e3_0 = e2_0_b.rebase_(e2_0.seqNum, 1)
351
-
352
- expectRebase(result)
353
- expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
354
- expectEventArraysEqual(result.newEvents, [e2_0, e2_0_e3_0])
355
- expectEventArraysEqual(result.rollbackEvents, [e2_0_b])
356
- expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
357
- expect(result.newSyncState.localHead).toMatchObject(e2_0_e3_0.seqNum)
358
- })
359
-
360
- it('should rebase single client event to end (more incoming events)', () => {
361
- const syncState = new SyncState.SyncState({
362
- pending: [e1_0],
363
- upstreamHead: EventSequenceNumber.ROOT,
364
- localHead: e1_0.seqNum,
365
- })
366
- const result = merge({
367
- syncState,
368
- payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1, e1_2, e1_3, e2_0] }),
369
- })
370
-
371
- const e1_0_e3_0 = e1_0.rebase_(e2_0.seqNum, 1)
372
-
373
- expectRebase(result)
374
- expectEventArraysEqual(result.newSyncState.pending, [e1_0_e3_0])
375
- expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
376
- expect(result.newSyncState.localHead).toMatchObject(e1_0_e3_0.seqNum)
377
- })
378
-
379
- it('should only rebase divergent events when first event matches', () => {
380
- const syncState = new SyncState.SyncState({
381
- pending: [e1_0, e1_1],
382
- upstreamHead: EventSequenceNumber.ROOT,
383
- localHead: e1_0.seqNum,
384
- })
385
- const result = merge({
386
- syncState,
387
- payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_0, e1_2, e1_3, e2_0] }),
388
- })
389
-
390
- const e1_1_e2_1 = e1_1.rebase_(e2_0.seqNum, 1)
391
-
392
- expectRebase(result)
393
- expectEventArraysEqual(result.newSyncState.pending, [e1_1_e2_1])
394
- expectEventArraysEqual(result.rollbackEvents, [e1_1])
395
- expectEventArraysEqual(result.newEvents, [e1_2, e1_3, e2_0, e1_1_e2_1])
396
- expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
397
- expect(result.newSyncState.localHead).toMatchObject(e1_1_e2_1.seqNum)
398
- })
399
-
400
- it('should rebase all client events when incoming chain starts differently', () => {
401
- const syncState = new SyncState.SyncState({
402
- pending: [e1_0, e1_1],
403
- upstreamHead: EventSequenceNumber.ROOT,
404
- localHead: e1_1.seqNum,
405
- })
406
- const result = merge({
407
- syncState,
408
- payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1, e1_2, e1_3, e2_0] }),
409
- })
410
-
411
- const e1_0_e2_1 = e1_0.rebase_(e2_0.seqNum, 1)
412
- const e1_1_e2_2 = e1_1.rebase_(e1_0_e2_1.seqNum, 1)
419
+ Vitest.describe('upstream-advance: rebase', () => {
420
+ Vitest.it.effect('should rebase single client event to end', () =>
421
+ Effect.gen(function* () {
422
+ const syncState = new SyncState.SyncState({
423
+ pending: [e1_0],
424
+ upstreamHead: EventSequenceNumber.Client.ROOT,
425
+ localHead: e1_0.seqNum,
426
+ })
427
+ const result = yield* merge({
428
+ syncState,
429
+ payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1] }),
430
+ })
413
431
 
414
- expectRebase(result)
415
- expectEventArraysEqual(result.newSyncState.pending, [e1_0_e2_1, e1_1_e2_2])
416
- expectEventArraysEqual(result.newEvents, [e1_1, e1_2, e1_3, e2_0, e1_0_e2_1, e1_1_e2_2])
417
- expectEventArraysEqual(result.rollbackEvents, [e1_0, e1_1])
418
- expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
419
- expect(result.newSyncState.localHead).toMatchObject(e1_1_e2_2.seqNum)
420
- })
432
+ const e1_0_e1_2 = e1_0.rebase_(e1_1.seqNum, 1)
433
+
434
+ expectRebase(result)
435
+ expectEventArraysEqual(result.newSyncState.pending, [e1_0_e1_2])
436
+ expect(result.newSyncState.upstreamHead).toMatchObject(e1_1.seqNum)
437
+ expect(result.newSyncState.localHead).toMatchObject(e1_0_e1_2.seqNum)
438
+ expectEventArraysEqual(result.rollbackEvents, [e1_0])
439
+ expectEventArraysEqual(result.newEvents, [e1_1, e1_0_e1_2])
440
+ }),
441
+ )
442
+
443
+ Vitest.it.effect('should rebase different event with same id', () =>
444
+ Effect.gen(function* () {
445
+ const e2_0_b = TestEvent.new({ global: 1, client: 0 }, e1_0.seqNum, '1_0_b', false)
446
+ const syncState = new SyncState.SyncState({
447
+ pending: [e2_0_b],
448
+ upstreamHead: EventSequenceNumber.Client.ROOT,
449
+ localHead: e2_0_b.seqNum,
450
+ })
451
+ const result = yield* merge({
452
+ syncState,
453
+ payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e2_0] }),
454
+ })
455
+ const e2_0_e3_0 = e2_0_b.rebase_(e2_0.seqNum, 1)
456
+
457
+ expectRebase(result)
458
+ expectEventArraysEqual(result.newSyncState.pending, [e2_0_e3_0])
459
+ expectEventArraysEqual(result.newEvents, [e2_0, e2_0_e3_0])
460
+ expectEventArraysEqual(result.rollbackEvents, [e2_0_b])
461
+ expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
462
+ expect(result.newSyncState.localHead).toMatchObject(e2_0_e3_0.seqNum)
463
+ }),
464
+ )
465
+
466
+ Vitest.it.effect('should rebase single client event to end (more incoming events)', () =>
467
+ Effect.gen(function* () {
468
+ const syncState = new SyncState.SyncState({
469
+ pending: [e1_0],
470
+ upstreamHead: EventSequenceNumber.Client.ROOT,
471
+ localHead: e1_0.seqNum,
472
+ })
473
+ const result = yield* merge({
474
+ syncState,
475
+ payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1, e1_2, e1_3, e2_0] }),
476
+ })
421
477
 
422
- describe('local-push', () => {
423
- describe('advance', () => {
424
- it('should advance with new events', () => {
425
- const syncState = new SyncState.SyncState({
426
- pending: [e1_0],
427
- upstreamHead: EventSequenceNumber.ROOT,
428
- localHead: e1_0.seqNum,
429
- })
430
- const result = merge({
431
- syncState,
432
- payload: SyncState.PayloadLocalPush.make({ newEvents: [e1_1, e1_2, e1_3] }),
433
- })
434
-
435
- expectAdvance(result)
436
- expectEventArraysEqual(result.newSyncState.pending, [e1_0, e1_1, e1_2, e1_3])
437
- expect(result.newSyncState.upstreamHead).toMatchObject(EventSequenceNumber.ROOT)
438
- expect(result.newSyncState.localHead).toMatchObject(e1_3.seqNum)
439
- expectEventArraysEqual(result.newEvents, [e1_1, e1_2, e1_3])
440
- expectEventArraysEqual(result.confirmedEvents, [])
478
+ const e1_0_e3_0 = e1_0.rebase_(e2_0.seqNum, 1)
479
+
480
+ expectRebase(result)
481
+ expectEventArraysEqual(result.newSyncState.pending, [e1_0_e3_0])
482
+ expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
483
+ expect(result.newSyncState.localHead).toMatchObject(e1_0_e3_0.seqNum)
484
+ }),
485
+ )
486
+
487
+ Vitest.it.effect('should only rebase divergent events when first event matches', () =>
488
+ Effect.gen(function* () {
489
+ const syncState = new SyncState.SyncState({
490
+ pending: [e1_0, e1_1],
491
+ upstreamHead: EventSequenceNumber.Client.ROOT,
492
+ localHead: e1_0.seqNum,
493
+ })
494
+ const result = yield* merge({
495
+ syncState,
496
+ payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_0, e1_2, e1_3, e2_0] }),
441
497
  })
442
- })
443
498
 
444
- describe('reject', () => {
445
- it('should reject when new events are greater than pending events', () => {
446
- const syncState = new SyncState.SyncState({
447
- pending: [e1_0, e1_1],
448
- upstreamHead: EventSequenceNumber.ROOT,
449
- localHead: e1_1.seqNum,
450
- })
451
- const result = merge({
452
- syncState,
453
- payload: SyncState.PayloadLocalPush.make({ newEvents: [e1_1, e1_2] }),
454
- })
455
-
456
- expectReject(result)
457
- expect(result.expectedMinimumId).toMatchObject(e1_2.seqNum)
499
+ const e1_1_e2_1 = e1_1.rebase_(e2_0.seqNum, 1)
500
+
501
+ expectRebase(result)
502
+ expectEventArraysEqual(result.newSyncState.pending, [e1_1_e2_1])
503
+ expectEventArraysEqual(result.rollbackEvents, [e1_1])
504
+ expectEventArraysEqual(result.newEvents, [e1_2, e1_3, e2_0, e1_1_e2_1])
505
+ expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
506
+ expect(result.newSyncState.localHead).toMatchObject(e1_1_e2_1.seqNum)
507
+ }),
508
+ )
509
+
510
+ Vitest.it.effect('should rebase all client events when incoming chain starts differently', () =>
511
+ Effect.gen(function* () {
512
+ const syncState = new SyncState.SyncState({
513
+ pending: [e1_0, e1_1],
514
+ upstreamHead: EventSequenceNumber.Client.ROOT,
515
+ localHead: e1_1.seqNum,
516
+ })
517
+ const result = yield* merge({
518
+ syncState,
519
+ payload: SyncState.PayloadUpstreamAdvance.make({ newEvents: [e1_1, e1_2, e1_3, e2_0] }),
458
520
  })
521
+
522
+ const e1_0_e2_1 = e1_0.rebase_(e2_0.seqNum, 1)
523
+ const e1_1_e2_2 = e1_1.rebase_(e1_0_e2_1.seqNum, 1)
524
+
525
+ expectRebase(result)
526
+ expectEventArraysEqual(result.newSyncState.pending, [e1_0_e2_1, e1_1_e2_2])
527
+ expectEventArraysEqual(result.newEvents, [e1_1, e1_2, e1_3, e2_0, e1_0_e2_1, e1_1_e2_2])
528
+ expectEventArraysEqual(result.rollbackEvents, [e1_0, e1_1])
529
+ expect(result.newSyncState.upstreamHead).toMatchObject(e2_0.seqNum)
530
+ expect(result.newSyncState.localHead).toMatchObject(e1_1_e2_2.seqNum)
531
+ }),
532
+ )
533
+
534
+ Vitest.describe('local-push', () => {
535
+ Vitest.describe('advance', () => {
536
+ Vitest.it.effect('should advance with new events', () =>
537
+ Effect.gen(function* () {
538
+ const syncState = new SyncState.SyncState({
539
+ pending: [e1_0],
540
+ upstreamHead: EventSequenceNumber.Client.ROOT,
541
+ localHead: e1_0.seqNum,
542
+ })
543
+ const result = yield* merge({
544
+ syncState,
545
+ payload: SyncState.PayloadLocalPush.make({ newEvents: [e1_1, e1_2, e1_3] }),
546
+ })
547
+
548
+ expectAdvance(result)
549
+ expectEventArraysEqual(result.newSyncState.pending, [e1_0, e1_1, e1_2, e1_3])
550
+ expect(result.newSyncState.upstreamHead).toMatchObject(EventSequenceNumber.Client.ROOT)
551
+ expect(result.newSyncState.localHead).toMatchObject(e1_3.seqNum)
552
+ expectEventArraysEqual(result.newEvents, [e1_1, e1_2, e1_3])
553
+ expectEventArraysEqual(result.confirmedEvents, [])
554
+ }),
555
+ )
556
+
557
+ // Leaders can choose to ignore client-only events while still returning them for broadcast.
558
+ // Ensure pending/local head only reflects events that must be pushed upstream.
559
+ Vitest.it.effect('keeps pending empty when pushing only client-only events that are being ignored', () =>
560
+ Effect.gen(function* () {
561
+ const syncState = new SyncState.SyncState({
562
+ pending: [],
563
+ upstreamHead: EventSequenceNumber.Client.ROOT,
564
+ localHead: EventSequenceNumber.Client.ROOT,
565
+ })
566
+
567
+ const result = yield* merge({
568
+ syncState,
569
+ payload: SyncState.PayloadLocalPush.make({ newEvents: [e0_1] }),
570
+ ignoreClientEvents: true,
571
+ })
572
+
573
+ expectAdvance(result)
574
+ expectEventArraysEqual(result.newSyncState.pending, [])
575
+ expect(result.newSyncState.upstreamHead).toMatchObject(EventSequenceNumber.Client.ROOT)
576
+ expect(result.newSyncState.localHead).toMatchObject(EventSequenceNumber.Client.ROOT)
577
+ expectEventArraysEqual(result.newEvents, [e0_1])
578
+ }),
579
+ )
580
+
581
+ Vitest.it.effect(
582
+ 'appends only upstream-bound events to pending when ignoring client-only pushes',
583
+ () =>
584
+ Effect.gen(function* () {
585
+ const syncState = new SyncState.SyncState({
586
+ pending: [],
587
+ upstreamHead: EventSequenceNumber.Client.ROOT,
588
+ localHead: EventSequenceNumber.Client.ROOT,
589
+ })
590
+
591
+ const result = yield* merge({
592
+ syncState,
593
+ payload: SyncState.PayloadLocalPush.make({ newEvents: [e0_1, e1_0] }),
594
+ ignoreClientEvents: true,
595
+ })
596
+
597
+ expectAdvance(result)
598
+ expectEventArraysEqual(result.newSyncState.pending, [e1_0])
599
+ expect(result.newSyncState.upstreamHead).toMatchObject(EventSequenceNumber.Client.ROOT)
600
+ expect(result.newSyncState.localHead).toMatchObject(e1_0.seqNum)
601
+ expectEventArraysEqual(result.newEvents, [e0_1, e1_0])
602
+ }),
603
+ )
604
+ })
605
+
606
+ Vitest.describe('reject', () => {
607
+ Vitest.it.effect('should reject when new events are greater than pending events', () =>
608
+ Effect.gen(function* () {
609
+ const syncState = new SyncState.SyncState({
610
+ pending: [e1_0, e1_1],
611
+ upstreamHead: EventSequenceNumber.Client.ROOT,
612
+ localHead: e1_1.seqNum,
613
+ })
614
+ const result = yield* merge({
615
+ syncState,
616
+ payload: SyncState.PayloadLocalPush.make({ newEvents: [e1_1, e1_2] }),
617
+ })
618
+
619
+ expectReject(result)
620
+ expect(result.expectedMinimumId).toMatchObject(e1_2.seqNum)
621
+ }),
622
+ )
459
623
  })
460
624
  })
461
625
  })
@@ -463,8 +627,8 @@ describe('syncstate', () => {
463
627
  })
464
628
 
465
629
  const expectEventArraysEqual = (
466
- actual: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>,
467
- expected: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>,
630
+ actual: ReadonlyArray<LiveStoreEvent.Client.EncodedWithMeta>,
631
+ expected: ReadonlyArray<LiveStoreEvent.Client.EncodedWithMeta>,
468
632
  ) => {
469
633
  expect(actual.length).toBe(expected.length)
470
634
  actual.forEach((event, i) => {
@@ -475,20 +639,20 @@ const expectEventArraysEqual = (
475
639
  })
476
640
  }
477
641
 
478
- function expectAdvance(
642
+ const expectAdvance: (
479
643
  result: typeof SyncState.MergeResult.Type,
480
- ): asserts result is typeof SyncState.MergeResultAdvance.Type {
644
+ ) => asserts result is typeof SyncState.MergeResultAdvance.Type = (result) => {
481
645
  expect(result._tag).toBe('advance')
482
646
  }
483
647
 
484
- function expectRebase(
648
+ const expectRebase: (
485
649
  result: typeof SyncState.MergeResult.Type,
486
- ): asserts result is typeof SyncState.MergeResultRebase.Type {
487
- expect(result._tag, `Expected rebase, got ${result}`).toBe('rebase')
650
+ ) => asserts result is typeof SyncState.MergeResultRebase.Type = (result) => {
651
+ expect(result._tag, `Expected rebase, got ${result._tag}`).toBe('rebase')
488
652
  }
489
653
 
490
- function expectReject(
654
+ const expectReject: (
491
655
  result: typeof SyncState.MergeResult.Type,
492
- ): asserts result is typeof SyncState.MergeResultReject.Type {
656
+ ) => asserts result is typeof SyncState.MergeResultReject.Type = (result) => {
493
657
  expect(result._tag).toBe('reject')
494
658
  }