@livestore/common 0.3.0-dev.4 → 0.3.0-dev.40

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 (470) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/__tests__/fixture.d.ts +83 -221
  3. package/dist/__tests__/fixture.d.ts.map +1 -1
  4. package/dist/__tests__/fixture.js +33 -11
  5. package/dist/__tests__/fixture.js.map +1 -1
  6. package/dist/adapter-types.d.ts +132 -75
  7. package/dist/adapter-types.d.ts.map +1 -1
  8. package/dist/adapter-types.js +36 -7
  9. package/dist/adapter-types.js.map +1 -1
  10. package/dist/bounded-collections.d.ts.map +1 -1
  11. package/dist/debug-info.d.ts +1 -1
  12. package/dist/debug-info.d.ts.map +1 -1
  13. package/dist/debug-info.js +1 -0
  14. package/dist/debug-info.js.map +1 -1
  15. package/dist/devtools/devtools-messages-client-session.d.ts +390 -0
  16. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -0
  17. package/dist/devtools/devtools-messages-client-session.js +97 -0
  18. package/dist/devtools/devtools-messages-client-session.js.map +1 -0
  19. package/dist/devtools/devtools-messages-common.d.ts +68 -0
  20. package/dist/devtools/devtools-messages-common.d.ts.map +1 -0
  21. package/dist/devtools/devtools-messages-common.js +60 -0
  22. package/dist/devtools/devtools-messages-common.js.map +1 -0
  23. package/dist/devtools/devtools-messages-leader.d.ts +394 -0
  24. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -0
  25. package/dist/devtools/devtools-messages-leader.js +147 -0
  26. package/dist/devtools/devtools-messages-leader.js.map +1 -0
  27. package/dist/devtools/devtools-messages.d.ts +3 -592
  28. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  29. package/dist/devtools/devtools-messages.js +3 -171
  30. package/dist/devtools/devtools-messages.js.map +1 -1
  31. package/dist/devtools/devtools-sessioninfo.d.ts +32 -0
  32. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -0
  33. package/dist/devtools/devtools-sessioninfo.js +36 -0
  34. package/dist/devtools/devtools-sessioninfo.js.map +1 -0
  35. package/dist/devtools/mod.d.ts +55 -0
  36. package/dist/devtools/mod.d.ts.map +1 -0
  37. package/dist/devtools/mod.js +33 -0
  38. package/dist/devtools/mod.js.map +1 -0
  39. package/dist/index.d.ts +7 -13
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +7 -9
  42. package/dist/index.js.map +1 -1
  43. package/dist/leader-thread/LeaderSyncProcessor.d.ts +62 -0
  44. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -0
  45. package/dist/leader-thread/LeaderSyncProcessor.js +593 -0
  46. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -0
  47. package/dist/leader-thread/connection.d.ts +34 -6
  48. package/dist/leader-thread/connection.d.ts.map +1 -1
  49. package/dist/leader-thread/connection.js +22 -7
  50. package/dist/leader-thread/connection.js.map +1 -1
  51. package/dist/leader-thread/eventlog.d.ts +27 -0
  52. package/dist/leader-thread/eventlog.d.ts.map +1 -0
  53. package/dist/leader-thread/eventlog.js +119 -0
  54. package/dist/leader-thread/eventlog.js.map +1 -0
  55. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  56. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  57. package/dist/leader-thread/leader-worker-devtools.js +165 -134
  58. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  59. package/dist/leader-thread/make-leader-thread-layer.d.ts +26 -12
  60. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  61. package/dist/leader-thread/make-leader-thread-layer.js +76 -48
  62. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  63. package/dist/leader-thread/materialize-event.d.ts +16 -0
  64. package/dist/leader-thread/materialize-event.d.ts.map +1 -0
  65. package/dist/leader-thread/materialize-event.js +105 -0
  66. package/dist/leader-thread/materialize-event.js.map +1 -0
  67. package/dist/leader-thread/mod.d.ts +1 -1
  68. package/dist/leader-thread/mod.d.ts.map +1 -1
  69. package/dist/leader-thread/mod.js +1 -1
  70. package/dist/leader-thread/mod.js.map +1 -1
  71. package/dist/leader-thread/recreate-db.d.ts +4 -2
  72. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  73. package/dist/leader-thread/recreate-db.js +33 -31
  74. package/dist/leader-thread/recreate-db.js.map +1 -1
  75. package/dist/leader-thread/shutdown-channel.d.ts +2 -5
  76. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  77. package/dist/leader-thread/shutdown-channel.js +2 -4
  78. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  79. package/dist/leader-thread/types.d.ts +89 -40
  80. package/dist/leader-thread/types.d.ts.map +1 -1
  81. package/dist/leader-thread/types.js +1 -3
  82. package/dist/leader-thread/types.js.map +1 -1
  83. package/dist/make-client-session.d.ts +21 -0
  84. package/dist/make-client-session.d.ts.map +1 -0
  85. package/dist/make-client-session.js +51 -0
  86. package/dist/make-client-session.js.map +1 -0
  87. package/dist/materializer-helper.d.ts +23 -0
  88. package/dist/materializer-helper.d.ts.map +1 -0
  89. package/dist/materializer-helper.js +84 -0
  90. package/dist/materializer-helper.js.map +1 -0
  91. package/dist/otel.d.ts +2 -0
  92. package/dist/otel.d.ts.map +1 -1
  93. package/dist/otel.js +5 -0
  94. package/dist/otel.js.map +1 -1
  95. package/dist/rematerialize-from-eventlog.d.ts +14 -0
  96. package/dist/rematerialize-from-eventlog.d.ts.map +1 -0
  97. package/dist/rematerialize-from-eventlog.js +64 -0
  98. package/dist/rematerialize-from-eventlog.js.map +1 -0
  99. package/dist/schema/EventDef.d.ts +146 -0
  100. package/dist/schema/EventDef.d.ts.map +1 -0
  101. package/dist/schema/EventDef.js +58 -0
  102. package/dist/schema/EventDef.js.map +1 -0
  103. package/dist/schema/EventId.d.ts +35 -15
  104. package/dist/schema/EventId.d.ts.map +1 -1
  105. package/dist/schema/EventId.js +57 -11
  106. package/dist/schema/EventId.js.map +1 -1
  107. package/dist/schema/EventId.test.d.ts +2 -0
  108. package/dist/schema/EventId.test.d.ts.map +1 -0
  109. package/dist/schema/EventId.test.js +11 -0
  110. package/dist/schema/EventId.test.js.map +1 -0
  111. package/dist/schema/LiveStoreEvent.d.ts +255 -0
  112. package/dist/schema/LiveStoreEvent.d.ts.map +1 -0
  113. package/dist/schema/LiveStoreEvent.js +118 -0
  114. package/dist/schema/LiveStoreEvent.js.map +1 -0
  115. package/dist/schema/events.d.ts +2 -0
  116. package/dist/schema/events.d.ts.map +1 -0
  117. package/dist/schema/events.js +2 -0
  118. package/dist/schema/events.js.map +1 -0
  119. package/dist/schema/mod.d.ts +7 -5
  120. package/dist/schema/mod.d.ts.map +1 -1
  121. package/dist/schema/mod.js +7 -5
  122. package/dist/schema/mod.js.map +1 -1
  123. package/dist/schema/schema.d.ts +48 -30
  124. package/dist/schema/schema.d.ts.map +1 -1
  125. package/dist/schema/schema.js +36 -43
  126. package/dist/schema/schema.js.map +1 -1
  127. package/dist/schema/state/mod.d.ts +3 -0
  128. package/dist/schema/state/mod.d.ts.map +1 -0
  129. package/dist/schema/state/mod.js +3 -0
  130. package/dist/schema/state/mod.js.map +1 -0
  131. package/dist/schema/state/sqlite/client-document-def.d.ts +223 -0
  132. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -0
  133. package/dist/schema/state/sqlite/client-document-def.js +170 -0
  134. package/dist/schema/state/sqlite/client-document-def.js.map +1 -0
  135. package/dist/schema/state/sqlite/client-document-def.test.d.ts +2 -0
  136. package/dist/schema/state/sqlite/client-document-def.test.d.ts.map +1 -0
  137. package/dist/schema/state/sqlite/client-document-def.test.js +201 -0
  138. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -0
  139. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +69 -0
  140. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -0
  141. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +71 -0
  142. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -0
  143. package/dist/schema/state/sqlite/db-schema/ast/validate.d.ts +3 -0
  144. package/dist/schema/state/sqlite/db-schema/ast/validate.d.ts.map +1 -0
  145. package/dist/schema/state/sqlite/db-schema/ast/validate.js +12 -0
  146. package/dist/schema/state/sqlite/db-schema/ast/validate.js.map +1 -0
  147. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +90 -0
  148. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -0
  149. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +87 -0
  150. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -0
  151. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.d.ts +2 -0
  152. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.d.ts.map +1 -0
  153. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +29 -0
  154. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -0
  155. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +90 -0
  156. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -0
  157. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +41 -0
  158. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -0
  159. package/dist/schema/state/sqlite/db-schema/hash.d.ts +2 -0
  160. package/dist/schema/state/sqlite/db-schema/hash.d.ts.map +1 -0
  161. package/dist/schema/state/sqlite/db-schema/hash.js +14 -0
  162. package/dist/schema/state/sqlite/db-schema/hash.js.map +1 -0
  163. package/dist/schema/state/sqlite/db-schema/mod.d.ts +3 -0
  164. package/dist/schema/state/sqlite/db-schema/mod.d.ts.map +1 -0
  165. package/dist/schema/state/sqlite/db-schema/mod.js +3 -0
  166. package/dist/schema/state/sqlite/db-schema/mod.js.map +1 -0
  167. package/dist/schema/state/sqlite/mod.d.ts +17 -0
  168. package/dist/schema/state/sqlite/mod.d.ts.map +1 -0
  169. package/dist/schema/state/sqlite/mod.js +41 -0
  170. package/dist/schema/state/sqlite/mod.js.map +1 -0
  171. package/dist/schema/state/sqlite/query-builder/api.d.ts +294 -0
  172. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -0
  173. package/dist/schema/state/sqlite/query-builder/api.js +6 -0
  174. package/dist/schema/state/sqlite/query-builder/api.js.map +1 -0
  175. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts +7 -0
  176. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -0
  177. package/dist/schema/state/sqlite/query-builder/astToSql.js +190 -0
  178. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -0
  179. package/dist/schema/state/sqlite/query-builder/impl.d.ts +7 -0
  180. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -0
  181. package/dist/schema/state/sqlite/query-builder/impl.js +286 -0
  182. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -0
  183. package/dist/schema/state/sqlite/query-builder/impl.test.d.ts +87 -0
  184. package/dist/schema/state/sqlite/query-builder/impl.test.d.ts.map +1 -0
  185. package/dist/schema/state/sqlite/query-builder/impl.test.js +554 -0
  186. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -0
  187. package/dist/{query-builder → schema/state/sqlite/query-builder}/mod.d.ts +7 -0
  188. package/dist/schema/state/sqlite/query-builder/mod.d.ts.map +1 -0
  189. package/dist/{query-builder → schema/state/sqlite/query-builder}/mod.js +7 -0
  190. package/dist/schema/state/sqlite/query-builder/mod.js.map +1 -0
  191. package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -0
  192. package/dist/schema/{schema-helpers.js → state/sqlite/schema-helpers.js} +1 -1
  193. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -0
  194. package/dist/schema/state/sqlite/system-tables.d.ts +574 -0
  195. package/dist/schema/state/sqlite/system-tables.d.ts.map +1 -0
  196. package/dist/schema/state/sqlite/system-tables.js +87 -0
  197. package/dist/schema/state/sqlite/system-tables.js.map +1 -0
  198. package/dist/schema/state/sqlite/table-def.d.ts +84 -0
  199. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -0
  200. package/dist/schema/state/sqlite/table-def.js +36 -0
  201. package/dist/schema/state/sqlite/table-def.js.map +1 -0
  202. package/dist/schema-management/common.d.ts +7 -7
  203. package/dist/schema-management/common.d.ts.map +1 -1
  204. package/dist/schema-management/common.js.map +1 -1
  205. package/dist/schema-management/migrations.d.ts +6 -6
  206. package/dist/schema-management/migrations.d.ts.map +1 -1
  207. package/dist/schema-management/migrations.js +33 -24
  208. package/dist/schema-management/migrations.js.map +1 -1
  209. package/dist/schema-management/validate-schema.d.ts +8 -0
  210. package/dist/schema-management/validate-schema.d.ts.map +1 -0
  211. package/dist/schema-management/validate-schema.js +39 -0
  212. package/dist/schema-management/validate-schema.js.map +1 -0
  213. package/dist/sql-queries/misc.d.ts.map +1 -1
  214. package/dist/sql-queries/sql-queries.d.ts +1 -1
  215. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  216. package/dist/sql-queries/sql-queries.js.map +1 -1
  217. package/dist/sql-queries/sql-query-builder.d.ts +1 -1
  218. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  219. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  220. package/dist/sql-queries/types.d.ts +2 -1
  221. package/dist/sql-queries/types.d.ts.map +1 -1
  222. package/dist/sql-queries/types.js.map +1 -1
  223. package/dist/sync/ClientSessionSyncProcessor.d.ts +66 -0
  224. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -0
  225. package/dist/sync/ClientSessionSyncProcessor.js +209 -0
  226. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -0
  227. package/dist/sync/index.d.ts +1 -1
  228. package/dist/sync/index.d.ts.map +1 -1
  229. package/dist/sync/index.js +1 -1
  230. package/dist/sync/index.js.map +1 -1
  231. package/dist/sync/next/compact-events.d.ts.map +1 -1
  232. package/dist/sync/next/facts.d.ts +19 -19
  233. package/dist/sync/next/facts.d.ts.map +1 -1
  234. package/dist/sync/next/facts.js +3 -3
  235. package/dist/sync/next/facts.js.map +1 -1
  236. package/dist/sync/next/history-dag-common.d.ts +6 -7
  237. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  238. package/dist/sync/next/history-dag-common.js +4 -2
  239. package/dist/sync/next/history-dag-common.js.map +1 -1
  240. package/dist/sync/next/history-dag.d.ts.map +1 -1
  241. package/dist/sync/next/history-dag.js +2 -2
  242. package/dist/sync/next/history-dag.js.map +1 -1
  243. package/dist/sync/next/rebase-events.d.ts +10 -8
  244. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  245. package/dist/sync/next/rebase-events.js +11 -8
  246. package/dist/sync/next/rebase-events.js.map +1 -1
  247. package/dist/sync/next/test/compact-events.calculator.test.js +38 -33
  248. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  249. package/dist/sync/next/test/compact-events.test.js +76 -76
  250. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  251. package/dist/sync/next/test/{mutation-fixtures.d.ts → event-fixtures.d.ts} +25 -25
  252. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -0
  253. package/dist/sync/next/test/{mutation-fixtures.js → event-fixtures.js} +67 -36
  254. package/dist/sync/next/test/event-fixtures.js.map +1 -0
  255. package/dist/sync/next/test/mod.d.ts +1 -1
  256. package/dist/sync/next/test/mod.d.ts.map +1 -1
  257. package/dist/sync/next/test/mod.js +1 -1
  258. package/dist/sync/next/test/mod.js.map +1 -1
  259. package/dist/sync/sync.d.ts +55 -20
  260. package/dist/sync/sync.d.ts.map +1 -1
  261. package/dist/sync/sync.js +7 -3
  262. package/dist/sync/sync.js.map +1 -1
  263. package/dist/sync/syncstate.d.ts +213 -82
  264. package/dist/sync/syncstate.d.ts.map +1 -1
  265. package/dist/sync/syncstate.js +319 -120
  266. package/dist/sync/syncstate.js.map +1 -1
  267. package/dist/sync/syncstate.test.js +295 -275
  268. package/dist/sync/syncstate.test.js.map +1 -1
  269. package/dist/sync/validate-push-payload.d.ts +2 -2
  270. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  271. package/dist/sync/validate-push-payload.js +2 -2
  272. package/dist/sync/validate-push-payload.js.map +1 -1
  273. package/dist/util.d.ts +2 -2
  274. package/dist/util.d.ts.map +1 -1
  275. package/dist/version.d.ts +1 -1
  276. package/dist/version.d.ts.map +1 -1
  277. package/dist/version.js +1 -1
  278. package/dist/version.js.map +1 -1
  279. package/package.json +13 -6
  280. package/src/__tests__/fixture.ts +36 -15
  281. package/src/adapter-types.ts +116 -83
  282. package/src/debug-info.ts +1 -0
  283. package/src/devtools/devtools-messages-client-session.ts +142 -0
  284. package/src/devtools/devtools-messages-common.ts +115 -0
  285. package/src/devtools/devtools-messages-leader.ts +191 -0
  286. package/src/devtools/devtools-messages.ts +3 -243
  287. package/src/devtools/devtools-sessioninfo.ts +101 -0
  288. package/src/devtools/mod.ts +59 -0
  289. package/src/index.ts +7 -15
  290. package/src/leader-thread/LeaderSyncProcessor.ts +933 -0
  291. package/src/leader-thread/connection.ts +54 -9
  292. package/src/leader-thread/eventlog.ts +194 -0
  293. package/src/leader-thread/leader-worker-devtools.ts +235 -191
  294. package/src/leader-thread/make-leader-thread-layer.ts +138 -78
  295. package/src/leader-thread/materialize-event.ts +169 -0
  296. package/src/leader-thread/mod.ts +1 -1
  297. package/src/leader-thread/recreate-db.ts +38 -39
  298. package/src/leader-thread/shutdown-channel.ts +2 -4
  299. package/src/leader-thread/types.ts +98 -53
  300. package/src/make-client-session.ts +119 -0
  301. package/src/materializer-helper.ts +135 -0
  302. package/src/otel.ts +8 -0
  303. package/src/rematerialize-from-eventlog.ts +117 -0
  304. package/src/schema/EventDef.ts +227 -0
  305. package/src/schema/EventId.test.ts +12 -0
  306. package/src/schema/EventId.ts +75 -15
  307. package/src/schema/LiveStoreEvent.ts +239 -0
  308. package/src/schema/events.ts +1 -0
  309. package/src/schema/mod.ts +7 -5
  310. package/src/schema/schema.ts +85 -81
  311. package/src/schema/state/mod.ts +2 -0
  312. package/src/schema/state/sqlite/client-document-def.test.ts +238 -0
  313. package/src/schema/state/sqlite/client-document-def.ts +444 -0
  314. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +142 -0
  315. package/src/schema/state/sqlite/db-schema/ast/validate.ts +13 -0
  316. package/src/schema/state/sqlite/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +206 -0
  317. package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +35 -0
  318. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +242 -0
  319. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +222 -0
  320. package/src/schema/state/sqlite/db-schema/hash.ts +14 -0
  321. package/src/schema/state/sqlite/db-schema/mod.ts +2 -0
  322. package/src/schema/state/sqlite/mod.ts +73 -0
  323. package/src/schema/state/sqlite/query-builder/api.ts +440 -0
  324. package/src/schema/state/sqlite/query-builder/astToSql.ts +232 -0
  325. package/src/schema/state/sqlite/query-builder/impl.test.ts +608 -0
  326. package/src/schema/state/sqlite/query-builder/impl.ts +350 -0
  327. package/src/{query-builder → schema/state/sqlite/query-builder}/mod.ts +7 -0
  328. package/src/schema/{schema-helpers.ts → state/sqlite/schema-helpers.ts} +1 -1
  329. package/src/schema/state/sqlite/system-tables.ts +116 -0
  330. package/src/schema/state/sqlite/table-def.ts +197 -0
  331. package/src/schema-management/common.ts +7 -7
  332. package/src/schema-management/migrations.ts +43 -37
  333. package/src/schema-management/validate-schema.ts +61 -0
  334. package/src/sql-queries/sql-queries.ts +1 -1
  335. package/src/sql-queries/sql-query-builder.ts +1 -2
  336. package/src/sql-queries/types.ts +3 -1
  337. package/src/sync/ClientSessionSyncProcessor.ts +332 -0
  338. package/src/sync/index.ts +1 -1
  339. package/src/sync/next/facts.ts +32 -33
  340. package/src/sync/next/history-dag-common.ts +9 -5
  341. package/src/sync/next/history-dag.ts +2 -2
  342. package/src/sync/next/rebase-events.ts +22 -16
  343. package/src/sync/next/test/compact-events.calculator.test.ts +45 -45
  344. package/src/sync/next/test/compact-events.test.ts +78 -78
  345. package/src/sync/next/test/event-fixtures.ts +219 -0
  346. package/src/sync/next/test/mod.ts +1 -1
  347. package/src/sync/sync.ts +51 -19
  348. package/src/sync/syncstate.test.ts +335 -308
  349. package/src/sync/syncstate.ts +394 -212
  350. package/src/sync/validate-push-payload.ts +7 -4
  351. package/src/version.ts +1 -1
  352. package/dist/derived-mutations.d.ts +0 -109
  353. package/dist/derived-mutations.d.ts.map +0 -1
  354. package/dist/derived-mutations.js +0 -54
  355. package/dist/derived-mutations.js.map +0 -1
  356. package/dist/derived-mutations.test.d.ts +0 -2
  357. package/dist/derived-mutations.test.d.ts.map +0 -1
  358. package/dist/derived-mutations.test.js +0 -93
  359. package/dist/derived-mutations.test.js.map +0 -1
  360. package/dist/devtools/devtools-bridge.d.ts +0 -12
  361. package/dist/devtools/devtools-bridge.d.ts.map +0 -1
  362. package/dist/devtools/devtools-bridge.js +0 -2
  363. package/dist/devtools/devtools-bridge.js.map +0 -1
  364. package/dist/devtools/devtools-window-message.d.ts +0 -29
  365. package/dist/devtools/devtools-window-message.d.ts.map +0 -1
  366. package/dist/devtools/devtools-window-message.js +0 -33
  367. package/dist/devtools/devtools-window-message.js.map +0 -1
  368. package/dist/devtools/index.d.ts +0 -42
  369. package/dist/devtools/index.d.ts.map +0 -1
  370. package/dist/devtools/index.js +0 -48
  371. package/dist/devtools/index.js.map +0 -1
  372. package/dist/init-singleton-tables.d.ts +0 -4
  373. package/dist/init-singleton-tables.d.ts.map +0 -1
  374. package/dist/init-singleton-tables.js +0 -16
  375. package/dist/init-singleton-tables.js.map +0 -1
  376. package/dist/leader-thread/apply-mutation.d.ts +0 -8
  377. package/dist/leader-thread/apply-mutation.d.ts.map +0 -1
  378. package/dist/leader-thread/apply-mutation.js +0 -95
  379. package/dist/leader-thread/apply-mutation.js.map +0 -1
  380. package/dist/leader-thread/leader-sync-processor.d.ts +0 -47
  381. package/dist/leader-thread/leader-sync-processor.d.ts.map +0 -1
  382. package/dist/leader-thread/leader-sync-processor.js +0 -422
  383. package/dist/leader-thread/leader-sync-processor.js.map +0 -1
  384. package/dist/leader-thread/mutationlog.d.ts +0 -23
  385. package/dist/leader-thread/mutationlog.d.ts.map +0 -1
  386. package/dist/leader-thread/mutationlog.js +0 -27
  387. package/dist/leader-thread/mutationlog.js.map +0 -1
  388. package/dist/leader-thread/pull-queue-set.d.ts +0 -7
  389. package/dist/leader-thread/pull-queue-set.d.ts.map +0 -1
  390. package/dist/leader-thread/pull-queue-set.js +0 -39
  391. package/dist/leader-thread/pull-queue-set.js.map +0 -1
  392. package/dist/mutation.d.ts +0 -13
  393. package/dist/mutation.d.ts.map +0 -1
  394. package/dist/mutation.js +0 -57
  395. package/dist/mutation.js.map +0 -1
  396. package/dist/query-builder/api.d.ts +0 -190
  397. package/dist/query-builder/api.d.ts.map +0 -1
  398. package/dist/query-builder/api.js +0 -8
  399. package/dist/query-builder/api.js.map +0 -1
  400. package/dist/query-builder/impl.d.ts +0 -12
  401. package/dist/query-builder/impl.d.ts.map +0 -1
  402. package/dist/query-builder/impl.js +0 -244
  403. package/dist/query-builder/impl.js.map +0 -1
  404. package/dist/query-builder/impl.test.d.ts +0 -2
  405. package/dist/query-builder/impl.test.d.ts.map +0 -1
  406. package/dist/query-builder/impl.test.js +0 -212
  407. package/dist/query-builder/impl.test.js.map +0 -1
  408. package/dist/query-builder/mod.d.ts.map +0 -1
  409. package/dist/query-builder/mod.js.map +0 -1
  410. package/dist/query-info.d.ts +0 -38
  411. package/dist/query-info.d.ts.map +0 -1
  412. package/dist/query-info.js +0 -7
  413. package/dist/query-info.js.map +0 -1
  414. package/dist/rehydrate-from-mutationlog.d.ts +0 -14
  415. package/dist/rehydrate-from-mutationlog.d.ts.map +0 -1
  416. package/dist/rehydrate-from-mutationlog.js +0 -72
  417. package/dist/rehydrate-from-mutationlog.js.map +0 -1
  418. package/dist/schema/MutationEvent.d.ts +0 -191
  419. package/dist/schema/MutationEvent.d.ts.map +0 -1
  420. package/dist/schema/MutationEvent.js +0 -56
  421. package/dist/schema/MutationEvent.js.map +0 -1
  422. package/dist/schema/mutations.d.ts +0 -107
  423. package/dist/schema/mutations.d.ts.map +0 -1
  424. package/dist/schema/mutations.js +0 -42
  425. package/dist/schema/mutations.js.map +0 -1
  426. package/dist/schema/schema-helpers.d.ts.map +0 -1
  427. package/dist/schema/schema-helpers.js.map +0 -1
  428. package/dist/schema/system-tables.d.ts +0 -399
  429. package/dist/schema/system-tables.d.ts.map +0 -1
  430. package/dist/schema/system-tables.js +0 -51
  431. package/dist/schema/system-tables.js.map +0 -1
  432. package/dist/schema/table-def.d.ts +0 -156
  433. package/dist/schema/table-def.d.ts.map +0 -1
  434. package/dist/schema/table-def.js +0 -79
  435. package/dist/schema/table-def.js.map +0 -1
  436. package/dist/schema-management/validate-mutation-defs.d.ts +0 -8
  437. package/dist/schema-management/validate-mutation-defs.d.ts.map +0 -1
  438. package/dist/schema-management/validate-mutation-defs.js +0 -39
  439. package/dist/schema-management/validate-mutation-defs.js.map +0 -1
  440. package/dist/sync/client-session-sync-processor.d.ts +0 -45
  441. package/dist/sync/client-session-sync-processor.d.ts.map +0 -1
  442. package/dist/sync/client-session-sync-processor.js +0 -131
  443. package/dist/sync/client-session-sync-processor.js.map +0 -1
  444. package/dist/sync/next/test/mutation-fixtures.d.ts.map +0 -1
  445. package/dist/sync/next/test/mutation-fixtures.js.map +0 -1
  446. package/src/derived-mutations.test.ts +0 -101
  447. package/src/derived-mutations.ts +0 -166
  448. package/src/devtools/devtools-bridge.ts +0 -13
  449. package/src/devtools/devtools-window-message.ts +0 -27
  450. package/src/devtools/index.ts +0 -48
  451. package/src/init-singleton-tables.ts +0 -24
  452. package/src/leader-thread/apply-mutation.ts +0 -143
  453. package/src/leader-thread/leader-sync-processor.ts +0 -666
  454. package/src/leader-thread/mutationlog.ts +0 -42
  455. package/src/leader-thread/pull-queue-set.ts +0 -58
  456. package/src/mutation.ts +0 -81
  457. package/src/query-builder/api.ts +0 -289
  458. package/src/query-builder/impl.test.ts +0 -239
  459. package/src/query-builder/impl.ts +0 -285
  460. package/src/query-info.ts +0 -78
  461. package/src/rehydrate-from-mutationlog.ts +0 -127
  462. package/src/schema/MutationEvent.ts +0 -161
  463. package/src/schema/mutations.ts +0 -192
  464. package/src/schema/system-tables.ts +0 -97
  465. package/src/schema/table-def.ts +0 -343
  466. package/src/schema-management/validate-mutation-defs.ts +0 -63
  467. package/src/sync/client-session-sync-processor.ts +0 -207
  468. package/src/sync/next/test/mutation-fixtures.ts +0 -231
  469. package/tsconfig.json +0 -11
  470. /package/dist/schema/{schema-helpers.d.ts → state/sqlite/schema-helpers.d.ts} +0 -0
@@ -1,68 +1,141 @@
1
- import type { HttpClient, Scope, WebChannel } from '@livestore/utils/effect'
2
- import { Deferred, Effect, FiberSet, Layer, Queue, SubscriptionRef } from '@livestore/utils/effect'
1
+ import type { HttpClient, Schema, Scope } from '@livestore/utils/effect'
2
+ import { Deferred, Effect, Layer, Queue, SubscriptionRef } from '@livestore/utils/effect'
3
3
 
4
- import type { BootStatus, MakeSynchronousDatabase, SqliteError, SynchronousDatabase } from '../adapter-types.js'
4
+ import type { BootStatus, MakeSqliteDb, SqliteError } from '../adapter-types.js'
5
5
  import { UnexpectedError } from '../adapter-types.js'
6
+ import type * as Devtools from '../devtools/mod.js'
6
7
  import type { LiveStoreSchema } from '../schema/mod.js'
7
- import { EventId, MutationEvent, mutationLogMetaTable, SYNC_STATUS_TABLE, syncStatusTable } from '../schema/mod.js'
8
- import { migrateTable } from '../schema-management/migrations.js'
9
- import type { InvalidPullError, IsOfflineError, SyncBackend } from '../sync/sync.js'
8
+ import { LiveStoreEvent } from '../schema/mod.js'
9
+ import type { InvalidPullError, IsOfflineError, SyncOptions } from '../sync/sync.js'
10
10
  import { sql } from '../util.js'
11
- import { execSql } from './connection.js'
12
- import { makeLeaderSyncProcessor } from './leader-sync-processor.js'
11
+ import * as Eventlog from './eventlog.js'
13
12
  import { bootDevtools } from './leader-worker-devtools.js'
14
- import { makePullQueueSet } from './pull-queue-set.js'
13
+ import { makeLeaderSyncProcessor } from './LeaderSyncProcessor.js'
14
+ import { makeMaterializeEvent } from './materialize-event.js'
15
15
  import { recreateDb } from './recreate-db.js'
16
- import type { DevtoolsOptions, InitialBlockingSyncContext, InitialSyncOptions, ShutdownState } from './types.js'
16
+ import type { ShutdownChannel } from './shutdown-channel.js'
17
+ import type {
18
+ DevtoolsOptions,
19
+ InitialBlockingSyncContext,
20
+ InitialSyncOptions,
21
+ LeaderSqliteDb,
22
+ ShutdownState,
23
+ } from './types.js'
17
24
  import { LeaderThreadCtx } from './types.js'
18
25
 
26
+ export interface MakeLeaderThreadLayerParams {
27
+ storeId: string
28
+ syncPayload: Schema.JsonValue | undefined
29
+ clientId: string
30
+ schema: LiveStoreSchema
31
+ makeSqliteDb: MakeSqliteDb
32
+ syncOptions: SyncOptions | undefined
33
+ dbState: LeaderSqliteDb
34
+ dbEventlog: LeaderSqliteDb
35
+ devtoolsOptions: DevtoolsOptions
36
+ shutdownChannel: ShutdownChannel
37
+ params?: {
38
+ localPushBatchSize?: number
39
+ backendPushBatchSize?: number
40
+ }
41
+ testing?: {
42
+ syncProcessor?: {
43
+ delays?: {
44
+ localPushProcessing?: Effect.Effect<void>
45
+ }
46
+ }
47
+ }
48
+ }
49
+
19
50
  export const makeLeaderThreadLayer = ({
20
51
  schema,
21
52
  storeId,
22
- originId,
23
- makeSyncDb,
24
- makeSyncBackend,
25
- db,
26
- dbLog,
53
+ clientId,
54
+ syncPayload,
55
+ makeSqliteDb,
56
+ syncOptions,
57
+ dbState,
58
+ dbEventlog,
27
59
  devtoolsOptions,
28
- initialSyncOptions = { _tag: 'Skip' },
29
- }: {
30
- storeId: string
31
- originId: string
32
- schema: LiveStoreSchema
33
- makeSyncDb: MakeSynchronousDatabase
34
- makeSyncBackend: Effect.Effect<SyncBackend, UnexpectedError, Scope.Scope> | undefined
35
- db: SynchronousDatabase
36
- dbLog: SynchronousDatabase
37
- devtoolsOptions: DevtoolsOptions
38
- initialSyncOptions: InitialSyncOptions | undefined
39
- }): Layer.Layer<LeaderThreadCtx, UnexpectedError, Scope.Scope | HttpClient.HttpClient> =>
60
+ shutdownChannel,
61
+ params,
62
+ testing,
63
+ }: MakeLeaderThreadLayerParams): Layer.Layer<LeaderThreadCtx, UnexpectedError, Scope.Scope | HttpClient.HttpClient> =>
40
64
  Effect.gen(function* () {
41
65
  const bootStatusQueue = yield* Queue.unbounded<BootStatus>().pipe(Effect.acquireRelease(Queue.shutdown))
42
66
 
43
67
  // TODO do more validation here than just checking the count of tables
44
68
  // Either happens on initial boot or if schema changes
45
- const dbMissing = db.select<{ count: number }>(sql`select count(*) as count from sqlite_master`)[0]!.count === 0
69
+ const dbEventlogMissing =
70
+ dbEventlog.select<{ count: number }>(sql`select count(*) as count from sqlite_master`)[0]!.count === 0
71
+
72
+ const dbStateMissing =
73
+ dbState.select<{ count: number }>(sql`select count(*) as count from sqlite_master`)[0]!.count === 0
74
+
75
+ const syncBackend =
76
+ syncOptions?.backend === undefined
77
+ ? undefined
78
+ : yield* syncOptions.backend({ storeId, clientId, payload: syncPayload })
79
+
80
+ if (syncBackend !== undefined) {
81
+ // We're already connecting to the sync backend concurrently
82
+ yield* syncBackend.connect.pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
83
+ }
84
+
85
+ const initialBlockingSyncContext = yield* makeInitialBlockingSyncContext({
86
+ initialSyncOptions: syncOptions?.initialSyncOptions ?? { _tag: 'Skip' },
87
+ bootStatusQueue,
88
+ })
89
+
90
+ const syncProcessor = yield* makeLeaderSyncProcessor({
91
+ schema,
92
+ dbEventlogMissing,
93
+ dbEventlog,
94
+ dbState,
95
+ dbStateMissing,
96
+ initialBlockingSyncContext,
97
+ onError: syncOptions?.onSyncError ?? 'ignore',
98
+ params: {
99
+ localPushBatchSize: params?.localPushBatchSize,
100
+ backendPushBatchSize: params?.backendPushBatchSize,
101
+ },
102
+ testing: {
103
+ delays: testing?.syncProcessor?.delays,
104
+ },
105
+ })
46
106
 
47
- const syncBackend = makeSyncBackend === undefined ? undefined : yield* makeSyncBackend
107
+ const extraIncomingMessagesQueue = yield* Queue.unbounded<Devtools.Leader.MessageToApp>().pipe(
108
+ Effect.acquireRelease(Queue.shutdown),
109
+ )
48
110
 
49
- const initialBlockingSyncContext = yield* makeInitialBlockingSyncContext({ initialSyncOptions, bootStatusQueue })
111
+ const devtoolsContext = devtoolsOptions.enabled
112
+ ? {
113
+ enabled: true as const,
114
+ syncBackendLatch: yield* Effect.makeLatch(true),
115
+ syncBackendLatchState: yield* SubscriptionRef.make<{ latchClosed: boolean }>({ latchClosed: false }),
116
+ }
117
+ : { enabled: false as const }
50
118
 
51
- const syncProcessor = yield* makeLeaderSyncProcessor({ schema, dbMissing, dbLog, initialBlockingSyncContext })
119
+ const materializeEvent = yield* makeMaterializeEvent({ schema, dbState, dbEventlog })
52
120
 
53
121
  const ctx = {
54
122
  schema,
55
123
  bootStatusQueue,
56
124
  storeId,
57
- originId,
58
- db,
59
- dbLog,
60
- makeSyncDb,
61
- mutationEventSchema: MutationEvent.makeMutationEventSchema(schema),
125
+ clientId,
126
+ dbState,
127
+ dbEventlog,
128
+ makeSqliteDb,
129
+ eventSchema: LiveStoreEvent.makeEventDefSchema(schema),
62
130
  shutdownStateSubRef: yield* SubscriptionRef.make<ShutdownState>('running'),
131
+ shutdownChannel,
63
132
  syncBackend,
64
133
  syncProcessor,
65
- connectedClientSessionPullQueues: yield* makePullQueueSet,
134
+ materializeEvent,
135
+ extraIncomingMessagesQueue,
136
+ devtools: devtoolsContext,
137
+ // State will be set during `bootLeaderThread`
138
+ initialState: {} as any as LeaderThreadCtx['Type']['initialState'],
66
139
  } satisfies typeof LeaderThreadCtx.Service
67
140
 
68
141
  // @ts-expect-error For debugging purposes
@@ -70,13 +143,18 @@ export const makeLeaderThreadLayer = ({
70
143
 
71
144
  const layer = Layer.succeed(LeaderThreadCtx, ctx)
72
145
 
73
- yield* bootLeaderThread({ dbMissing, initialBlockingSyncContext, devtoolsOptions }).pipe(Effect.provide(layer))
146
+ ctx.initialState = yield* bootLeaderThread({
147
+ dbStateMissing,
148
+ initialBlockingSyncContext,
149
+ devtoolsOptions,
150
+ }).pipe(Effect.provide(layer))
74
151
 
75
152
  return layer
76
153
  }).pipe(
77
154
  Effect.withSpan('@livestore/common:leader-thread:boot'),
78
155
  Effect.withSpanScoped('@livestore/common:leader-thread'),
79
156
  UnexpectedError.mapToUnexpectedError,
157
+ Effect.tapCauseLogPretty,
80
158
  Layer.unwrapScoped,
81
159
  )
82
160
 
@@ -90,7 +168,7 @@ const makeInitialBlockingSyncContext = ({
90
168
  Effect.gen(function* () {
91
169
  const ctx = {
92
170
  isDone: false,
93
- processedMutations: 0,
171
+ processedEvents: 0,
94
172
  total: -1,
95
173
  }
96
174
 
@@ -113,10 +191,10 @@ const makeInitialBlockingSyncContext = ({
113
191
  ctx.total = remaining + processed
114
192
  }
115
193
 
116
- ctx.processedMutations += processed
194
+ ctx.processedEvents += processed
117
195
  yield* Queue.offer(bootStatusQueue, {
118
196
  stage: 'syncing',
119
- progress: { done: ctx.processedMutations, total: ctx.total },
197
+ progress: { done: ctx.processedEvents, total: ctx.total },
120
198
  })
121
199
 
122
200
  if (remaining === 0 && blockingDeferred !== undefined) {
@@ -132,61 +210,43 @@ const makeInitialBlockingSyncContext = ({
132
210
  * It also starts various background processes (e.g. syncing)
133
211
  */
134
212
  const bootLeaderThread = ({
135
- dbMissing,
213
+ dbStateMissing,
136
214
  initialBlockingSyncContext,
137
215
  devtoolsOptions,
138
216
  }: {
139
- dbMissing: boolean
217
+ dbStateMissing: boolean
140
218
  initialBlockingSyncContext: InitialBlockingSyncContext
141
219
  devtoolsOptions: DevtoolsOptions
142
220
  }): Effect.Effect<
143
- void,
221
+ LeaderThreadCtx['Type']['initialState'],
144
222
  UnexpectedError | SqliteError | IsOfflineError | InvalidPullError,
145
223
  LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient
146
224
  > =>
147
225
  Effect.gen(function* () {
148
- const { dbLog, bootStatusQueue, syncProcessor } = yield* LeaderThreadCtx
226
+ const { dbEventlog, bootStatusQueue, syncProcessor } = yield* LeaderThreadCtx
149
227
 
150
- yield* migrateTable({
151
- db: dbLog,
152
- behaviour: 'create-if-not-exists',
153
- tableAst: mutationLogMetaTable.sqliteDef.ast,
154
- skipMetaTable: true,
155
- })
228
+ yield* Eventlog.initEventlogDb(dbEventlog)
156
229
 
157
- yield* migrateTable({
158
- db: dbLog,
159
- behaviour: 'create-if-not-exists',
160
- tableAst: syncStatusTable.sqliteDef.ast,
161
- skipMetaTable: true,
162
- })
230
+ const { migrationsReport } = dbStateMissing ? yield* recreateDb : { migrationsReport: { migrations: [] } }
163
231
 
164
- // Create sync status row if it doesn't exist
165
- yield* execSql(
166
- dbLog,
167
- sql`INSERT INTO ${SYNC_STATUS_TABLE} (head)
168
- SELECT ${EventId.ROOT.global}
169
- WHERE NOT EXISTS (SELECT 1 FROM ${SYNC_STATUS_TABLE})`,
170
- {},
171
- )
172
-
173
- const dbReady = yield* Deferred.make<void>()
174
-
175
- // We're already starting pulling from the sync backend concurrently but wait until the db is ready before
176
- // processing any incoming mutations
177
- yield* syncProcessor.boot({ dbReady })
178
-
179
- if (dbMissing) {
180
- yield* recreateDb
181
- }
182
-
183
- yield* Deferred.succeed(dbReady, void 0)
232
+ // NOTE the sync processor depends on the dbs being initialized properly
233
+ const { initialLeaderHead } = yield* syncProcessor.boot
184
234
 
185
235
  if (initialBlockingSyncContext.blockingDeferred !== undefined) {
186
- yield* initialBlockingSyncContext.blockingDeferred
236
+ // Provides a syncing status right away before the first pull response comes in
237
+ yield* Queue.offer(bootStatusQueue, {
238
+ stage: 'syncing',
239
+ progress: { done: 0, total: -1 },
240
+ })
241
+
242
+ yield* initialBlockingSyncContext.blockingDeferred.pipe(
243
+ Effect.withSpan('@livestore/common:leader-thread:initial-sync-blocking'),
244
+ )
187
245
  }
188
246
 
189
247
  yield* Queue.offer(bootStatusQueue, { stage: 'done' })
190
248
 
191
249
  yield* bootDevtools(devtoolsOptions).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
250
+
251
+ return { migrationsReport, leaderHead: initialLeaderHead }
192
252
  })
@@ -0,0 +1,169 @@
1
+ import { LS_DEV, shouldNeverHappen } from '@livestore/utils'
2
+ import { Effect, ReadonlyArray, Schema } from '@livestore/utils/effect'
3
+
4
+ import type { SqliteDb } from '../adapter-types.js'
5
+ import { getExecArgsFromEvent } from '../materializer-helper.js'
6
+ import type { LiveStoreSchema } from '../schema/mod.js'
7
+ import { EventId, getEventDef, SystemTables } from '../schema/mod.js'
8
+ import { insertRow } from '../sql-queries/index.js'
9
+ import { sql } from '../util.js'
10
+ import { execSql, execSqlPrepared } from './connection.js'
11
+ import * as Eventlog from './eventlog.js'
12
+ import type { MaterializeEvent } from './types.js'
13
+
14
+ export const makeMaterializeEvent = ({
15
+ schema,
16
+ dbState: db,
17
+ dbEventlog,
18
+ }: {
19
+ schema: LiveStoreSchema
20
+ dbState: SqliteDb
21
+ dbEventlog: SqliteDb
22
+ }): Effect.Effect<MaterializeEvent, never> =>
23
+ Effect.gen(function* () {
24
+ const eventDefSchemaHashMap = new Map(
25
+ // TODO Running `Schema.hash` can be a bottleneck for larger schemas. There is an opportunity to run this
26
+ // at build time and lookup the pre-computed hash at runtime.
27
+ // Also see https://github.com/Effect-TS/effect/issues/2719
28
+ [...schema.eventsDefsMap.entries()].map(([k, v]) => [k, Schema.hash(v.schema)] as const),
29
+ )
30
+
31
+ return (eventEncoded, options) =>
32
+ Effect.gen(function* () {
33
+ const skipEventlog = options?.skipEventlog ?? false
34
+
35
+ const eventName = eventEncoded.name
36
+ const { eventDef, materializer } = getEventDef(schema, eventName)
37
+
38
+ const execArgsArr = getExecArgsFromEvent({
39
+ eventDef,
40
+ materializer,
41
+ db,
42
+ event: { decoded: undefined, encoded: eventEncoded },
43
+ })
44
+
45
+ // NOTE we might want to bring this back if we want to debug no-op events
46
+ // const makeExecuteOptions = (statementSql: string, bindValues: any) => ({
47
+ // onRowsChanged: (rowsChanged: number) => {
48
+ // if (rowsChanged === 0) {
49
+ // console.warn(`Event "${eventDef.name}" did not affect any rows:`, statementSql, bindValues)
50
+ // }
51
+ // },
52
+ // })
53
+
54
+ // console.group('[@livestore/common:leader-thread:materializeEvent]', { eventName })
55
+
56
+ const session = db.session()
57
+
58
+ for (const { statementSql, bindValues } of execArgsArr) {
59
+ // console.debug(eventName, statementSql, bindValues)
60
+ // TODO use cached prepared statements instead of exec
61
+ yield* execSqlPrepared(db, statementSql, bindValues)
62
+ }
63
+
64
+ const changeset = session.changeset()
65
+ session.finish()
66
+
67
+ // TODO use prepared statements
68
+ yield* execSql(
69
+ db,
70
+ ...insertRow({
71
+ tableName: SystemTables.SESSION_CHANGESET_META_TABLE,
72
+ columns: SystemTables.sessionChangesetMetaTable.sqliteDef.columns,
73
+ values: {
74
+ idGlobal: eventEncoded.id.global,
75
+ idClient: eventEncoded.id.client,
76
+ // NOTE the changeset will be empty (i.e. null) for no-op events
77
+ changeset: changeset ?? null,
78
+ debug: LS_DEV ? execArgsArr : null,
79
+ },
80
+ }),
81
+ )
82
+
83
+ // console.groupEnd()
84
+
85
+ // write to eventlog
86
+ if (skipEventlog === false) {
87
+ const eventName = eventEncoded.name
88
+ const eventDefSchemaHash =
89
+ eventDefSchemaHashMap.get(eventName) ?? shouldNeverHappen(`Unknown event definition: ${eventName}`)
90
+
91
+ yield* Eventlog.insertIntoEventlog(
92
+ eventEncoded,
93
+ dbEventlog,
94
+ eventDefSchemaHash,
95
+ eventEncoded.clientId,
96
+ eventEncoded.sessionId,
97
+ )
98
+ } else {
99
+ // console.debug('[@livestore/common:leader-thread] skipping eventlog write', mutation, statementSql, bindValues)
100
+ }
101
+
102
+ return {
103
+ sessionChangeset: changeset
104
+ ? {
105
+ _tag: 'sessionChangeset' as const,
106
+ data: changeset,
107
+ debug: LS_DEV ? execArgsArr : null,
108
+ }
109
+ : { _tag: 'no-op' as const },
110
+ }
111
+ }).pipe(
112
+ Effect.withSpan(`@livestore/common:leader-thread:materializeEvent`, {
113
+ attributes: {
114
+ eventName: eventEncoded.name,
115
+ eventId: eventEncoded.id,
116
+ 'span.label': `${EventId.toString(eventEncoded.id)} ${eventEncoded.name}`,
117
+ },
118
+ }),
119
+ // Effect.logDuration('@livestore/common:leader-thread:materializeEvent'),
120
+ )
121
+ })
122
+
123
+ export const rollback = ({
124
+ dbState,
125
+ dbEventlog,
126
+ eventIdsToRollback,
127
+ }: {
128
+ dbState: SqliteDb
129
+ dbEventlog: SqliteDb
130
+ eventIdsToRollback: EventId.EventId[]
131
+ }) =>
132
+ Effect.gen(function* () {
133
+ const rollbackEvents = dbState
134
+ .select<SystemTables.SessionChangesetMetaRow>(
135
+ sql`SELECT * FROM ${SystemTables.SESSION_CHANGESET_META_TABLE} WHERE (idGlobal, idClient) IN (${eventIdsToRollback.map((id) => `(${id.global}, ${id.client})`).join(', ')})`,
136
+ )
137
+ .map((_) => ({ id: { global: _.idGlobal, client: _.idClient }, changeset: _.changeset, debug: _.debug }))
138
+ .toSorted((a, b) => EventId.compare(a.id, b.id))
139
+
140
+ // Apply changesets in reverse order
141
+ for (let i = rollbackEvents.length - 1; i >= 0; i--) {
142
+ const { changeset } = rollbackEvents[i]!
143
+ if (changeset !== null) {
144
+ dbState.makeChangeset(changeset).invert().apply()
145
+ }
146
+ }
147
+
148
+ const eventIdPairChunks = ReadonlyArray.chunksOf(100)(
149
+ eventIdsToRollback.map((id) => `(${id.global}, ${id.client})`),
150
+ )
151
+
152
+ // Delete the changeset rows
153
+ for (const eventIdPairChunk of eventIdPairChunks) {
154
+ dbState.execute(
155
+ sql`DELETE FROM ${SystemTables.SESSION_CHANGESET_META_TABLE} WHERE (idGlobal, idClient) IN (${eventIdPairChunk.join(', ')})`,
156
+ )
157
+ }
158
+
159
+ // Delete the eventlog rows
160
+ for (const eventIdPairChunk of eventIdPairChunks) {
161
+ dbEventlog.execute(
162
+ sql`DELETE FROM ${SystemTables.EVENTLOG_META_TABLE} WHERE (idGlobal, idClient) IN (${eventIdPairChunk.join(', ')})`,
163
+ )
164
+ }
165
+ }).pipe(
166
+ Effect.withSpan('@livestore/common:LeaderSyncProcessor:rollback', {
167
+ attributes: { count: eventIdsToRollback.length },
168
+ }),
169
+ )
@@ -3,4 +3,4 @@ export * from './types.js'
3
3
  export * as ShutdownChannel from './shutdown-channel.js'
4
4
  export * from './leader-worker-devtools.js'
5
5
  export * from './make-leader-thread-layer.js'
6
- export * from './mutationlog.js'
6
+ export * as Eventlog from './eventlog.js'
@@ -2,85 +2,80 @@ import { casesHandled } from '@livestore/utils'
2
2
  import type { HttpClient } from '@livestore/utils/effect'
3
3
  import { Effect, Queue } from '@livestore/utils/effect'
4
4
 
5
- import type { InvalidPullError, IsOfflineError, MigrationHooks, SqliteError } from '../index.js'
6
- import { initializeSingletonTables, migrateDb, rehydrateFromMutationLog, UnexpectedError } from '../index.js'
5
+ import type { InvalidPullError, IsOfflineError, MigrationHooks, MigrationsReport, SqliteError } from '../index.js'
6
+ import { migrateDb, rematerializeFromEventlog, UnexpectedError } from '../index.js'
7
7
  import { configureConnection } from './connection.js'
8
8
  import { LeaderThreadCtx } from './types.js'
9
9
 
10
10
  export const recreateDb: Effect.Effect<
11
- void,
11
+ { migrationsReport: MigrationsReport },
12
12
  UnexpectedError | SqliteError | IsOfflineError | InvalidPullError,
13
13
  LeaderThreadCtx | HttpClient.HttpClient
14
14
  > = Effect.gen(function* () {
15
- const { db, dbLog, makeSyncDb, schema, bootStatusQueue } = yield* LeaderThreadCtx
15
+ const { dbState, dbEventlog, schema, bootStatusQueue, materializeEvent } = yield* LeaderThreadCtx
16
16
 
17
- const migrationOptions = schema.migrationOptions
17
+ const migrationOptions = schema.state.sqlite.migrations
18
+ let migrationsReport: MigrationsReport
18
19
 
19
20
  yield* Effect.addFinalizer(
20
21
  Effect.fn('recreateDb:finalizer')(function* (ex) {
21
- if (ex._tag === 'Failure') db.destroy()
22
+ if (ex._tag === 'Failure') dbState.destroy()
22
23
  }),
23
24
  )
24
25
 
25
26
  // NOTE to speed up the operations below, we're creating a temporary in-memory database
26
27
  // and later we'll overwrite the persisted database with the new data
27
- const tmpSyncDb = yield* makeSyncDb({ _tag: 'in-memory' })
28
- yield* configureConnection(tmpSyncDb, { fkEnabled: true })
28
+ // TODO bring back this optimization
29
+ // const tmpDb = yield* makeSqliteDb({ _tag: 'in-memory' })
30
+ const tmpDb = dbState
31
+ yield* configureConnection(tmpDb, { foreignKeys: true })
29
32
 
30
33
  const initDb = (hooks: Partial<MigrationHooks> | undefined) =>
31
34
  Effect.gen(function* () {
32
- yield* Effect.tryAll(() => hooks?.init?.(tmpSyncDb)).pipe(UnexpectedError.mapToUnexpectedError)
35
+ yield* Effect.tryAll(() => hooks?.init?.(tmpDb)).pipe(UnexpectedError.mapToUnexpectedError)
33
36
 
34
- yield* migrateDb({
35
- db: tmpSyncDb,
37
+ const migrationsReport = yield* migrateDb({
38
+ db: tmpDb,
36
39
  schema,
37
40
  onProgress: ({ done, total }) =>
38
41
  Queue.offer(bootStatusQueue, { stage: 'migrating', progress: { done, total } }),
39
42
  })
40
43
 
41
- initializeSingletonTables(schema, tmpSyncDb)
44
+ yield* Effect.tryAll(() => hooks?.pre?.(tmpDb)).pipe(UnexpectedError.mapToUnexpectedError)
42
45
 
43
- yield* Effect.tryAll(() => hooks?.pre?.(tmpSyncDb)).pipe(UnexpectedError.mapToUnexpectedError)
44
-
45
- return tmpSyncDb
46
+ return { migrationsReport, tmpDb }
46
47
  })
47
48
 
48
49
  switch (migrationOptions.strategy) {
49
- case 'from-mutation-log': {
50
+ case 'auto': {
50
51
  const hooks = migrationOptions.hooks
51
- const tmpSyncDb = yield* initDb(hooks)
52
+ const initResult = yield* initDb(hooks)
53
+
54
+ migrationsReport = initResult.migrationsReport
52
55
 
53
- yield* rehydrateFromMutationLog({
54
- db: tmpSyncDb,
55
- logDb: dbLog,
56
+ yield* rematerializeFromEventlog({
57
+ // db: initResult.tmpDb,
58
+ dbEventlog,
56
59
  schema,
57
- migrationOptions,
60
+ materializeEvent,
58
61
  onProgress: ({ done, total }) =>
59
62
  Queue.offer(bootStatusQueue, { stage: 'rehydrating', progress: { done, total } }),
60
63
  })
61
64
 
62
- yield* Effect.tryAll(() => hooks?.post?.(tmpSyncDb)).pipe(UnexpectedError.mapToUnexpectedError)
63
-
64
- break
65
- }
66
- case 'hard-reset': {
67
- const hooks = migrationOptions.hooks
68
- const tmpInMemoryDb = yield* initDb(hooks)
69
-
70
- // The database is migrated but empty now, so nothing else to do
71
-
72
- yield* Effect.tryAll(() => hooks?.post?.(tmpInMemoryDb)).pipe(UnexpectedError.mapToUnexpectedError)
65
+ yield* Effect.tryAll(() => hooks?.post?.(initResult.tmpDb)).pipe(UnexpectedError.mapToUnexpectedError)
73
66
 
74
67
  break
75
68
  }
76
69
  case 'manual': {
77
- const oldDbData = db.export()
70
+ const oldDbData = dbState.export()
71
+
72
+ migrationsReport = { migrations: [] }
78
73
 
79
74
  const newDbData = yield* Effect.tryAll(() => migrationOptions.migrate(oldDbData)).pipe(
80
75
  UnexpectedError.mapToUnexpectedError,
81
76
  )
82
77
 
83
- tmpSyncDb.import(newDbData)
78
+ tmpDb.import(newDbData)
84
79
 
85
80
  // TODO validate schema
86
81
 
@@ -91,17 +86,21 @@ export const recreateDb: Effect.Effect<
91
86
  }
92
87
  }
93
88
 
89
+ // TODO bring back
94
90
  // Import the temporary in-memory database into the persistent database
95
- yield* Effect.sync(() => db.import(tmpSyncDb)).pipe(
96
- Effect.withSpan('@livestore/common:leader-thread:recreateDb:import'),
97
- )
91
+ // yield* Effect.sync(() => db.import(tmpDb)).pipe(
92
+ // Effect.withSpan('@livestore/common:leader-thread:recreateDb:import'),
93
+ // )
98
94
 
99
95
  // TODO maybe bring back re-using this initial snapshot to avoid calling `.export()` again
100
96
  // We've disabled this for now as it made the code too complex, as we often run syncing right after
101
97
  // so the snapshot is no longer up to date
102
- // const snapshotFromTmpDb = tmpSyncDb.export()
98
+ // const snapshotFromTmpDb = tmpDb.export()
99
+
100
+ // TODO bring back
101
+ // tmpDb.close()
103
102
 
104
- tmpSyncDb.close()
103
+ return { migrationsReport }
105
104
  }).pipe(
106
105
  Effect.scoped, // NOTE we're closing the scope here so finalizers are called when the effect is done
107
106
  Effect.withSpan('@livestore/common:leader-thread:recreateDb'),
@@ -1,11 +1,9 @@
1
1
  import type { WebChannel } from '@livestore/utils/effect'
2
2
  import { Schema } from '@livestore/utils/effect'
3
3
 
4
- import { IntentionalShutdownCause } from '../index.js'
4
+ import { IntentionalShutdownCause, UnexpectedError } from '../index.js'
5
5
 
6
- export class DedicatedWorkerDisconnectBroadcast extends Schema.TaggedStruct('DedicatedWorkerDisconnectBroadcast', {}) {}
7
-
8
- export class All extends Schema.Union(IntentionalShutdownCause, DedicatedWorkerDisconnectBroadcast) {}
6
+ export class All extends Schema.Union(IntentionalShutdownCause, UnexpectedError) {}
9
7
 
10
8
  /**
11
9
  * Used internally by an adapter to shutdown gracefully.