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

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 (465) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ClientSessionLeaderThreadProxy.d.ts +20 -12
  3. package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
  4. package/dist/ClientSessionLeaderThreadProxy.js.map +1 -1
  5. package/dist/adapter-types.d.ts +14 -6
  6. package/dist/adapter-types.d.ts.map +1 -1
  7. package/dist/adapter-types.js.map +1 -1
  8. package/dist/debug-info.d.ts.map +1 -1
  9. package/dist/debug-info.js +33 -6
  10. package/dist/debug-info.js.map +1 -1
  11. package/dist/devtools/devtools-messages-client-session.d.ts +28 -23
  12. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
  13. package/dist/devtools/devtools-messages-client-session.js +2 -2
  14. package/dist/devtools/devtools-messages-client-session.js.map +1 -1
  15. package/dist/devtools/devtools-messages-common.d.ts +7 -14
  16. package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
  17. package/dist/devtools/devtools-messages-common.js +1 -6
  18. package/dist/devtools/devtools-messages-common.js.map +1 -1
  19. package/dist/devtools/devtools-messages-leader.d.ts +38 -29
  20. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
  21. package/dist/devtools/devtools-messages-leader.js +9 -8
  22. package/dist/devtools/devtools-messages-leader.js.map +1 -1
  23. package/dist/devtools/devtools-sessioninfo.d.ts +14 -2
  24. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
  25. package/dist/devtools/devtools-sessioninfo.js +7 -4
  26. package/dist/devtools/devtools-sessioninfo.js.map +1 -1
  27. package/dist/devtools/mod.d.ts +13 -2
  28. package/dist/devtools/mod.d.ts.map +1 -1
  29. package/dist/devtools/mod.js +10 -3
  30. package/dist/devtools/mod.js.map +1 -1
  31. package/dist/errors.d.ts +52 -10
  32. package/dist/errors.d.ts.map +1 -1
  33. package/dist/errors.js +25 -6
  34. package/dist/errors.js.map +1 -1
  35. package/dist/index.d.ts +2 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +2 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/leader-thread/LeaderSyncProcessor.d.ts +41 -4
  40. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  41. package/dist/leader-thread/LeaderSyncProcessor.js +158 -75
  42. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  43. package/dist/leader-thread/eventlog.d.ts +21 -22
  44. package/dist/leader-thread/eventlog.d.ts.map +1 -1
  45. package/dist/leader-thread/eventlog.js +77 -20
  46. package/dist/leader-thread/eventlog.js.map +1 -1
  47. package/dist/leader-thread/leader-worker-devtools.d.ts +2 -2
  48. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  49. package/dist/leader-thread/leader-worker-devtools.js +56 -45
  50. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  51. package/dist/leader-thread/make-leader-thread-layer.d.ts +6 -6
  52. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  53. package/dist/leader-thread/make-leader-thread-layer.js +79 -27
  54. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  55. package/dist/leader-thread/make-leader-thread-layer.test.d.ts +2 -0
  56. package/dist/leader-thread/make-leader-thread-layer.test.d.ts.map +1 -0
  57. package/dist/leader-thread/make-leader-thread-layer.test.js +32 -0
  58. package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -0
  59. package/dist/leader-thread/materialize-event.d.ts +3 -3
  60. package/dist/leader-thread/materialize-event.d.ts.map +1 -1
  61. package/dist/leader-thread/materialize-event.js +25 -11
  62. package/dist/leader-thread/materialize-event.js.map +1 -1
  63. package/dist/leader-thread/mod.d.ts +1 -0
  64. package/dist/leader-thread/mod.d.ts.map +1 -1
  65. package/dist/leader-thread/mod.js +1 -0
  66. package/dist/leader-thread/mod.js.map +1 -1
  67. package/dist/leader-thread/recreate-db.d.ts +2 -3
  68. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  69. package/dist/leader-thread/recreate-db.js +5 -5
  70. package/dist/leader-thread/recreate-db.js.map +1 -1
  71. package/dist/leader-thread/shutdown-channel.d.ts +2 -2
  72. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  73. package/dist/leader-thread/shutdown-channel.js +2 -2
  74. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  75. package/dist/leader-thread/stream-events.d.ts +56 -0
  76. package/dist/leader-thread/stream-events.d.ts.map +1 -0
  77. package/dist/leader-thread/stream-events.js +166 -0
  78. package/dist/leader-thread/stream-events.js.map +1 -0
  79. package/dist/leader-thread/types.d.ts +98 -20
  80. package/dist/leader-thread/types.d.ts.map +1 -1
  81. package/dist/leader-thread/types.js +13 -0
  82. package/dist/leader-thread/types.js.map +1 -1
  83. package/dist/logging.d.ts +40 -0
  84. package/dist/logging.d.ts.map +1 -0
  85. package/dist/logging.js +33 -0
  86. package/dist/logging.js.map +1 -0
  87. package/dist/make-client-session.d.ts +5 -3
  88. package/dist/make-client-session.d.ts.map +1 -1
  89. package/dist/make-client-session.js +5 -2
  90. package/dist/make-client-session.js.map +1 -1
  91. package/dist/materializer-helper.d.ts +6 -6
  92. package/dist/materializer-helper.d.ts.map +1 -1
  93. package/dist/materializer-helper.js +20 -4
  94. package/dist/materializer-helper.js.map +1 -1
  95. package/dist/otel.d.ts +2 -1
  96. package/dist/otel.d.ts.map +1 -1
  97. package/dist/otel.js +5 -0
  98. package/dist/otel.js.map +1 -1
  99. package/dist/rematerialize-from-eventlog.d.ts +2 -2
  100. package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
  101. package/dist/rematerialize-from-eventlog.js +29 -20
  102. package/dist/rematerialize-from-eventlog.js.map +1 -1
  103. package/dist/schema/EventDef/define.d.ts +147 -0
  104. package/dist/schema/EventDef/define.d.ts.map +1 -0
  105. package/dist/schema/EventDef/define.js +139 -0
  106. package/dist/schema/EventDef/define.js.map +1 -0
  107. package/dist/schema/EventDef/event-def.d.ts +106 -0
  108. package/dist/schema/EventDef/event-def.d.ts.map +1 -0
  109. package/dist/schema/EventDef/event-def.js +2 -0
  110. package/dist/schema/EventDef/event-def.js.map +1 -0
  111. package/dist/schema/EventDef/facts.d.ts +118 -0
  112. package/dist/schema/EventDef/facts.d.ts.map +1 -0
  113. package/dist/schema/EventDef/facts.js +53 -0
  114. package/dist/schema/EventDef/facts.js.map +1 -0
  115. package/dist/schema/EventDef/materializer.d.ts +155 -0
  116. package/dist/schema/EventDef/materializer.d.ts.map +1 -0
  117. package/dist/schema/EventDef/materializer.js +83 -0
  118. package/dist/schema/EventDef/materializer.js.map +1 -0
  119. package/dist/schema/EventDef/mod.d.ts +5 -0
  120. package/dist/schema/EventDef/mod.d.ts.map +1 -0
  121. package/dist/schema/EventDef/mod.js +5 -0
  122. package/dist/schema/EventDef/mod.js.map +1 -0
  123. package/dist/schema/EventSequenceNumber/client.d.ts +136 -0
  124. package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -0
  125. package/dist/schema/EventSequenceNumber/client.js +193 -0
  126. package/dist/schema/EventSequenceNumber/client.js.map +1 -0
  127. package/dist/schema/EventSequenceNumber/global.d.ts +15 -0
  128. package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -0
  129. package/dist/schema/EventSequenceNumber/global.js +14 -0
  130. package/dist/schema/EventSequenceNumber/global.js.map +1 -0
  131. package/dist/schema/EventSequenceNumber/mod.d.ts +37 -0
  132. package/dist/schema/EventSequenceNumber/mod.d.ts.map +1 -0
  133. package/dist/schema/EventSequenceNumber/mod.js +37 -0
  134. package/dist/schema/EventSequenceNumber/mod.js.map +1 -0
  135. package/dist/schema/EventSequenceNumber.test.js +43 -43
  136. package/dist/schema/EventSequenceNumber.test.js.map +1 -1
  137. package/dist/schema/{LiveStoreEvent.d.ts → LiveStoreEvent/client.d.ts} +89 -106
  138. package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -0
  139. package/dist/schema/{LiveStoreEvent.js → LiveStoreEvent/client.js} +74 -58
  140. package/dist/schema/LiveStoreEvent/client.js.map +1 -0
  141. package/dist/schema/LiveStoreEvent/for-event-def.d.ts +52 -0
  142. package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -0
  143. package/dist/schema/LiveStoreEvent/for-event-def.js +2 -0
  144. package/dist/schema/LiveStoreEvent/for-event-def.js.map +1 -0
  145. package/dist/schema/LiveStoreEvent/global.d.ts +36 -0
  146. package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -0
  147. package/dist/schema/LiveStoreEvent/global.js +31 -0
  148. package/dist/schema/LiveStoreEvent/global.js.map +1 -0
  149. package/dist/schema/LiveStoreEvent/input.d.ts +46 -0
  150. package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -0
  151. package/dist/schema/LiveStoreEvent/input.js +26 -0
  152. package/dist/schema/LiveStoreEvent/input.js.map +1 -0
  153. package/dist/schema/LiveStoreEvent/mod.d.ts +5 -0
  154. package/dist/schema/LiveStoreEvent/mod.d.ts.map +1 -0
  155. package/dist/schema/LiveStoreEvent/mod.js +5 -0
  156. package/dist/schema/LiveStoreEvent/mod.js.map +1 -0
  157. package/dist/schema/events.d.ts +1 -1
  158. package/dist/schema/events.d.ts.map +1 -1
  159. package/dist/schema/events.js +1 -1
  160. package/dist/schema/events.js.map +1 -1
  161. package/dist/schema/mod.d.ts +6 -4
  162. package/dist/schema/mod.d.ts.map +1 -1
  163. package/dist/schema/mod.js +5 -4
  164. package/dist/schema/mod.js.map +1 -1
  165. package/dist/schema/schema.d.ts +16 -1
  166. package/dist/schema/schema.d.ts.map +1 -1
  167. package/dist/schema/schema.js +27 -2
  168. package/dist/schema/schema.js.map +1 -1
  169. package/dist/schema/state/sqlite/client-document-def.d.ts +36 -6
  170. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  171. package/dist/schema/state/sqlite/client-document-def.js +97 -6
  172. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  173. package/dist/schema/state/sqlite/client-document-def.test.js +16 -0
  174. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
  175. package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
  176. package/dist/schema/state/sqlite/column-annotations.js +14 -6
  177. package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
  178. package/dist/schema/state/sqlite/column-annotations.test.js +1 -1
  179. package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
  180. package/dist/schema/state/sqlite/column-def.js +69 -22
  181. package/dist/schema/state/sqlite/column-def.js.map +1 -1
  182. package/dist/schema/state/sqlite/column-def.test.js +48 -10
  183. package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
  184. package/dist/schema/state/sqlite/column-spec.d.ts.map +1 -1
  185. package/dist/schema/state/sqlite/column-spec.js +30 -12
  186. package/dist/schema/state/sqlite/column-spec.js.map +1 -1
  187. package/dist/schema/state/sqlite/column-spec.test.js +23 -14
  188. package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
  189. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +2 -1
  190. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -1
  191. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +23 -6
  192. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
  193. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +14 -8
  194. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
  195. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +5 -3
  196. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
  197. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
  198. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +2 -1
  199. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
  200. package/dist/schema/state/sqlite/mod.d.ts +3 -3
  201. package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
  202. package/dist/schema/state/sqlite/mod.js +3 -3
  203. package/dist/schema/state/sqlite/mod.js.map +1 -1
  204. package/dist/schema/state/sqlite/query-builder/api.d.ts +19 -11
  205. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
  206. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
  207. package/dist/schema/state/sqlite/query-builder/astToSql.js +22 -15
  208. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
  209. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
  210. package/dist/schema/state/sqlite/query-builder/impl.js +6 -3
  211. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
  212. package/dist/schema/state/sqlite/query-builder/impl.test.js +252 -88
  213. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  214. package/dist/schema/state/sqlite/schema-helpers.d.ts +2 -2
  215. package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -1
  216. package/dist/schema/state/sqlite/schema-helpers.js +22 -12
  217. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
  218. package/dist/schema/state/sqlite/schema-helpers.test.d.ts +2 -0
  219. package/dist/schema/state/sqlite/schema-helpers.test.d.ts.map +1 -0
  220. package/dist/schema/state/sqlite/schema-helpers.test.js +36 -0
  221. package/dist/schema/state/sqlite/schema-helpers.test.js.map +1 -0
  222. package/dist/schema/state/sqlite/{system-tables.d.ts → system-tables/eventlog-tables.d.ts} +63 -456
  223. package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts.map +1 -0
  224. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +54 -0
  225. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -0
  226. package/dist/schema/state/sqlite/system-tables/mod.d.ts +3 -0
  227. package/dist/schema/state/sqlite/system-tables/mod.d.ts.map +1 -0
  228. package/dist/schema/state/sqlite/system-tables/mod.js +3 -0
  229. package/dist/schema/state/sqlite/system-tables/mod.js.map +1 -0
  230. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +456 -0
  231. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -0
  232. package/dist/schema/state/sqlite/system-tables/state-tables.js +55 -0
  233. package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -0
  234. package/dist/schema/state/sqlite/table-def.d.ts +4 -4
  235. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  236. package/dist/schema/state/sqlite/table-def.js +2 -2
  237. package/dist/schema/state/sqlite/table-def.js.map +1 -1
  238. package/dist/schema/state/sqlite/table-def.test.js +80 -0
  239. package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
  240. package/dist/schema/unknown-events.d.ts +47 -0
  241. package/dist/schema/unknown-events.d.ts.map +1 -0
  242. package/dist/schema/unknown-events.js +69 -0
  243. package/dist/schema/unknown-events.js.map +1 -0
  244. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts +2 -0
  245. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts.map +1 -0
  246. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +73 -0
  247. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -0
  248. package/dist/schema-management/migrations.d.ts +32 -2
  249. package/dist/schema-management/migrations.d.ts.map +1 -1
  250. package/dist/schema-management/migrations.js +37 -5
  251. package/dist/schema-management/migrations.js.map +1 -1
  252. package/dist/schema-management/validate-schema.d.ts +3 -3
  253. package/dist/schema-management/validate-schema.d.ts.map +1 -1
  254. package/dist/schema-management/validate-schema.js +2 -2
  255. package/dist/schema-management/validate-schema.js.map +1 -1
  256. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  257. package/dist/sql-queries/sql-queries.js +11 -1
  258. package/dist/sql-queries/sql-queries.js.map +1 -1
  259. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  260. package/dist/sql-queries/sql-query-builder.js +2 -1
  261. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  262. package/dist/sqlite-types.d.ts +3 -3
  263. package/dist/sqlite-types.d.ts.map +1 -1
  264. package/dist/sync/ClientSessionSyncProcessor.d.ts +11 -13
  265. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  266. package/dist/sync/ClientSessionSyncProcessor.js +45 -42
  267. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  268. package/dist/sync/errors.d.ts +66 -0
  269. package/dist/sync/errors.d.ts.map +1 -0
  270. package/dist/sync/errors.js +36 -0
  271. package/dist/sync/errors.js.map +1 -0
  272. package/dist/sync/index.d.ts +3 -0
  273. package/dist/sync/index.d.ts.map +1 -1
  274. package/dist/sync/index.js +3 -0
  275. package/dist/sync/index.js.map +1 -1
  276. package/dist/sync/mock-sync-backend.d.ts +23 -0
  277. package/dist/sync/mock-sync-backend.d.ts.map +1 -0
  278. package/dist/sync/mock-sync-backend.js +114 -0
  279. package/dist/sync/mock-sync-backend.js.map +1 -0
  280. package/dist/sync/next/compact-events.d.ts.map +1 -1
  281. package/dist/sync/next/compact-events.js +6 -7
  282. package/dist/sync/next/compact-events.js.map +1 -1
  283. package/dist/sync/next/facts.d.ts +5 -5
  284. package/dist/sync/next/facts.d.ts.map +1 -1
  285. package/dist/sync/next/facts.js +1 -2
  286. package/dist/sync/next/facts.js.map +1 -1
  287. package/dist/sync/next/history-dag-common.d.ts +54 -15
  288. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  289. package/dist/sync/next/history-dag-common.js +198 -9
  290. package/dist/sync/next/history-dag-common.js.map +1 -1
  291. package/dist/sync/next/history-dag.d.ts.map +1 -1
  292. package/dist/sync/next/history-dag.js +10 -8
  293. package/dist/sync/next/history-dag.js.map +1 -1
  294. package/dist/sync/next/rebase-events.d.ts +5 -5
  295. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  296. package/dist/sync/next/rebase-events.js +5 -5
  297. package/dist/sync/next/rebase-events.js.map +1 -1
  298. package/dist/sync/next/test/event-fixtures.d.ts +2 -2
  299. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
  300. package/dist/sync/next/test/event-fixtures.js +9 -9
  301. package/dist/sync/next/test/event-fixtures.js.map +1 -1
  302. package/dist/sync/sync-backend-kv.d.ts +7 -0
  303. package/dist/sync/sync-backend-kv.d.ts.map +1 -0
  304. package/dist/sync/sync-backend-kv.js +18 -0
  305. package/dist/sync/sync-backend-kv.js.map +1 -0
  306. package/dist/sync/sync-backend.d.ts +105 -0
  307. package/dist/sync/sync-backend.d.ts.map +1 -0
  308. package/dist/sync/sync-backend.js +61 -0
  309. package/dist/sync/sync-backend.js.map +1 -0
  310. package/dist/sync/sync.d.ts +9 -86
  311. package/dist/sync/sync.d.ts.map +1 -1
  312. package/dist/sync/sync.js +2 -27
  313. package/dist/sync/sync.js.map +1 -1
  314. package/dist/sync/syncstate.d.ts +57 -44
  315. package/dist/sync/syncstate.d.ts.map +1 -1
  316. package/dist/sync/syncstate.js +50 -45
  317. package/dist/sync/syncstate.js.map +1 -1
  318. package/dist/sync/syncstate.test.js +83 -46
  319. package/dist/sync/syncstate.test.js.map +1 -1
  320. package/dist/sync/transport-chunking.d.ts +36 -0
  321. package/dist/sync/transport-chunking.d.ts.map +1 -0
  322. package/dist/sync/transport-chunking.js +56 -0
  323. package/dist/sync/transport-chunking.js.map +1 -0
  324. package/dist/sync/validate-push-payload.d.ts +2 -2
  325. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  326. package/dist/sync/validate-push-payload.js +6 -6
  327. package/dist/sync/validate-push-payload.js.map +1 -1
  328. package/dist/testing/event-factory.d.ts +68 -0
  329. package/dist/testing/event-factory.d.ts.map +1 -0
  330. package/dist/testing/event-factory.js +78 -0
  331. package/dist/testing/event-factory.js.map +1 -0
  332. package/dist/testing/mod.d.ts +2 -0
  333. package/dist/testing/mod.d.ts.map +1 -0
  334. package/dist/testing/mod.js +2 -0
  335. package/dist/testing/mod.js.map +1 -0
  336. package/dist/version.d.ts +16 -6
  337. package/dist/version.d.ts.map +1 -1
  338. package/dist/version.js +16 -6
  339. package/dist/version.js.map +1 -1
  340. package/package.json +7 -8
  341. package/src/ClientSessionLeaderThreadProxy.ts +20 -12
  342. package/src/adapter-types.ts +18 -6
  343. package/src/debug-info.ts +37 -6
  344. package/src/devtools/devtools-messages-client-session.ts +2 -2
  345. package/src/devtools/devtools-messages-common.ts +1 -8
  346. package/src/devtools/devtools-messages-leader.ts +9 -8
  347. package/src/devtools/devtools-sessioninfo.ts +8 -5
  348. package/src/devtools/mod.ts +11 -2
  349. package/src/errors.ts +38 -11
  350. package/src/index.ts +2 -1
  351. package/src/leader-thread/LeaderSyncProcessor.ts +277 -105
  352. package/src/leader-thread/eventlog.ts +113 -38
  353. package/src/leader-thread/leader-worker-devtools.ts +86 -55
  354. package/src/leader-thread/make-leader-thread-layer.test.ts +44 -0
  355. package/src/leader-thread/make-leader-thread-layer.ts +156 -37
  356. package/src/leader-thread/materialize-event.ts +37 -12
  357. package/src/leader-thread/mod.ts +1 -0
  358. package/src/leader-thread/recreate-db.ts +15 -7
  359. package/src/leader-thread/shutdown-channel.ts +16 -2
  360. package/src/leader-thread/stream-events.ts +201 -0
  361. package/src/leader-thread/types.ts +70 -20
  362. package/src/logging.ts +62 -0
  363. package/src/make-client-session.ts +9 -3
  364. package/src/materializer-helper.ts +27 -10
  365. package/src/otel.ts +10 -0
  366. package/src/rematerialize-from-eventlog.ts +37 -27
  367. package/src/schema/EventDef/define.ts +201 -0
  368. package/src/schema/EventDef/event-def.ts +120 -0
  369. package/src/schema/EventDef/facts.ts +135 -0
  370. package/src/schema/EventDef/materializer.ts +172 -0
  371. package/src/schema/EventDef/mod.ts +4 -0
  372. package/src/schema/EventSequenceNumber/client.ts +257 -0
  373. package/src/schema/EventSequenceNumber/global.ts +19 -0
  374. package/src/schema/EventSequenceNumber/mod.ts +37 -0
  375. package/src/schema/EventSequenceNumber.test.ts +70 -52
  376. package/src/schema/LiveStoreEvent/client.ts +221 -0
  377. package/src/schema/LiveStoreEvent/for-event-def.ts +60 -0
  378. package/src/schema/LiveStoreEvent/global.ts +45 -0
  379. package/src/schema/LiveStoreEvent/input.ts +63 -0
  380. package/src/schema/LiveStoreEvent/mod.ts +4 -0
  381. package/src/schema/events.ts +1 -1
  382. package/src/schema/mod.ts +6 -4
  383. package/src/schema/schema.ts +39 -3
  384. package/src/schema/state/sqlite/client-document-def.test.ts +19 -2
  385. package/src/schema/state/sqlite/client-document-def.ts +127 -25
  386. package/src/schema/state/sqlite/column-annotations.test.ts +1 -1
  387. package/src/schema/state/sqlite/column-annotations.ts +16 -6
  388. package/src/schema/state/sqlite/column-def.test.ts +62 -10
  389. package/src/schema/state/sqlite/column-def.ts +88 -21
  390. package/src/schema/state/sqlite/column-spec.test.ts +29 -16
  391. package/src/schema/state/sqlite/column-spec.ts +36 -11
  392. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +26 -6
  393. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +29 -12
  394. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +12 -17
  395. package/src/schema/state/sqlite/mod.ts +4 -3
  396. package/src/schema/state/sqlite/query-builder/api.ts +25 -11
  397. package/src/schema/state/sqlite/query-builder/astToSql.ts +23 -14
  398. package/src/schema/state/sqlite/query-builder/impl.test.ts +305 -92
  399. package/src/schema/state/sqlite/query-builder/impl.ts +8 -3
  400. package/src/schema/state/sqlite/schema-helpers.test.ts +44 -0
  401. package/src/schema/state/sqlite/schema-helpers.ts +28 -20
  402. package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +64 -0
  403. package/src/schema/state/sqlite/system-tables/mod.ts +2 -0
  404. package/src/schema/state/sqlite/system-tables/state-tables.ts +69 -0
  405. package/src/schema/state/sqlite/table-def.test.ts +101 -0
  406. package/src/schema/state/sqlite/table-def.ts +8 -6
  407. package/src/schema/unknown-events.ts +131 -0
  408. package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +86 -0
  409. package/src/schema-management/migrations.ts +41 -8
  410. package/src/schema-management/validate-schema.ts +3 -3
  411. package/src/sql-queries/sql-queries.ts +9 -1
  412. package/src/sql-queries/sql-query-builder.ts +2 -1
  413. package/src/sqlite-types.ts +3 -3
  414. package/src/sync/ClientSessionSyncProcessor.ts +69 -62
  415. package/src/sync/errors.ts +38 -0
  416. package/src/sync/index.ts +3 -0
  417. package/src/sync/mock-sync-backend.ts +184 -0
  418. package/src/sync/next/compact-events.ts +6 -7
  419. package/src/sync/next/facts.ts +7 -9
  420. package/src/sync/next/history-dag-common.ts +277 -26
  421. package/src/sync/next/history-dag.ts +16 -10
  422. package/src/sync/next/rebase-events.ts +11 -11
  423. package/src/sync/next/test/event-fixtures.ts +11 -11
  424. package/src/sync/sync-backend-kv.ts +22 -0
  425. package/src/sync/sync-backend.ts +185 -0
  426. package/src/sync/sync.ts +9 -91
  427. package/src/sync/syncstate.test.ts +96 -52
  428. package/src/sync/syncstate.ts +69 -58
  429. package/src/sync/transport-chunking.ts +90 -0
  430. package/src/sync/validate-push-payload.ts +8 -9
  431. package/src/testing/event-factory.ts +131 -0
  432. package/src/testing/mod.ts +1 -0
  433. package/src/version.ts +16 -6
  434. package/dist/schema/EventDef.d.ts +0 -123
  435. package/dist/schema/EventDef.d.ts.map +0 -1
  436. package/dist/schema/EventDef.js +0 -46
  437. package/dist/schema/EventDef.js.map +0 -1
  438. package/dist/schema/EventSequenceNumber.d.ts +0 -80
  439. package/dist/schema/EventSequenceNumber.d.ts.map +0 -1
  440. package/dist/schema/EventSequenceNumber.js +0 -139
  441. package/dist/schema/EventSequenceNumber.js.map +0 -1
  442. package/dist/schema/LiveStoreEvent.d.ts.map +0 -1
  443. package/dist/schema/LiveStoreEvent.js.map +0 -1
  444. package/dist/schema/state/sqlite/system-tables.d.ts.map +0 -1
  445. package/dist/schema/state/sqlite/system-tables.js +0 -79
  446. package/dist/schema/state/sqlite/system-tables.js.map +0 -1
  447. package/dist/schema-management/migrations.test.d.ts +0 -2
  448. package/dist/schema-management/migrations.test.d.ts.map +0 -1
  449. package/dist/schema-management/migrations.test.js +0 -52
  450. package/dist/schema-management/migrations.test.js.map +0 -1
  451. package/dist/sync/next/graphology.d.ts +0 -8
  452. package/dist/sync/next/graphology.d.ts.map +0 -1
  453. package/dist/sync/next/graphology.js +0 -30
  454. package/dist/sync/next/graphology.js.map +0 -1
  455. package/dist/sync/next/graphology_.d.ts +0 -3
  456. package/dist/sync/next/graphology_.d.ts.map +0 -1
  457. package/dist/sync/next/graphology_.js +0 -3
  458. package/dist/sync/next/graphology_.js.map +0 -1
  459. package/src/schema/EventDef.ts +0 -219
  460. package/src/schema/EventSequenceNumber.ts +0 -199
  461. package/src/schema/LiveStoreEvent.ts +0 -287
  462. package/src/schema/state/sqlite/system-tables.ts +0 -104
  463. package/src/sync/next/ambient.d.ts +0 -3
  464. package/src/sync/next/graphology.ts +0 -41
  465. package/src/sync/next/graphology_.ts +0 -2
@@ -0,0 +1,201 @@
1
+ import type { Subscribable } from '@livestore/utils/effect'
2
+ import { Chunk, Effect, Option, Queue, Stream } from '@livestore/utils/effect'
3
+ import { EventSequenceNumber, type LiveStoreEvent } from '../schema/mod.ts'
4
+ import type * as SyncState from '../sync/syncstate.ts'
5
+ import * as Eventlog from './eventlog.ts'
6
+ import type { LeaderSqliteDb, StreamEventsOptions } from './types.ts'
7
+
8
+ /**
9
+ * Streams events for leader-thread adapters.
10
+ *
11
+ * Provides a continuous stream from the eventlog as the upstream head advances.
12
+ * When an until event is passed in the stream finalizes upon reaching it.
13
+ *
14
+ * The batch size is set to 100 by default as this was meassured to provide the
15
+ * best performance and 1000 as the upper limit.
16
+ *
17
+ * Adapters that call this helper:
18
+ * - `packages/@livestore/adapter-web/src/in-memory/in-memory-adapter.ts`
19
+ * - `packages/@livestore/adapter-web/src/web-worker/leader-worker/make-leader-worker.ts`
20
+ * - `packages/@livestore/adapter-node/src/client-session/adapter.ts`
21
+ * - `packages/@livestore/adapter-node/src/make-leader-worker.ts`
22
+ * - `packages/@livestore/adapter-cloudflare/src/make-adapter.ts`
23
+ *
24
+ * Each caller resolves dependencies inside the leader scope before invoking this helper,
25
+ * so the stream stays environment-agnostic and does not leak `LeaderThreadCtx` into runtime
26
+ * entry points such as `Store.eventsStream`.
27
+ *
28
+ * Test files:
29
+ * Unit: `tests/package-common/src/leader-thread/stream-events.test.ts`
30
+ * Integration: `packages/@livestore/livestore/src/store/store-eventstream.test.ts`
31
+ * Performance: `tests/perf-eventlog/tests/suites/event-streaming.test.ts`
32
+ *
33
+ * Optimization explorations
34
+ *
35
+ * In order to alleviate the occurence of many small queries when the syncState
36
+ * is sequentially progressing quickly we have explored some time-based batching
37
+ * approaches. It remains to be determined if and when the added complexity of
38
+ * these approaches are worth the benefit. They come with some drawbacks such as
39
+ * degraded time to first event or general performance degredation for larger
40
+ * query steps. These aspects can likely be mitigated with some more work but
41
+ * that is best assessed when we have a final implementation of event streaming
42
+ * with support for session and leader level streams.
43
+ *
44
+ * Fetch plans into a Sink
45
+ * https://gist.github.com/slashv/f1223689f2d1171d2eeb60a2823f4c7c
46
+ *
47
+ * Fetch plans into sink and decompose into windows
48
+ * https://gist.github.com/slashv/a8f55f50121c080937f42e44b4039ac8
49
+ *
50
+ * Mailbox and Latch approach (suggestion by Tim Smart)
51
+ * https://gist.github.com/slashv/d6b12395c85415bf0d3363372a1636c3
52
+ */
53
+ export const streamEventsWithSyncState = ({
54
+ dbEventlog,
55
+ syncState,
56
+ options,
57
+ }: {
58
+ dbEventlog: LeaderSqliteDb
59
+ syncState: Subscribable.Subscribable<SyncState.SyncState>
60
+ options: StreamEventsOptions
61
+ }): Stream.Stream<LiveStoreEvent.Client.Encoded> => {
62
+ const initialCursor = options.since ?? EventSequenceNumber.Client.ROOT
63
+ const batchSize = options.batchSize ?? 100
64
+
65
+ return Stream.unwrapScoped(
66
+ Effect.gen(function* () {
67
+ /**
68
+ * Single-element Queue allows suspending the event stream until head
69
+ * advances because Queue.take is a suspending effect. SubscriptionRef in
70
+ * comparrison lacks a primitive for suspending a stream until a new value
71
+ * is set and would require polling.
72
+ *
73
+ * The use of a sliding Queue here is useful since it ensures only the
74
+ * lastest head from syncState is the one present on the queue without the
75
+ * need for manual substitution.
76
+ */
77
+ const headQueue = yield* Queue.sliding<EventSequenceNumber.Client.Composite>(1)
78
+
79
+ /**
80
+ * We run a separate fiber which listens to changes in syncState and
81
+ * offer the latest head to the headQueue. Keeping track of the previous
82
+ * value is done to prevent syncState changes unrelated to the
83
+ * upstreamHead triggering empty queries.
84
+ *
85
+ * When we implement support for leader and session level streams
86
+ * this will need to be adapted to support the relevant value from
87
+ * syncState that we are interested in tracking.
88
+ */
89
+ let prevGlobalHead = -1
90
+ yield* syncState.changes.pipe(
91
+ Stream.map((state) => state.upstreamHead),
92
+ Stream.filter((head) => {
93
+ if (head.global > prevGlobalHead) {
94
+ prevGlobalHead = head.global
95
+ return true
96
+ }
97
+ return false
98
+ }),
99
+ Stream.runForEach((head) => Queue.offer(headQueue, head)),
100
+ Effect.forkScoped,
101
+ )
102
+
103
+ return Stream.paginateChunkEffect(
104
+ { cursor: initialCursor, head: EventSequenceNumber.Client.ROOT },
105
+ ({ cursor, head }) =>
106
+ Effect.gen(function* () {
107
+ /**
108
+ * Early check guards agains:
109
+ * since === until : Prevent empty query
110
+ * since > until : Incorrectly inverted interval
111
+ */
112
+ if (options.until && EventSequenceNumber.Client.isGreaterThanOrEqual(cursor, options.until)) {
113
+ return [Chunk.empty(), Option.none()]
114
+ }
115
+
116
+ /**
117
+ * There are two scenarios where we take the next head from the headQueue:
118
+ *
119
+ * 1. We need to wait for the head to advance
120
+ * The Stream suspends until a new head is available on the headQueue
121
+ *
122
+ * 2. Head has advanced during itteration
123
+ * While itterating towards the lastest head taken from the headQueue
124
+ * in increments of batchSize it's possible the head could have
125
+ * advanced. This leads to a suboptimal amount of queries. Therefor we
126
+ * check if the headQueue is full which tells us that there's a new
127
+ * head available to take. Example:
128
+ *
129
+ * batchSize: 2
130
+ *
131
+ * --> head at: e3
132
+ * First query: e0 -> e2 (two events)
133
+ * --> head advances to: e4
134
+ * Second query: e2 -> e3 (one event but we could have taken 2)
135
+ * --> Take the new head of e4
136
+ * Third query: e3 -> e4 (unnecessary third query)
137
+ *
138
+ *
139
+ * To define the target, which will be used as the temporary until
140
+ * marker for the eventlog query, we select the lowest of three possible values:
141
+ *
142
+ * hardStop: A user supplied until marker
143
+ * current cursor + batchSize: A batchSize step towards the latest head from headQueue
144
+ * nextHead: The latest head from headQueue
145
+ */
146
+ const waitForHead = EventSequenceNumber.Client.isGreaterThanOrEqual(cursor, head)
147
+ const maybeHead = waitForHead
148
+ ? yield* Queue.take(headQueue).pipe(Effect.map(Option.some))
149
+ : yield* Queue.poll(headQueue)
150
+ const nextHead = Option.getOrElse(maybeHead, () => head)
151
+ const hardStop = options.until?.global ?? Number.POSITIVE_INFINITY
152
+ const target = EventSequenceNumber.Client.Composite.make({
153
+ global: Math.min(hardStop, cursor.global + batchSize, nextHead.global),
154
+ client: EventSequenceNumber.Client.DEFAULT,
155
+ })
156
+
157
+ /**
158
+ * Eventlog.getEventsFromEventlog returns a Chunk from each
159
+ * query which is what we emit at each itteration.
160
+ */
161
+ const chunk = yield* Eventlog.getEventsFromEventlog({
162
+ dbEventlog,
163
+ options: {
164
+ ...options,
165
+ since: cursor,
166
+ until: target,
167
+ },
168
+ })
169
+
170
+ /**
171
+ * We construct the state for the following itteration of the stream
172
+ * loop by setting the current target as the since cursor and pass
173
+ * along the latest head.
174
+ *
175
+ * If we have the reached the user supplied until marker we signal the
176
+ * finalization of the stream by passing Option.none() instead.
177
+ */
178
+ const reachedUntil =
179
+ options.until !== undefined && EventSequenceNumber.Client.isGreaterThanOrEqual(target, options.until)
180
+
181
+ const nextState: Option.Option<{
182
+ cursor: EventSequenceNumber.Client.Composite
183
+ head: EventSequenceNumber.Client.Composite
184
+ }> = reachedUntil ? Option.none() : Option.some({ cursor: target, head: nextHead })
185
+
186
+ const spanAttributes = {
187
+ 'livestore.streamEvents.cursor.global': cursor.global,
188
+ 'livestore.streamEvents.target.global': target.global,
189
+ 'livestore.streamEvents.batchSize': batchSize,
190
+ 'livestore.streamEvents.waitedForHead': waitForHead,
191
+ }
192
+
193
+ return yield* Effect.succeed<[Chunk.Chunk<LiveStoreEvent.Client.Encoded>, typeof nextState]>([
194
+ chunk,
195
+ nextState,
196
+ ]).pipe(Effect.withSpan('@livestore/common:streamEvents:segment', { attributes: spanAttributes }))
197
+ }),
198
+ )
199
+ }),
200
+ )
201
+ }
@@ -13,7 +13,7 @@ import { Context, Schema } from '@livestore/utils/effect'
13
13
  import type { MeshNode } from '@livestore/webmesh'
14
14
 
15
15
  import type { MigrationsReport } from '../defs.ts'
16
- import type { SqliteError } from '../errors.ts'
16
+ import type { MaterializeError } from '../errors.ts'
17
17
  import type {
18
18
  BootStatus,
19
19
  Devtools,
@@ -22,9 +22,9 @@ import type {
22
22
  PersistenceInfo,
23
23
  SqliteDb,
24
24
  SyncBackend,
25
- UnexpectedError,
25
+ UnknownError,
26
26
  } from '../index.ts'
27
- import type { EventSequenceNumber, LiveStoreEvent, LiveStoreSchema } from '../schema/mod.ts'
27
+ import { EventSequenceNumber, type LiveStoreEvent, type LiveStoreSchema } from '../schema/mod.ts'
28
28
  import type * as SyncState from '../sync/syncstate.ts'
29
29
  import type { ShutdownChannel } from './shutdown-channel.ts'
30
30
 
@@ -43,7 +43,7 @@ export const InitialSyncOptions = Schema.Union(InitialSyncOptionsSkip, InitialSy
43
43
  export type InitialSyncOptions = typeof InitialSyncOptions.Type
44
44
 
45
45
  export type InitialSyncInfo = Option.Option<{
46
- cursor: EventSequenceNumber.EventSequenceNumber
46
+ eventSequenceNumber: EventSequenceNumber.Global.Type
47
47
  metadata: Option.Option<Schema.JsonValue>
48
48
  }>
49
49
 
@@ -66,7 +66,7 @@ export type DevtoolsOptions =
66
66
  persistenceInfo: PersistenceInfoPair
67
67
  mode: 'proxy' | 'direct'
68
68
  },
69
- UnexpectedError,
69
+ UnknownError,
70
70
  Scope.Scope | HttpClient.HttpClient | LeaderThreadCtx
71
71
  >
72
72
  }
@@ -96,13 +96,13 @@ export class LeaderThreadCtx extends Context.Tag('LeaderThreadCtx')<
96
96
  // TODO we should find a more elegant way to handle cases which need this ref for their implementation
97
97
  shutdownStateSubRef: SubscriptionRef.SubscriptionRef<ShutdownState>
98
98
  shutdownChannel: ShutdownChannel
99
- eventSchema: LiveStoreEvent.ForEventDefRecord<any>
99
+ eventSchema: LiveStoreEvent.ForEventDef.ForRecord<any>
100
100
  devtools: DevtoolsContext
101
- syncBackend: SyncBackend | undefined
101
+ syncBackend: SyncBackend.SyncBackend | undefined
102
102
  syncProcessor: LeaderSyncProcessor
103
103
  materializeEvent: MaterializeEvent
104
104
  initialState: {
105
- leaderHead: EventSequenceNumber.EventSequenceNumber
105
+ leaderHead: EventSequenceNumber.Client.Composite
106
106
  migrationsReport: MigrationsReport
107
107
  }
108
108
  /**
@@ -111,11 +111,12 @@ export class LeaderThreadCtx extends Context.Tag('LeaderThreadCtx')<
111
111
  * This is currently separated from `.devtools` as it also needs to work when devtools are disabled
112
112
  */
113
113
  extraIncomingMessagesQueue: Queue.Queue<Devtools.Leader.MessageToApp>
114
+ networkStatus: Subscribable.Subscribable<SyncBackend.NetworkStatus>
114
115
  }
115
116
  >() {}
116
117
 
117
118
  export type MaterializeEvent = (
118
- eventEncoded: LiveStoreEvent.EncodedWithMeta,
119
+ eventEncoded: LiveStoreEvent.Client.EncodedWithMeta,
119
120
  options?: {
120
121
  /** Needed for rematerializeFromEventlog */
121
122
  skipEventlog?: boolean
@@ -125,31 +126,80 @@ export type MaterializeEvent = (
125
126
  sessionChangeset: { _tag: 'sessionChangeset'; data: Uint8Array<ArrayBuffer>; debug: any } | { _tag: 'no-op' }
126
127
  hash: Option.Option<number>
127
128
  },
128
- SqliteError | UnexpectedError
129
+ MaterializeError
129
130
  >
130
131
 
131
132
  export type InitialBlockingSyncContext = {
132
133
  blockingDeferred: Deferred.Deferred<void> | undefined
133
- update: (_: { remaining: number; processed: number }) => Effect.Effect<void>
134
+ update: (_: { pageInfo: SyncBackend.PullResPageInfo; processed: number }) => Effect.Effect<void>
135
+ }
136
+
137
+ export const STREAM_EVENTS_BATCH_SIZE_DEFAULT = 100
138
+ export const STREAM_EVENTS_BATCH_SIZE_MAX = 1_000
139
+
140
+ export const StreamEventsOptionsFields = {
141
+ since: Schema.optional(EventSequenceNumber.Client.Composite),
142
+ until: Schema.optional(EventSequenceNumber.Client.Composite),
143
+ filter: Schema.optional(Schema.Array(Schema.String)),
144
+ clientIds: Schema.optional(Schema.Array(Schema.String)),
145
+ sessionIds: Schema.optional(Schema.Array(Schema.String)),
146
+ batchSize: Schema.optional(Schema.Int.pipe(Schema.between(1, STREAM_EVENTS_BATCH_SIZE_MAX))),
147
+ includeClientOnly: Schema.optional(Schema.Boolean),
148
+ } as const
149
+
150
+ export const StreamEventsOptionsSchema = Schema.Struct(StreamEventsOptionsFields)
151
+
152
+ export interface StreamEventsOptions {
153
+ /**
154
+ * Only include events after this logical timestamp (exclusive).
155
+ * Defaults to `EventSequenceNumber.Client.ROOT` when omitted.
156
+ */
157
+ since?: EventSequenceNumber.Client.Composite
158
+ /**
159
+ * Only include events up to this logical timestamp (inclusive).
160
+ */
161
+ until?: EventSequenceNumber.Client.Composite
162
+ /**
163
+ * Only include events of the given names.
164
+ */
165
+ filter?: ReadonlyArray<string>
166
+ /**
167
+ * Only include events from specific client identifiers.
168
+ */
169
+ clientIds?: ReadonlyArray<string>
170
+ /**
171
+ * Only include events from specific session identifiers.
172
+ */
173
+ sessionIds?: ReadonlyArray<string>
174
+ /**
175
+ * Number of events to fetch in each batch when streaming from the eventlog.
176
+ * Defaults to 100.
177
+ */
178
+ batchSize?: number
179
+ /**
180
+ * Include client-only events (i.e. events with a positive client sequence number).
181
+ */
182
+ includeClientOnly?: boolean
134
183
  }
135
184
 
136
185
  export interface LeaderSyncProcessor {
137
186
  /** Used by client sessions to subscribe to upstream sync state changes */
138
187
  pull: (args: {
139
- cursor: EventSequenceNumber.EventSequenceNumber
140
- }) => Stream.Stream<{ payload: typeof SyncState.PayloadUpstream.Type }, UnexpectedError>
188
+ cursor: EventSequenceNumber.Client.Composite
189
+ }) => Stream.Stream<{ payload: typeof SyncState.PayloadUpstream.Type }, UnknownError>
141
190
  /** The `pullQueue` API can be used instead of `pull` when more convenient */
142
191
  pullQueue: (args: {
143
- cursor: EventSequenceNumber.EventSequenceNumber
144
- }) => Effect.Effect<Queue.Queue<{ payload: typeof SyncState.PayloadUpstream.Type }>, UnexpectedError, Scope.Scope>
192
+ cursor: EventSequenceNumber.Client.Composite
193
+ }) => Effect.Effect<Queue.Queue<{ payload: typeof SyncState.PayloadUpstream.Type }>, UnknownError, Scope.Scope>
145
194
 
146
195
  /** Used by client sessions to push events to the leader thread */
147
196
  push: (
148
197
  /** `batch` needs to follow the same rules as `batch` in `SyncBackend.push` */
149
- batch: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>,
198
+ batch: ReadonlyArray<LiveStoreEvent.Client.EncodedWithMeta>,
150
199
  options?: {
151
200
  /**
152
201
  * If true, the effect will only finish when the local push has been processed (i.e. succeeded or was rejected).
202
+ * `true` doesn't mean the events have been pushed to the sync backend.
153
203
  * @default false
154
204
  */
155
205
  waitForProcessing?: boolean
@@ -158,14 +208,14 @@ export interface LeaderSyncProcessor {
158
208
 
159
209
  /** Currently only used by devtools which don't provide their own event numbers */
160
210
  pushPartial: (args: {
161
- event: LiveStoreEvent.PartialAnyEncoded
211
+ event: LiveStoreEvent.Input.Encoded
162
212
  clientId: string
163
213
  sessionId: string
164
- }) => Effect.Effect<void, UnexpectedError>
214
+ }) => Effect.Effect<void, UnknownError>
165
215
 
166
216
  boot: Effect.Effect<
167
- { initialLeaderHead: EventSequenceNumber.EventSequenceNumber },
168
- UnexpectedError,
217
+ { initialLeaderHead: EventSequenceNumber.Client.Composite },
218
+ UnknownError,
169
219
  LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient
170
220
  >
171
221
  syncState: Subscribable.Subscribable<SyncState.SyncState>
package/src/logging.ts ADDED
@@ -0,0 +1,62 @@
1
+ import { isDevEnv } from '@livestore/utils'
2
+ import { Effect, type Layer, Logger, LogLevel } from '@livestore/utils/effect'
3
+
4
+ /**
5
+ * Optional Effect logger configuration that LiveStore entry points accept.
6
+ *
7
+ * When provided, `logger` replaces the default pretty logger for the runtime.
8
+ * Use `logLevel` to control verbosity. Set to `LogLevel.None` to disable logging
9
+ * entirely while keeping the same logger implementation.
10
+ */
11
+ export type WithLoggerOptions = {
12
+ /** Optional Effect logger layer to control logging output. */
13
+ logger?: Layer.Layer<never> | undefined
14
+ /** Optional minimum log level for the runtime. */
15
+ logLevel?: LogLevel.LogLevel | undefined
16
+ }
17
+
18
+ /**
19
+ * Common defaults for resolving a logger configuration.
20
+ * - `threadName` is used by the default pretty logger when `logger` is not provided.
21
+ * - `mode` selects pretty logger mode (e.g. 'browser' for web workers).
22
+ * - `defaultLogLevel` is used when `logLevel` is not provided.
23
+ */
24
+ export type LoggerDefaults = {
25
+ threadName?: string
26
+ mode?: 'tty' | 'browser'
27
+ defaultLogLevel?: LogLevel.LogLevel
28
+ /** Optional default logger layer to use when `config.logger` is not provided. */
29
+ defaultLogger?: Layer.Layer<never>
30
+ }
31
+
32
+ /**
33
+ * Resolve the logger layer to provide to the Effect runtime.
34
+ */
35
+ export const resolveLoggerLayer = (config?: WithLoggerOptions, defaults?: LoggerDefaults): Layer.Layer<never> => {
36
+ if (config?.logger) return config.logger
37
+ if (defaults?.defaultLogger) return defaults.defaultLogger
38
+ const threadName = defaults?.threadName ?? 'livestore'
39
+ const mode = defaults?.mode
40
+ return Logger.prettyWithThread(threadName, mode ? { mode } : {})
41
+ }
42
+
43
+ /**
44
+ * Resolve the minimum log level, falling back to `defaults.defaultLogLevel` then `LogLevel.Debug`.
45
+ */
46
+ export const resolveLogLevel = (config?: WithLoggerOptions, defaults?: LoggerDefaults): LogLevel.LogLevel => {
47
+ if (config?.logLevel !== undefined) return config.logLevel
48
+ if (defaults?.defaultLogLevel !== undefined) return defaults.defaultLogLevel
49
+ return isDevEnv() ? LogLevel.Debug : LogLevel.Info
50
+ }
51
+
52
+ /**
53
+ * Wrap an effect by applying the resolved minimum log level and providing the resolved logger layer.
54
+ */
55
+ export const withLoggerConfig = <TEnv, TError, TOut>(
56
+ config?: WithLoggerOptions,
57
+ defaults?: LoggerDefaults,
58
+ ): ((effect: Effect.Effect<TOut, TError, TEnv>) => Effect.Effect<TOut, TError, TEnv>) => {
59
+ const level = resolveLogLevel(config, defaults)
60
+ const layer = resolveLoggerLayer(config, defaults)
61
+ return (effect) => effect.pipe(Logger.withMinimumLogLevel(level), Effect.provide(layer))
62
+ }
@@ -8,7 +8,7 @@ import type {
8
8
  ClientSessionLeaderThreadProxy,
9
9
  LockStatus,
10
10
  SqliteDb,
11
- UnexpectedError,
11
+ UnknownError,
12
12
  } from './adapter-types.ts'
13
13
  import * as Devtools from './devtools/mod.ts'
14
14
  import { liveStoreVersion } from './version.ts'
@@ -33,6 +33,7 @@ export const makeClientSession = <R>({
33
33
  webmeshMode,
34
34
  registerBeforeUnload,
35
35
  debugInstanceId,
36
+ origin,
36
37
  }: AdapterArgs & {
37
38
  clientId: string
38
39
  sessionId: string
@@ -43,9 +44,11 @@ export const makeClientSession = <R>({
43
44
  connectWebmeshNode: (args: {
44
45
  webmeshNode: Webmesh.MeshNode
45
46
  sessionInfo: Devtools.SessionInfo.SessionInfo
46
- }) => Effect.Effect<void, UnexpectedError, Scope.Scope | R>
47
+ }) => Effect.Effect<void, UnknownError, Scope.Scope | R>
47
48
  webmeshMode: 'direct' | 'proxy'
48
49
  registerBeforeUnload: (onBeforeUnload: () => void) => () => void
50
+ /** Browser origin of the client session; used for origin-scoped DevTools mesh channels */
51
+ origin: string | undefined
49
52
  }): Effect.Effect<ClientSession, never, Scope.Scope | R> =>
50
53
  Effect.gen(function* () {
51
54
  const devtools: ClientSession['devtools'] = devtoolsEnabled
@@ -67,11 +70,14 @@ export const makeClientSession = <R>({
67
70
  sessionId,
68
71
  schemaAlias,
69
72
  isLeader,
73
+ origin,
70
74
  })
71
75
 
72
76
  yield* connectWebmeshNode({ webmeshNode, sessionInfo })
73
77
 
74
- const sessionInfoBroadcastChannel = yield* Devtools.makeSessionInfoBroadcastChannel(webmeshNode)
78
+ const sessionInfoBroadcastChannel = yield* Devtools.makeSessionInfoBroadcastChannel(webmeshNode, {
79
+ origin,
80
+ })
75
81
 
76
82
  yield* Devtools.SessionInfo.provideSessionInfo({
77
83
  webChannel: sessionInfoBroadcastChannel,
@@ -3,9 +3,9 @@ import { Hash, Option, Schema } from '@livestore/utils/effect'
3
3
 
4
4
  import type { SqliteDb } from './adapter-types.ts'
5
5
  import { SessionIdSymbol } from './adapter-types.ts'
6
- import type { EventDef, Materializer, MaterializerContextQuery, MaterializerResult } from './schema/EventDef.ts'
7
- import type * as LiveStoreEvent from './schema/LiveStoreEvent.ts'
8
- import { getEventDef, type LiveStoreSchema } from './schema/schema.ts'
6
+ import type { EventDef, Materializer, MaterializerContextQuery, MaterializerResult } from './schema/EventDef/mod.ts'
7
+ import type * as LiveStoreEvent from './schema/LiveStoreEvent/mod.ts'
8
+ import type { LiveStoreSchema } from './schema/schema.ts'
9
9
  import type { QueryBuilder } from './schema/state/sqlite/query-builder/api.ts'
10
10
  import { isQueryBuilder } from './schema/state/sqlite/query-builder/api.ts'
11
11
  import { getResultSchema } from './schema/state/sqlite/query-builder/impl.ts'
@@ -24,15 +24,20 @@ export const getExecStatementsFromMaterializer = ({
24
24
  dbState: SqliteDb
25
25
  /** Both encoded and decoded events are supported to reduce the number of times we need to decode/encode */
26
26
  event:
27
- | { decoded: LiveStoreEvent.AnyDecoded; encoded: undefined }
28
- | { decoded: undefined; encoded: LiveStoreEvent.AnyEncoded }
27
+ | { decoded: LiveStoreEvent.Client.Decoded; encoded: undefined }
28
+ | { decoded: undefined; encoded: LiveStoreEvent.Client.Encoded }
29
29
  }): ReadonlyArray<{
30
30
  statementSql: string
31
31
  bindValues: PreparedBindValues
32
32
  writeTables: ReadonlySet<string> | undefined
33
33
  }> => {
34
- const eventArgsDecoded =
35
- event.decoded === undefined ? Schema.decodeUnknownSync(eventDef.schema)(event.encoded!.args) : event.decoded.args
34
+ const eventDecoded =
35
+ event.decoded === undefined
36
+ ? {
37
+ ...event.encoded!,
38
+ args: Schema.decodeUnknownSync(eventDef.schema)(event.encoded!.args),
39
+ }
40
+ : event.decoded
36
41
 
37
42
  const eventArgsEncoded = isNil(event.decoded?.args)
38
43
  ? undefined
@@ -58,11 +63,12 @@ export const getExecStatementsFromMaterializer = ({
58
63
  }
59
64
 
60
65
  const statementResults = fromMaterializerResult(
61
- materializer(eventArgsDecoded, {
66
+ materializer(eventDecoded.args, {
62
67
  eventDef,
63
68
  query,
64
69
  // TODO properly implement this
65
70
  currentFacts: new Map(),
71
+ event: eventDecoded,
66
72
  }),
67
73
  )
68
74
 
@@ -79,9 +85,20 @@ export const getExecStatementsFromMaterializer = ({
79
85
 
80
86
  export const makeMaterializerHash =
81
87
  ({ schema, dbState }: { schema: LiveStoreSchema; dbState: SqliteDb }) =>
82
- (event: LiveStoreEvent.AnyEncoded): Option.Option<number> => {
88
+ (event: LiveStoreEvent.Client.Encoded): Option.Option<number> => {
83
89
  if (isDevEnv()) {
84
- const { eventDef, materializer } = getEventDef(schema, event.name)
90
+ // Hashing is only needed during dev-mode diagnostics. Skip work entirely for
91
+ // unknown events (no definition/materializer) so we do not introduce noisy
92
+ // warnings while still returning `Option.none()` to disable hash checks.
93
+ const eventDef = schema.eventsDefsMap.get(event.name)
94
+ const materializer = schema.state.materializers.get(event.name)
95
+ if (eventDef === undefined || materializer === undefined) {
96
+ return Option.none()
97
+ }
98
+ // For known events we replay the materializer with the encoded payload and
99
+ // hash the resulting SQL statements. This lets us cheaply detect
100
+ // side-effects or logic drift between leader/client materializers without
101
+ // mutating the underlying state.
85
102
  const materializerResults = getExecStatementsFromMaterializer({
86
103
  eventDef,
87
104
  materializer,
package/src/otel.ts CHANGED
@@ -2,6 +2,16 @@ import { makeNoopTracer } from '@livestore/utils'
2
2
  import { Effect, identity, Layer, OtelTracer } from '@livestore/utils/effect'
3
3
  import * as otel from '@opentelemetry/api'
4
4
 
5
+ export const OtelLiveDummy: Layer.Layer<OtelTracer.OtelTracer> = Layer.suspend(() => {
6
+ const OtelTracerLive = Layer.succeed(OtelTracer.OtelTracer, makeNoopTracer())
7
+
8
+ const TracingLive = Layer.unwrapEffect(Effect.map(OtelTracer.make, Layer.setTracer)).pipe(
9
+ Layer.provideMerge(OtelTracerLive),
10
+ )
11
+
12
+ return TracingLive
13
+ })
14
+
5
15
  export const provideOtel =
6
16
  ({ otelTracer, parentSpanContext }: { otelTracer?: otel.Tracer; parentSpanContext?: otel.Context }) =>
7
17
  <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, Exclude<R, OtelTracer.OtelTracer>> => {
@@ -1,10 +1,10 @@
1
1
  import { memoizeByRef } from '@livestore/utils'
2
2
  import { Chunk, Effect, Option, Schema, Stream } from '@livestore/utils/effect'
3
3
 
4
- import { type SqliteDb, UnexpectedError } from './adapter-types.ts'
4
+ import { type SqliteDb, UnknownError } from './adapter-types.ts'
5
5
  import type { MaterializeEvent } from './leader-thread/mod.ts'
6
6
  import type { EventDef, LiveStoreSchema } from './schema/mod.ts'
7
- import { EventSequenceNumber, getEventDef, LiveStoreEvent, SystemTables } from './schema/mod.ts'
7
+ import { EventSequenceNumber, LiveStoreEvent, resolveEventDef, SystemTables } from './schema/mod.ts'
8
8
  import type { PreparedBindValues } from './util.ts'
9
9
  import { sql } from './util.ts'
10
10
 
@@ -31,20 +31,47 @@ export const rematerializeFromEventlog = ({
31
31
 
32
32
  const processEvent = (row: SystemTables.EventlogMetaRow) =>
33
33
  Effect.gen(function* () {
34
- const eventDef = getEventDef(schema, row.name)
34
+ const args = JSON.parse(row.argsJson)
35
+ const eventEncoded = LiveStoreEvent.Client.EncodedWithMeta.make({
36
+ name: row.name,
37
+ args,
38
+ seqNum: {
39
+ global: row.seqNumGlobal,
40
+ client: row.seqNumClient,
41
+ rebaseGeneration: row.seqNumRebaseGeneration,
42
+ },
43
+ parentSeqNum: {
44
+ global: row.parentSeqNumGlobal,
45
+ client: row.parentSeqNumClient,
46
+ rebaseGeneration: row.parentSeqNumRebaseGeneration,
47
+ },
48
+ clientId: row.clientId,
49
+ sessionId: row.sessionId,
50
+ })
51
+
52
+ const resolution = yield* resolveEventDef(schema, {
53
+ operation: '@livestore/common:rematerializeFromEventlog:processEvent',
54
+ event: eventEncoded,
55
+ }).pipe(UnknownError.mapToUnknownError)
56
+
57
+ if (resolution._tag === 'unknown') {
58
+ // Old snapshots can contain newer events. Skip until the runtime has
59
+ // been updated; the event stays in the log for future replays.
60
+ return
61
+ }
35
62
 
36
- if (hashEventDef(eventDef.eventDef) !== row.schemaHash) {
63
+ const { eventDef } = resolution
64
+
65
+ if (hashEventDef(eventDef) !== row.schemaHash) {
37
66
  yield* Effect.logWarning(
38
67
  `Schema hash mismatch for event definition ${row.name}. Trying to materialize event anyway.`,
39
68
  )
40
69
  }
41
70
 
42
- const args = JSON.parse(row.argsJson)
43
-
44
71
  // Checking whether the schema has changed in an incompatible way
45
- yield* Schema.decodeUnknown(eventDef.eventDef.schema)(args).pipe(
72
+ yield* Schema.decodeUnknown(eventDef.schema)(args).pipe(
46
73
  Effect.mapError((cause) =>
47
- UnexpectedError.make({
74
+ UnknownError.make({
48
75
  cause,
49
76
  note: `\
50
77
  There was an error during rematerializing from the eventlog while decoding
@@ -55,23 +82,6 @@ This likely means the schema has changed in an incompatible way.
55
82
  ),
56
83
  )
57
84
 
58
- const eventEncoded = LiveStoreEvent.EncodedWithMeta.make({
59
- seqNum: {
60
- global: row.seqNumGlobal,
61
- client: row.seqNumClient,
62
- rebaseGeneration: row.seqNumRebaseGeneration,
63
- },
64
- parentSeqNum: {
65
- global: row.parentSeqNumGlobal,
66
- client: row.parentSeqNumClient,
67
- rebaseGeneration: row.parentSeqNumRebaseGeneration,
68
- },
69
- name: row.name,
70
- args,
71
- clientId: row.clientId,
72
- sessionId: row.sessionId,
73
- })
74
-
75
85
  yield* materializeEvent(eventEncoded, { skipEventlog: true })
76
86
  }).pipe(Effect.withSpan(`@livestore/common:rematerializeFromEventlog:processEvent`))
77
87
 
@@ -96,9 +106,9 @@ LIMIT ${CHUNK_SIZE}
96
106
  const lastId = Chunk.isChunk(item)
97
107
  ? Chunk.last(item).pipe(
98
108
  Option.map((_) => ({ global: _.seqNumGlobal, client: _.seqNumClient })),
99
- Option.getOrElse(() => EventSequenceNumber.ROOT),
109
+ Option.getOrElse(() => EventSequenceNumber.Client.ROOT),
100
110
  )
101
- : EventSequenceNumber.ROOT
111
+ : EventSequenceNumber.Client.ROOT
102
112
  const nextItem = Chunk.fromIterable(
103
113
  stmt.select<SystemTables.EventlogMetaRow>({
104
114
  $seqNumGlobal: lastId?.global,