@livestore/common 0.3.0-dev.9 → 0.3.0

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