@livestore/common 0.4.0 → 0.5.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (421) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ClientSessionLeaderThreadProxy.d.ts +1 -1
  3. package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
  4. package/dist/MaterializationJournal.d.ts +44 -0
  5. package/dist/MaterializationJournal.d.ts.map +1 -0
  6. package/dist/MaterializationJournal.js +112 -0
  7. package/dist/MaterializationJournal.js.map +1 -0
  8. package/dist/StateHead.d.ts +26 -0
  9. package/dist/StateHead.d.ts.map +1 -0
  10. package/dist/StateHead.js +50 -0
  11. package/dist/StateHead.js.map +1 -0
  12. package/dist/WorkerTransportError.d.ts +3 -3
  13. package/dist/WorkerTransportError.d.ts.map +1 -1
  14. package/dist/WorkerTransportError.js +3 -3
  15. package/dist/WorkerTransportError.js.map +1 -1
  16. package/dist/__tests__/fixture.d.ts +1 -1
  17. package/dist/__tests__/fixture.d.ts.map +1 -1
  18. package/dist/__tests__/fixture.js +3 -3
  19. package/dist/__tests__/fixture.js.map +1 -1
  20. package/dist/adapter-types.d.ts +29 -57
  21. package/dist/adapter-types.d.ts.map +1 -1
  22. package/dist/adapter-types.js +20 -37
  23. package/dist/adapter-types.js.map +1 -1
  24. package/dist/debug-info.d.ts +56 -56
  25. package/dist/debug-info.d.ts.map +1 -1
  26. package/dist/debug-info.js +28 -41
  27. package/dist/debug-info.js.map +1 -1
  28. package/dist/defs.d.ts +9 -9
  29. package/dist/defs.js +2 -2
  30. package/dist/devtools/devtools-compatibility.test.js +1 -0
  31. package/dist/devtools/devtools-compatibility.test.js.map +1 -1
  32. package/dist/devtools/devtools-messages-client-session.d.ts +520 -332
  33. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
  34. package/dist/devtools/devtools-messages-client-session.js +76 -74
  35. package/dist/devtools/devtools-messages-client-session.js.map +1 -1
  36. package/dist/devtools/devtools-messages-common.d.ts +27 -27
  37. package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
  38. package/dist/devtools/devtools-messages-common.js +5 -5
  39. package/dist/devtools/devtools-messages-common.js.map +1 -1
  40. package/dist/devtools/devtools-messages-leader.d.ts +405 -343
  41. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
  42. package/dist/devtools/devtools-messages-leader.js +101 -89
  43. package/dist/devtools/devtools-messages-leader.js.map +1 -1
  44. package/dist/devtools/devtools-sessioninfo.d.ts +18 -19
  45. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
  46. package/dist/devtools/devtools-sessioninfo.js +8 -5
  47. package/dist/devtools/devtools-sessioninfo.js.map +1 -1
  48. package/dist/devtools/mod.d.ts +4 -5
  49. package/dist/devtools/mod.d.ts.map +1 -1
  50. package/dist/devtools/mod.js +9 -5
  51. package/dist/devtools/mod.js.map +1 -1
  52. package/dist/errors.d.ts +45 -69
  53. package/dist/errors.d.ts.map +1 -1
  54. package/dist/errors.js +18 -16
  55. package/dist/errors.js.map +1 -1
  56. package/dist/index.d.ts +4 -1
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +4 -1
  59. package/dist/index.js.map +1 -1
  60. package/dist/leader-thread/LeaderSyncProcessor.d.ts +66 -18
  61. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  62. package/dist/leader-thread/LeaderSyncProcessor.js +519 -461
  63. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  64. package/dist/leader-thread/RejectedPushError.d.ts +67 -36
  65. package/dist/leader-thread/RejectedPushError.d.ts.map +1 -1
  66. package/dist/leader-thread/RejectedPushError.js +24 -5
  67. package/dist/leader-thread/RejectedPushError.js.map +1 -1
  68. package/dist/leader-thread/connection.d.ts +1 -0
  69. package/dist/leader-thread/connection.d.ts.map +1 -1
  70. package/dist/leader-thread/connection.js +9 -8
  71. package/dist/leader-thread/connection.js.map +1 -1
  72. package/dist/leader-thread/eventlog.d.ts +4 -4
  73. package/dist/leader-thread/eventlog.d.ts.map +1 -1
  74. package/dist/leader-thread/eventlog.js +6 -6
  75. package/dist/leader-thread/eventlog.js.map +1 -1
  76. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  77. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  78. package/dist/leader-thread/leader-worker-devtools.js +33 -17
  79. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  80. package/dist/leader-thread/make-leader-thread-layer.d.ts +9 -5
  81. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  82. package/dist/leader-thread/make-leader-thread-layer.js +25 -35
  83. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  84. package/dist/leader-thread/make-leader-thread-layer.test.js +7 -7
  85. package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -1
  86. package/dist/leader-thread/materialize-event.d.ts +2 -1
  87. package/dist/leader-thread/materialize-event.d.ts.map +1 -1
  88. package/dist/leader-thread/materialize-event.js +4 -0
  89. package/dist/leader-thread/materialize-event.js.map +1 -1
  90. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  91. package/dist/leader-thread/recreate-db.js +18 -39
  92. package/dist/leader-thread/recreate-db.js.map +1 -1
  93. package/dist/leader-thread/shutdown-channel.d.ts +2 -6
  94. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  95. package/dist/leader-thread/shutdown-channel.js +2 -3
  96. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  97. package/dist/leader-thread/stream-events.d.ts +4 -7
  98. package/dist/leader-thread/stream-events.d.ts.map +1 -1
  99. package/dist/leader-thread/stream-events.js +13 -16
  100. package/dist/leader-thread/stream-events.js.map +1 -1
  101. package/dist/leader-thread/types.d.ts +32 -69
  102. package/dist/leader-thread/types.d.ts.map +1 -1
  103. package/dist/leader-thread/types.js +5 -5
  104. package/dist/leader-thread/types.js.map +1 -1
  105. package/dist/logging.d.ts +5 -30
  106. package/dist/logging.d.ts.map +1 -1
  107. package/dist/logging.js +1 -32
  108. package/dist/logging.js.map +1 -1
  109. package/dist/make-client-session.d.ts +1 -2
  110. package/dist/make-client-session.d.ts.map +1 -1
  111. package/dist/make-client-session.js +3 -3
  112. package/dist/make-client-session.js.map +1 -1
  113. package/dist/materializer-helper.d.ts +0 -1
  114. package/dist/materializer-helper.d.ts.map +1 -1
  115. package/dist/materializer-helper.js +7 -35
  116. package/dist/materializer-helper.js.map +1 -1
  117. package/dist/otel.d.ts +2 -3
  118. package/dist/otel.d.ts.map +1 -1
  119. package/dist/otel.js +2 -7
  120. package/dist/otel.js.map +1 -1
  121. package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
  122. package/dist/rematerialize-from-eventlog.js +28 -26
  123. package/dist/rematerialize-from-eventlog.js.map +1 -1
  124. package/dist/schema/EventDef/define.d.ts +4 -4
  125. package/dist/schema/EventDef/define.d.ts.map +1 -1
  126. package/dist/schema/EventDef/define.js +5 -5
  127. package/dist/schema/EventDef/define.js.map +1 -1
  128. package/dist/schema/EventDef/define.test.d.ts +2 -0
  129. package/dist/schema/EventDef/define.test.d.ts.map +1 -0
  130. package/dist/schema/EventDef/define.test.js +23 -0
  131. package/dist/schema/EventDef/define.test.js.map +1 -0
  132. package/dist/schema/EventDef/deprecated.d.ts +8 -13
  133. package/dist/schema/EventDef/deprecated.d.ts.map +1 -1
  134. package/dist/schema/EventDef/deprecated.js +12 -13
  135. package/dist/schema/EventDef/deprecated.js.map +1 -1
  136. package/dist/schema/EventDef/deprecated.test.js +1 -1
  137. package/dist/schema/EventDef/deprecated.test.js.map +1 -1
  138. package/dist/schema/EventDef/event-def.d.ts +1 -1
  139. package/dist/schema/EventDef/event-def.d.ts.map +1 -1
  140. package/dist/schema/EventSequenceNumber/client.d.ts +12 -12
  141. package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -1
  142. package/dist/schema/EventSequenceNumber/client.js +8 -9
  143. package/dist/schema/EventSequenceNumber/client.js.map +1 -1
  144. package/dist/schema/EventSequenceNumber/global.d.ts +2 -2
  145. package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -1
  146. package/dist/schema/EventSequenceNumber/global.js +1 -1
  147. package/dist/schema/EventSequenceNumber/global.js.map +1 -1
  148. package/dist/schema/EventSequenceNumber.test.js +5 -5
  149. package/dist/schema/EventSequenceNumber.test.js.map +1 -1
  150. package/dist/schema/LiveStoreEvent/client.d.ts +50 -179
  151. package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -1
  152. package/dist/schema/LiveStoreEvent/client.js +32 -29
  153. package/dist/schema/LiveStoreEvent/client.js.map +1 -1
  154. package/dist/schema/LiveStoreEvent/client.test.js +11 -2
  155. package/dist/schema/LiveStoreEvent/client.test.js.map +1 -1
  156. package/dist/schema/LiveStoreEvent/for-event-def.d.ts +7 -7
  157. package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -1
  158. package/dist/schema/LiveStoreEvent/global.d.ts +6 -6
  159. package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -1
  160. package/dist/schema/LiveStoreEvent/global.js +1 -1
  161. package/dist/schema/LiveStoreEvent/global.js.map +1 -1
  162. package/dist/schema/LiveStoreEvent/input.d.ts +5 -5
  163. package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -1
  164. package/dist/schema/LiveStoreEvent/input.js +3 -3
  165. package/dist/schema/LiveStoreEvent/input.js.map +1 -1
  166. package/dist/schema/mod.d.ts +1 -0
  167. package/dist/schema/mod.d.ts.map +1 -1
  168. package/dist/schema/mod.js +1 -0
  169. package/dist/schema/mod.js.map +1 -1
  170. package/dist/schema/schema.d.ts.map +1 -1
  171. package/dist/schema/schema.js +3 -2
  172. package/dist/schema/schema.js.map +1 -1
  173. package/dist/schema/state/sqlite/client-document-def.d.ts +12 -17
  174. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  175. package/dist/schema/state/sqlite/client-document-def.js +23 -20
  176. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  177. package/dist/schema/state/sqlite/client-document-def.test.js +29 -8
  178. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
  179. package/dist/schema/state/sqlite/column-annotations.d.ts +13 -13
  180. package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
  181. package/dist/schema/state/sqlite/column-annotations.js +13 -15
  182. package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
  183. package/dist/schema/state/sqlite/column-annotations.test.js +19 -43
  184. package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
  185. package/dist/schema/state/sqlite/column-def.d.ts +1 -1
  186. package/dist/schema/state/sqlite/column-def.d.ts.map +1 -1
  187. package/dist/schema/state/sqlite/column-def.js +57 -31
  188. package/dist/schema/state/sqlite/column-def.js.map +1 -1
  189. package/dist/schema/state/sqlite/column-def.test.js +118 -72
  190. package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
  191. package/dist/schema/state/sqlite/column-spec.js.map +1 -1
  192. package/dist/schema/state/sqlite/column-spec.test.js +2 -2
  193. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +2 -2
  194. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -1
  195. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +13 -4
  196. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
  197. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +9 -9
  198. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
  199. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +8 -13
  200. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
  201. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +27 -16
  202. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -1
  203. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +13 -11
  204. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
  205. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +5 -3
  206. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
  207. package/dist/schema/state/sqlite/mod.d.ts +1 -3
  208. package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
  209. package/dist/schema/state/sqlite/mod.js +1 -1
  210. package/dist/schema/state/sqlite/mod.js.map +1 -1
  211. package/dist/schema/state/sqlite/persistence.d.ts +11 -0
  212. package/dist/schema/state/sqlite/persistence.d.ts.map +1 -0
  213. package/dist/schema/state/sqlite/persistence.js +10 -0
  214. package/dist/schema/state/sqlite/persistence.js.map +1 -0
  215. package/dist/schema/state/sqlite/query-builder/api.d.ts +7 -7
  216. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
  217. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
  218. package/dist/schema/state/sqlite/query-builder/astToSql.js +27 -23
  219. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
  220. package/dist/schema/state/sqlite/query-builder/impl.d.ts +3 -1
  221. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
  222. package/dist/schema/state/sqlite/query-builder/impl.js +16 -14
  223. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
  224. package/dist/schema/state/sqlite/query-builder/impl.test.js +362 -596
  225. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  226. package/dist/schema/state/sqlite/schema-helpers.js +1 -1
  227. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
  228. package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts +102 -134
  229. package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts.map +1 -1
  230. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +2 -2
  231. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -1
  232. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +328 -106
  233. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -1
  234. package/dist/schema/state/sqlite/system-tables/state-tables.js +33 -1
  235. package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -1
  236. package/dist/schema/state/sqlite/table-def.d.ts +16 -19
  237. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  238. package/dist/schema/state/sqlite/table-def.js +53 -3
  239. package/dist/schema/state/sqlite/table-def.js.map +1 -1
  240. package/dist/schema/state/sqlite/table-def.test.js +153 -36
  241. package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
  242. package/dist/schema/unknown-events.d.ts.map +1 -1
  243. package/dist/schema/unknown-events.js +2 -1
  244. package/dist/schema/unknown-events.js.map +1 -1
  245. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +2 -2
  246. package/dist/session-id-symbol.d.ts +29 -0
  247. package/dist/session-id-symbol.d.ts.map +1 -0
  248. package/dist/session-id-symbol.js +44 -0
  249. package/dist/session-id-symbol.js.map +1 -0
  250. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  251. package/dist/sql-queries/sql-queries.js +8 -10
  252. package/dist/sql-queries/sql-queries.js.map +1 -1
  253. package/dist/sql-queries/types.d.ts +6 -7
  254. package/dist/sql-queries/types.d.ts.map +1 -1
  255. package/dist/sql-queries/types.js.map +1 -1
  256. package/dist/sqlite-db-helper.d.ts +21 -1
  257. package/dist/sqlite-db-helper.d.ts.map +1 -1
  258. package/dist/sqlite-db-helper.js +37 -2
  259. package/dist/sqlite-db-helper.js.map +1 -1
  260. package/dist/sqlite-types.d.ts +3 -6
  261. package/dist/sqlite-types.d.ts.map +1 -1
  262. package/dist/sqlite-types.js +3 -3
  263. package/dist/sqlite-types.js.map +1 -1
  264. package/dist/sync/ClientSessionSyncProcessor.d.ts +38 -16
  265. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  266. package/dist/sync/ClientSessionSyncProcessor.js +196 -66
  267. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  268. package/dist/sync/errors.d.ts +12 -18
  269. package/dist/sync/errors.d.ts.map +1 -1
  270. package/dist/sync/errors.js +2 -2
  271. package/dist/sync/errors.js.map +1 -1
  272. package/dist/sync/mock-sync-backend.d.ts +2 -3
  273. package/dist/sync/mock-sync-backend.d.ts.map +1 -1
  274. package/dist/sync/mock-sync-backend.js +54 -33
  275. package/dist/sync/mock-sync-backend.js.map +1 -1
  276. package/dist/sync/mock-sync-backend.test.d.ts +2 -0
  277. package/dist/sync/mock-sync-backend.test.d.ts.map +1 -0
  278. package/dist/sync/mock-sync-backend.test.js +49 -0
  279. package/dist/sync/mock-sync-backend.test.js.map +1 -0
  280. package/dist/sync/next/history-dag-common.d.ts +4 -0
  281. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  282. package/dist/sync/next/history-dag-common.js +52 -31
  283. package/dist/sync/next/history-dag-common.js.map +1 -1
  284. package/dist/sync/next/history-dag.d.ts.map +1 -1
  285. package/dist/sync/next/history-dag.js +2 -1
  286. package/dist/sync/next/history-dag.js.map +1 -1
  287. package/dist/sync/next/test/compact-events.calculator.test.js +2 -2
  288. package/dist/sync/next/test/event-fixtures.d.ts +7 -7
  289. package/dist/sync/next/test/event-fixtures.js +1 -1
  290. package/dist/sync/next/test/event-fixtures.js.map +1 -1
  291. package/dist/sync/next/test/history-dag-common.test.d.ts +2 -0
  292. package/dist/sync/next/test/history-dag-common.test.d.ts.map +1 -0
  293. package/dist/sync/next/test/history-dag-common.test.js +73 -0
  294. package/dist/sync/next/test/history-dag-common.test.js.map +1 -0
  295. package/dist/sync/sync-backend-kv.d.ts.map +1 -1
  296. package/dist/sync/sync-backend-kv.js +4 -2
  297. package/dist/sync/sync-backend-kv.js.map +1 -1
  298. package/dist/sync/sync-backend.d.ts +15 -15
  299. package/dist/sync/sync-backend.d.ts.map +1 -1
  300. package/dist/sync/sync-backend.js +9 -5
  301. package/dist/sync/sync-backend.js.map +1 -1
  302. package/dist/sync/sync.d.ts +1 -1
  303. package/dist/sync/sync.d.ts.map +1 -1
  304. package/dist/sync/syncstate.d.ts +97 -173
  305. package/dist/sync/syncstate.d.ts.map +1 -1
  306. package/dist/sync/syncstate.js +34 -37
  307. package/dist/sync/syncstate.js.map +1 -1
  308. package/dist/sync/syncstate.test.js +100 -61
  309. package/dist/sync/syncstate.test.js.map +1 -1
  310. package/dist/sync/transport-chunking.d.ts +15 -16
  311. package/dist/sync/transport-chunking.d.ts.map +1 -1
  312. package/dist/sync/transport-chunking.js +23 -32
  313. package/dist/sync/transport-chunking.js.map +1 -1
  314. package/dist/util.d.ts +11 -4
  315. package/dist/util.d.ts.map +1 -1
  316. package/dist/util.js +19 -2
  317. package/dist/util.js.map +1 -1
  318. package/dist/version.d.ts.map +1 -1
  319. package/dist/version.js.map +1 -1
  320. package/package.json +19 -37
  321. package/src/ClientSessionLeaderThreadProxy.ts +1 -1
  322. package/src/MaterializationJournal.ts +184 -0
  323. package/src/StateHead.ts +80 -0
  324. package/src/WorkerTransportError.ts +4 -4
  325. package/src/__tests__/fixture.ts +3 -3
  326. package/src/adapter-types.ts +24 -61
  327. package/src/debug-info.ts +50 -70
  328. package/src/defs.ts +2 -2
  329. package/src/devtools/devtools-compatibility.test.ts +1 -0
  330. package/src/devtools/devtools-messages-client-session.ts +56 -65
  331. package/src/devtools/devtools-messages-common.ts +12 -11
  332. package/src/devtools/devtools-messages-leader.ts +71 -69
  333. package/src/devtools/devtools-sessioninfo.ts +13 -11
  334. package/src/devtools/mod.ts +4 -5
  335. package/src/errors.ts +46 -34
  336. package/src/index.ts +8 -1
  337. package/src/leader-thread/LeaderSyncProcessor.ts +794 -691
  338. package/src/leader-thread/RejectedPushError.ts +40 -27
  339. package/src/leader-thread/connection.ts +12 -8
  340. package/src/leader-thread/eventlog.ts +7 -7
  341. package/src/leader-thread/leader-worker-devtools.ts +37 -19
  342. package/src/leader-thread/make-leader-thread-layer.test.ts +7 -7
  343. package/src/leader-thread/make-leader-thread-layer.ts +56 -53
  344. package/src/leader-thread/materialize-event.ts +13 -8
  345. package/src/leader-thread/recreate-db.ts +24 -59
  346. package/src/leader-thread/shutdown-channel.ts +3 -14
  347. package/src/leader-thread/stream-events.ts +104 -101
  348. package/src/leader-thread/types.ts +24 -62
  349. package/src/logging.ts +5 -52
  350. package/src/make-client-session.ts +6 -6
  351. package/src/materializer-helper.ts +8 -37
  352. package/src/otel.ts +5 -14
  353. package/src/rematerialize-from-eventlog.ts +97 -94
  354. package/src/schema/EventDef/define.test.ts +28 -0
  355. package/src/schema/EventDef/define.ts +20 -19
  356. package/src/schema/EventDef/deprecated.test.ts +1 -8
  357. package/src/schema/EventDef/deprecated.ts +17 -20
  358. package/src/schema/EventDef/event-def.ts +2 -4
  359. package/src/schema/EventSequenceNumber/client.ts +8 -9
  360. package/src/schema/EventSequenceNumber/global.ts +1 -1
  361. package/src/schema/EventSequenceNumber.test.ts +5 -5
  362. package/src/schema/LiveStoreEvent/client.test.ts +17 -4
  363. package/src/schema/LiveStoreEvent/client.ts +36 -35
  364. package/src/schema/LiveStoreEvent/for-event-def.ts +7 -7
  365. package/src/schema/LiveStoreEvent/global.ts +1 -1
  366. package/src/schema/LiveStoreEvent/input.ts +6 -6
  367. package/src/schema/mod.ts +1 -0
  368. package/src/schema/schema.ts +3 -2
  369. package/src/schema/state/sqlite/client-document-def.test.ts +32 -13
  370. package/src/schema/state/sqlite/client-document-def.ts +95 -80
  371. package/src/schema/state/sqlite/column-annotations.test.ts +26 -45
  372. package/src/schema/state/sqlite/column-annotations.ts +26 -30
  373. package/src/schema/state/sqlite/column-def.test.ts +132 -77
  374. package/src/schema/state/sqlite/column-def.ts +72 -37
  375. package/src/schema/state/sqlite/column-spec.test.ts +2 -2
  376. package/src/schema/state/sqlite/column-spec.ts +3 -2
  377. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +15 -5
  378. package/src/schema/state/sqlite/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +123 -63
  379. package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +35 -16
  380. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +25 -31
  381. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +35 -21
  382. package/src/schema/state/sqlite/mod.ts +2 -4
  383. package/src/schema/state/sqlite/persistence.ts +11 -0
  384. package/src/schema/state/sqlite/query-builder/api.ts +9 -9
  385. package/src/schema/state/sqlite/query-builder/astToSql.ts +31 -26
  386. package/src/schema/state/sqlite/query-builder/impl.test.ts +433 -669
  387. package/src/schema/state/sqlite/query-builder/impl.ts +19 -15
  388. package/src/schema/state/sqlite/schema-helpers.ts +1 -1
  389. package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +2 -2
  390. package/src/schema/state/sqlite/system-tables/state-tables.ts +41 -1
  391. package/src/schema/state/sqlite/table-def.test.ts +204 -66
  392. package/src/schema/state/sqlite/table-def.ts +96 -45
  393. package/src/schema/unknown-events.ts +3 -2
  394. package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +2 -2
  395. package/src/session-id-symbol.ts +59 -0
  396. package/src/sql-queries/sql-queries.ts +8 -12
  397. package/src/sql-queries/types.ts +6 -7
  398. package/src/sqlite-db-helper.ts +64 -2
  399. package/src/sqlite-types.ts +5 -8
  400. package/src/sync/ClientSessionSyncProcessor.ts +303 -119
  401. package/src/sync/errors.ts +14 -12
  402. package/src/sync/mock-sync-backend.test.ts +78 -0
  403. package/src/sync/mock-sync-backend.ts +93 -47
  404. package/src/sync/next/history-dag-common.ts +60 -34
  405. package/src/sync/next/history-dag.ts +4 -1
  406. package/src/sync/next/test/compact-events.calculator.test.ts +2 -2
  407. package/src/sync/next/test/event-fixtures.ts +1 -1
  408. package/src/sync/next/test/history-dag-common.test.ts +87 -0
  409. package/src/sync/sync-backend-kv.ts +4 -2
  410. package/src/sync/sync-backend.ts +15 -15
  411. package/src/sync/sync.ts +1 -1
  412. package/src/sync/syncstate.test.ts +191 -140
  413. package/src/sync/syncstate.ts +63 -53
  414. package/src/sync/transport-chunking.ts +34 -39
  415. package/src/util.ts +18 -9
  416. package/src/version.ts +1 -2
  417. package/dist/sql-queries/misc.d.ts +0 -2
  418. package/dist/sql-queries/misc.d.ts.map +0 -1
  419. package/dist/sql-queries/misc.js +0 -2
  420. package/dist/sql-queries/misc.js.map +0 -1
  421. package/src/sql-queries/misc.ts +0 -2
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Push validation errors returned by {@link LeaderSyncProcessor.push}.
3
3
  *
4
- * All three errors share a common {@link RejectedPushErrorTypeId} so consumers can catch the
4
+ * All errors share a common {@link RejectedPushErrorTypeId} so consumers can catch the
5
5
  * family as a group via {@link isRejectedPushError} instead of matching individual tags.
6
6
  * Recovery is the same in every case: the client should rebase and retry.
7
7
  *
@@ -23,19 +23,16 @@ export const RejectedPushErrorTypeId = '~@livestore/common/RejectedPushError' as
23
23
  */
24
24
  export class NonMonotonicBatchError extends Schema.TaggedError<NonMonotonicBatchError>(
25
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
- ) {
26
+ )('NonMonotonicBatchError', {
27
+ /** The sequence number that broke the monotonic invariant (i.e. the one that is >= the next). */
28
+ precedingSeqNum: EventSequenceNumber.Client.Composite,
29
+ /** The sequence number that was expected to be greater than `precedingSeqNum`. */
30
+ violatingSeqNum: EventSequenceNumber.Client.Composite,
31
+ /** The index in the batch where the violation occurred. */
32
+ violationIndex: Schema.Finite,
33
+ /** The session that produced the malformed batch. */
34
+ sessionId: Schema.String,
35
+ }) {
39
36
  readonly [RejectedPushErrorTypeId] = RejectedPushErrorTypeId
40
37
 
41
38
  override get message(): string {
@@ -43,6 +40,24 @@ export class NonMonotonicBatchError extends Schema.TaggedError<NonMonotonicBatch
43
40
  }
44
41
  }
45
42
 
43
+ /** A pushed batch skips an event required to connect it to the leader's admitted push prefix. */
44
+ export class NonContiguousBatchError extends Schema.TaggedError<NonContiguousBatchError>(
45
+ `${RejectedPushErrorTypeId}/NonContiguousBatchError`,
46
+ )('NonContiguousBatchError', {
47
+ expectedSeqNum: EventSequenceNumber.Client.Composite,
48
+ providedSeqNum: EventSequenceNumber.Client.Composite,
49
+ expectedParentSeqNum: EventSequenceNumber.Client.Composite,
50
+ providedParentSeqNum: EventSequenceNumber.Client.Composite,
51
+ violationIndex: Schema.Finite,
52
+ sessionId: Schema.String,
53
+ }) {
54
+ readonly [RejectedPushErrorTypeId] = RejectedPushErrorTypeId
55
+
56
+ override get message(): string {
57
+ return `Pushed events are not contiguous at index ${this.violationIndex} (session ${this.sessionId}): expected ${EventSequenceNumber.Client.toString(this.expectedSeqNum)} after ${EventSequenceNumber.Client.toString(this.expectedParentSeqNum)}, got ${EventSequenceNumber.Client.toString(this.providedSeqNum)} after ${EventSequenceNumber.Client.toString(this.providedParentSeqNum)}`
58
+ }
59
+ }
60
+
46
61
  /**
47
62
  * A pushed batch of events failed validation because its rebase generation is older than the leader's current rebase generation.
48
63
  *
@@ -52,17 +67,14 @@ export class NonMonotonicBatchError extends Schema.TaggedError<NonMonotonicBatch
52
67
  */
53
68
  export class StaleRebaseGenerationError extends Schema.TaggedError<StaleRebaseGenerationError>(
54
69
  `${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
- ) {
70
+ )('StaleRebaseGenerationError', {
71
+ /** The leader's current rebase generation. */
72
+ currentRebaseGeneration: Schema.Finite,
73
+ /** The rebase generation carried by the dropped events. */
74
+ providedRebaseGeneration: Schema.Finite,
75
+ /** The session that produced the stale batch. */
76
+ sessionId: Schema.String,
77
+ }) {
66
78
  readonly [RejectedPushErrorTypeId] = RejectedPushErrorTypeId
67
79
 
68
80
  override get message(): string {
@@ -94,11 +106,12 @@ export class LeaderAheadError extends Schema.TaggedError<LeaderAheadError>(
94
106
  }
95
107
  }
96
108
 
97
- export const RejectedPushError = Schema.Union(
109
+ export const RejectedPushError = Schema.Union([
98
110
  LeaderAheadError,
111
+ NonContiguousBatchError,
99
112
  NonMonotonicBatchError,
100
113
  StaleRebaseGenerationError,
101
- )
114
+ ])
102
115
 
103
116
  export type RejectedPushError = typeof RejectedPushError.Type
104
117
 
@@ -83,14 +83,18 @@ export const execSql = (sqliteDb: SqliteDb, sql: string, bind: BindValues) => {
83
83
  )
84
84
  }
85
85
 
86
- // const selectSqlPrepared = <T>(stmt: PreparedStatement, bind: BindValues) => {
87
- // const bindValues = prepareBindValues(bind, stmt.sql)
88
- // return Effect.try({
89
- // try: () => stmt.select<T>(bindValues),
90
- // catch: (cause) =>
91
- // new SqliteError({ cause, query: { bindValues, sql: stmt.sql }, code: (cause as WaSqlite.SQLiteError).code }),
92
- // })
93
- // }
86
+ export const selectSql = <T>(sqliteDb: SqliteDb, sql: string, bind: BindValues) => {
87
+ const bindValues = prepareBindValues(bind, sql)
88
+ return Effect.try({
89
+ try: () => sqliteDb.select<T>(sql, bindValues),
90
+ catch: (cause) =>
91
+ new SqliteError({ cause, query: { bindValues, sql }, code: (cause as WaSqlite.SQLiteError).code }),
92
+ }).pipe(
93
+ Effect.withSpan(`@livestore/common:selectSql`, {
94
+ attributes: { 'span.label': sql, sql, bindValueKeys: Object.keys(bindValues) },
95
+ }),
96
+ )
97
+ }
94
98
 
95
99
  // TODO actually use prepared statements
96
100
  export const execSqlPrepared = (sqliteDb: SqliteDb, sql: string, bindValues: PreparedBindValues) => {
@@ -1,5 +1,5 @@
1
1
  import { LS_DEV, shouldNeverHappen } from '@livestore/utils'
2
- import { Chunk, Effect, Option, Schema } from '@livestore/utils/effect'
2
+ import { Effect, Option, Schema } from '@livestore/utils/effect'
3
3
 
4
4
  import type { SqliteDb } from '../adapter-types.ts'
5
5
  import { migrateTable } from '../schema-management/migrations.ts'
@@ -107,7 +107,7 @@ export const getEventsFromEventlog = ({
107
107
  }: {
108
108
  dbEventlog: SqliteDb
109
109
  options: StreamEventsOptions
110
- }): Effect.Effect<Chunk.Chunk<LiveStoreEvent.Client.Encoded>> =>
110
+ }): Effect.Effect<ReadonlyArray<LiveStoreEvent.Client.Encoded>> =>
111
111
  Effect.gen(function* () {
112
112
  const since = options.since ?? EventSequenceNumber.Client.ROOT
113
113
  const batchSize = options.batchSize ?? STREAM_EVENTS_BATCH_SIZE_DEFAULT
@@ -146,7 +146,7 @@ export const getEventsFromEventlog = ({
146
146
  const eventlogEvents = yield* Effect.sync(() => dbEventlog.select(makeQuery()))
147
147
 
148
148
  if (eventlogEvents.length === 0) {
149
- return Chunk.empty<LiveStoreEvent.Client.Encoded>()
149
+ return []
150
150
  }
151
151
 
152
152
  const spanAttributes = {
@@ -174,7 +174,7 @@ export const getEventsFromEventlog = ({
174
174
  })
175
175
  })
176
176
 
177
- return Chunk.fromIterable(encodedEvents)
177
+ return encodedEvents
178
178
  }).pipe(Effect.withSpan('@livestore/common:eventlog:getEventsFromEventlog', { attributes: spanAttributes }))
179
179
  })
180
180
 
@@ -201,7 +201,7 @@ export const updateBackendHead = (dbEventlog: SqliteDb, head: EventSequenceNumbe
201
201
  dbEventlog.execute(sql`UPDATE ${SYNC_STATUS_TABLE} SET head = ${head.global}`)
202
202
 
203
203
  export const getBackendIdFromDb = (dbEventlog: SqliteDb): Option.Option<string> =>
204
- Option.fromNullable(
204
+ Option.fromNullishOr(
205
205
  dbEventlog.select<{ backendId: string | null }>(sql`select backendId from ${SYNC_STATUS_TABLE}`)[0]?.backendId,
206
206
  )
207
207
 
@@ -284,14 +284,14 @@ export const getSyncBackendCursorInfo = ({ remoteHead }: { remoteHead: EventSequ
284
284
  if (remoteHead === EventSequenceNumber.Client.ROOT.global) return Option.none()
285
285
 
286
286
  const EventlogQuerySchema = Schema.Struct({
287
- syncMetadataJson: Schema.parseJson(Schema.Option(Schema.JsonValue)),
287
+ syncMetadataJson: Schema.fromJsonString(Schema.toCodecJson(Schema.Option(Schema.Json))),
288
288
  }).pipe(Schema.pluck('syncMetadataJson'), Schema.Array, Schema.head)
289
289
 
290
290
  const syncMetadataOption = yield* Effect.sync(() =>
291
291
  dbEventlog.select<{ syncMetadataJson: string }>(
292
292
  sql`SELECT syncMetadataJson FROM ${EVENTLOG_META_TABLE} WHERE seqNumGlobal = ${remoteHead} ORDER BY seqNumClient ASC LIMIT 1`,
293
293
  ),
294
- ).pipe(Effect.andThen(Schema.decode(EventlogQuerySchema)), Effect.map(Option.flatten), Effect.orDie)
294
+ ).pipe(Effect.andThen(Schema.decodeEffect(EventlogQuerySchema)), Effect.map(Option.flatten), Effect.orDie)
295
295
 
296
296
  return Option.some({
297
297
  eventSequenceNumber: remoteHead,
@@ -1,4 +1,4 @@
1
- import { Effect, FiberMap, Option, Stream, SubscriptionRef } from '@livestore/utils/effect'
1
+ import { Cause, Effect, FiberMap, Option, Stream, SubscriptionRef } from '@livestore/utils/effect'
2
2
  import { nanoid } from '@livestore/utils/nanoid'
3
3
 
4
4
  import {
@@ -18,7 +18,8 @@ type SendMessageToDevtools = (message: Devtools.Leader.MessageFromApp) => Effect
18
18
 
19
19
  /**
20
20
  * Type guard for DevtoolsViteNotInstalledError.
21
- * This error is defined in @livestore/adapter-node but we need to handle it here.
21
+ * Adapter-specific devtools boot implementations may surface this tagged error;
22
+ * common handles it structurally to keep devtools startup environment-agnostic.
22
23
  */
23
24
  const isDevtoolsViteNotInstalledError = (
24
25
  error: unknown,
@@ -47,7 +48,7 @@ export const bootDevtools = Effect.fn('@livestore/common:leader-thread:devtools:
47
48
  Effect.as(Option.none()),
48
49
  ),
49
50
  ),
50
- Effect.catchAllCause((cause) =>
51
+ Effect.catchCause((cause) =>
51
52
  Effect.logWarning(
52
53
  `[@livestore/devtools] Failed to start devtools server. Devtools will be disabled.`,
53
54
  cause,
@@ -80,7 +81,7 @@ export const bootDevtools = Effect.fn('@livestore/common:leader-thread:devtools:
80
81
  .pipe(
81
82
  Effect.withSpan('@livestore/common:leader-thread:devtools:sendToDevtools'),
82
83
  Effect.interruptible,
83
- Effect.ignoreLogged,
84
+ Effect.ignore,
84
85
  )
85
86
 
86
87
  const syncState = yield* syncProcessor.syncState
@@ -92,7 +93,7 @@ export const bootDevtools = Effect.fn('@livestore/common:leader-thread:devtools:
92
93
  )
93
94
 
94
95
  yield* listenToDevtools({
95
- incomingMessages: channel.listen.pipe(Stream.flatten(), Stream.orDie),
96
+ incomingMessages: channel.listen.pipe(Stream.mapEffect(Effect.fromResult), Stream.orDie),
96
97
  sendMessage,
97
98
  persistenceInfo,
98
99
  })
@@ -181,7 +182,9 @@ const listenToDevtools = ({
181
182
  appVersion: liveStoreVersion,
182
183
  receivedVersion: decodedEvent.liveStoreVersion,
183
184
  appDevtoolsProtocolVersion: devtoolsProtocolVersion,
184
- receivedDevtoolsProtocolVersion: resolveDevtoolsProtocolVersion(decodedEvent.devtoolsProtocolVersion),
185
+ receivedDevtoolsProtocolVersion: resolveDevtoolsProtocolVersion(
186
+ decodedEvent.devtoolsProtocolVersion,
187
+ ),
185
188
  }),
186
189
  )
187
190
  return
@@ -204,10 +207,13 @@ const listenToDevtools = ({
204
207
  Effect.sync(() => db.close()),
205
208
  ).pipe(
206
209
  Effect.flatMap((db) =>
207
- Effect.try(() => {
208
- db.import(data)
209
- const rows = db.select<{ name: string }>(`select name from sqlite_master where type = 'table'`)
210
- return new Set(rows.map((r) => r.name))
210
+ Effect.try({
211
+ try: () => {
212
+ db.import(data)
213
+ const rows = db.select<{ name: string }>(`select name from sqlite_master where type = 'table'`)
214
+ return new Set(rows.map((r) => r.name))
215
+ },
216
+ catch: (cause) => new Cause.UnknownError(cause),
211
217
  }),
212
218
  ),
213
219
  )
@@ -217,10 +223,16 @@ const listenToDevtools = ({
217
223
  if (tableNames.has(SystemTables.EVENTLOG_META_TABLE) === true) {
218
224
  databaseKind = 'eventlog'
219
225
  yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
220
- yield* Effect.try(() => dbEventlog.import(data))
226
+ yield* Effect.try({
227
+ try: () => dbEventlog.import(data),
228
+ catch: (cause) => new Cause.UnknownError(cause),
229
+ })
221
230
 
222
231
  if (batchId === undefined) {
223
- yield* Effect.try(() => dbState.destroy())
232
+ yield* Effect.try({
233
+ try: () => dbState.destroy(),
234
+ catch: (cause) => new Cause.UnknownError(cause),
235
+ })
224
236
  }
225
237
  } else if (
226
238
  tableNames.has(SystemTables.SCHEMA_META_TABLE) === true &&
@@ -228,10 +240,16 @@ const listenToDevtools = ({
228
240
  ) {
229
241
  databaseKind = 'state'
230
242
  yield* SubscriptionRef.set(shutdownStateSubRef, 'shutting-down')
231
- yield* Effect.try(() => dbState.import(data))
243
+ yield* Effect.try({
244
+ try: () => dbState.import(data),
245
+ catch: (cause) => new Cause.UnknownError(cause),
246
+ })
232
247
 
233
248
  if (batchId === undefined) {
234
- yield* Effect.try(() => dbEventlog.destroy())
249
+ yield* Effect.try({
250
+ try: () => dbEventlog.destroy(),
251
+ catch: (cause) => new Cause.UnknownError(cause),
252
+ })
235
253
  }
236
254
  } else {
237
255
  return yield* Effect.fail({ _tag: 'unsupported-database' } as const)
@@ -261,9 +279,9 @@ const listenToDevtools = ({
261
279
  }),
262
280
  ),
263
281
  ),
264
- Effect.catchAll((cause) =>
282
+ Effect.catch((cause) =>
265
283
  Effect.logWarning('Error importing database file', cause).pipe(
266
- Effect.zipRight(
284
+ Effect.andThen(
267
285
  sendMessage(
268
286
  Devtools.Leader.LoadDatabaseFile.Error.make({
269
287
  ...reqPayload,
@@ -339,7 +357,7 @@ const listenToDevtools = ({
339
357
  // TODO consider piggybacking on the existing leader-thread sync-pulling
340
358
  yield* syncBackend.pull(Option.none(), { live: true }).pipe(
341
359
  Stream.map((_) => _.batch),
342
- Stream.flattenIterables,
360
+ Stream.flattenIterable,
343
361
  Stream.tap(({ eventEncoded, metadata }) =>
344
362
  sendMessage(
345
363
  Devtools.Leader.SyncHistoryRes.make({
@@ -388,9 +406,9 @@ const listenToDevtools = ({
388
406
  yield* Effect.sleep(1000)
389
407
 
390
408
  yield* Stream.zipLatest(
391
- syncBackend.isConnected.changes,
409
+ SubscriptionRef.changes(syncBackend.isConnected),
392
410
  devtools.enabled === true
393
- ? devtools.syncBackendLatchState.changes
411
+ ? SubscriptionRef.changes(devtools.syncBackendLatchState)
394
412
  : Stream.make({ latchClosed: false }),
395
413
  ).pipe(
396
414
  Stream.tap(([isConnected, { latchClosed }]) =>
@@ -1,5 +1,5 @@
1
1
  import { Vitest } from '@livestore/utils-dev/node-vitest'
2
- import { Effect, Stream, SubscriptionRef } from '@livestore/utils/effect'
2
+ import { Effect, Fiber, Latch, 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'
@@ -7,7 +7,7 @@ import { makeNetworkStatusSubscribable } from './make-leader-thread-layer.ts'
7
7
  import type { DevtoolsContext } from './types.ts'
8
8
 
9
9
  Vitest.describe('makeNetworkStatusSubscribable', () => {
10
- Vitest.scopedLive('tracks sync backend connectivity and devtools latch state', () =>
10
+ Vitest.live('tracks sync backend connectivity and devtools latch state', () =>
11
11
  Effect.gen(function* () {
12
12
  const mockBackend = yield* makeMockSyncBackend({ startConnected: false })
13
13
  const syncBackend = yield* mockBackend.makeSyncBackend
@@ -15,7 +15,7 @@ Vitest.describe('makeNetworkStatusSubscribable', () => {
15
15
 
16
16
  const devtoolsContext: DevtoolsContext = {
17
17
  enabled: true,
18
- syncBackendLatch: yield* Effect.makeLatch(true),
18
+ syncBackendLatch: yield* Latch.make(true),
19
19
  syncBackendLatchState: latchStateRef,
20
20
  }
21
21
 
@@ -26,17 +26,17 @@ Vitest.describe('makeNetworkStatusSubscribable', () => {
26
26
  Vitest.expect(initial.devtools.latchClosed).toBe(false)
27
27
 
28
28
  const waitFor = (predicate: (status: SyncBackend.NetworkStatus) => boolean) =>
29
- networkStatus.changes.pipe(Stream.filter(predicate), Stream.runHead, Effect.flatten)
29
+ networkStatus.changes.pipe(Stream.filter(predicate), Stream.runFirstUnsafe)
30
30
 
31
31
  const onlineFiber = yield* waitFor((status) => status.isConnected).pipe(Effect.forkScoped)
32
32
  yield* mockBackend.connect
33
- const online = yield* onlineFiber
33
+ const online = yield* Fiber.join(onlineFiber)
34
34
  Vitest.expect(online.isConnected).toBe(true)
35
- Vitest.expect(online.timestampMs).toBeGreaterThan(initial.timestampMs)
35
+ Vitest.expect(online.timestampMs).toBeGreaterThanOrEqual(initial.timestampMs)
36
36
 
37
37
  const latchedFiber = yield* waitFor((status) => status.devtools.latchClosed).pipe(Effect.forkScoped)
38
38
  yield* SubscriptionRef.set(latchStateRef, { latchClosed: true })
39
- const latched = yield* latchedFiber
39
+ const latched = yield* Fiber.join(latchedFiber)
40
40
  Vitest.expect(latched.devtools.latchClosed).toBe(true)
41
41
  Vitest.expect(latched.timestampMs).toBeGreaterThanOrEqual(online.timestampMs)
42
42
  }),
@@ -1,12 +1,15 @@
1
1
  import { omitUndefineds, shouldNeverHappen } from '@livestore/utils'
2
- import type { HttpClient, Scope } from '@livestore/utils/effect'
3
2
  import {
3
+ type HttpClient,
4
+ type Scope,
4
5
  Deferred,
5
6
  Effect,
6
7
  KeyValueStore,
8
+ Latch,
7
9
  Layer,
8
- PlatformError,
10
+ Option,
9
11
  Queue,
12
+ ReadonlyArray,
10
13
  Schema,
11
14
  Stream,
12
15
  Subscribable,
@@ -24,12 +27,13 @@ import type { MigrationsReport } from '../defs.ts'
24
27
  import type * as Devtools from '../devtools/mod.ts'
25
28
  import type { LiveStoreSchema } from '../schema/mod.ts'
26
29
  import { EventSequenceNumber, LiveStoreEvent, SystemTables } from '../schema/mod.ts'
30
+ import type * as StateHead from '../StateHead.ts'
27
31
  import type { SyncBackend, SyncOptions } from '../sync/sync.ts'
28
32
  import { SyncState } from '../sync/syncstate.ts'
29
33
  import { sql } from '../util.ts'
30
34
  import * as Eventlog from './eventlog.ts'
31
- import { makeLeaderSyncProcessor } from './LeaderSyncProcessor.ts'
32
35
  import { bootDevtools } from './leader-worker-devtools.ts'
36
+ import * as LeaderSyncProcessor from './LeaderSyncProcessor.ts'
33
37
  import { makeMaterializeEvent } from './materialize-event.ts'
34
38
  import { recreateDb } from './recreate-db.ts'
35
39
  import type { ShutdownChannel } from './shutdown-channel.ts'
@@ -45,8 +49,8 @@ import { LeaderThreadCtx } from './types.ts'
45
49
 
46
50
  export interface MakeLeaderThreadLayerParams {
47
51
  storeId: string
48
- syncPayloadSchema: Schema.Schema<any> | undefined
49
- syncPayloadEncoded: Schema.JsonValue | undefined
52
+ syncPayloadSchema: Schema.Decoder<Schema.Json> | undefined
53
+ syncPayloadEncoded: Schema.Json | undefined
50
54
  clientId: string
51
55
  schema: LiveStoreSchema
52
56
  makeSqliteDb: MakeSqliteDb
@@ -66,6 +70,9 @@ export interface MakeLeaderThreadLayerParams {
66
70
  delays?: {
67
71
  localPushProcessing?: Effect.Effect<void>
68
72
  }
73
+ hooks?: {
74
+ localPushAdmitted?: (events: ReadonlyArray<LiveStoreEvent.Client.EncodedWithMeta>) => Effect.Effect<void>
75
+ }
69
76
  }
70
77
  }
71
78
  }
@@ -74,7 +81,7 @@ export const makeLeaderThreadLayer = ({
74
81
  schema,
75
82
  storeId,
76
83
  clientId,
77
- syncPayloadSchema = Schema.JsonValue,
84
+ syncPayloadSchema = Schema.Json,
78
85
  syncPayloadEncoded,
79
86
  makeSqliteDb,
80
87
  syncOptions,
@@ -85,12 +92,18 @@ export const makeLeaderThreadLayer = ({
85
92
  bootWarning,
86
93
  params,
87
94
  testing,
88
- }: MakeLeaderThreadLayerParams): Layer.Layer<LeaderThreadCtx, UnknownError, Scope.Scope | HttpClient.HttpClient> =>
95
+ }: MakeLeaderThreadLayerParams): Layer.Layer<
96
+ LeaderThreadCtx,
97
+ UnknownError,
98
+ Scope.Scope | HttpClient.HttpClient | StateHead.StateHead
99
+ > =>
89
100
  Effect.gen(function* () {
90
101
  const syncPayloadDecoded =
91
- syncPayloadEncoded === undefined ? undefined : yield* Schema.decodeUnknown(syncPayloadSchema)(syncPayloadEncoded)
102
+ syncPayloadEncoded === undefined
103
+ ? undefined
104
+ : yield* Schema.decodeUnknownEffect(syncPayloadSchema)(syncPayloadEncoded)
92
105
 
93
- const bootStatusQueue = yield* Queue.unbounded<BootStatus>().pipe(Effect.acquireRelease(Queue.shutdown))
106
+ const bootStatusQueue = yield* Effect.acquireRelease(Queue.unbounded<BootStatus>(), Queue.shutdown)
94
107
 
95
108
  // Emit boot warning if present (e.g., OPFS unavailable in private browsing)
96
109
  if (bootWarning !== undefined) {
@@ -114,29 +127,30 @@ export const makeLeaderThreadLayer = ({
114
127
  KeyValueStore.makeStringOnly({
115
128
  get: (_key) =>
116
129
  Effect.sync(() => Eventlog.getBackendIdFromDb(dbEventlog)).pipe(
117
- Effect.catchAllDefect((cause) =>
118
- PlatformError.BadArgument.make({
119
- method: 'getBackendIdFromDb',
120
- description: 'Failed to get backendId',
121
- module: 'KeyValueStore',
122
- cause,
123
- }),
130
+ Effect.map(Option.getOrUndefined),
131
+ Effect.catchDefect(
132
+ (cause) =>
133
+ new KeyValueStore.KeyValueStoreError({
134
+ method: 'getBackendIdFromDb',
135
+ message: 'Failed to get backendId',
136
+ cause,
137
+ }),
124
138
  ),
125
139
  ),
126
140
  set: (_key, value) =>
127
141
  Effect.sync(() => Eventlog.updateBackendId(dbEventlog, value)).pipe(
128
- Effect.catchAllDefect((cause) =>
129
- PlatformError.BadArgument.make({
130
- method: 'updateBackendId',
131
- module: 'KeyValueStore',
132
- description: 'Failed to update backendId',
133
- cause,
134
- }),
142
+ Effect.catchDefect(
143
+ (cause) =>
144
+ new KeyValueStore.KeyValueStoreError({
145
+ method: 'updateBackendId',
146
+ message: 'Failed to update backendId',
147
+ cause,
148
+ }),
135
149
  ),
136
150
  ),
137
- clear: Effect.dieMessage(`Not implemented. Should never be used.`),
138
- remove: () => Effect.dieMessage(`Not implemented. Should never be used.`),
139
- size: Effect.dieMessage(`Not implemented. Should never be used.`),
151
+ clear: Effect.die(new Error(`Not implemented. Should never be used.`)),
152
+ remove: () => Effect.die(new Error(`Not implemented. Should never be used.`)),
153
+ size: Effect.die(new Error(`Not implemented. Should never be used.`)),
140
154
  }),
141
155
  ),
142
156
  ),
@@ -161,7 +175,7 @@ export const makeLeaderThreadLayer = ({
161
175
  ? yield* recreateDb({ dbState, dbEventlog, schema, bootStatusQueue, materializeEvent })
162
176
  : { migrationsReport: { migrations: [] } }
163
177
 
164
- const syncProcessor = yield* makeLeaderSyncProcessor({
178
+ const syncProcessor = yield* LeaderSyncProcessor.make({
165
179
  schema,
166
180
  dbState,
167
181
  initialSyncState: getInitialSyncState({ dbEventlog, dbState, dbEventlogMissing }),
@@ -176,19 +190,20 @@ export const makeLeaderThreadLayer = ({
176
190
  }),
177
191
  },
178
192
  testing: {
179
- ...omitUndefineds({ delays: testing?.syncProcessor?.delays }),
193
+ ...omitUndefineds({ delays: testing?.syncProcessor?.delays, hooks: testing?.syncProcessor?.hooks }),
180
194
  },
181
195
  })
182
196
 
183
- const extraIncomingMessagesQueue = yield* Queue.unbounded<Devtools.Leader.MessageToApp>().pipe(
184
- Effect.acquireRelease(Queue.shutdown),
197
+ const extraIncomingMessagesQueue = yield* Effect.acquireRelease(
198
+ Queue.unbounded<Devtools.Leader.MessageToApp>(),
199
+ Queue.shutdown,
185
200
  )
186
201
 
187
202
  const devtoolsContext =
188
203
  devtoolsOptions.enabled === true
189
204
  ? {
190
205
  enabled: true as const,
191
- syncBackendLatch: yield* Effect.makeLatch(true),
206
+ syncBackendLatch: yield* Latch.make(true),
192
207
  syncBackendLatchState: yield* SubscriptionRef.make<{ latchClosed: boolean }>({ latchClosed: false }),
193
208
  }
194
209
  : { enabled: false as const }
@@ -213,13 +228,13 @@ export const makeLeaderThreadLayer = ({
213
228
  devtools: devtoolsContext,
214
229
  networkStatus,
215
230
  // State will be set during `bootLeaderThread`
216
- initialState: {} as any as LeaderThreadCtx['Type']['initialState'],
217
- } satisfies typeof LeaderThreadCtx.Service
231
+ initialState: {} as any as LeaderThreadCtx['Service']['initialState'],
232
+ } satisfies LeaderThreadCtx['Service']
218
233
 
219
234
  // @ts-expect-error For debugging purposes
220
235
  globalThis.__leaderThreadCtx = ctx
221
236
 
222
- const layer = Layer.succeed(LeaderThreadCtx, ctx)
237
+ const layer = Layer.succeed(LeaderThreadCtx, LeaderThreadCtx.of(ctx))
223
238
 
224
239
  ctx.initialState = yield* bootLeaderThread({
225
240
  migrationsReport,
@@ -233,29 +248,17 @@ export const makeLeaderThreadLayer = ({
233
248
  Effect.withSpanScoped('@livestore/common:leader-thread'),
234
249
  UnknownError.mapToUnknownError,
235
250
  Effect.tapCauseLogPretty,
236
- Layer.unwrapScoped,
251
+ Layer.unwrap,
237
252
  )
238
253
 
239
254
  const hasEventlogTables = (db: SqliteDb) => {
240
255
  const tableNames = new Set(db.select<{ name: string }>(sql`select name from sqlite_master`).map((_) => _.name))
241
- const eventlogTables = new Set(SystemTables.eventlogSystemTables.map((_) => _.sqliteDef.name))
242
- return isSubsetOf(eventlogTables, tableNames)
256
+ return ReadonlyArray.every(SystemTables.eventlogSystemTables, (_) => tableNames.has(_.sqliteDef.name))
243
257
  }
244
258
 
245
259
  const hasStateTables = (db: SqliteDb) => {
246
260
  const tableNames = new Set(db.select<{ name: string }>(sql`select name from sqlite_master`).map((_) => _.name))
247
- const stateTables = new Set(SystemTables.stateSystemTables.map((_) => _.sqliteDef.name))
248
- return isSubsetOf(stateTables, tableNames)
249
- }
250
-
251
- const isSubsetOf = (a: Set<string>, b: Set<string>): boolean => {
252
- for (const item of a) {
253
- if (b.has(item) === false) {
254
- return false
255
- }
256
- }
257
-
258
- return true
261
+ return ReadonlyArray.every(SystemTables.stateSystemTables, (_) => tableNames.has(_.sqliteDef.name))
259
262
  }
260
263
 
261
264
  const getInitialSyncState = ({
@@ -361,7 +364,7 @@ const bootLeaderThread = ({
361
364
  initialBlockingSyncContext: InitialBlockingSyncContext
362
365
  devtoolsOptions: DevtoolsOptions
363
366
  }): Effect.Effect<
364
- LeaderThreadCtx['Type']['initialState'],
367
+ LeaderThreadCtx['Service']['initialState'],
365
368
  UnknownError | MaterializerHashMismatchError,
366
369
  LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient
367
370
  > =>
@@ -378,7 +381,7 @@ const bootLeaderThread = ({
378
381
  progress: { done: 0, total: -1 },
379
382
  })
380
383
 
381
- yield* initialBlockingSyncContext.blockingDeferred.pipe(
384
+ yield* Deferred.await(initialBlockingSyncContext.blockingDeferred).pipe(
382
385
  Effect.withSpan('@livestore/common:leader-thread:initial-sync-blocking'),
383
386
  )
384
387
  }
@@ -421,7 +424,7 @@ export const makeNetworkStatusSubscribable = ({
421
424
  }))
422
425
 
423
426
  if (syncBackend !== undefined) {
424
- yield* syncBackend.isConnected.changes.pipe(
427
+ yield* SubscriptionRef.changes(syncBackend.isConnected).pipe(
425
428
  Stream.tap((isConnected) => updateNetworkStatus({ isConnected })),
426
429
  Stream.runDrain,
427
430
  Effect.interruptible,
@@ -431,7 +434,7 @@ export const makeNetworkStatusSubscribable = ({
431
434
  }
432
435
 
433
436
  if (devtoolsContext.enabled === true) {
434
- yield* devtoolsContext.syncBackendLatchState.changes.pipe(
437
+ yield* SubscriptionRef.changes(devtoolsContext.syncBackendLatchState).pipe(
435
438
  Stream.tap(({ latchClosed }) => updateNetworkStatus({ latchClosed })),
436
439
  Stream.runDrain,
437
440
  Effect.interruptible,