@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,44 +1,40 @@
1
1
  import type {
2
2
  Deferred,
3
3
  Effect,
4
- Fiber,
5
4
  HttpClient,
6
5
  Option,
7
6
  Queue,
8
7
  Scope,
8
+ Stream,
9
+ Subscribable,
9
10
  SubscriptionRef,
10
- WebChannel,
11
11
  } from '@livestore/utils/effect'
12
12
  import { Context, Schema } from '@livestore/utils/effect'
13
+ import type { MeshNode } from '@livestore/webmesh'
13
14
 
15
+ import type { LeaderPullCursor, SqliteError } from '../adapter-types.js'
14
16
  import type {
15
17
  BootStatus,
16
18
  Devtools,
17
- InvalidPushError,
18
- MakeSynchronousDatabase,
19
+ LeaderAheadError,
20
+ MakeSqliteDb,
21
+ MigrationsReport,
19
22
  PersistenceInfo,
23
+ SqliteDb,
20
24
  SyncBackend,
21
- SynchronousDatabase,
22
25
  UnexpectedError,
23
26
  } from '../index.js'
24
- import type { EventId, LiveStoreSchema, MutationEvent } from '../schema/mod.js'
25
- import type { PayloadUpstream, SyncState } from '../sync/syncstate.js'
27
+ import type { EventId, LiveStoreEvent, LiveStoreSchema } from '../schema/mod.js'
28
+ import type * as SyncState from '../sync/syncstate.js'
26
29
  import type { ShutdownChannel } from './shutdown-channel.js'
27
30
 
28
31
  export type ShutdownState = 'running' | 'shutting-down'
29
32
 
30
- export class OuterWorkerCtx extends Context.Tag('OuterWorkerCtx')<
31
- OuterWorkerCtx,
32
- {
33
- innerFiber: Fiber.RuntimeFiber<any, any>
34
- }
35
- >() {}
36
-
37
33
  export const InitialSyncOptionsSkip = Schema.TaggedStruct('Skip', {})
38
34
  export type InitialSyncOptionsSkip = typeof InitialSyncOptionsSkip.Type
39
35
 
40
36
  export const InitialSyncOptionsBlocking = Schema.TaggedStruct('Blocking', {
41
- timeout: Schema.DurationFromMillis,
37
+ timeout: Schema.Union(Schema.DurationFromMillis, Schema.Number),
42
38
  })
43
39
 
44
40
  export type InitialSyncOptionsBlocking = typeof InitialSyncOptionsBlocking.Type
@@ -55,8 +51,8 @@ export type InitialSyncInfo = Option.Option<{
55
51
  // | { _tag: 'Recreate'; snapshotRef: Ref.Ref<Uint8Array | undefined>; syncInfo: InitialSyncInfo }
56
52
  // | { _tag: 'Reuse'; syncInfo: InitialSyncInfo }
57
53
 
58
- export type LeaderDatabase = SynchronousDatabase<{ dbPointer: number; persistenceInfo: PersistenceInfo }>
59
- export type PersistenceInfoPair = { db: PersistenceInfo; mutationLog: PersistenceInfo }
54
+ export type LeaderSqliteDb = SqliteDb<{ dbPointer: number; persistenceInfo: PersistenceInfo }>
55
+ export type PersistenceInfoPair = { state: PersistenceInfo; eventlog: PersistenceInfo }
60
56
 
61
57
  export type DevtoolsOptions =
62
58
  | {
@@ -64,66 +60,115 @@ export type DevtoolsOptions =
64
60
  }
65
61
  | {
66
62
  enabled: true
67
- makeContext: Effect.Effect<
63
+ boot: Effect.Effect<
68
64
  {
69
- devtoolsWebChannel: WebChannel.WebChannel<Devtools.MessageToAppLeader, Devtools.MessageFromAppLeader>
70
- shutdownChannel: ShutdownChannel
65
+ node: MeshNode
71
66
  persistenceInfo: PersistenceInfoPair
67
+ mode: 'proxy' | 'direct'
72
68
  },
73
69
  UnexpectedError,
74
- Scope.Scope
70
+ Scope.Scope | HttpClient.HttpClient | LeaderThreadCtx
75
71
  >
76
72
  }
77
73
 
74
+ export type DevtoolsContext =
75
+ | {
76
+ enabled: true
77
+ // syncBackendPullLatch: Effect.Latch
78
+ // syncBackendPushLatch: Effect.Latch
79
+ syncBackendLatch: Effect.Latch
80
+ syncBackendLatchState: SubscriptionRef.SubscriptionRef<{ latchClosed: boolean }>
81
+ }
82
+ | {
83
+ enabled: false
84
+ }
85
+
78
86
  export class LeaderThreadCtx extends Context.Tag('LeaderThreadCtx')<
79
87
  LeaderThreadCtx,
80
88
  {
81
89
  schema: LiveStoreSchema
82
90
  storeId: string
83
- originId: string
84
- makeSyncDb: MakeSynchronousDatabase
85
- db: LeaderDatabase
86
- dbLog: LeaderDatabase
91
+ clientId: string
92
+ makeSqliteDb: MakeSqliteDb
93
+ dbState: LeaderSqliteDb
94
+ dbEventlog: LeaderSqliteDb
87
95
  bootStatusQueue: Queue.Queue<BootStatus>
88
96
  // TODO we should find a more elegant way to handle cases which need this ref for their implementation
89
97
  shutdownStateSubRef: SubscriptionRef.SubscriptionRef<ShutdownState>
90
- mutationEventSchema: MutationEvent.ForMutationDefRecord<any>
91
- // devtools: DevtoolsContext
98
+ shutdownChannel: ShutdownChannel
99
+ eventSchema: LiveStoreEvent.ForEventDefRecord<any>
100
+ devtools: DevtoolsContext
92
101
  syncBackend: SyncBackend | undefined
93
- syncProcessor: SyncProcessor
94
- connectedClientSessionPullQueues: PullQueueSet
102
+ syncProcessor: LeaderSyncProcessor
103
+ materializeEvent: MaterializeEvent
104
+ initialState: {
105
+ leaderHead: EventId.EventId
106
+ migrationsReport: MigrationsReport
107
+ }
108
+ /**
109
+ * e.g. used for `store._dev` APIs
110
+ *
111
+ * This is currently separated from `.devtools` as it also needs to work when devtools are disabled
112
+ */
113
+ extraIncomingMessagesQueue: Queue.Queue<Devtools.Leader.MessageToApp>
95
114
  }
96
115
  >() {}
97
116
 
117
+ export type MaterializeEvent = (
118
+ eventEncoded: LiveStoreEvent.EncodedWithMeta,
119
+ options?: {
120
+ /** Needed for rematerializeFromEventlog */
121
+ skipEventlog?: boolean
122
+ },
123
+ ) => Effect.Effect<
124
+ { sessionChangeset: { _tag: 'sessionChangeset'; data: Uint8Array; debug: any } | { _tag: 'no-op' } },
125
+ SqliteError | UnexpectedError
126
+ >
127
+
98
128
  export type InitialBlockingSyncContext = {
99
129
  blockingDeferred: Deferred.Deferred<void> | undefined
100
130
  update: (_: { remaining: number; processed: number }) => Effect.Effect<void>
101
131
  }
102
132
 
103
- export type PullQueueItem = {
104
- // mutationEvents: ReadonlyArray<MutationEvent.AnyEncoded>
105
- // backendHead: number
106
- payload: PayloadUpstream
107
- // TODO move `remaining` into `PayloadUpstream`
108
- remaining: number
109
- }
110
-
111
- export interface SyncProcessor {
133
+ export interface LeaderSyncProcessor {
134
+ /** Used by client sessions to subscribe to upstream sync state changes */
135
+ pull: (args: {
136
+ cursor: LeaderPullCursor
137
+ }) => Stream.Stream<{ payload: typeof SyncState.PayloadUpstream.Type; mergeCounter: number }, UnexpectedError>
138
+ /** The `pullQueue` API can be used instead of `pull` when more convenient */
139
+ pullQueue: (args: {
140
+ cursor: LeaderPullCursor
141
+ }) => Effect.Effect<
142
+ Queue.Queue<{ payload: typeof SyncState.PayloadUpstream.Type; mergeCounter: number }>,
143
+ UnexpectedError,
144
+ Scope.Scope
145
+ >
146
+
147
+ /** Used by client sessions to push events to the leader thread */
112
148
  push: (
113
149
  /** `batch` needs to follow the same rules as `batch` in `SyncBackend.push` */
114
- batch: ReadonlyArray<MutationEvent.EncodedWithMeta>,
115
- ) => Effect.Effect<void, UnexpectedError | InvalidPushError, HttpClient.HttpClient | LeaderThreadCtx>
116
-
117
- pushPartial: (mutationEvent: MutationEvent.PartialAnyEncoded) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx>
118
- boot: (args: {
119
- dbReady: Deferred.Deferred<void>
120
- }) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient>
121
- syncState: Effect.Effect<SyncState, UnexpectedError>
122
- }
123
-
124
- export interface PullQueueSet {
125
- makeQueue: (
126
- since: EventId.EventId,
127
- ) => Effect.Effect<Queue.Queue<PullQueueItem>, UnexpectedError, Scope.Scope | LeaderThreadCtx>
128
- offer: (item: PullQueueItem) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx>
150
+ batch: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>,
151
+ options?: {
152
+ /**
153
+ * If true, the effect will only finish when the local push has been processed (i.e. succeeded or was rejected).
154
+ * @default false
155
+ */
156
+ waitForProcessing?: boolean
157
+ },
158
+ ) => Effect.Effect<void, LeaderAheadError>
159
+
160
+ /** Currently only used by devtools which don't provide their own event numbers */
161
+ pushPartial: (args: {
162
+ event: LiveStoreEvent.PartialAnyEncoded
163
+ clientId: string
164
+ sessionId: string
165
+ }) => Effect.Effect<void, UnexpectedError>
166
+
167
+ boot: Effect.Effect<
168
+ { initialLeaderHead: EventId.EventId },
169
+ UnexpectedError,
170
+ LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient
171
+ >
172
+ syncState: Subscribable.Subscribable<SyncState.SyncState>
173
+ getMergeCounter: () => number
129
174
  }
@@ -0,0 +1,119 @@
1
+ import type { Scope, SubscriptionRef } from '@livestore/utils/effect'
2
+ import { Effect, Stream } from '@livestore/utils/effect'
3
+ import * as Webmesh from '@livestore/webmesh'
4
+
5
+ import type {
6
+ AdapterArgs,
7
+ ClientSession,
8
+ ClientSessionLeaderThreadProxy,
9
+ LockStatus,
10
+ SqliteDb,
11
+ UnexpectedError,
12
+ } from './adapter-types.js'
13
+ import * as Devtools from './devtools/mod.js'
14
+
15
+ declare global {
16
+ // eslint-disable-next-line no-var
17
+ var __debugWebmeshNode: any
18
+ }
19
+
20
+ export const makeClientSession = <R>({
21
+ storeId,
22
+ clientId,
23
+ sessionId,
24
+ devtoolsEnabled,
25
+ connectDevtoolsToStore,
26
+ lockStatus,
27
+ leaderThread,
28
+ schema,
29
+ sqliteDb,
30
+ shutdown,
31
+ connectWebmeshNode,
32
+ webmeshMode,
33
+ }: AdapterArgs & {
34
+ clientId: string
35
+ sessionId: string
36
+ lockStatus: SubscriptionRef.SubscriptionRef<LockStatus>
37
+ leaderThread: ClientSessionLeaderThreadProxy
38
+ sqliteDb: SqliteDb
39
+ connectWebmeshNode: (args: {
40
+ webmeshNode: Webmesh.MeshNode
41
+ sessionInfo: Devtools.SessionInfo.SessionInfo
42
+ }) => Effect.Effect<void, UnexpectedError, Scope.Scope | R>
43
+ webmeshMode: 'direct' | 'proxy'
44
+ }): Effect.Effect<ClientSession, never, Scope.Scope | R> =>
45
+ Effect.gen(function* () {
46
+ const devtools: ClientSession['devtools'] = devtoolsEnabled
47
+ ? { enabled: true, pullLatch: yield* Effect.makeLatch(true), pushLatch: yield* Effect.makeLatch(true) }
48
+ : { enabled: false }
49
+
50
+ if (devtoolsEnabled) {
51
+ yield* Effect.gen(function* () {
52
+ const webmeshNode = yield* Webmesh.makeMeshNode(
53
+ Devtools.makeNodeName.client.session({ storeId, clientId, sessionId }),
54
+ )
55
+
56
+ globalThis.__debugWebmeshNode = webmeshNode
57
+
58
+ const schemaAlias = schema.devtools.alias
59
+ const sessionInfo = Devtools.SessionInfo.SessionInfo.make({
60
+ storeId,
61
+ clientId,
62
+ sessionId,
63
+ schemaAlias,
64
+ isLeader: true, // TODO actually check if we are leader
65
+ })
66
+
67
+ yield* connectWebmeshNode({ webmeshNode, sessionInfo })
68
+
69
+ const sessionInfoBroadcastChannel = yield* Devtools.makeSessionInfoBroadcastChannel(webmeshNode)
70
+
71
+ yield* Devtools.SessionInfo.provideSessionInfo({
72
+ webChannel: sessionInfoBroadcastChannel,
73
+ sessionInfo,
74
+ }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
75
+
76
+ yield* webmeshNode.listenForChannel.pipe(
77
+ Stream.filter(
78
+ (res) =>
79
+ Devtools.isChannelName.devtoolsClientSession(res.channelName, { storeId, clientId, sessionId }) &&
80
+ res.mode === webmeshMode,
81
+ ),
82
+ Stream.tap(
83
+ Effect.fnUntraced(
84
+ function* ({ channelName, source }) {
85
+ const clientSessionDevtoolsChannel = yield* webmeshNode.makeChannel({
86
+ target: source,
87
+ channelName,
88
+ schema: {
89
+ listen: Devtools.ClientSession.MessageToApp,
90
+ send: Devtools.ClientSession.MessageFromApp,
91
+ },
92
+ mode: webmeshMode,
93
+ })
94
+
95
+ yield* connectDevtoolsToStore(clientSessionDevtoolsChannel)
96
+ },
97
+ Effect.tapCauseLogPretty,
98
+ Effect.forkScoped,
99
+ ),
100
+ ),
101
+ Stream.runDrain,
102
+ )
103
+ }).pipe(
104
+ Effect.withSpan('@livestore/common:make-client-session:devtools'),
105
+ Effect.tapCauseLogPretty,
106
+ Effect.forkScoped,
107
+ )
108
+ }
109
+
110
+ return {
111
+ sqliteDb,
112
+ leaderThread,
113
+ devtools,
114
+ lockStatus,
115
+ clientId,
116
+ sessionId,
117
+ shutdown,
118
+ } satisfies ClientSession
119
+ })
@@ -0,0 +1,135 @@
1
+ import { isReadonlyArray } from '@livestore/utils'
2
+ import { Schema } from '@livestore/utils/effect'
3
+
4
+ import type { SqliteDb } from './adapter-types.js'
5
+ import { SessionIdSymbol } from './adapter-types.js'
6
+ import type { EventDef, Materializer, MaterializerContextQuery, MaterializerResult } from './schema/EventDef.js'
7
+ import type * as LiveStoreEvent from './schema/LiveStoreEvent.js'
8
+ import type { QueryBuilder } from './schema/state/sqlite/query-builder/api.js'
9
+ import { isQueryBuilder } from './schema/state/sqlite/query-builder/api.js'
10
+ import { getResultSchema } from './schema/state/sqlite/query-builder/impl.js'
11
+ import { type BindValues } from './sql-queries/sql-queries.js'
12
+ import type { ParamsObject, PreparedBindValues } from './util.js'
13
+ import { prepareBindValues } from './util.js'
14
+
15
+ export const getExecArgsFromEvent = ({
16
+ eventDef,
17
+ materializer,
18
+ db,
19
+ event,
20
+ }: {
21
+ eventDef: EventDef.AnyWithoutFn
22
+ materializer: Materializer
23
+ db: SqliteDb
24
+ /** Both encoded and decoded events are supported to reduce the number of times we need to decode/encode */
25
+ event:
26
+ | {
27
+ decoded: LiveStoreEvent.AnyDecoded | LiveStoreEvent.PartialAnyDecoded
28
+ encoded: undefined
29
+ }
30
+ | {
31
+ decoded: undefined
32
+ encoded: LiveStoreEvent.AnyEncoded | LiveStoreEvent.PartialAnyEncoded
33
+ }
34
+ }): ReadonlyArray<{
35
+ statementSql: string
36
+ bindValues: PreparedBindValues
37
+ writeTables: ReadonlySet<string> | undefined
38
+ }> => {
39
+ const eventArgsDecoded =
40
+ event.decoded === undefined ? Schema.decodeUnknownSync(eventDef.schema)(event.encoded!.args) : event.decoded.args
41
+ const eventArgsEncoded = event.encoded?.args ?? Schema.encodeUnknownSync(eventDef.schema)(event.decoded!.args)
42
+
43
+ const query: MaterializerContextQuery = (
44
+ rawQueryOrQueryBuilder:
45
+ | {
46
+ query: string
47
+ bindValues: ParamsObject
48
+ }
49
+ | QueryBuilder.Any,
50
+ ) => {
51
+ if (isQueryBuilder(rawQueryOrQueryBuilder)) {
52
+ const { query, bindValues } = rawQueryOrQueryBuilder.asSql()
53
+ const rawResults = db.select(query, prepareBindValues(bindValues, query))
54
+ const resultSchema = getResultSchema(rawQueryOrQueryBuilder)
55
+ return Schema.decodeSync(resultSchema)(rawResults)
56
+ } else {
57
+ const { query, bindValues } = rawQueryOrQueryBuilder
58
+ return db.select(query, prepareBindValues(bindValues, query))
59
+ }
60
+ }
61
+
62
+ const res = materializer(eventArgsDecoded, {
63
+ eventDef,
64
+ query,
65
+ // TODO properly implement this
66
+ currentFacts: new Map(),
67
+ })
68
+
69
+ const statementRes = mapMaterializerResult(res)
70
+
71
+ return statementRes.map((statementRes) => {
72
+ const statementSql = statementRes.sql
73
+
74
+ const bindValues = typeof statementRes === 'string' ? eventArgsEncoded : statementRes.bindValues
75
+
76
+ const writeTables = typeof statementRes === 'string' ? undefined : statementRes.writeTables
77
+
78
+ return { statementSql, bindValues: prepareBindValues(bindValues ?? {}, statementSql), writeTables }
79
+ })
80
+ }
81
+
82
+ const mapMaterializerResult = (
83
+ materializerResult: MaterializerResult | ReadonlyArray<MaterializerResult>,
84
+ ): ReadonlyArray<{
85
+ sql: string
86
+ bindValues: BindValues
87
+ writeTables: ReadonlySet<string> | undefined
88
+ }> => {
89
+ if (isReadonlyArray(materializerResult)) {
90
+ return materializerResult.flatMap(mapMaterializerResult)
91
+ }
92
+ if (isQueryBuilder(materializerResult)) {
93
+ const { query, bindValues } = materializerResult.asSql()
94
+ return [{ sql: query, bindValues: bindValues as BindValues, writeTables: undefined }]
95
+ } else if (typeof materializerResult === 'string') {
96
+ return [{ sql: materializerResult, bindValues: {} as BindValues, writeTables: undefined }]
97
+ } else {
98
+ return [
99
+ {
100
+ sql: materializerResult.sql,
101
+ bindValues: materializerResult.bindValues,
102
+ writeTables: materializerResult.writeTables,
103
+ },
104
+ ]
105
+ }
106
+ }
107
+
108
+ // NOTE we should explore whether there is a more elegant solution
109
+ // e.g. by leveraging the schema to replace the sessionIdSymbol
110
+ export const replaceSessionIdSymbol = (
111
+ bindValues: Record<string, unknown> | ReadonlyArray<unknown>,
112
+ sessionId: string,
113
+ ) => {
114
+ deepReplaceValue(bindValues, SessionIdSymbol, sessionId)
115
+ }
116
+
117
+ const deepReplaceValue = <S, R>(input: any, searchValue: S, replaceValue: R): void => {
118
+ if (Array.isArray(input)) {
119
+ for (const i in input) {
120
+ if (input[i] === searchValue) {
121
+ input[i] = replaceValue
122
+ } else {
123
+ deepReplaceValue(input[i], searchValue, replaceValue)
124
+ }
125
+ }
126
+ } else if (typeof input === 'object' && input !== null) {
127
+ for (const key in input) {
128
+ if (input[key] === searchValue) {
129
+ input[key] = replaceValue
130
+ } else {
131
+ deepReplaceValue(input[key], searchValue, replaceValue)
132
+ }
133
+ }
134
+ }
135
+ }
package/src/otel.ts CHANGED
@@ -18,3 +18,11 @@ export const provideOtel =
18
18
  Effect.provide(TracingLive),
19
19
  )
20
20
  }
21
+
22
+ export const getDurationMsFromSpan = (span: otel.Span): number => {
23
+ const durationHr: [seconds: number, nanos: number] = (span as any)._duration
24
+ return durationHr[0] * 1000 + durationHr[1] / 1_000_000
25
+ }
26
+
27
+ export const getStartTimeHighResFromSpan = (span: otel.Span): DOMHighResTimeStamp =>
28
+ (span as any)._performanceStartTime as DOMHighResTimeStamp
@@ -0,0 +1,117 @@
1
+ import { memoizeByRef } from '@livestore/utils'
2
+ import { Chunk, Effect, Option, Schema, Stream } from '@livestore/utils/effect'
3
+
4
+ import { type SqliteDb, UnexpectedError } from './adapter-types.js'
5
+ import type { MaterializeEvent } from './leader-thread/mod.js'
6
+ import type { EventDef, LiveStoreSchema } from './schema/mod.js'
7
+ import { EventId, getEventDef, LiveStoreEvent, SystemTables } from './schema/mod.js'
8
+ import type { PreparedBindValues } from './util.js'
9
+ import { sql } from './util.js'
10
+
11
+ export const rematerializeFromEventlog = ({
12
+ dbEventlog,
13
+ // TODO re-use this db when bringing back the boot in-memory db implementation
14
+ // db,
15
+ schema,
16
+ onProgress,
17
+ materializeEvent,
18
+ }: {
19
+ dbEventlog: SqliteDb
20
+ // db: SqliteDb
21
+ schema: LiveStoreSchema
22
+ onProgress: (_: { done: number; total: number }) => Effect.Effect<void>
23
+ materializeEvent: MaterializeEvent
24
+ }) =>
25
+ Effect.gen(function* () {
26
+ const eventsCount = dbEventlog.select<{ count: number }>(
27
+ `SELECT COUNT(*) AS count FROM ${SystemTables.EVENTLOG_META_TABLE}`,
28
+ )[0]!.count
29
+
30
+ const hashEvent = memoizeByRef((event: EventDef.AnyWithoutFn) => Schema.hash(event.schema))
31
+
32
+ const processEvent = (row: SystemTables.EventlogMetaRow) =>
33
+ Effect.gen(function* () {
34
+ const eventDef = getEventDef(schema, row.name)
35
+
36
+ if (hashEvent(eventDef.eventDef) !== row.schemaHash) {
37
+ yield* Effect.logWarning(
38
+ `Schema hash mismatch for event definition ${row.name}. Trying to materialize event anyway.`,
39
+ )
40
+ }
41
+
42
+ const args = JSON.parse(row.argsJson)
43
+
44
+ // Checking whether the schema has changed in an incompatible way
45
+ yield* Schema.decodeUnknown(eventDef.eventDef.schema)(args).pipe(
46
+ Effect.mapError((cause) =>
47
+ UnexpectedError.make({
48
+ cause,
49
+ note: `\
50
+ There was an error during rematerializing from the eventlog while decoding
51
+ the persisted event args for event definition "${row.name}".
52
+ This likely means the schema has changed in an incompatible way.
53
+ `,
54
+ }),
55
+ ),
56
+ )
57
+
58
+ const eventEncoded = LiveStoreEvent.EncodedWithMeta.make({
59
+ id: { global: row.idGlobal, client: row.idClient },
60
+ parentId: { global: row.parentIdGlobal, client: row.parentIdClient },
61
+ name: row.name,
62
+ args,
63
+ clientId: row.clientId,
64
+ sessionId: row.sessionId,
65
+ })
66
+
67
+ yield* materializeEvent(eventEncoded, { skipEventlog: true })
68
+ }).pipe(Effect.withSpan(`@livestore/common:rematerializeFromEventlog:processEvent`))
69
+
70
+ const CHUNK_SIZE = 100
71
+
72
+ const stmt = dbEventlog.prepare(sql`\
73
+ SELECT * FROM ${SystemTables.EVENTLOG_META_TABLE}
74
+ WHERE idGlobal > $idGlobal OR (idGlobal = $idGlobal AND idClient > $idClient)
75
+ ORDER BY idGlobal ASC, idClient ASC
76
+ LIMIT ${CHUNK_SIZE}
77
+ `)
78
+
79
+ let processedEvents = 0
80
+
81
+ yield* Stream.unfoldChunk<
82
+ Chunk.Chunk<SystemTables.EventlogMetaRow> | { _tag: 'Initial ' },
83
+ SystemTables.EventlogMetaRow
84
+ >({ _tag: 'Initial ' }, (item) => {
85
+ // End stream if no more rows
86
+ if (Chunk.isChunk(item) && item.length === 0) return Option.none()
87
+
88
+ const lastId = Chunk.isChunk(item)
89
+ ? Chunk.last(item).pipe(
90
+ Option.map((_) => ({ global: _.idGlobal, client: _.idClient })),
91
+ Option.getOrElse(() => EventId.ROOT),
92
+ )
93
+ : EventId.ROOT
94
+ const nextItem = Chunk.fromIterable(
95
+ stmt.select<SystemTables.EventlogMetaRow>({
96
+ $idGlobal: lastId?.global,
97
+ $idClient: lastId?.client,
98
+ } as any as PreparedBindValues),
99
+ )
100
+ const prevItem = Chunk.isChunk(item) ? item : Chunk.empty()
101
+ return Option.some([prevItem, nextItem])
102
+ }).pipe(
103
+ Stream.bufferChunks({ capacity: 2 }),
104
+ Stream.tap((row) =>
105
+ Effect.gen(function* () {
106
+ yield* processEvent(row)
107
+
108
+ processedEvents++
109
+ yield* onProgress({ done: processedEvents, total: eventsCount })
110
+ }),
111
+ ),
112
+ Stream.runDrain,
113
+ )
114
+ }).pipe(
115
+ Effect.withPerformanceMeasure('@livestore/common:rematerializeFromEventlog'),
116
+ Effect.withSpan('@livestore/common:rematerializeFromEventlog'),
117
+ )