@livestore/common 0.4.0-dev.22 → 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 (313) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ClientSessionLeaderThreadProxy.d.ts +9 -9
  3. package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
  4. package/dist/WorkerTransportError.d.ts +11 -0
  5. package/dist/WorkerTransportError.d.ts.map +1 -0
  6. package/dist/WorkerTransportError.js +11 -0
  7. package/dist/WorkerTransportError.js.map +1 -0
  8. package/dist/adapter-types.d.ts +3 -3
  9. package/dist/adapter-types.d.ts.map +1 -1
  10. package/dist/adapter-types.js.map +1 -1
  11. package/dist/bounded-collections.d.ts.map +1 -1
  12. package/dist/bounded-collections.js +6 -4
  13. package/dist/bounded-collections.js.map +1 -1
  14. package/dist/debug-info.js +4 -4
  15. package/dist/debug-info.js.map +1 -1
  16. package/dist/devtools/devtools-messages-common.js +1 -1
  17. package/dist/devtools/devtools-messages-common.js.map +1 -1
  18. package/dist/devtools/mod.js +1 -1
  19. package/dist/devtools/mod.js.map +1 -1
  20. package/dist/errors.d.ts +15 -15
  21. package/dist/errors.d.ts.map +1 -1
  22. package/dist/errors.js +11 -11
  23. package/dist/errors.js.map +1 -1
  24. package/dist/index.d.ts +2 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +2 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/leader-thread/LeaderSyncProcessor.d.ts +20 -6
  29. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  30. package/dist/leader-thread/LeaderSyncProcessor.js +287 -257
  31. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  32. package/dist/leader-thread/RejectedPushError.d.ts +107 -0
  33. package/dist/leader-thread/RejectedPushError.d.ts.map +1 -0
  34. package/dist/leader-thread/RejectedPushError.js +78 -0
  35. package/dist/leader-thread/RejectedPushError.js.map +1 -0
  36. package/dist/leader-thread/connection.js +1 -1
  37. package/dist/leader-thread/connection.js.map +1 -1
  38. package/dist/leader-thread/eventlog.d.ts.map +1 -1
  39. package/dist/leader-thread/eventlog.js +12 -11
  40. package/dist/leader-thread/eventlog.js.map +1 -1
  41. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -2
  42. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  43. package/dist/leader-thread/leader-worker-devtools.js +25 -14
  44. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  45. package/dist/leader-thread/make-leader-thread-layer.d.ts +8 -3
  46. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  47. package/dist/leader-thread/make-leader-thread-layer.js +7 -10
  48. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  49. package/dist/leader-thread/make-leader-thread-layer.test.js +1 -1
  50. package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -1
  51. package/dist/leader-thread/materialize-event.js +4 -4
  52. package/dist/leader-thread/materialize-event.js.map +1 -1
  53. package/dist/leader-thread/recreate-db.js +1 -1
  54. package/dist/leader-thread/recreate-db.js.map +1 -1
  55. package/dist/leader-thread/shutdown-channel.d.ts +2 -2
  56. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  57. package/dist/leader-thread/shutdown-channel.js +2 -2
  58. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  59. package/dist/leader-thread/stream-events.d.ts.map +1 -1
  60. package/dist/leader-thread/stream-events.js +4 -3
  61. package/dist/leader-thread/stream-events.js.map +1 -1
  62. package/dist/leader-thread/types.d.ts +7 -6
  63. package/dist/leader-thread/types.d.ts.map +1 -1
  64. package/dist/leader-thread/types.js.map +1 -1
  65. package/dist/logging.js +4 -4
  66. package/dist/logging.js.map +1 -1
  67. package/dist/make-client-session.js +2 -2
  68. package/dist/make-client-session.js.map +1 -1
  69. package/dist/materializer-helper.js +6 -6
  70. package/dist/materializer-helper.js.map +1 -1
  71. package/dist/otel.d.ts +1 -1
  72. package/dist/otel.d.ts.map +1 -1
  73. package/dist/otel.js +2 -2
  74. package/dist/otel.js.map +1 -1
  75. package/dist/rematerialize-from-eventlog.d.ts +1 -1
  76. package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
  77. package/dist/rematerialize-from-eventlog.js +11 -9
  78. package/dist/rematerialize-from-eventlog.js.map +1 -1
  79. package/dist/schema/EventDef/define.d.ts +2 -2
  80. package/dist/schema/EventDef/define.d.ts.map +1 -1
  81. package/dist/schema/EventDef/define.js +4 -4
  82. package/dist/schema/EventDef/define.js.map +1 -1
  83. package/dist/schema/EventDef/deprecated.js +3 -3
  84. package/dist/schema/EventDef/deprecated.js.map +1 -1
  85. package/dist/schema/EventDef/deprecated.test.js +1 -1
  86. package/dist/schema/EventDef/deprecated.test.js.map +1 -1
  87. package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -1
  88. package/dist/schema/EventSequenceNumber/client.js +11 -11
  89. package/dist/schema/EventSequenceNumber/client.js.map +1 -1
  90. package/dist/schema/EventSequenceNumber.test.js +1 -1
  91. package/dist/schema/EventSequenceNumber.test.js.map +1 -1
  92. package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -1
  93. package/dist/schema/LiveStoreEvent/client.js +6 -3
  94. package/dist/schema/LiveStoreEvent/client.js.map +1 -1
  95. package/dist/schema/LiveStoreEvent/client.test.d.ts +2 -0
  96. package/dist/schema/LiveStoreEvent/client.test.d.ts.map +1 -0
  97. package/dist/schema/LiveStoreEvent/client.test.js +83 -0
  98. package/dist/schema/LiveStoreEvent/client.test.js.map +1 -0
  99. package/dist/schema/schema.d.ts.map +1 -1
  100. package/dist/schema/schema.js +7 -4
  101. package/dist/schema/schema.js.map +1 -1
  102. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  103. package/dist/schema/state/sqlite/client-document-def.js +18 -6
  104. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  105. package/dist/schema/state/sqlite/client-document-def.test.js +1 -1
  106. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
  107. package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
  108. package/dist/schema/state/sqlite/column-annotations.js +1 -1
  109. package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
  110. package/dist/schema/state/sqlite/column-annotations.test.js +1 -1
  111. package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
  112. package/dist/schema/state/sqlite/column-def.d.ts.map +1 -1
  113. package/dist/schema/state/sqlite/column-def.js +36 -34
  114. package/dist/schema/state/sqlite/column-def.js.map +1 -1
  115. package/dist/schema/state/sqlite/column-def.test.js +7 -6
  116. package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
  117. package/dist/schema/state/sqlite/column-spec.d.ts.map +1 -1
  118. package/dist/schema/state/sqlite/column-spec.js +8 -8
  119. package/dist/schema/state/sqlite/column-spec.js.map +1 -1
  120. package/dist/schema/state/sqlite/column-spec.test.js +1 -1
  121. package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
  122. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +2 -2
  123. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
  124. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +2 -2
  125. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
  126. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +11 -2
  127. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
  128. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +1 -1
  129. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -1
  130. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +1 -1
  131. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
  132. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +1 -1
  133. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
  134. package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
  135. package/dist/schema/state/sqlite/mod.js +3 -5
  136. package/dist/schema/state/sqlite/mod.js.map +1 -1
  137. package/dist/schema/state/sqlite/query-builder/api.d.ts +10 -2
  138. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
  139. package/dist/schema/state/sqlite/query-builder/astToSql.js +11 -11
  140. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
  141. package/dist/schema/state/sqlite/query-builder/impl.d.ts +1 -1
  142. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
  143. package/dist/schema/state/sqlite/query-builder/impl.js +28 -14
  144. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
  145. package/dist/schema/state/sqlite/query-builder/impl.test.js +3 -2
  146. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  147. package/dist/schema/state/sqlite/schema-helpers.js +2 -2
  148. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
  149. package/dist/schema/state/sqlite/table-def.d.ts +5 -3
  150. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  151. package/dist/schema/state/sqlite/table-def.js +1 -1
  152. package/dist/schema/state/sqlite/table-def.js.map +1 -1
  153. package/dist/schema/state/sqlite/table-def.test.js +57 -4
  154. package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
  155. package/dist/schema/unknown-events.d.ts +1 -1
  156. package/dist/schema/unknown-events.d.ts.map +1 -1
  157. package/dist/schema/unknown-events.js +1 -1
  158. package/dist/schema/unknown-events.js.map +1 -1
  159. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +1 -1
  160. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -1
  161. package/dist/schema-management/common.js +2 -2
  162. package/dist/schema-management/common.js.map +1 -1
  163. package/dist/schema-management/migrations.js +1 -1
  164. package/dist/schema-management/migrations.js.map +1 -1
  165. package/dist/sql-queries/sql-queries.js +8 -6
  166. package/dist/sql-queries/sql-queries.js.map +1 -1
  167. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  168. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  169. package/dist/sqlite-db-helper.js +3 -3
  170. package/dist/sqlite-db-helper.js.map +1 -1
  171. package/dist/sqlite-types.d.ts +2 -2
  172. package/dist/sqlite-types.d.ts.map +1 -1
  173. package/dist/sqlite-types.js.map +1 -1
  174. package/dist/sync/ClientSessionSyncProcessor.d.ts +8 -9
  175. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  176. package/dist/sync/ClientSessionSyncProcessor.js +95 -113
  177. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  178. package/dist/sync/errors.d.ts +0 -38
  179. package/dist/sync/errors.d.ts.map +1 -1
  180. package/dist/sync/errors.js +3 -20
  181. package/dist/sync/errors.js.map +1 -1
  182. package/dist/sync/mock-sync-backend.d.ts +5 -3
  183. package/dist/sync/mock-sync-backend.d.ts.map +1 -1
  184. package/dist/sync/mock-sync-backend.js +70 -68
  185. package/dist/sync/mock-sync-backend.js.map +1 -1
  186. package/dist/sync/next/compact-events.js +6 -6
  187. package/dist/sync/next/compact-events.js.map +1 -1
  188. package/dist/sync/next/facts.d.ts.map +1 -1
  189. package/dist/sync/next/facts.js +6 -6
  190. package/dist/sync/next/facts.js.map +1 -1
  191. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  192. package/dist/sync/next/history-dag-common.js +6 -6
  193. package/dist/sync/next/history-dag-common.js.map +1 -1
  194. package/dist/sync/next/history-dag.js +3 -3
  195. package/dist/sync/next/history-dag.js.map +1 -1
  196. package/dist/sync/next/rebase-events.js +1 -1
  197. package/dist/sync/next/rebase-events.js.map +1 -1
  198. package/dist/sync/next/test/compact-events.calculator.test.js +2 -2
  199. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  200. package/dist/sync/next/test/compact-events.test.d.ts.map +1 -1
  201. package/dist/sync/next/test/compact-events.test.js +2 -2
  202. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  203. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
  204. package/dist/sync/next/test/event-fixtures.js +2 -2
  205. package/dist/sync/next/test/event-fixtures.js.map +1 -1
  206. package/dist/sync/sync-backend-kv.d.ts.map +1 -1
  207. package/dist/sync/sync-backend-kv.js.map +1 -1
  208. package/dist/sync/sync-backend.d.ts +3 -3
  209. package/dist/sync/sync-backend.d.ts.map +1 -1
  210. package/dist/sync/sync-backend.js +1 -1
  211. package/dist/sync/sync-backend.js.map +1 -1
  212. package/dist/sync/sync.d.ts +20 -0
  213. package/dist/sync/sync.d.ts.map +1 -1
  214. package/dist/sync/syncstate.d.ts +4 -17
  215. package/dist/sync/syncstate.d.ts.map +1 -1
  216. package/dist/sync/syncstate.js +51 -74
  217. package/dist/sync/syncstate.js.map +1 -1
  218. package/dist/sync/syncstate.test.js +112 -96
  219. package/dist/sync/syncstate.test.js.map +1 -1
  220. package/dist/sync/transport-chunking.js +3 -3
  221. package/dist/sync/transport-chunking.js.map +1 -1
  222. package/dist/sync/validate-push-payload.d.ts +2 -2
  223. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  224. package/dist/sync/validate-push-payload.js +4 -6
  225. package/dist/sync/validate-push-payload.js.map +1 -1
  226. package/dist/util.js +2 -2
  227. package/dist/util.js.map +1 -1
  228. package/dist/version.d.ts.map +1 -1
  229. package/dist/version.js +2 -5
  230. package/dist/version.js.map +1 -1
  231. package/package.json +66 -12
  232. package/src/ClientSessionLeaderThreadProxy.ts +9 -9
  233. package/src/WorkerTransportError.ts +12 -0
  234. package/src/adapter-types.ts +9 -3
  235. package/src/bounded-collections.ts +6 -5
  236. package/src/debug-info.ts +4 -4
  237. package/src/devtools/devtools-messages-common.ts +1 -1
  238. package/src/devtools/mod.ts +1 -1
  239. package/src/errors.ts +18 -17
  240. package/src/index.ts +2 -0
  241. package/src/leader-thread/LeaderSyncProcessor.ts +421 -392
  242. package/src/leader-thread/RejectedPushError.ts +106 -0
  243. package/src/leader-thread/connection.ts +1 -1
  244. package/src/leader-thread/eventlog.ts +16 -14
  245. package/src/leader-thread/leader-worker-devtools.ts +96 -66
  246. package/src/leader-thread/make-leader-thread-layer.test.ts +1 -1
  247. package/src/leader-thread/make-leader-thread-layer.ts +33 -31
  248. package/src/leader-thread/materialize-event.ts +4 -4
  249. package/src/leader-thread/recreate-db.ts +1 -1
  250. package/src/leader-thread/shutdown-channel.ts +2 -6
  251. package/src/leader-thread/stream-events.ts +10 -5
  252. package/src/leader-thread/types.ts +7 -6
  253. package/src/logging.ts +4 -4
  254. package/src/make-client-session.ts +2 -2
  255. package/src/materializer-helper.ts +9 -9
  256. package/src/otel.ts +3 -2
  257. package/src/rematerialize-from-eventlog.ts +60 -60
  258. package/src/schema/EventDef/define.ts +6 -6
  259. package/src/schema/EventDef/deprecated.test.ts +2 -1
  260. package/src/schema/EventDef/deprecated.ts +3 -3
  261. package/src/schema/EventSequenceNumber/client.ts +11 -11
  262. package/src/schema/EventSequenceNumber.test.ts +2 -1
  263. package/src/schema/LiveStoreEvent/client.test.ts +97 -0
  264. package/src/schema/LiveStoreEvent/client.ts +6 -3
  265. package/src/schema/schema.ts +9 -4
  266. package/src/schema/state/sqlite/client-document-def.test.ts +2 -1
  267. package/src/schema/state/sqlite/client-document-def.ts +20 -6
  268. package/src/schema/state/sqlite/column-annotations.test.ts +2 -1
  269. package/src/schema/state/sqlite/column-annotations.ts +2 -1
  270. package/src/schema/state/sqlite/column-def.test.ts +8 -6
  271. package/src/schema/state/sqlite/column-def.ts +41 -36
  272. package/src/schema/state/sqlite/column-spec.test.ts +3 -1
  273. package/src/schema/state/sqlite/column-spec.ts +9 -8
  274. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +2 -2
  275. package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +2 -1
  276. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +13 -4
  277. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +3 -3
  278. package/src/schema/state/sqlite/mod.ts +4 -5
  279. package/src/schema/state/sqlite/query-builder/api.ts +12 -5
  280. package/src/schema/state/sqlite/query-builder/astToSql.ts +11 -11
  281. package/src/schema/state/sqlite/query-builder/impl.test.ts +4 -2
  282. package/src/schema/state/sqlite/query-builder/impl.ts +26 -12
  283. package/src/schema/state/sqlite/schema-helpers.ts +2 -2
  284. package/src/schema/state/sqlite/table-def.test.ts +67 -4
  285. package/src/schema/state/sqlite/table-def.ts +8 -15
  286. package/src/schema/unknown-events.ts +2 -2
  287. package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +3 -1
  288. package/src/schema-management/common.ts +2 -2
  289. package/src/schema-management/migrations.ts +1 -1
  290. package/src/sql-queries/sql-queries.ts +10 -6
  291. package/src/sql-queries/sql-query-builder.ts +1 -0
  292. package/src/sqlite-db-helper.ts +3 -3
  293. package/src/sqlite-types.ts +3 -2
  294. package/src/sync/ClientSessionSyncProcessor.ts +148 -152
  295. package/src/sync/errors.ts +10 -22
  296. package/src/sync/mock-sync-backend.ts +139 -97
  297. package/src/sync/next/compact-events.ts +5 -5
  298. package/src/sync/next/facts.ts +7 -6
  299. package/src/sync/next/history-dag-common.ts +9 -6
  300. package/src/sync/next/history-dag.ts +3 -3
  301. package/src/sync/next/rebase-events.ts +1 -1
  302. package/src/sync/next/test/compact-events.calculator.test.ts +3 -2
  303. package/src/sync/next/test/compact-events.test.ts +4 -3
  304. package/src/sync/next/test/event-fixtures.ts +2 -2
  305. package/src/sync/sync-backend-kv.ts +1 -0
  306. package/src/sync/sync-backend.ts +5 -4
  307. package/src/sync/sync.ts +21 -0
  308. package/src/sync/syncstate.test.ts +513 -435
  309. package/src/sync/syncstate.ts +80 -86
  310. package/src/sync/transport-chunking.ts +3 -3
  311. package/src/sync/validate-push-payload.ts +4 -6
  312. package/src/util.ts +2 -2
  313. package/src/version.ts +2 -6
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Push validation errors returned by {@link LeaderSyncProcessor.push}.
3
+ *
4
+ * All three errors share a common {@link RejectedPushErrorTypeId} so consumers can catch the
5
+ * family as a group via {@link isRejectedPushError} instead of matching individual tags.
6
+ * Recovery is the same in every case: the client should rebase and retry.
7
+ *
8
+ * @module
9
+ */
10
+ import { Predicate, Schema } from '@livestore/utils/effect'
11
+
12
+ import { EventSequenceNumber } from '../schema/mod.ts'
13
+
14
+ export const RejectedPushErrorTypeId = '~@livestore/common/RejectedPushError' as const
15
+
16
+ /**
17
+ * A pushed batch of events failed validation because its sequence numbers are not strictly increasing.
18
+ *
19
+ * @remarks
20
+ *
21
+ * This is a defensive check — callers are expected to construct monotonic event batches.
22
+ * The client should rebase and retry.
23
+ */
24
+ export class NonMonotonicBatchError extends Schema.TaggedError<NonMonotonicBatchError>(
25
+ `${RejectedPushErrorTypeId}/NonMonotonicBatchError`,
26
+ )(
27
+ 'NonMonotonicBatchError',
28
+ {
29
+ /** The sequence number that broke the monotonic invariant (i.e. the one that is >= the next). */
30
+ precedingSeqNum: EventSequenceNumber.Client.Composite,
31
+ /** The sequence number that was expected to be greater than `precedingSeqNum`. */
32
+ violatingSeqNum: EventSequenceNumber.Client.Composite,
33
+ /** The index in the batch where the violation occurred. */
34
+ violationIndex: Schema.Number,
35
+ /** The session that produced the malformed batch. */
36
+ sessionId: Schema.String,
37
+ },
38
+ ) {
39
+ readonly [RejectedPushErrorTypeId] = RejectedPushErrorTypeId
40
+
41
+ override get message(): string {
42
+ return `Pushed events' sequence numbers are not strictly increasing at index ${this.violationIndex} (session ${this.sessionId}): ${EventSequenceNumber.Client.toString(this.precedingSeqNum)} >= ${EventSequenceNumber.Client.toString(this.violatingSeqNum)}`
43
+ }
44
+ }
45
+
46
+ /**
47
+ * A pushed batch of events failed validation because its rebase generation is older than the leader's current rebase generation.
48
+ *
49
+ * @remarks
50
+ *
51
+ * This happens when events were enqueued before a backend-pull-triggered rebase incremented the generation.
52
+ */
53
+ export class StaleRebaseGenerationError extends Schema.TaggedError<StaleRebaseGenerationError>(
54
+ `${RejectedPushErrorTypeId}/StaleRebaseGenerationError`,
55
+ )(
56
+ 'StaleRebaseGenerationError',
57
+ {
58
+ /** The leader's current rebase generation. */
59
+ currentRebaseGeneration: Schema.Number,
60
+ /** The rebase generation carried by the dropped events. */
61
+ providedRebaseGeneration: Schema.Number,
62
+ /** The session that produced the stale batch. */
63
+ sessionId: Schema.String,
64
+ },
65
+ ) {
66
+ readonly [RejectedPushErrorTypeId] = RejectedPushErrorTypeId
67
+
68
+ override get message(): string {
69
+ return `Pushed events have stale rebase generation (session ${this.sessionId}): expected >= ${this.currentRebaseGeneration}, got ${this.providedRebaseGeneration}`
70
+ }
71
+ }
72
+
73
+ /**
74
+ * A pushed batch of events was rejected because the leader's push head has already advanced
75
+ * past the batch's first event.
76
+ *
77
+ * @remarks
78
+ *
79
+ * This occurs when another client session (or a backend pull) has pushed events that the current
80
+ * session hasn't seen yet.
81
+ */
82
+ export class LeaderAheadError extends Schema.TaggedError<LeaderAheadError>(
83
+ `${RejectedPushErrorTypeId}/LeaderAheadError`,
84
+ )('LeaderAheadError', {
85
+ minimumExpectedNum: EventSequenceNumber.Client.Composite,
86
+ providedNum: EventSequenceNumber.Client.Composite,
87
+ /** The session that produced the stale batch. */
88
+ sessionId: Schema.String,
89
+ }) {
90
+ readonly [RejectedPushErrorTypeId] = RejectedPushErrorTypeId
91
+
92
+ override get message(): string {
93
+ return `Leader push head is ahead of batch (session ${this.sessionId}): expected > ${EventSequenceNumber.Client.toString(this.minimumExpectedNum)}, got ${EventSequenceNumber.Client.toString(this.providedNum)}`
94
+ }
95
+ }
96
+
97
+ export const RejectedPushError = Schema.Union(
98
+ LeaderAheadError,
99
+ NonMonotonicBatchError,
100
+ StaleRebaseGenerationError,
101
+ )
102
+
103
+ export type RejectedPushError = typeof RejectedPushError.Type
104
+
105
+ export const isRejectedPushError = (u: unknown): u is RejectedPushError =>
106
+ Predicate.hasProperty(u, RejectedPushErrorTypeId)
@@ -62,7 +62,7 @@ export const configureConnection = (sqliteDb: SqliteDb, { foreignKeys, lockingMo
62
62
  -- disable WAL until we have it working properly
63
63
  -- PRAGMA journal_mode=WAL;
64
64
  PRAGMA page_size=8192;
65
- PRAGMA foreign_keys=${foreignKeys ? 'ON' : 'OFF'};
65
+ PRAGMA foreign_keys=${foreignKeys === true ? 'ON' : 'OFF'};
66
66
  ${lockingMode === undefined ? '' : sql`PRAGMA locking_mode=${lockingMode};`}
67
67
  `,
68
68
  {},
@@ -1,6 +1,8 @@
1
1
  import { LS_DEV, shouldNeverHappen } from '@livestore/utils'
2
2
  import { Chunk, Effect, Option, Schema } from '@livestore/utils/effect'
3
+
3
4
  import type { SqliteDb } from '../adapter-types.ts'
5
+ import { migrateTable } from '../schema-management/migrations.ts'
4
6
  import * as EventSequenceNumber from '../schema/EventSequenceNumber/mod.ts'
5
7
  import * as LiveStoreEvent from '../schema/LiveStoreEvent/mod.ts'
6
8
  import {
@@ -10,7 +12,6 @@ import {
10
12
  SYNC_STATUS_TABLE,
11
13
  } from '../schema/state/sqlite/system-tables/eventlog-tables.ts'
12
14
  import { sessionChangesetMetaTable } from '../schema/state/sqlite/system-tables/state-tables.ts'
13
- import { migrateTable } from '../schema-management/migrations.ts'
14
15
  import { insertRow, updateRows } from '../sql-queries/sql-queries.ts'
15
16
  import type { PreparedBindValues } from '../util.ts'
16
17
  import { sql } from '../util.ts'
@@ -58,13 +59,14 @@ export const getEventsSince = ({
58
59
  sessionChangesetMetaTable.where('seqNumGlobal', '>=', since.global),
59
60
  )
60
61
 
62
+ // Create a Map for O(1) lookup instead of O(n) find
63
+ const sessionChangesetMap = new Map(
64
+ sessionChangesetRowsDecoded.map((row) => [`${row.seqNumGlobal}:${row.seqNumClient}`, row]),
65
+ )
66
+
61
67
  return pendingEvents
62
68
  .map((eventlogEvent) => {
63
- const sessionChangeset = sessionChangesetRowsDecoded.find(
64
- (readModelEvent) =>
65
- readModelEvent.seqNumGlobal === eventlogEvent.seqNumGlobal &&
66
- readModelEvent.seqNumClient === eventlogEvent.seqNumClient,
67
- )
69
+ const sessionChangeset = sessionChangesetMap.get(`${eventlogEvent.seqNumGlobal}:${eventlogEvent.seqNumClient}`)
68
70
  return LiveStoreEvent.Client.EncodedWithMeta.make({
69
71
  name: eventlogEvent.name,
70
72
  args: eventlogEvent.argsJson,
@@ -82,7 +84,7 @@ export const getEventsSince = ({
82
84
  sessionId: eventlogEvent.sessionId,
83
85
  meta: {
84
86
  sessionChangeset:
85
- sessionChangeset && sessionChangeset.changeset !== null
87
+ sessionChangeset !== undefined && sessionChangeset.changeset !== null
86
88
  ? {
87
89
  _tag: 'sessionChangeset' as const,
88
90
  data: sessionChangeset.changeset,
@@ -96,7 +98,7 @@ export const getEventsSince = ({
96
98
  })
97
99
  })
98
100
  .filter((_) => EventSequenceNumber.Client.compare(_.seqNum, since) > 0)
99
- .sort((a, b) => EventSequenceNumber.Client.compare(a.seqNum, b.seqNum))
101
+ .toSorted((a, b) => EventSequenceNumber.Client.compare(a.seqNum, b.seqNum))
100
102
  }
101
103
 
102
104
  export const getEventsFromEventlog = ({
@@ -113,19 +115,19 @@ export const getEventsFromEventlog = ({
113
115
  const makeQuery = () => {
114
116
  let query = eventlogMetaTable.where('seqNumGlobal', '>', since.global)
115
117
 
116
- if (options.until) {
118
+ if (options.until !== undefined) {
117
119
  query = query.where('seqNumGlobal', '<=', options.until.global)
118
120
  }
119
121
 
120
- if (options.filter && options.filter.length > 0) {
122
+ if (options.filter !== undefined && options.filter.length > 0) {
121
123
  query = query.where({ name: { op: 'IN', value: options.filter } })
122
124
  }
123
125
 
124
- if (options.clientIds && options.clientIds.length > 0) {
126
+ if (options.clientIds !== undefined && options.clientIds.length > 0) {
125
127
  query = query.where({ clientId: { op: 'IN', value: options.clientIds } })
126
128
  }
127
129
 
128
- if (options.sessionIds && options.sessionIds.length > 0) {
130
+ if (options.sessionIds !== undefined && options.sessionIds.length > 0) {
129
131
  query = query.where({ sessionId: { op: 'IN', value: options.sessionIds } })
130
132
  }
131
133
 
@@ -185,7 +187,7 @@ export const getClientHeadFromDb = (dbEventlog: SqliteDb): EventSequenceNumber.C
185
187
  sql`select seqNumGlobal, seqNumClient, seqNumRebaseGeneration from ${EVENTLOG_META_TABLE} order by seqNumGlobal DESC, seqNumClient DESC limit 1`,
186
188
  )[0]
187
189
 
188
- return res
190
+ return res !== undefined
189
191
  ? { global: res.seqNumGlobal, client: res.seqNumClient, rebaseGeneration: res.seqNumRebaseGeneration }
190
192
  : EventSequenceNumber.Client.ROOT
191
193
  }
@@ -215,7 +217,7 @@ export const insertIntoEventlog = (
215
217
  ) =>
216
218
  Effect.gen(function* () {
217
219
  // Check history consistency during LS_DEV
218
- if (LS_DEV && eventEncoded.parentSeqNum.global !== EventSequenceNumber.Client.ROOT.global) {
220
+ if (LS_DEV === true && eventEncoded.parentSeqNum.global !== EventSequenceNumber.Client.ROOT.global) {
219
221
  const parentEventExists =
220
222
  dbEventlog.select<{ count: number }>(
221
223
  `SELECT COUNT(*) as count FROM ${EVENTLOG_META_TABLE} WHERE seqNumGlobal = ? AND seqNumClient = ?`,
@@ -8,63 +8,91 @@ import { LeaderThreadCtx } from './types.ts'
8
8
 
9
9
  type SendMessageToDevtools = (message: Devtools.Leader.MessageFromApp) => Effect.Effect<void>
10
10
 
11
- // TODO bind scope to the webchannel lifetime
12
- export const bootDevtools = (options: DevtoolsOptions) =>
13
- Effect.gen(function* () {
14
- if (options.enabled === false) {
15
- return
16
- }
17
-
18
- const { syncProcessor, extraIncomingMessagesQueue, clientId, storeId } = yield* LeaderThreadCtx
19
-
20
- yield* listenToDevtools({
21
- incomingMessages: Stream.fromQueue(extraIncomingMessagesQueue),
22
- sendMessage: () => Effect.void,
23
- }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
24
-
25
- const { node, persistenceInfo, mode } = yield* options.boot
26
-
27
- yield* node.listenForChannel.pipe(
28
- Stream.filter(
29
- (res) =>
30
- Devtools.isChannelName.devtoolsClientLeader(res.channelName, { storeId, clientId }) && res.mode === mode,
31
- ),
32
- Stream.tap(({ channelName, source }) =>
33
- Effect.gen(function* () {
34
- const channel = yield* node.makeChannel({
35
- target: source,
36
- channelName,
37
- schema: { listen: Devtools.Leader.MessageToApp, send: Devtools.Leader.MessageFromApp },
38
- mode,
39
- })
40
-
41
- const sendMessage: SendMessageToDevtools = (message) =>
42
- channel
43
- .send(message)
44
- .pipe(
45
- Effect.withSpan('@livestore/common:leader-thread:devtools:sendToDevtools'),
46
- Effect.interruptible,
47
- Effect.ignoreLogged,
48
- )
49
-
50
- const syncState = yield* syncProcessor.syncState
11
+ /**
12
+ * Type guard for DevtoolsViteNotInstalledError.
13
+ * This error is defined in @livestore/adapter-node but we need to handle it here.
14
+ */
15
+ const isDevtoolsViteNotInstalledError = (
16
+ error: unknown,
17
+ ): error is { _tag: 'DevtoolsViteNotInstalledError'; message: string } =>
18
+ typeof error === 'object' && error !== null && '_tag' in error && error._tag === 'DevtoolsViteNotInstalledError'
51
19
 
52
- yield* syncProcessor.pull({ cursor: syncState.localHead }).pipe(
53
- Stream.tap(({ payload }) => sendMessage(Devtools.Leader.SyncPull.make({ payload, liveStoreVersion }))),
54
- Stream.runDrain,
55
- Effect.forkScoped,
56
- )
57
-
58
- yield* listenToDevtools({
59
- incomingMessages: channel.listen.pipe(Stream.flatten(), Stream.orDie),
60
- sendMessage,
61
- persistenceInfo,
62
- })
63
- }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped),
20
+ // TODO bind scope to the webchannel lifetime
21
+ export const bootDevtools = Effect.fn('@livestore/common:leader-thread:devtools:boot')(function* (
22
+ options: DevtoolsOptions,
23
+ ) {
24
+ if (options.enabled === false) {
25
+ return
26
+ }
27
+
28
+ const { syncProcessor, extraIncomingMessagesQueue, clientId, storeId } = yield* LeaderThreadCtx
29
+
30
+ yield* listenToDevtools({
31
+ incomingMessages: Stream.fromQueue(extraIncomingMessagesQueue),
32
+ sendMessage: () => Effect.void,
33
+ }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
34
+
35
+ const bootResult = yield* options.boot.pipe(
36
+ Effect.map(Option.some),
37
+ Effect.catchIf(isDevtoolsViteNotInstalledError, (error) =>
38
+ Effect.logWarning(`[@livestore/devtools] ${error.message} Devtools will be disabled.`).pipe(
39
+ Effect.as(Option.none()),
64
40
  ),
65
- Stream.runDrain,
66
- )
67
- }).pipe(Effect.withSpan('@livestore/common:leader-thread:devtools:boot'))
41
+ ),
42
+ Effect.catchAllCause((cause) =>
43
+ Effect.logWarning(
44
+ `[@livestore/devtools] Failed to start devtools server. Devtools will be disabled.`,
45
+ cause,
46
+ ).pipe(Effect.as(Option.none())),
47
+ ),
48
+ )
49
+
50
+ if (Option.isNone(bootResult) === true) {
51
+ return
52
+ }
53
+
54
+ const { node, persistenceInfo, mode } = bootResult.value
55
+
56
+ yield* node.listenForChannel.pipe(
57
+ Stream.filter(
58
+ (res) => Devtools.isChannelName.devtoolsClientLeader(res.channelName, { storeId, clientId }) && res.mode === mode,
59
+ ),
60
+ Stream.tap(({ channelName, source }) =>
61
+ Effect.gen(function* () {
62
+ const channel = yield* node.makeChannel({
63
+ target: source,
64
+ channelName,
65
+ schema: { listen: Devtools.Leader.MessageToApp, send: Devtools.Leader.MessageFromApp },
66
+ mode,
67
+ })
68
+
69
+ const sendMessage: SendMessageToDevtools = (message) =>
70
+ channel
71
+ .send(message)
72
+ .pipe(
73
+ Effect.withSpan('@livestore/common:leader-thread:devtools:sendToDevtools'),
74
+ Effect.interruptible,
75
+ Effect.ignoreLogged,
76
+ )
77
+
78
+ const syncState = yield* syncProcessor.syncState
79
+
80
+ yield* syncProcessor.pull({ cursor: syncState.localHead }).pipe(
81
+ Stream.tap(({ payload }) => sendMessage(Devtools.Leader.SyncPull.make({ payload, liveStoreVersion }))),
82
+ Stream.runDrain,
83
+ Effect.forkScoped,
84
+ )
85
+
86
+ yield* listenToDevtools({
87
+ incomingMessages: channel.listen.pipe(Stream.flatten(), Stream.orDie),
88
+ sendMessage,
89
+ persistenceInfo,
90
+ })
91
+ }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped),
92
+ ),
93
+ Stream.runDrain,
94
+ )
95
+ })
68
96
 
69
97
  const listenToDevtools = ({
70
98
  incomingMessages,
@@ -103,7 +131,7 @@ const listenToDevtools = ({
103
131
  loadDatabaseBatchTracker.set(batchId, entry)
104
132
  const finished = entry.has('state') && entry.has('eventlog')
105
133
 
106
- if (finished) {
134
+ if (finished === true) {
107
135
  loadDatabaseBatchTracker.delete(batchId)
108
136
  }
109
137
 
@@ -129,7 +157,7 @@ const listenToDevtools = ({
129
157
  // So far I could only observe this problem with webmesh proxy channels (e.g. for Expo)
130
158
  // Proof: https://share.cleanshot.com/V9G87B0B
131
159
  // Also see `store/devtools.ts` for same problem
132
- if (handledRequestIds.has(requestId)) {
160
+ if (handledRequestIds.has(requestId) === true) {
133
161
  // yield* Effect.logWarning(`Duplicate message`, decodedEvent)
134
162
  return
135
163
  }
@@ -177,24 +205,24 @@ const listenToDevtools = ({
177
205
 
178
206
  let databaseKind: LoadDatabaseKind | undefined
179
207
 
180
- if (tableNames.has(SystemTables.EVENTLOG_META_TABLE)) {
208
+ if (tableNames.has(SystemTables.EVENTLOG_META_TABLE) === true) {
181
209
  databaseKind = 'eventlog'
182
210
  yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
183
- yield* Effect.try(() => void dbEventlog.import(data))
211
+ yield* Effect.try(() => dbEventlog.import(data))
184
212
 
185
213
  if (batchId === undefined) {
186
- yield* Effect.try(() => void dbState.destroy())
214
+ yield* Effect.try(() => dbState.destroy())
187
215
  }
188
216
  } else if (
189
- tableNames.has(SystemTables.SCHEMA_META_TABLE) &&
190
- tableNames.has(SystemTables.SCHEMA_EVENT_DEFS_META_TABLE)
217
+ tableNames.has(SystemTables.SCHEMA_META_TABLE) === true &&
218
+ tableNames.has(SystemTables.SCHEMA_EVENT_DEFS_META_TABLE) === true
191
219
  ) {
192
220
  databaseKind = 'state'
193
221
  yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
194
- yield* Effect.try(() => void dbState.import(data))
222
+ yield* Effect.try(() => dbState.import(data))
195
223
 
196
224
  if (batchId === undefined) {
197
- yield* Effect.try(() => void dbEventlog.destroy())
225
+ yield* Effect.try(() => dbEventlog.destroy())
198
226
  }
199
227
  } else {
200
228
  return yield* Effect.fail({ _tag: 'unsupported-database' } as const)
@@ -210,7 +238,7 @@ const listenToDevtools = ({
210
238
 
211
239
  yield* sendMessage(Devtools.Leader.LoadDatabaseFile.Success.make({ ...reqPayload }))
212
240
 
213
- if (shouldShutdown) {
241
+ if (shouldShutdown === true) {
214
242
  yield* shutdownChannel.send(IntentionalShutdownCause.make({ reason: 'devtools-import' }))
215
243
  }
216
244
  })
@@ -352,7 +380,9 @@ const listenToDevtools = ({
352
380
 
353
381
  yield* Stream.zipLatest(
354
382
  syncBackend.isConnected.changes,
355
- devtools.enabled ? devtools.syncBackendLatchState.changes : Stream.make({ latchClosed: false }),
383
+ devtools.enabled === true
384
+ ? devtools.syncBackendLatchState.changes
385
+ : Stream.make({ latchClosed: false }),
356
386
  ).pipe(
357
387
  Stream.tap(([isConnected, { latchClosed }]) =>
358
388
  sendMessage(
@@ -1,5 +1,5 @@
1
- import { Effect, Stream, SubscriptionRef } from '@livestore/utils/effect'
2
1
  import { Vitest } from '@livestore/utils-dev/node-vitest'
2
+ import { Effect, Stream, SubscriptionRef } from '@livestore/utils/effect'
3
3
 
4
4
  import { makeMockSyncBackend } from '../sync/mock-sync-backend.ts'
5
5
  import type { SyncBackend } from '../sync/sync.ts'
@@ -12,19 +12,19 @@ import {
12
12
  Subscribable,
13
13
  SubscriptionRef,
14
14
  } from '@livestore/utils/effect'
15
+
15
16
  import {
16
17
  type BootStatus,
17
18
  type MakeSqliteDb,
18
19
  type MaterializerHashMismatchError,
19
20
  type SqliteDb,
20
- type SqliteError,
21
21
  UnknownError,
22
22
  } from '../adapter-types.ts'
23
23
  import type { MigrationsReport } from '../defs.ts'
24
24
  import type * as Devtools from '../devtools/mod.ts'
25
25
  import type { LiveStoreSchema } from '../schema/mod.ts'
26
26
  import { EventSequenceNumber, LiveStoreEvent, SystemTables } from '../schema/mod.ts'
27
- import type { InvalidPullError, IsOfflineError, SyncBackend, SyncOptions } from '../sync/sync.ts'
27
+ import type { SyncBackend, SyncOptions } from '../sync/sync.ts'
28
28
  import { SyncState } from '../sync/syncstate.ts'
29
29
  import { sql } from '../util.ts'
30
30
  import * as Eventlog from './eventlog.ts'
@@ -156,9 +156,10 @@ export const makeLeaderThreadLayer = ({
156
156
 
157
157
  // Recreate state database if needed BEFORE creating sync processor
158
158
  // This ensures all system tables exist before any queries are made
159
- const { migrationsReport } = dbStateMissing
160
- ? yield* recreateDb({ dbState, dbEventlog, schema, bootStatusQueue, materializeEvent })
161
- : { migrationsReport: { migrations: [] } }
159
+ const { migrationsReport } =
160
+ dbStateMissing === true
161
+ ? yield* recreateDb({ dbState, dbEventlog, schema, bootStatusQueue, materializeEvent })
162
+ : { migrationsReport: { migrations: [] } }
162
163
 
163
164
  const syncProcessor = yield* makeLeaderSyncProcessor({
164
165
  schema,
@@ -166,6 +167,7 @@ export const makeLeaderThreadLayer = ({
166
167
  initialSyncState: getInitialSyncState({ dbEventlog, dbState, dbEventlogMissing }),
167
168
  initialBlockingSyncContext,
168
169
  onError: syncOptions?.onSyncError ?? 'ignore',
170
+ onBackendIdMismatch: syncOptions?.onBackendIdMismatch ?? 'reset',
169
171
  livePull: syncOptions?.livePull ?? true,
170
172
  params: {
171
173
  ...omitUndefineds({
@@ -182,13 +184,14 @@ export const makeLeaderThreadLayer = ({
182
184
  Effect.acquireRelease(Queue.shutdown),
183
185
  )
184
186
 
185
- const devtoolsContext = devtoolsOptions.enabled
186
- ? {
187
- enabled: true as const,
188
- syncBackendLatch: yield* Effect.makeLatch(true),
189
- syncBackendLatchState: yield* SubscriptionRef.make<{ latchClosed: boolean }>({ latchClosed: false }),
190
- }
191
- : { enabled: false as const }
187
+ const devtoolsContext =
188
+ devtoolsOptions.enabled === true
189
+ ? {
190
+ enabled: true as const,
191
+ syncBackendLatch: yield* Effect.makeLatch(true),
192
+ syncBackendLatchState: yield* SubscriptionRef.make<{ latchClosed: boolean }>({ latchClosed: false }),
193
+ }
194
+ : { enabled: false as const }
192
195
 
193
196
  const networkStatus = yield* makeNetworkStatusSubscribable({ syncBackend, devtoolsContext })
194
197
 
@@ -247,7 +250,7 @@ const hasStateTables = (db: SqliteDb) => {
247
250
 
248
251
  const isSubsetOf = (a: Set<string>, b: Set<string>): boolean => {
249
252
  for (const item of a) {
250
- if (!b.has(item)) {
253
+ if (b.has(item) === false) {
251
254
  return false
252
255
  }
253
256
  }
@@ -264,13 +267,11 @@ const getInitialSyncState = ({
264
267
  dbState: SqliteDb
265
268
  dbEventlogMissing: boolean
266
269
  }) => {
267
- const initialBackendHead = dbEventlogMissing
268
- ? EventSequenceNumber.Client.ROOT.global
269
- : Eventlog.getBackendHeadFromDb(dbEventlog)
270
+ const initialBackendHead =
271
+ dbEventlogMissing === true ? EventSequenceNumber.Client.ROOT.global : Eventlog.getBackendHeadFromDb(dbEventlog)
270
272
 
271
- const initialLocalHead = dbEventlogMissing
272
- ? EventSequenceNumber.Client.ROOT
273
- : Eventlog.getClientHeadFromDb(dbEventlog)
273
+ const initialLocalHead =
274
+ dbEventlogMissing === true ? EventSequenceNumber.Client.ROOT : Eventlog.getClientHeadFromDb(dbEventlog)
274
275
 
275
276
  if (initialBackendHead > initialLocalHead.global) {
276
277
  return shouldNeverHappen(
@@ -285,17 +286,18 @@ const getInitialSyncState = ({
285
286
  client: EventSequenceNumber.Client.DEFAULT,
286
287
  rebaseGeneration: EventSequenceNumber.Client.REBASE_GENERATION_DEFAULT,
287
288
  },
288
- pending: dbEventlogMissing
289
- ? []
290
- : Eventlog.getEventsSince({
291
- dbEventlog,
292
- dbState,
293
- since: {
294
- global: initialBackendHead,
295
- client: EventSequenceNumber.Client.DEFAULT,
296
- rebaseGeneration: initialLocalHead.rebaseGeneration,
297
- },
298
- }),
289
+ pending:
290
+ dbEventlogMissing === true
291
+ ? []
292
+ : Eventlog.getEventsSince({
293
+ dbEventlog,
294
+ dbState,
295
+ since: {
296
+ global: initialBackendHead,
297
+ client: EventSequenceNumber.Client.DEFAULT,
298
+ rebaseGeneration: initialLocalHead.rebaseGeneration,
299
+ },
300
+ }),
299
301
  })
300
302
  }
301
303
 
@@ -360,7 +362,7 @@ const bootLeaderThread = ({
360
362
  devtoolsOptions: DevtoolsOptions
361
363
  }): Effect.Effect<
362
364
  LeaderThreadCtx['Type']['initialState'],
363
- UnknownError | SqliteError | IsOfflineError | InvalidPullError | MaterializerHashMismatchError,
365
+ UnknownError | MaterializerHashMismatchError,
364
366
  LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient
365
367
  > =>
366
368
  Effect.gen(function* () {
@@ -73,7 +73,7 @@ export const makeMaterializeEvent = ({
73
73
  event: { decoded: undefined, encoded: eventEncoded },
74
74
  })
75
75
 
76
- const materializerHash = isDevEnv() ? Option.some(hashMaterializerResults(execArgsArr)) : Option.none()
76
+ const materializerHash = isDevEnv() === true ? Option.some(hashMaterializerResults(execArgsArr)) : Option.none()
77
77
 
78
78
  if (
79
79
  materializerHash._tag === 'Some' &&
@@ -119,7 +119,7 @@ export const makeMaterializeEvent = ({
119
119
  seqNumRebaseGeneration: eventEncoded.seqNum.rebaseGeneration,
120
120
  // NOTE the changeset will be empty (i.e. null) for no-op events
121
121
  changeset: changeset ?? null,
122
- debug: LS_DEV ? execArgsArr : null,
122
+ debug: LS_DEV === true ? execArgsArr : null,
123
123
  },
124
124
  }),
125
125
  )
@@ -144,11 +144,11 @@ export const makeMaterializeEvent = ({
144
144
  }
145
145
 
146
146
  return {
147
- sessionChangeset: changeset
147
+ sessionChangeset: changeset !== undefined
148
148
  ? {
149
149
  _tag: 'sessionChangeset' as const,
150
150
  data: changeset,
151
- debug: LS_DEV ? execArgsArr : null,
151
+ debug: LS_DEV === true ? execArgsArr : null,
152
152
  }
153
153
  : { _tag: 'no-op' as const },
154
154
  hash: materializerHash,
@@ -31,7 +31,7 @@ export const recreateDb = ({
31
31
  }): Effect.Effect<{ migrationsReport: MigrationsReport }, UnknownError | MaterializeError | SqliteError> =>
32
32
  Effect.gen(function* () {
33
33
  const migrationOptions = schema.state.sqlite.migrations
34
- let migrationsReport: MigrationsReport
34
+ let migrationsReport: MigrationsReport = { migrations: [] }
35
35
 
36
36
  yield* Effect.addFinalizer(
37
37
  Effect.fn('recreateDb:finalizer')(function* (ex) {
@@ -2,10 +2,8 @@ import type { WebChannel } from '@livestore/utils/effect'
2
2
  import { Schema } from '@livestore/utils/effect'
3
3
 
4
4
  import {
5
+ BackendIdMismatchError,
5
6
  IntentionalShutdownCause,
6
- InvalidPullError,
7
- InvalidPushError,
8
- IsOfflineError,
9
7
  MaterializeError,
10
8
  UnknownError,
11
9
  } from '../index.ts'
@@ -13,9 +11,7 @@ import {
13
11
  export class All extends Schema.Union(
14
12
  IntentionalShutdownCause,
15
13
  UnknownError,
16
- IsOfflineError,
17
- InvalidPushError,
18
- InvalidPullError,
14
+ BackendIdMismatchError,
19
15
  MaterializeError,
20
16
  ) {}
21
17