@livestore/common 0.4.0-dev.21 → 0.4.0-dev.23

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