@livestore/common 0.3.0-dev.9 → 0.3.1-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (479) hide show
  1. package/LICENSE +201 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/__tests__/fixture.d.ts +83 -221
  4. package/dist/__tests__/fixture.d.ts.map +1 -1
  5. package/dist/__tests__/fixture.js +33 -11
  6. package/dist/__tests__/fixture.js.map +1 -1
  7. package/dist/adapter-types.d.ts +120 -64
  8. package/dist/adapter-types.d.ts.map +1 -1
  9. package/dist/adapter-types.js +39 -8
  10. package/dist/adapter-types.js.map +1 -1
  11. package/dist/bounded-collections.d.ts.map +1 -1
  12. package/dist/debug-info.d.ts +1 -1
  13. package/dist/debug-info.d.ts.map +1 -1
  14. package/dist/debug-info.js +1 -0
  15. package/dist/debug-info.js.map +1 -1
  16. package/dist/devtools/devtools-messages-client-session.d.ts +390 -0
  17. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -0
  18. package/dist/devtools/devtools-messages-client-session.js +97 -0
  19. package/dist/devtools/devtools-messages-client-session.js.map +1 -0
  20. package/dist/devtools/devtools-messages-common.d.ts +68 -0
  21. package/dist/devtools/devtools-messages-common.d.ts.map +1 -0
  22. package/dist/devtools/devtools-messages-common.js +60 -0
  23. package/dist/devtools/devtools-messages-common.js.map +1 -0
  24. package/dist/devtools/devtools-messages-leader.d.ts +394 -0
  25. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -0
  26. package/dist/devtools/devtools-messages-leader.js +147 -0
  27. package/dist/devtools/devtools-messages-leader.js.map +1 -0
  28. package/dist/devtools/devtools-messages.d.ts +3 -580
  29. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  30. package/dist/devtools/devtools-messages.js +3 -174
  31. package/dist/devtools/devtools-messages.js.map +1 -1
  32. package/dist/devtools/devtools-sessioninfo.d.ts +32 -0
  33. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -0
  34. package/dist/devtools/devtools-sessioninfo.js +36 -0
  35. package/dist/devtools/devtools-sessioninfo.js.map +1 -0
  36. package/dist/devtools/mod.d.ts +55 -0
  37. package/dist/devtools/mod.d.ts.map +1 -0
  38. package/dist/devtools/mod.js +33 -0
  39. package/dist/devtools/mod.js.map +1 -0
  40. package/dist/index.d.ts +7 -9
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +7 -9
  43. package/dist/index.js.map +1 -1
  44. package/dist/leader-thread/LeaderSyncProcessor.d.ts +36 -11
  45. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  46. package/dist/leader-thread/LeaderSyncProcessor.js +426 -252
  47. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  48. package/dist/leader-thread/connection.d.ts +34 -6
  49. package/dist/leader-thread/connection.d.ts.map +1 -1
  50. package/dist/leader-thread/connection.js +22 -7
  51. package/dist/leader-thread/connection.js.map +1 -1
  52. package/dist/leader-thread/eventlog.d.ts +27 -0
  53. package/dist/leader-thread/eventlog.d.ts.map +1 -0
  54. package/dist/leader-thread/eventlog.js +119 -0
  55. package/dist/leader-thread/eventlog.js.map +1 -0
  56. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  57. package/dist/leader-thread/leader-worker-devtools.js +155 -80
  58. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  59. package/dist/leader-thread/make-leader-thread-layer.d.ts +22 -9
  60. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  61. package/dist/leader-thread/make-leader-thread-layer.js +67 -45
  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 +109 -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 +28 -32
  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 +79 -38
  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 +23 -0
  84. package/dist/make-client-session.d.ts.map +1 -0
  85. package/dist/make-client-session.js +57 -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 +86 -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/EventSequenceNumber.d.ts +57 -0
  104. package/dist/schema/EventSequenceNumber.d.ts.map +1 -0
  105. package/dist/schema/EventSequenceNumber.js +82 -0
  106. package/dist/schema/EventSequenceNumber.js.map +1 -0
  107. package/dist/schema/EventSequenceNumber.test.d.ts +2 -0
  108. package/dist/schema/EventSequenceNumber.test.d.ts.map +1 -0
  109. package/dist/schema/EventSequenceNumber.test.js +11 -0
  110. package/dist/schema/EventSequenceNumber.test.js.map +1 -0
  111. package/dist/schema/LiveStoreEvent.d.ts +257 -0
  112. package/dist/schema/LiveStoreEvent.d.ts.map +1 -0
  113. package/dist/schema/LiveStoreEvent.js +117 -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 +8 -6
  120. package/dist/schema/mod.d.ts.map +1 -1
  121. package/dist/schema/mod.js +8 -6
  122. package/dist/schema/mod.js.map +1 -1
  123. package/dist/schema/schema.d.ts +50 -32
  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 +563 -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 +88 -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 +27 -18
  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 +40 -19
  224. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  225. package/dist/sync/ClientSessionSyncProcessor.js +149 -73
  226. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  227. package/dist/sync/next/compact-events.d.ts.map +1 -1
  228. package/dist/sync/next/compact-events.js +38 -35
  229. package/dist/sync/next/compact-events.js.map +1 -1
  230. package/dist/sync/next/facts.d.ts +21 -21
  231. package/dist/sync/next/facts.d.ts.map +1 -1
  232. package/dist/sync/next/facts.js +11 -11
  233. package/dist/sync/next/facts.js.map +1 -1
  234. package/dist/sync/next/history-dag-common.d.ts +9 -7
  235. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  236. package/dist/sync/next/history-dag-common.js +10 -5
  237. package/dist/sync/next/history-dag-common.js.map +1 -1
  238. package/dist/sync/next/history-dag.d.ts +0 -2
  239. package/dist/sync/next/history-dag.d.ts.map +1 -1
  240. package/dist/sync/next/history-dag.js +16 -14
  241. package/dist/sync/next/history-dag.js.map +1 -1
  242. package/dist/sync/next/rebase-events.d.ts +10 -8
  243. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  244. package/dist/sync/next/rebase-events.js +18 -10
  245. package/dist/sync/next/rebase-events.js.map +1 -1
  246. package/dist/sync/next/test/compact-events.calculator.test.js +39 -34
  247. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  248. package/dist/sync/next/test/compact-events.test.js +77 -77
  249. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  250. package/dist/sync/next/test/{mutation-fixtures.d.ts → event-fixtures.d.ts} +35 -25
  251. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -0
  252. package/dist/sync/next/test/{mutation-fixtures.js → event-fixtures.js} +83 -38
  253. package/dist/sync/next/test/event-fixtures.js.map +1 -0
  254. package/dist/sync/next/test/mod.d.ts +1 -1
  255. package/dist/sync/next/test/mod.d.ts.map +1 -1
  256. package/dist/sync/next/test/mod.js +1 -1
  257. package/dist/sync/next/test/mod.js.map +1 -1
  258. package/dist/sync/sync.d.ts +46 -21
  259. package/dist/sync/sync.d.ts.map +1 -1
  260. package/dist/sync/sync.js +10 -6
  261. package/dist/sync/sync.js.map +1 -1
  262. package/dist/sync/syncstate.d.ts +193 -84
  263. package/dist/sync/syncstate.d.ts.map +1 -1
  264. package/dist/sync/syncstate.js +305 -151
  265. package/dist/sync/syncstate.js.map +1 -1
  266. package/dist/sync/syncstate.test.js +267 -303
  267. package/dist/sync/syncstate.test.js.map +1 -1
  268. package/dist/sync/validate-push-payload.d.ts +2 -2
  269. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  270. package/dist/sync/validate-push-payload.js +4 -4
  271. package/dist/sync/validate-push-payload.js.map +1 -1
  272. package/dist/util.d.ts +2 -2
  273. package/dist/util.d.ts.map +1 -1
  274. package/dist/version.d.ts +3 -3
  275. package/dist/version.js +3 -3
  276. package/package.json +11 -4
  277. package/src/__tests__/fixture.ts +36 -15
  278. package/src/adapter-types.ts +107 -68
  279. package/src/debug-info.ts +1 -0
  280. package/src/devtools/devtools-messages-client-session.ts +142 -0
  281. package/src/devtools/devtools-messages-common.ts +115 -0
  282. package/src/devtools/devtools-messages-leader.ts +191 -0
  283. package/src/devtools/devtools-messages.ts +3 -246
  284. package/src/devtools/devtools-sessioninfo.ts +101 -0
  285. package/src/devtools/mod.ts +59 -0
  286. package/src/index.ts +7 -9
  287. package/src/leader-thread/LeaderSyncProcessor.ts +664 -394
  288. package/src/leader-thread/connection.ts +54 -9
  289. package/src/leader-thread/eventlog.ts +199 -0
  290. package/src/leader-thread/leader-worker-devtools.ts +227 -104
  291. package/src/leader-thread/make-leader-thread-layer.ts +121 -72
  292. package/src/leader-thread/materialize-event.ts +173 -0
  293. package/src/leader-thread/mod.ts +1 -1
  294. package/src/leader-thread/recreate-db.ts +33 -38
  295. package/src/leader-thread/shutdown-channel.ts +2 -4
  296. package/src/leader-thread/types.ts +84 -46
  297. package/src/make-client-session.ts +136 -0
  298. package/src/materializer-helper.ts +138 -0
  299. package/src/otel.ts +8 -0
  300. package/src/rematerialize-from-eventlog.ts +117 -0
  301. package/src/schema/EventDef.ts +227 -0
  302. package/src/schema/EventSequenceNumber.test.ts +12 -0
  303. package/src/schema/EventSequenceNumber.ts +121 -0
  304. package/src/schema/LiveStoreEvent.ts +240 -0
  305. package/src/schema/events.ts +1 -0
  306. package/src/schema/mod.ts +8 -6
  307. package/src/schema/schema.ts +88 -84
  308. package/src/schema/state/mod.ts +2 -0
  309. package/src/schema/state/sqlite/client-document-def.test.ts +238 -0
  310. package/src/schema/state/sqlite/client-document-def.ts +444 -0
  311. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +142 -0
  312. package/src/schema/state/sqlite/db-schema/ast/validate.ts +13 -0
  313. package/src/schema/state/sqlite/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +206 -0
  314. package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +35 -0
  315. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +242 -0
  316. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +222 -0
  317. package/src/schema/state/sqlite/db-schema/hash.ts +14 -0
  318. package/src/schema/state/sqlite/db-schema/mod.ts +2 -0
  319. package/src/schema/state/sqlite/mod.ts +73 -0
  320. package/src/schema/state/sqlite/query-builder/api.ts +440 -0
  321. package/src/schema/state/sqlite/query-builder/astToSql.ts +232 -0
  322. package/src/schema/state/sqlite/query-builder/impl.test.ts +617 -0
  323. package/src/schema/state/sqlite/query-builder/impl.ts +351 -0
  324. package/src/{query-builder → schema/state/sqlite/query-builder}/mod.ts +7 -0
  325. package/src/schema/{schema-helpers.ts → state/sqlite/schema-helpers.ts} +1 -1
  326. package/src/schema/state/sqlite/system-tables.ts +117 -0
  327. package/src/schema/state/sqlite/table-def.ts +197 -0
  328. package/src/schema-management/common.ts +7 -7
  329. package/src/schema-management/migrations.ts +37 -31
  330. package/src/schema-management/validate-schema.ts +61 -0
  331. package/src/sql-queries/sql-queries.ts +1 -1
  332. package/src/sql-queries/sql-query-builder.ts +1 -2
  333. package/src/sql-queries/types.ts +3 -1
  334. package/src/sync/ClientSessionSyncProcessor.ts +218 -94
  335. package/src/sync/next/compact-events.ts +38 -35
  336. package/src/sync/next/facts.ts +43 -41
  337. package/src/sync/next/history-dag-common.ts +17 -10
  338. package/src/sync/next/history-dag.ts +16 -17
  339. package/src/sync/next/rebase-events.ts +29 -17
  340. package/src/sync/next/test/compact-events.calculator.test.ts +46 -46
  341. package/src/sync/next/test/compact-events.test.ts +79 -79
  342. package/src/sync/next/test/event-fixtures.ts +228 -0
  343. package/src/sync/next/test/mod.ts +1 -1
  344. package/src/sync/sync.ts +46 -21
  345. package/src/sync/syncstate.test.ts +312 -345
  346. package/src/sync/syncstate.ts +414 -224
  347. package/src/sync/validate-push-payload.ts +6 -6
  348. package/src/version.ts +3 -3
  349. package/dist/derived-mutations.d.ts +0 -109
  350. package/dist/derived-mutations.d.ts.map +0 -1
  351. package/dist/derived-mutations.js +0 -54
  352. package/dist/derived-mutations.js.map +0 -1
  353. package/dist/derived-mutations.test.d.ts +0 -2
  354. package/dist/derived-mutations.test.d.ts.map +0 -1
  355. package/dist/derived-mutations.test.js +0 -93
  356. package/dist/derived-mutations.test.js.map +0 -1
  357. package/dist/devtools/devtools-bridge.d.ts +0 -13
  358. package/dist/devtools/devtools-bridge.d.ts.map +0 -1
  359. package/dist/devtools/devtools-bridge.js +0 -2
  360. package/dist/devtools/devtools-bridge.js.map +0 -1
  361. package/dist/devtools/devtools-window-message.d.ts +0 -29
  362. package/dist/devtools/devtools-window-message.d.ts.map +0 -1
  363. package/dist/devtools/devtools-window-message.js +0 -33
  364. package/dist/devtools/devtools-window-message.js.map +0 -1
  365. package/dist/devtools/index.d.ts +0 -42
  366. package/dist/devtools/index.d.ts.map +0 -1
  367. package/dist/devtools/index.js +0 -48
  368. package/dist/devtools/index.js.map +0 -1
  369. package/dist/init-singleton-tables.d.ts +0 -4
  370. package/dist/init-singleton-tables.d.ts.map +0 -1
  371. package/dist/init-singleton-tables.js +0 -16
  372. package/dist/init-singleton-tables.js.map +0 -1
  373. package/dist/leader-thread/apply-mutation.d.ts +0 -11
  374. package/dist/leader-thread/apply-mutation.d.ts.map +0 -1
  375. package/dist/leader-thread/apply-mutation.js +0 -107
  376. package/dist/leader-thread/apply-mutation.js.map +0 -1
  377. package/dist/leader-thread/leader-sync-processor.d.ts +0 -47
  378. package/dist/leader-thread/leader-sync-processor.d.ts.map +0 -1
  379. package/dist/leader-thread/leader-sync-processor.js +0 -430
  380. package/dist/leader-thread/leader-sync-processor.js.map +0 -1
  381. package/dist/leader-thread/mutationlog.d.ts +0 -10
  382. package/dist/leader-thread/mutationlog.d.ts.map +0 -1
  383. package/dist/leader-thread/mutationlog.js +0 -28
  384. package/dist/leader-thread/mutationlog.js.map +0 -1
  385. package/dist/leader-thread/pull-queue-set.d.ts +0 -7
  386. package/dist/leader-thread/pull-queue-set.d.ts.map +0 -1
  387. package/dist/leader-thread/pull-queue-set.js +0 -39
  388. package/dist/leader-thread/pull-queue-set.js.map +0 -1
  389. package/dist/mutation.d.ts +0 -20
  390. package/dist/mutation.d.ts.map +0 -1
  391. package/dist/mutation.js +0 -57
  392. package/dist/mutation.js.map +0 -1
  393. package/dist/query-builder/api.d.ts +0 -190
  394. package/dist/query-builder/api.d.ts.map +0 -1
  395. package/dist/query-builder/api.js +0 -8
  396. package/dist/query-builder/api.js.map +0 -1
  397. package/dist/query-builder/impl.d.ts +0 -12
  398. package/dist/query-builder/impl.d.ts.map +0 -1
  399. package/dist/query-builder/impl.js +0 -244
  400. package/dist/query-builder/impl.js.map +0 -1
  401. package/dist/query-builder/impl.test.d.ts +0 -2
  402. package/dist/query-builder/impl.test.d.ts.map +0 -1
  403. package/dist/query-builder/impl.test.js +0 -212
  404. package/dist/query-builder/impl.test.js.map +0 -1
  405. package/dist/query-builder/mod.d.ts.map +0 -1
  406. package/dist/query-builder/mod.js.map +0 -1
  407. package/dist/query-info.d.ts +0 -38
  408. package/dist/query-info.d.ts.map +0 -1
  409. package/dist/query-info.js +0 -7
  410. package/dist/query-info.js.map +0 -1
  411. package/dist/rehydrate-from-mutationlog.d.ts +0 -14
  412. package/dist/rehydrate-from-mutationlog.d.ts.map +0 -1
  413. package/dist/rehydrate-from-mutationlog.js +0 -66
  414. package/dist/rehydrate-from-mutationlog.js.map +0 -1
  415. package/dist/schema/EventId.d.ts +0 -39
  416. package/dist/schema/EventId.d.ts.map +0 -1
  417. package/dist/schema/EventId.js +0 -38
  418. package/dist/schema/EventId.js.map +0 -1
  419. package/dist/schema/EventId.test.d.ts +0 -2
  420. package/dist/schema/EventId.test.d.ts.map +0 -1
  421. package/dist/schema/EventId.test.js +0 -11
  422. package/dist/schema/EventId.test.js.map +0 -1
  423. package/dist/schema/MutationEvent.d.ts +0 -167
  424. package/dist/schema/MutationEvent.d.ts.map +0 -1
  425. package/dist/schema/MutationEvent.js +0 -72
  426. package/dist/schema/MutationEvent.js.map +0 -1
  427. package/dist/schema/MutationEvent.test.d.ts +0 -2
  428. package/dist/schema/MutationEvent.test.d.ts.map +0 -1
  429. package/dist/schema/MutationEvent.test.js +0 -2
  430. package/dist/schema/MutationEvent.test.js.map +0 -1
  431. package/dist/schema/mutations.d.ts +0 -107
  432. package/dist/schema/mutations.d.ts.map +0 -1
  433. package/dist/schema/mutations.js +0 -42
  434. package/dist/schema/mutations.js.map +0 -1
  435. package/dist/schema/schema-helpers.d.ts.map +0 -1
  436. package/dist/schema/schema-helpers.js.map +0 -1
  437. package/dist/schema/system-tables.d.ts +0 -399
  438. package/dist/schema/system-tables.d.ts.map +0 -1
  439. package/dist/schema/system-tables.js +0 -59
  440. package/dist/schema/system-tables.js.map +0 -1
  441. package/dist/schema/table-def.d.ts +0 -156
  442. package/dist/schema/table-def.d.ts.map +0 -1
  443. package/dist/schema/table-def.js +0 -79
  444. package/dist/schema/table-def.js.map +0 -1
  445. package/dist/schema-management/validate-mutation-defs.d.ts +0 -8
  446. package/dist/schema-management/validate-mutation-defs.d.ts.map +0 -1
  447. package/dist/schema-management/validate-mutation-defs.js +0 -39
  448. package/dist/schema-management/validate-mutation-defs.js.map +0 -1
  449. package/dist/sync/client-session-sync-processor.d.ts +0 -45
  450. package/dist/sync/client-session-sync-processor.d.ts.map +0 -1
  451. package/dist/sync/client-session-sync-processor.js +0 -131
  452. package/dist/sync/client-session-sync-processor.js.map +0 -1
  453. package/dist/sync/next/test/mutation-fixtures.d.ts.map +0 -1
  454. package/dist/sync/next/test/mutation-fixtures.js.map +0 -1
  455. package/src/derived-mutations.test.ts +0 -101
  456. package/src/derived-mutations.ts +0 -170
  457. package/src/devtools/devtools-bridge.ts +0 -14
  458. package/src/devtools/devtools-window-message.ts +0 -27
  459. package/src/devtools/index.ts +0 -48
  460. package/src/init-singleton-tables.ts +0 -24
  461. package/src/leader-thread/apply-mutation.ts +0 -161
  462. package/src/leader-thread/mutationlog.ts +0 -46
  463. package/src/leader-thread/pull-queue-set.ts +0 -58
  464. package/src/mutation.ts +0 -91
  465. package/src/query-builder/api.ts +0 -289
  466. package/src/query-builder/impl.test.ts +0 -239
  467. package/src/query-builder/impl.ts +0 -285
  468. package/src/query-info.ts +0 -78
  469. package/src/rehydrate-from-mutationlog.ts +0 -119
  470. package/src/schema/EventId.test.ts +0 -12
  471. package/src/schema/EventId.ts +0 -60
  472. package/src/schema/MutationEvent.ts +0 -185
  473. package/src/schema/mutations.ts +0 -192
  474. package/src/schema/system-tables.ts +0 -105
  475. package/src/schema/table-def.ts +0 -343
  476. package/src/schema-management/validate-mutation-defs.ts +0 -63
  477. package/src/sync/next/test/mutation-fixtures.ts +0 -224
  478. package/tsconfig.json +0 -11
  479. /package/dist/schema/{schema-helpers.d.ts → state/sqlite/schema-helpers.d.ts} +0 -0
@@ -1,45 +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
9
  Subscribable,
10
10
  SubscriptionRef,
11
- WebChannel,
12
11
  } from '@livestore/utils/effect'
13
12
  import { Context, Schema } from '@livestore/utils/effect'
13
+ import type { MeshNode } from '@livestore/webmesh'
14
14
 
15
+ import type { LeaderPullCursor, SqliteError } from '../adapter-types.js'
15
16
  import type {
16
17
  BootStatus,
17
18
  Devtools,
18
- InvalidPushError,
19
- MakeSynchronousDatabase,
19
+ LeaderAheadError,
20
+ MakeSqliteDb,
21
+ MigrationsReport,
20
22
  PersistenceInfo,
23
+ SqliteDb,
21
24
  SyncBackend,
22
- SynchronousDatabase,
23
25
  UnexpectedError,
24
26
  } from '../index.js'
25
- import type { EventId, LiveStoreSchema, MutationEvent } from '../schema/mod.js'
27
+ import type { EventSequenceNumber, LiveStoreEvent, LiveStoreSchema } from '../schema/mod.js'
26
28
  import type * as SyncState from '../sync/syncstate.js'
27
29
  import type { ShutdownChannel } from './shutdown-channel.js'
28
30
 
29
31
  export type ShutdownState = 'running' | 'shutting-down'
30
32
 
31
- export class OuterWorkerCtx extends Context.Tag('OuterWorkerCtx')<
32
- OuterWorkerCtx,
33
- {
34
- innerFiber: Fiber.RuntimeFiber<any, any>
35
- }
36
- >() {}
37
-
38
33
  export const InitialSyncOptionsSkip = Schema.TaggedStruct('Skip', {})
39
34
  export type InitialSyncOptionsSkip = typeof InitialSyncOptionsSkip.Type
40
35
 
41
36
  export const InitialSyncOptionsBlocking = Schema.TaggedStruct('Blocking', {
42
- timeout: Schema.DurationFromMillis,
37
+ timeout: Schema.Union(Schema.DurationFromMillis, Schema.Number),
43
38
  })
44
39
 
45
40
  export type InitialSyncOptionsBlocking = typeof InitialSyncOptionsBlocking.Type
@@ -48,7 +43,7 @@ export const InitialSyncOptions = Schema.Union(InitialSyncOptionsSkip, InitialSy
48
43
  export type InitialSyncOptions = typeof InitialSyncOptions.Type
49
44
 
50
45
  export type InitialSyncInfo = Option.Option<{
51
- cursor: EventId.EventId
46
+ cursor: EventSequenceNumber.EventSequenceNumber
52
47
  metadata: Option.Option<Schema.JsonValue>
53
48
  }>
54
49
 
@@ -56,8 +51,8 @@ export type InitialSyncInfo = Option.Option<{
56
51
  // | { _tag: 'Recreate'; snapshotRef: Ref.Ref<Uint8Array | undefined>; syncInfo: InitialSyncInfo }
57
52
  // | { _tag: 'Reuse'; syncInfo: InitialSyncInfo }
58
53
 
59
- export type LeaderDatabase = SynchronousDatabase<{ dbPointer: number; persistenceInfo: PersistenceInfo }>
60
- export type PersistenceInfoPair = { db: PersistenceInfo; mutationLog: PersistenceInfo }
54
+ export type LeaderSqliteDb = SqliteDb<{ dbPointer: number; persistenceInfo: PersistenceInfo }>
55
+ export type PersistenceInfoPair = { state: PersistenceInfo; eventlog: PersistenceInfo }
61
56
 
62
57
  export type DevtoolsOptions =
63
58
  | {
@@ -65,53 +60,94 @@ export type DevtoolsOptions =
65
60
  }
66
61
  | {
67
62
  enabled: true
68
- makeContext: Effect.Effect<
63
+ boot: Effect.Effect<
69
64
  {
70
- devtoolsWebChannel: WebChannel.WebChannel<Devtools.MessageToAppLeader, Devtools.MessageFromAppLeader>
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
91
  clientId: string
84
- makeSyncDb: MakeSynchronousDatabase
85
- db: LeaderDatabase
86
- dbLog: LeaderDatabase
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
98
  shutdownChannel: ShutdownChannel
91
- mutationEventSchema: MutationEvent.ForMutationDefRecord<any>
92
- // devtools: DevtoolsContext
99
+ eventSchema: LiveStoreEvent.ForEventDefRecord<any>
100
+ devtools: DevtoolsContext
93
101
  syncBackend: SyncBackend | undefined
94
102
  syncProcessor: LeaderSyncProcessor
95
- connectedClientSessionPullQueues: PullQueueSet
96
- /** e.g. used for `store.__dev` APIs */
97
- extraIncomingMessagesQueue: Queue.Queue<Devtools.MessageToAppLeader>
103
+ materializeEvent: MaterializeEvent
104
+ initialState: {
105
+ leaderHead: EventSequenceNumber.EventSequenceNumber
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>
98
114
  }
99
115
  >() {}
100
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
+
101
128
  export type InitialBlockingSyncContext = {
102
129
  blockingDeferred: Deferred.Deferred<void> | undefined
103
130
  update: (_: { remaining: number; processed: number }) => Effect.Effect<void>
104
131
  }
105
132
 
106
- export type PullQueueItem = {
107
- payload: SyncState.PayloadUpstream
108
- remaining: number
109
- }
110
-
111
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>,
150
+ batch: ReadonlyArray<LiveStoreEvent.EncodedWithMeta>,
115
151
  options?: {
116
152
  /**
117
153
  * If true, the effect will only finish when the local push has been processed (i.e. succeeded or was rejected).
@@ -119,18 +155,20 @@ export interface LeaderSyncProcessor {
119
155
  */
120
156
  waitForProcessing?: boolean
121
157
  },
122
- ) => Effect.Effect<void, InvalidPushError>
158
+ ) => Effect.Effect<void, LeaderAheadError>
123
159
 
124
- pushPartial: (mutationEvent: MutationEvent.PartialAnyEncoded) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx>
125
- boot: (args: {
126
- dbReady: Deferred.Deferred<void>
127
- }) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient>
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: EventSequenceNumber.EventSequenceNumber },
169
+ UnexpectedError,
170
+ LeaderThreadCtx | Scope.Scope | HttpClient.HttpClient
171
+ >
128
172
  syncState: Subscribable.Subscribable<SyncState.SyncState>
129
- }
130
-
131
- export interface PullQueueSet {
132
- makeQueue: (
133
- since: EventId.EventId,
134
- ) => Effect.Effect<Queue.Queue<PullQueueItem>, UnexpectedError, Scope.Scope | LeaderThreadCtx>
135
- offer: (item: PullQueueItem) => Effect.Effect<void, UnexpectedError, LeaderThreadCtx>
173
+ getMergeCounter: () => number
136
174
  }
@@ -0,0 +1,136 @@
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
+ import { liveStoreVersion } from './version.js'
15
+
16
+ declare global {
17
+ // eslint-disable-next-line no-var
18
+ var __debugWebmeshNode: any
19
+ }
20
+
21
+ export const makeClientSession = <R>({
22
+ storeId,
23
+ clientId,
24
+ sessionId,
25
+ isLeader,
26
+ devtoolsEnabled,
27
+ connectDevtoolsToStore,
28
+ lockStatus,
29
+ leaderThread,
30
+ schema,
31
+ sqliteDb,
32
+ shutdown,
33
+ connectWebmeshNode,
34
+ webmeshMode,
35
+ registerBeforeUnload,
36
+ debugInstanceId,
37
+ }: AdapterArgs & {
38
+ clientId: string
39
+ sessionId: string
40
+ isLeader: boolean
41
+ lockStatus: SubscriptionRef.SubscriptionRef<LockStatus>
42
+ leaderThread: ClientSessionLeaderThreadProxy
43
+ sqliteDb: SqliteDb
44
+ connectWebmeshNode: (args: {
45
+ webmeshNode: Webmesh.MeshNode
46
+ sessionInfo: Devtools.SessionInfo.SessionInfo
47
+ }) => Effect.Effect<void, UnexpectedError, Scope.Scope | R>
48
+ webmeshMode: 'direct' | 'proxy'
49
+ registerBeforeUnload: (onBeforeUnload: () => void) => () => void
50
+ }): Effect.Effect<ClientSession, never, Scope.Scope | R> =>
51
+ Effect.gen(function* () {
52
+ const devtools: ClientSession['devtools'] = devtoolsEnabled
53
+ ? { enabled: true, pullLatch: yield* Effect.makeLatch(true), pushLatch: yield* Effect.makeLatch(true) }
54
+ : { enabled: false }
55
+
56
+ if (devtoolsEnabled) {
57
+ yield* Effect.gen(function* () {
58
+ const webmeshNode = yield* Webmesh.makeMeshNode(
59
+ Devtools.makeNodeName.client.session({ storeId, clientId, sessionId }),
60
+ )
61
+
62
+ globalThis.__debugWebmeshNode = webmeshNode
63
+
64
+ const schemaAlias = schema.devtools.alias
65
+ const sessionInfo = Devtools.SessionInfo.SessionInfo.make({
66
+ storeId,
67
+ clientId,
68
+ sessionId,
69
+ schemaAlias,
70
+ isLeader,
71
+ })
72
+
73
+ yield* connectWebmeshNode({ webmeshNode, sessionInfo })
74
+
75
+ const sessionInfoBroadcastChannel = yield* Devtools.makeSessionInfoBroadcastChannel(webmeshNode)
76
+
77
+ yield* Devtools.SessionInfo.provideSessionInfo({
78
+ webChannel: sessionInfoBroadcastChannel,
79
+ sessionInfo,
80
+ }).pipe(Effect.tapCauseLogPretty, Effect.forkScoped)
81
+
82
+ yield* webmeshNode.listenForChannel.pipe(
83
+ Stream.filter(
84
+ (res) =>
85
+ Devtools.isChannelName.devtoolsClientSession(res.channelName, { storeId, clientId, sessionId }) &&
86
+ res.mode === webmeshMode,
87
+ ),
88
+ Stream.tap(
89
+ Effect.fnUntraced(
90
+ function* ({ channelName, source }) {
91
+ const clientSessionDevtoolsChannel = yield* webmeshNode.makeChannel({
92
+ target: source,
93
+ channelName,
94
+ schema: { listen: Devtools.ClientSession.MessageToApp, send: Devtools.ClientSession.MessageFromApp },
95
+ mode: webmeshMode,
96
+ })
97
+
98
+ const sendDisconnect = clientSessionDevtoolsChannel
99
+ .send(Devtools.ClientSession.Disconnect.make({ clientId, liveStoreVersion, sessionId }))
100
+ .pipe(Effect.orDie)
101
+
102
+ // Disconnect on shutdown (e.g. when switching stores)
103
+ yield* Effect.addFinalizer(() => sendDisconnect)
104
+
105
+ // Disconnect on before unload
106
+ yield* Effect.acquireRelease(
107
+ Effect.sync(() => registerBeforeUnload(() => sendDisconnect.pipe(Effect.runFork))),
108
+ (unsub) => Effect.sync(() => unsub()),
109
+ )
110
+
111
+ yield* connectDevtoolsToStore(clientSessionDevtoolsChannel)
112
+ },
113
+ Effect.tapCauseLogPretty,
114
+ Effect.forkScoped,
115
+ ),
116
+ ),
117
+ Stream.runDrain,
118
+ )
119
+ }).pipe(
120
+ Effect.withSpan('@livestore/common:make-client-session:devtools'),
121
+ Effect.tapCauseLogPretty,
122
+ Effect.forkScoped,
123
+ )
124
+ }
125
+
126
+ return {
127
+ sqliteDb,
128
+ leaderThread,
129
+ devtools,
130
+ lockStatus,
131
+ clientId,
132
+ sessionId,
133
+ shutdown,
134
+ debugInstanceId,
135
+ } satisfies ClientSession
136
+ })
@@ -0,0 +1,138 @@
1
+ import { isNil, 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
+
42
+ const eventArgsEncoded = isNil(event.decoded?.args)
43
+ ? undefined
44
+ : Schema.encodeUnknownSync(eventDef.schema)(event.decoded!.args)
45
+
46
+ const query: MaterializerContextQuery = (
47
+ rawQueryOrQueryBuilder:
48
+ | {
49
+ query: string
50
+ bindValues: ParamsObject
51
+ }
52
+ | QueryBuilder.Any,
53
+ ) => {
54
+ if (isQueryBuilder(rawQueryOrQueryBuilder)) {
55
+ const { query, bindValues } = rawQueryOrQueryBuilder.asSql()
56
+ const rawResults = db.select(query, prepareBindValues(bindValues, query))
57
+ const resultSchema = getResultSchema(rawQueryOrQueryBuilder)
58
+ return Schema.decodeSync(resultSchema)(rawResults)
59
+ } else {
60
+ const { query, bindValues } = rawQueryOrQueryBuilder
61
+ return db.select(query, prepareBindValues(bindValues, query))
62
+ }
63
+ }
64
+
65
+ const res = materializer(eventArgsDecoded, {
66
+ eventDef,
67
+ query,
68
+ // TODO properly implement this
69
+ currentFacts: new Map(),
70
+ })
71
+
72
+ const statementRes = mapMaterializerResult(res)
73
+
74
+ return statementRes.map((statementRes) => {
75
+ const statementSql = statementRes.sql
76
+
77
+ const bindValues = typeof statementRes === 'string' ? eventArgsEncoded : statementRes.bindValues
78
+
79
+ const writeTables = typeof statementRes === 'string' ? undefined : statementRes.writeTables
80
+
81
+ return { statementSql, bindValues: prepareBindValues(bindValues ?? {}, statementSql), writeTables }
82
+ })
83
+ }
84
+
85
+ const mapMaterializerResult = (
86
+ materializerResult: MaterializerResult | ReadonlyArray<MaterializerResult>,
87
+ ): ReadonlyArray<{
88
+ sql: string
89
+ bindValues: BindValues
90
+ writeTables: ReadonlySet<string> | undefined
91
+ }> => {
92
+ if (isReadonlyArray(materializerResult)) {
93
+ return materializerResult.flatMap(mapMaterializerResult)
94
+ }
95
+ if (isQueryBuilder(materializerResult)) {
96
+ const { query, bindValues } = materializerResult.asSql()
97
+ return [{ sql: query, bindValues: bindValues as BindValues, writeTables: undefined }]
98
+ } else if (typeof materializerResult === 'string') {
99
+ return [{ sql: materializerResult, bindValues: {} as BindValues, writeTables: undefined }]
100
+ } else {
101
+ return [
102
+ {
103
+ sql: materializerResult.sql,
104
+ bindValues: materializerResult.bindValues,
105
+ writeTables: materializerResult.writeTables,
106
+ },
107
+ ]
108
+ }
109
+ }
110
+
111
+ // NOTE we should explore whether there is a more elegant solution
112
+ // e.g. by leveraging the schema to replace the sessionIdSymbol
113
+ export const replaceSessionIdSymbol = (
114
+ bindValues: Record<string, unknown> | ReadonlyArray<unknown>,
115
+ sessionId: string,
116
+ ) => {
117
+ deepReplaceValue(bindValues, SessionIdSymbol, sessionId)
118
+ }
119
+
120
+ const deepReplaceValue = <S, R>(input: any, searchValue: S, replaceValue: R): void => {
121
+ if (Array.isArray(input)) {
122
+ for (const i in input) {
123
+ if (input[i] === searchValue) {
124
+ input[i] = replaceValue
125
+ } else {
126
+ deepReplaceValue(input[i], searchValue, replaceValue)
127
+ }
128
+ }
129
+ } else if (typeof input === 'object' && input !== null) {
130
+ for (const key in input) {
131
+ if (input[key] === searchValue) {
132
+ input[key] = replaceValue
133
+ } else {
134
+ deepReplaceValue(input[key], searchValue, replaceValue)
135
+ }
136
+ }
137
+ }
138
+ }
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 { EventSequenceNumber, 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
+ seqNum: { global: row.seqNumGlobal, client: row.seqNumClient },
60
+ parentSeqNum: { global: row.parentSeqNumGlobal, client: row.parentSeqNumClient },
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 seqNumGlobal > $seqNumGlobal OR (seqNumGlobal = $seqNumGlobal AND seqNumClient > $seqNumClient)
75
+ ORDER BY seqNumGlobal ASC, seqNumClient 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: _.seqNumGlobal, client: _.seqNumClient })),
91
+ Option.getOrElse(() => EventSequenceNumber.ROOT),
92
+ )
93
+ : EventSequenceNumber.ROOT
94
+ const nextItem = Chunk.fromIterable(
95
+ stmt.select<SystemTables.EventlogMetaRow>({
96
+ $seqNumGlobal: lastId?.global,
97
+ $seqNumClient: 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
+ )