@livestore/common 0.3.0-dev.3 → 0.3.0-dev.31

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 (426) 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 +128 -68
  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 +389 -0
  16. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -0
  17. package/dist/devtools/devtools-messages-client-session.js +96 -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 +28 -0
  32. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -0
  33. package/dist/devtools/devtools-sessioninfo.js +34 -0
  34. package/dist/devtools/devtools-sessioninfo.js.map +1 -0
  35. package/dist/devtools/mod.d.ts +39 -0
  36. package/dist/devtools/mod.d.ts.map +1 -0
  37. package/dist/devtools/mod.js +27 -0
  38. package/dist/devtools/mod.js.map +1 -0
  39. package/dist/index.d.ts +4 -11
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +4 -7
  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 +589 -0
  46. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -0
  47. package/dist/leader-thread/apply-event.d.ts +16 -0
  48. package/dist/leader-thread/apply-event.d.ts.map +1 -0
  49. package/dist/leader-thread/apply-event.js +103 -0
  50. package/dist/leader-thread/apply-event.js.map +1 -0
  51. package/dist/leader-thread/connection.d.ts +34 -6
  52. package/dist/leader-thread/connection.d.ts.map +1 -1
  53. package/dist/leader-thread/connection.js +22 -7
  54. package/dist/leader-thread/connection.js.map +1 -1
  55. package/dist/leader-thread/eventlog.d.ts +27 -0
  56. package/dist/leader-thread/eventlog.d.ts.map +1 -0
  57. package/dist/leader-thread/eventlog.js +123 -0
  58. package/dist/leader-thread/eventlog.js.map +1 -0
  59. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  60. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  61. package/dist/leader-thread/leader-worker-devtools.js +154 -132
  62. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  63. package/dist/leader-thread/make-leader-thread-layer.d.ts +26 -12
  64. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  65. package/dist/leader-thread/make-leader-thread-layer.js +82 -47
  66. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  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 +35 -25
  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 +86 -39
  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/materializer-helper.d.ts +23 -0
  84. package/dist/materializer-helper.d.ts.map +1 -0
  85. package/dist/materializer-helper.js +70 -0
  86. package/dist/materializer-helper.js.map +1 -0
  87. package/dist/otel.d.ts +2 -0
  88. package/dist/otel.d.ts.map +1 -1
  89. package/dist/otel.js +5 -0
  90. package/dist/otel.js.map +1 -1
  91. package/dist/query-builder/api.d.ts +158 -55
  92. package/dist/query-builder/api.d.ts.map +1 -1
  93. package/dist/query-builder/api.js +3 -5
  94. package/dist/query-builder/api.js.map +1 -1
  95. package/dist/query-builder/astToSql.d.ts +7 -0
  96. package/dist/query-builder/astToSql.d.ts.map +1 -0
  97. package/dist/query-builder/astToSql.js +190 -0
  98. package/dist/query-builder/astToSql.js.map +1 -0
  99. package/dist/query-builder/impl.d.ts +3 -8
  100. package/dist/query-builder/impl.d.ts.map +1 -1
  101. package/dist/query-builder/impl.js +166 -124
  102. package/dist/query-builder/impl.js.map +1 -1
  103. package/dist/query-builder/impl.test.d.ts +86 -1
  104. package/dist/query-builder/impl.test.d.ts.map +1 -1
  105. package/dist/query-builder/impl.test.js +411 -69
  106. package/dist/query-builder/impl.test.js.map +1 -1
  107. package/dist/query-builder/mod.d.ts +7 -0
  108. package/dist/query-builder/mod.d.ts.map +1 -1
  109. package/dist/query-builder/mod.js +7 -0
  110. package/dist/query-builder/mod.js.map +1 -1
  111. package/dist/rehydrate-from-eventlog.d.ts +14 -0
  112. package/dist/rehydrate-from-eventlog.d.ts.map +1 -0
  113. package/dist/rehydrate-from-eventlog.js +65 -0
  114. package/dist/rehydrate-from-eventlog.js.map +1 -0
  115. package/dist/schema/EventDef.d.ts +136 -0
  116. package/dist/schema/EventDef.d.ts.map +1 -0
  117. package/dist/schema/EventDef.js +58 -0
  118. package/dist/schema/EventDef.js.map +1 -0
  119. package/dist/schema/EventId.d.ts +35 -15
  120. package/dist/schema/EventId.d.ts.map +1 -1
  121. package/dist/schema/EventId.js +57 -11
  122. package/dist/schema/EventId.js.map +1 -1
  123. package/dist/schema/EventId.test.d.ts +2 -0
  124. package/dist/schema/EventId.test.d.ts.map +1 -0
  125. package/dist/schema/EventId.test.js +11 -0
  126. package/dist/schema/EventId.test.js.map +1 -0
  127. package/dist/schema/LiveStoreEvent.d.ts +255 -0
  128. package/dist/schema/LiveStoreEvent.d.ts.map +1 -0
  129. package/dist/schema/LiveStoreEvent.js +118 -0
  130. package/dist/schema/LiveStoreEvent.js.map +1 -0
  131. package/dist/schema/client-document-def.d.ts +223 -0
  132. package/dist/schema/client-document-def.d.ts.map +1 -0
  133. package/dist/schema/client-document-def.js +170 -0
  134. package/dist/schema/client-document-def.js.map +1 -0
  135. package/dist/schema/client-document-def.test.d.ts +2 -0
  136. package/dist/schema/client-document-def.test.d.ts.map +1 -0
  137. package/dist/schema/client-document-def.test.js +201 -0
  138. package/dist/schema/client-document-def.test.js.map +1 -0
  139. package/dist/schema/db-schema/ast/sqlite.d.ts +69 -0
  140. package/dist/schema/db-schema/ast/sqlite.d.ts.map +1 -0
  141. package/dist/schema/db-schema/ast/sqlite.js +71 -0
  142. package/dist/schema/db-schema/ast/sqlite.js.map +1 -0
  143. package/dist/schema/db-schema/ast/validate.d.ts +3 -0
  144. package/dist/schema/db-schema/ast/validate.d.ts.map +1 -0
  145. package/dist/schema/db-schema/ast/validate.js +12 -0
  146. package/dist/schema/db-schema/ast/validate.js.map +1 -0
  147. package/dist/schema/db-schema/dsl/field-defs.d.ts +90 -0
  148. package/dist/schema/db-schema/dsl/field-defs.d.ts.map +1 -0
  149. package/dist/schema/db-schema/dsl/field-defs.js +87 -0
  150. package/dist/schema/db-schema/dsl/field-defs.js.map +1 -0
  151. package/dist/schema/db-schema/dsl/field-defs.test.d.ts +2 -0
  152. package/dist/schema/db-schema/dsl/field-defs.test.d.ts.map +1 -0
  153. package/dist/schema/db-schema/dsl/field-defs.test.js +29 -0
  154. package/dist/schema/db-schema/dsl/field-defs.test.js.map +1 -0
  155. package/dist/schema/db-schema/dsl/mod.d.ts +90 -0
  156. package/dist/schema/db-schema/dsl/mod.d.ts.map +1 -0
  157. package/dist/schema/db-schema/dsl/mod.js +41 -0
  158. package/dist/schema/db-schema/dsl/mod.js.map +1 -0
  159. package/dist/schema/db-schema/hash.d.ts +2 -0
  160. package/dist/schema/db-schema/hash.d.ts.map +1 -0
  161. package/dist/schema/db-schema/hash.js +14 -0
  162. package/dist/schema/db-schema/hash.js.map +1 -0
  163. package/dist/schema/db-schema/mod.d.ts +3 -0
  164. package/dist/schema/db-schema/mod.d.ts.map +1 -0
  165. package/dist/schema/db-schema/mod.js +3 -0
  166. package/dist/schema/db-schema/mod.js.map +1 -0
  167. package/dist/schema/events.d.ts +2 -0
  168. package/dist/schema/events.d.ts.map +1 -0
  169. package/dist/schema/events.js +2 -0
  170. package/dist/schema/events.js.map +1 -0
  171. package/dist/schema/mod.d.ts +5 -3
  172. package/dist/schema/mod.d.ts.map +1 -1
  173. package/dist/schema/mod.js +5 -3
  174. package/dist/schema/mod.js.map +1 -1
  175. package/dist/schema/schema-helpers.d.ts.map +1 -1
  176. package/dist/schema/schema-helpers.js +1 -1
  177. package/dist/schema/schema-helpers.js.map +1 -1
  178. package/dist/schema/schema.d.ts +30 -23
  179. package/dist/schema/schema.d.ts.map +1 -1
  180. package/dist/schema/schema.js +48 -35
  181. package/dist/schema/schema.js.map +1 -1
  182. package/dist/schema/sqlite-state.d.ts +12 -0
  183. package/dist/schema/sqlite-state.d.ts.map +1 -0
  184. package/dist/schema/sqlite-state.js +36 -0
  185. package/dist/schema/sqlite-state.js.map +1 -0
  186. package/dist/schema/system-tables.d.ts +179 -125
  187. package/dist/schema/system-tables.d.ts.map +1 -1
  188. package/dist/schema/system-tables.js +76 -41
  189. package/dist/schema/system-tables.js.map +1 -1
  190. package/dist/schema/table-def.d.ts +37 -109
  191. package/dist/schema/table-def.d.ts.map +1 -1
  192. package/dist/schema/table-def.js +23 -66
  193. package/dist/schema/table-def.js.map +1 -1
  194. package/dist/schema/view.d.ts +3 -0
  195. package/dist/schema/view.d.ts.map +1 -0
  196. package/dist/schema/view.js +3 -0
  197. package/dist/schema/view.js.map +1 -0
  198. package/dist/schema-management/common.d.ts +7 -7
  199. package/dist/schema-management/common.d.ts.map +1 -1
  200. package/dist/schema-management/common.js.map +1 -1
  201. package/dist/schema-management/migrations.d.ts +6 -6
  202. package/dist/schema-management/migrations.d.ts.map +1 -1
  203. package/dist/schema-management/migrations.js +19 -14
  204. package/dist/schema-management/migrations.js.map +1 -1
  205. package/dist/schema-management/validate-mutation-defs.d.ts +3 -3
  206. package/dist/schema-management/validate-mutation-defs.d.ts.map +1 -1
  207. package/dist/schema-management/validate-mutation-defs.js +17 -17
  208. package/dist/schema-management/validate-mutation-defs.js.map +1 -1
  209. package/dist/sql-queries/misc.d.ts.map +1 -1
  210. package/dist/sql-queries/sql-queries.d.ts +1 -1
  211. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  212. package/dist/sql-queries/sql-queries.js.map +1 -1
  213. package/dist/sql-queries/sql-query-builder.d.ts +1 -1
  214. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  215. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  216. package/dist/sql-queries/types.d.ts +2 -1
  217. package/dist/sql-queries/types.d.ts.map +1 -1
  218. package/dist/sql-queries/types.js.map +1 -1
  219. package/dist/sync/ClientSessionSyncProcessor.d.ts +66 -0
  220. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -0
  221. package/dist/sync/ClientSessionSyncProcessor.js +209 -0
  222. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -0
  223. package/dist/sync/index.d.ts +1 -1
  224. package/dist/sync/index.d.ts.map +1 -1
  225. package/dist/sync/index.js +1 -1
  226. package/dist/sync/index.js.map +1 -1
  227. package/dist/sync/next/compact-events.d.ts.map +1 -1
  228. package/dist/sync/next/facts.d.ts +19 -19
  229. package/dist/sync/next/facts.d.ts.map +1 -1
  230. package/dist/sync/next/facts.js +3 -3
  231. package/dist/sync/next/facts.js.map +1 -1
  232. package/dist/sync/next/history-dag-common.d.ts +6 -7
  233. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  234. package/dist/sync/next/history-dag-common.js +4 -2
  235. package/dist/sync/next/history-dag-common.js.map +1 -1
  236. package/dist/sync/next/history-dag.d.ts.map +1 -1
  237. package/dist/sync/next/history-dag.js +2 -2
  238. package/dist/sync/next/history-dag.js.map +1 -1
  239. package/dist/sync/next/rebase-events.d.ts +10 -8
  240. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  241. package/dist/sync/next/rebase-events.js +11 -8
  242. package/dist/sync/next/rebase-events.js.map +1 -1
  243. package/dist/sync/next/test/compact-events.calculator.test.js +38 -33
  244. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  245. package/dist/sync/next/test/compact-events.test.js +76 -76
  246. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  247. package/dist/sync/next/test/{mutation-fixtures.d.ts → event-fixtures.d.ts} +29 -29
  248. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -0
  249. package/dist/sync/next/test/{mutation-fixtures.js → event-fixtures.js} +67 -36
  250. package/dist/sync/next/test/event-fixtures.js.map +1 -0
  251. package/dist/sync/next/test/mod.d.ts +1 -1
  252. package/dist/sync/next/test/mod.d.ts.map +1 -1
  253. package/dist/sync/next/test/mod.js +1 -1
  254. package/dist/sync/next/test/mod.js.map +1 -1
  255. package/dist/sync/sync.d.ts +55 -20
  256. package/dist/sync/sync.d.ts.map +1 -1
  257. package/dist/sync/sync.js +7 -3
  258. package/dist/sync/sync.js.map +1 -1
  259. package/dist/sync/syncstate.d.ts +213 -82
  260. package/dist/sync/syncstate.d.ts.map +1 -1
  261. package/dist/sync/syncstate.js +319 -120
  262. package/dist/sync/syncstate.js.map +1 -1
  263. package/dist/sync/syncstate.test.js +295 -275
  264. package/dist/sync/syncstate.test.js.map +1 -1
  265. package/dist/sync/validate-push-payload.d.ts +2 -2
  266. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  267. package/dist/sync/validate-push-payload.js +2 -2
  268. package/dist/sync/validate-push-payload.js.map +1 -1
  269. package/dist/util.d.ts +2 -2
  270. package/dist/util.d.ts.map +1 -1
  271. package/dist/version.d.ts +1 -1
  272. package/dist/version.d.ts.map +1 -1
  273. package/dist/version.js +1 -1
  274. package/dist/version.js.map +1 -1
  275. package/package.json +6 -6
  276. package/src/__tests__/fixture.ts +36 -15
  277. package/src/adapter-types.ts +111 -74
  278. package/src/debug-info.ts +1 -0
  279. package/src/devtools/devtools-messages-client-session.ts +141 -0
  280. package/src/devtools/devtools-messages-common.ts +115 -0
  281. package/src/devtools/devtools-messages-leader.ts +191 -0
  282. package/src/devtools/devtools-messages.ts +3 -243
  283. package/src/devtools/devtools-sessioninfo.ts +99 -0
  284. package/src/devtools/mod.ts +36 -0
  285. package/src/index.ts +4 -13
  286. package/src/leader-thread/LeaderSyncProcessor.ts +935 -0
  287. package/src/leader-thread/apply-event.ts +173 -0
  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 +212 -189
  291. package/src/leader-thread/make-leader-thread-layer.ts +143 -77
  292. package/src/leader-thread/mod.ts +1 -1
  293. package/src/leader-thread/recreate-db.ts +41 -30
  294. package/src/leader-thread/shutdown-channel.ts +2 -4
  295. package/src/leader-thread/types.ts +95 -51
  296. package/src/materializer-helper.ts +110 -0
  297. package/src/otel.ts +8 -0
  298. package/src/query-builder/api.ts +236 -85
  299. package/src/query-builder/astToSql.ts +232 -0
  300. package/src/query-builder/impl.test.ts +447 -78
  301. package/src/query-builder/impl.ts +209 -144
  302. package/src/query-builder/mod.ts +7 -0
  303. package/src/rehydrate-from-eventlog.ts +114 -0
  304. package/src/schema/EventDef.ts +216 -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/client-document-def.test.ts +239 -0
  309. package/src/schema/client-document-def.ts +444 -0
  310. package/src/schema/db-schema/ast/sqlite.ts +142 -0
  311. package/src/schema/db-schema/ast/validate.ts +13 -0
  312. package/src/schema/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +206 -0
  313. package/src/schema/db-schema/dsl/field-defs.test.ts +35 -0
  314. package/src/schema/db-schema/dsl/field-defs.ts +242 -0
  315. package/src/schema/db-schema/dsl/mod.ts +222 -0
  316. package/src/schema/db-schema/hash.ts +14 -0
  317. package/src/schema/db-schema/mod.ts +2 -0
  318. package/src/schema/events.ts +1 -0
  319. package/src/schema/mod.ts +5 -3
  320. package/src/schema/schema-helpers.ts +1 -1
  321. package/src/schema/schema.ts +84 -62
  322. package/src/schema/sqlite-state.ts +62 -0
  323. package/src/schema/system-tables.ts +68 -50
  324. package/src/schema/table-def.ts +68 -214
  325. package/src/schema/view.ts +2 -0
  326. package/src/schema-management/common.ts +7 -7
  327. package/src/schema-management/migrations.ts +27 -24
  328. package/src/schema-management/validate-mutation-defs.ts +22 -24
  329. package/src/sql-queries/sql-queries.ts +1 -1
  330. package/src/sql-queries/sql-query-builder.ts +1 -2
  331. package/src/sql-queries/types.ts +3 -1
  332. package/src/sync/ClientSessionSyncProcessor.ts +332 -0
  333. package/src/sync/index.ts +1 -1
  334. package/src/sync/next/facts.ts +32 -33
  335. package/src/sync/next/history-dag-common.ts +9 -5
  336. package/src/sync/next/history-dag.ts +2 -2
  337. package/src/sync/next/rebase-events.ts +22 -16
  338. package/src/sync/next/test/compact-events.calculator.test.ts +45 -45
  339. package/src/sync/next/test/compact-events.test.ts +78 -78
  340. package/src/sync/next/test/event-fixtures.ts +219 -0
  341. package/src/sync/next/test/mod.ts +1 -1
  342. package/src/sync/sync.ts +51 -19
  343. package/src/sync/syncstate.test.ts +335 -308
  344. package/src/sync/syncstate.ts +394 -212
  345. package/src/sync/validate-push-payload.ts +7 -4
  346. package/src/version.ts +1 -1
  347. package/tmp/pack.tgz +0 -0
  348. package/tsconfig.json +2 -1
  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 -12
  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/index.d.ts +0 -42
  362. package/dist/devtools/index.d.ts.map +0 -1
  363. package/dist/devtools/index.js +0 -48
  364. package/dist/devtools/index.js.map +0 -1
  365. package/dist/init-singleton-tables.d.ts +0 -4
  366. package/dist/init-singleton-tables.d.ts.map +0 -1
  367. package/dist/init-singleton-tables.js +0 -16
  368. package/dist/init-singleton-tables.js.map +0 -1
  369. package/dist/leader-thread/apply-mutation.d.ts +0 -8
  370. package/dist/leader-thread/apply-mutation.d.ts.map +0 -1
  371. package/dist/leader-thread/apply-mutation.js +0 -95
  372. package/dist/leader-thread/apply-mutation.js.map +0 -1
  373. package/dist/leader-thread/leader-sync-processor.d.ts +0 -47
  374. package/dist/leader-thread/leader-sync-processor.d.ts.map +0 -1
  375. package/dist/leader-thread/leader-sync-processor.js +0 -422
  376. package/dist/leader-thread/leader-sync-processor.js.map +0 -1
  377. package/dist/leader-thread/mutationlog.d.ts +0 -23
  378. package/dist/leader-thread/mutationlog.d.ts.map +0 -1
  379. package/dist/leader-thread/mutationlog.js +0 -27
  380. package/dist/leader-thread/mutationlog.js.map +0 -1
  381. package/dist/leader-thread/pull-queue-set.d.ts +0 -7
  382. package/dist/leader-thread/pull-queue-set.d.ts.map +0 -1
  383. package/dist/leader-thread/pull-queue-set.js +0 -39
  384. package/dist/leader-thread/pull-queue-set.js.map +0 -1
  385. package/dist/mutation.d.ts +0 -13
  386. package/dist/mutation.d.ts.map +0 -1
  387. package/dist/mutation.js +0 -57
  388. package/dist/mutation.js.map +0 -1
  389. package/dist/query-info.d.ts +0 -38
  390. package/dist/query-info.d.ts.map +0 -1
  391. package/dist/query-info.js +0 -7
  392. package/dist/query-info.js.map +0 -1
  393. package/dist/rehydrate-from-mutationlog.d.ts +0 -14
  394. package/dist/rehydrate-from-mutationlog.d.ts.map +0 -1
  395. package/dist/rehydrate-from-mutationlog.js +0 -72
  396. package/dist/rehydrate-from-mutationlog.js.map +0 -1
  397. package/dist/schema/MutationEvent.d.ts +0 -191
  398. package/dist/schema/MutationEvent.d.ts.map +0 -1
  399. package/dist/schema/MutationEvent.js +0 -56
  400. package/dist/schema/MutationEvent.js.map +0 -1
  401. package/dist/schema/mutations.d.ts +0 -107
  402. package/dist/schema/mutations.d.ts.map +0 -1
  403. package/dist/schema/mutations.js +0 -42
  404. package/dist/schema/mutations.js.map +0 -1
  405. package/dist/sync/client-session-sync-processor.d.ts +0 -45
  406. package/dist/sync/client-session-sync-processor.d.ts.map +0 -1
  407. package/dist/sync/client-session-sync-processor.js +0 -131
  408. package/dist/sync/client-session-sync-processor.js.map +0 -1
  409. package/dist/sync/next/test/mutation-fixtures.d.ts.map +0 -1
  410. package/dist/sync/next/test/mutation-fixtures.js.map +0 -1
  411. package/src/derived-mutations.test.ts +0 -101
  412. package/src/derived-mutations.ts +0 -166
  413. package/src/devtools/devtools-bridge.ts +0 -13
  414. package/src/devtools/index.ts +0 -48
  415. package/src/init-singleton-tables.ts +0 -24
  416. package/src/leader-thread/apply-mutation.ts +0 -143
  417. package/src/leader-thread/leader-sync-processor.ts +0 -666
  418. package/src/leader-thread/mutationlog.ts +0 -42
  419. package/src/leader-thread/pull-queue-set.ts +0 -58
  420. package/src/mutation.ts +0 -81
  421. package/src/query-info.ts +0 -78
  422. package/src/rehydrate-from-mutationlog.ts +0 -127
  423. package/src/schema/MutationEvent.ts +0 -161
  424. package/src/schema/mutations.ts +0 -192
  425. package/src/sync/client-session-sync-processor.ts +0 -207
  426. package/src/sync/next/test/mutation-fixtures.ts +0 -231
@@ -1,27 +1,29 @@
1
- import { Option, Predicate, Schema } from '@livestore/utils/effect'
1
+ import { casesHandled, shouldNeverHappen } from '@livestore/utils'
2
+ import { Match, Option, Predicate, Schema } from '@livestore/utils/effect'
2
3
 
3
- import type { QueryInfo } from '../query-info.js'
4
- import type { DbSchema } from '../schema/mod.js'
4
+ import type { State } from '../schema/mod.js'
5
5
  import type { QueryBuilder, QueryBuilderAst } from './api.js'
6
- import { QueryBuilderAstSymbol, TypeId } from './api.js'
6
+ import { QueryBuilderAstSymbol, QueryBuilderTypeId } from './api.js'
7
+ import { astToSql } from './astToSql.js'
7
8
 
8
- export const makeQueryBuilder = <TResult, TTableDef extends DbSchema.TableDefBase>(
9
+ export const makeQueryBuilder = <TResult, TTableDef extends State.SQLite.TableDefBase>(
9
10
  tableDef: TTableDef,
10
11
  ast: QueryBuilderAst = emptyAst(tableDef),
11
- ): QueryBuilder<TResult, TTableDef, never, QueryInfo.None> => {
12
+ ): QueryBuilder<TResult, TTableDef, never> => {
12
13
  const api = {
13
14
  // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
14
15
  select() {
15
- assertQueryBuilderAst(ast)
16
+ assertSelectQueryBuilderAst(ast)
16
17
 
17
18
  // eslint-disable-next-line prefer-rest-params
18
19
  const params = [...arguments]
19
20
 
20
- if (params.length === 2 && typeof params[0] === 'string' && typeof params[1] === 'object') {
21
- const [col, options] = params as any as [string, { pluck: boolean }]
21
+ // Pluck if there's only one column selected
22
+ if (params.length === 1) {
23
+ const [col] = params as any as [string]
22
24
  return makeQueryBuilder(tableDef, {
23
25
  ...ast,
24
- resultSchemaSingle: options.pluck ? ast.resultSchemaSingle.pipe(Schema.pluck(col)) : ast.resultSchemaSingle,
26
+ resultSchemaSingle: ast.resultSchemaSingle.pipe(Schema.pluck(col)),
25
27
  select: { columns: [col] },
26
28
  })
27
29
  }
@@ -36,8 +38,9 @@ export const makeQueryBuilder = <TResult, TTableDef extends DbSchema.TableDefBas
36
38
  }) as any
37
39
  },
38
40
  // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
39
- where() {
40
- if (isRowQuery(ast)) return invalidQueryBuilder()
41
+ where: function () {
42
+ if (ast._tag === 'InsertQuery') return invalidQueryBuilder('Cannot use where with insert')
43
+ if (ast._tag === 'RowQuery') return invalidQueryBuilder('Cannot use where with row')
41
44
 
42
45
  if (arguments.length === 1) {
43
46
  // eslint-disable-next-line prefer-rest-params
@@ -50,24 +53,45 @@ export const makeQueryBuilder = <TResult, TTableDef extends DbSchema.TableDefBas
50
53
  : { col, op: '=', value },
51
54
  )
52
55
 
53
- return makeQueryBuilder(tableDef, {
54
- ...ast,
55
- where: [...ast.where, ...newOps],
56
- }) as any
56
+ switch (ast._tag) {
57
+ case 'CountQuery':
58
+ case 'SelectQuery':
59
+ case 'UpdateQuery':
60
+ case 'DeleteQuery': {
61
+ return makeQueryBuilder(tableDef, {
62
+ ...ast,
63
+ where: [...ast.where, ...newOps],
64
+ }) as any
65
+ }
66
+ default: {
67
+ return casesHandled(ast)
68
+ }
69
+ }
57
70
  }
58
71
 
59
72
  // eslint-disable-next-line prefer-rest-params
60
73
  const [col, opOrValue, valueOrUndefined] = arguments
61
74
  const op = valueOrUndefined === undefined ? '=' : opOrValue
62
75
  const value = valueOrUndefined === undefined ? opOrValue : valueOrUndefined
63
- return makeQueryBuilder(tableDef, {
64
- ...ast,
65
- where: [...ast.where, { col, op, value }],
66
- })
76
+
77
+ switch (ast._tag) {
78
+ case 'CountQuery':
79
+ case 'SelectQuery':
80
+ case 'UpdateQuery':
81
+ case 'DeleteQuery': {
82
+ return makeQueryBuilder(tableDef, {
83
+ ...ast,
84
+ where: [...ast.where, { col, op, value }],
85
+ }) as any
86
+ }
87
+ default: {
88
+ return casesHandled(ast)
89
+ }
90
+ }
67
91
  },
68
92
  // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
69
93
  orderBy() {
70
- assertQueryBuilderAst(ast)
94
+ assertSelectQueryBuilderAst(ast)
71
95
 
72
96
  if (arguments.length === 0 || arguments.length > 2) return invalidQueryBuilder()
73
97
 
@@ -89,12 +113,12 @@ export const makeQueryBuilder = <TResult, TTableDef extends DbSchema.TableDefBas
89
113
  }) as any
90
114
  },
91
115
  limit: (limit) => {
92
- assertQueryBuilderAst(ast)
116
+ assertSelectQueryBuilderAst(ast)
93
117
 
94
118
  return makeQueryBuilder(tableDef, { ...ast, limit: Option.some(limit) })
95
119
  },
96
120
  offset: (offset) => {
97
- assertQueryBuilderAst(ast)
121
+ assertSelectQueryBuilderAst(ast)
98
122
 
99
123
  return makeQueryBuilder(tableDef, { ...ast, offset: Option.some(offset) })
100
124
  },
@@ -102,58 +126,129 @@ export const makeQueryBuilder = <TResult, TTableDef extends DbSchema.TableDefBas
102
126
  if (isRowQuery(ast)) return invalidQueryBuilder()
103
127
 
104
128
  return makeQueryBuilder(tableDef, {
105
- ...ast,
129
+ _tag: 'CountQuery',
130
+ tableDef,
131
+ where: [],
106
132
  resultSchema: Schema.Struct({ count: Schema.Number }).pipe(
107
133
  Schema.pluck('count'),
108
134
  Schema.Array,
109
135
  Schema.headOrElse(),
110
136
  ),
111
- _tag: 'CountQuery',
112
137
  })
113
138
  },
114
139
  first: (options) => {
115
- assertQueryBuilderAst(ast)
140
+ assertSelectQueryBuilderAst(ast)
116
141
 
117
142
  if (ast.limit._tag === 'Some') return invalidQueryBuilder(`.first() can't be called after .limit()`)
118
143
 
119
144
  return makeQueryBuilder(tableDef, {
120
145
  ...ast,
121
146
  limit: Option.some(1),
122
- // TODO improve
123
- pickFirst: options?.fallback ? { fallback: options.fallback } : { fallback: () => undefined },
147
+ pickFirst: options?.fallback ? { fallback: options.fallback } : 'no-fallback',
124
148
  })
125
149
  },
126
- // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
127
- row() {
128
- // eslint-disable-next-line prefer-rest-params
129
- const params = [...arguments]
150
+ // // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
151
+ // getOrCreate() {
152
+ // if (tableDef.options.isClientDocumentTable === false) {
153
+ // return invalidQueryBuilder(`getOrCreate() is not allowed when table is not a client document table`)
154
+ // }
155
+
156
+ // // eslint-disable-next-line prefer-rest-params
157
+ // const params = [...arguments]
158
+
159
+ // let id: string | number
160
+
161
+ // // TODO refactor to handle default id
162
+ // id = params[0] as string | number
163
+ // if (id === undefined) {
164
+ // invalidQueryBuilder(`Id missing for row query on non-singleton table ${tableDef.sqliteDef.name}`)
165
+ // }
166
+
167
+ // // TODO validate all required columns are present and values are matching the schema
168
+ // const insertValues: Record<string, unknown> = params[1]?.insertValues ?? {}
169
+
170
+ // return makeQueryBuilder(tableDef, {
171
+ // _tag: 'RowQuery',
172
+ // id,
173
+ // tableDef,
174
+ // insertValues,
175
+ // }) as any
176
+ // },
177
+ insert: (values) => {
178
+ const filteredValues = Object.fromEntries(Object.entries(values).filter(([, value]) => value !== undefined))
130
179
 
131
- let id: string
180
+ return makeQueryBuilder(tableDef, {
181
+ _tag: 'InsertQuery',
182
+ tableDef,
183
+ values: filteredValues,
184
+ onConflict: undefined,
185
+ returning: undefined,
186
+ resultSchema: Schema.Void,
187
+ }) as any
188
+ },
189
+ onConflict: (
190
+ targetOrTargets: string | string[],
191
+ action: 'ignore' | 'replace' | 'update',
192
+ updateValues?: Record<string, unknown>,
193
+ ) => {
194
+ const targets = Array.isArray(targetOrTargets) ? targetOrTargets : [targetOrTargets]
195
+
196
+ assertInsertQueryBuilderAst(ast)
197
+
198
+ const onConflict = Match.value(action).pipe(
199
+ Match.when('ignore', () => ({ targets, action: { _tag: 'ignore' } }) satisfies QueryBuilderAst.OnConflict),
200
+ Match.when('replace', () => ({ targets, action: { _tag: 'replace' } }) satisfies QueryBuilderAst.OnConflict),
201
+ Match.when(
202
+ 'update',
203
+ () => ({ targets, action: { _tag: 'update', update: updateValues! } }) satisfies QueryBuilderAst.OnConflict,
204
+ ),
205
+ Match.exhaustive,
206
+ )
132
207
 
133
- if (tableDef.options.isSingleton) {
134
- id = tableDef.sqliteDef.columns.id!.default.pipe(Option.getOrThrow)
135
- } else {
136
- id = params[0] as string
137
- if (id === undefined) {
138
- invalidQueryBuilder(`Id missing for row query on non-singleton table ${tableDef.sqliteDef.name}`)
139
- }
140
- }
208
+ return makeQueryBuilder(tableDef, {
209
+ ...ast,
210
+ onConflict,
211
+ }) as any
212
+ },
213
+
214
+ returning: (...columns) => {
215
+ assertWriteQueryBuilderAst(ast)
216
+
217
+ return makeQueryBuilder(tableDef, {
218
+ ...ast,
219
+ returning: columns,
220
+ resultSchema: tableDef.rowSchema.pipe(Schema.pick(...columns), Schema.Array),
221
+ }) as any
222
+ },
141
223
 
142
- // TODO validate all required columns are present and values are matching the schema
143
- const insertValues: Record<string, unknown> = params[1]?.insertValues ?? {}
224
+ update: (values) => {
225
+ const filteredValues = Object.fromEntries(Object.entries(values).filter(([, value]) => value !== undefined))
144
226
 
145
227
  return makeQueryBuilder(tableDef, {
146
- _tag: 'RowQuery',
147
- id,
228
+ _tag: 'UpdateQuery',
148
229
  tableDef,
149
- insertValues,
230
+ values: filteredValues,
231
+ where: [],
232
+ returning: undefined,
233
+ resultSchema: Schema.Void,
150
234
  }) as any
151
235
  },
152
- } satisfies QueryBuilder.ApiFull<TResult, TTableDef, never, QueryInfo.None>
236
+
237
+ delete: () => {
238
+ return makeQueryBuilder(tableDef, {
239
+ _tag: 'DeleteQuery',
240
+ tableDef,
241
+ where: [],
242
+ returning: undefined,
243
+ resultSchema: Schema.Void,
244
+ }) as any
245
+ },
246
+ } satisfies QueryBuilder.ApiFull<TResult, TTableDef, never>
153
247
 
154
248
  return {
155
- [TypeId]: TypeId,
249
+ [QueryBuilderTypeId]: QueryBuilderTypeId,
156
250
  [QueryBuilderAstSymbol]: ast,
251
+ ['ResultType']: 'only-for-type-inference' as TResult,
157
252
  asSql: () => astToSql(ast),
158
253
  toString: () => {
159
254
  try {
@@ -167,119 +262,89 @@ export const makeQueryBuilder = <TResult, TTableDef extends DbSchema.TableDefBas
167
262
  } satisfies QueryBuilder<TResult, TTableDef>
168
263
  }
169
264
 
170
- const emptyAst = (tableDef: DbSchema.TableDefBase) =>
171
- ({
172
- _tag: 'SelectQuery',
173
- columns: [],
174
- pickFirst: false,
175
- select: { columns: [] },
176
- orderBy: [],
177
- offset: Option.none(),
178
- limit: Option.none(),
179
- tableDef,
180
- where: [],
181
- resultSchemaSingle: tableDef.schema,
182
- }) satisfies QueryBuilderAst
183
-
184
- const astToSql = (ast: QueryBuilderAst) => {
185
- if (isRowQuery(ast)) {
186
- // TODO
187
- return { query: `SELECT * FROM '${ast.tableDef.sqliteDef.name}' WHERE id = ?`, bindValues: [ast.id as TODO] }
265
+ const emptyAst = (tableDef: State.SQLite.TableDefBase): QueryBuilderAst.SelectQuery => ({
266
+ _tag: 'SelectQuery',
267
+ columns: [],
268
+ pickFirst: false,
269
+ select: { columns: [] },
270
+ orderBy: [],
271
+ offset: Option.none(),
272
+ limit: Option.none(),
273
+ tableDef,
274
+ where: [],
275
+ resultSchemaSingle: tableDef.rowSchema,
276
+ })
277
+
278
+ // Helper functions
279
+ // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
280
+ function assertSelectQueryBuilderAst(ast: QueryBuilderAst): asserts ast is QueryBuilderAst.SelectQuery {
281
+ if (ast._tag !== 'SelectQuery') {
282
+ return shouldNeverHappen('Expected SelectQuery but got ' + ast._tag)
188
283
  }
284
+ }
189
285
 
190
- const bindValues: unknown[] = []
191
-
192
- // TODO bind values
193
- const whereStmt =
194
- ast.where.length > 0
195
- ? `WHERE ${ast.where
196
- .map(({ col, op, value }) => {
197
- if (value === null) {
198
- if (op !== '=' && op !== '!=') {
199
- throw new Error(`Unsupported operator for NULL value: ${op}`)
200
- }
201
- const opStmt = op === '=' ? 'IS' : 'IS NOT'
202
- return `${col} ${opStmt} NULL`
203
- } else {
204
- const colDef = ast.tableDef.sqliteDef.columns[col]
205
- if (colDef === undefined) {
206
- throw new Error(`Column ${col} not found`)
207
- }
208
- const isArray = op === 'IN' || op === 'NOT IN'
209
- const colSchema = isArray ? Schema.Array(colDef.schema) : colDef.schema
210
- const encodedValue = Schema.encodeSync(colSchema)(value)
211
-
212
- if (isArray) {
213
- bindValues.push(...encodedValue)
214
- const placeholders = Array.from({ length: encodedValue.length }, () => '?').join(', ')
215
- return `${col} ${op} (${placeholders})`
216
- } else {
217
- bindValues.push(encodedValue)
218
- return `${col} ${op} ?`
219
- }
220
- }
221
- })
222
- .join(' AND ')}`
223
- : ''
224
-
225
- if (ast._tag === 'CountQuery') {
226
- const selectFromStmt = `SELECT COUNT(*) as count FROM '${ast.tableDef.sqliteDef.name}'`
227
- const query = [selectFromStmt, whereStmt].filter((_) => _.length > 0).join(' ')
228
- return { query, bindValues }
286
+ // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
287
+ function assertInsertQueryBuilderAst(ast: QueryBuilderAst): asserts ast is QueryBuilderAst.InsertQuery {
288
+ if (ast._tag !== 'InsertQuery') {
289
+ return shouldNeverHappen('Expected InsertQuery but got ' + ast._tag)
229
290
  }
230
- const columnsStmt = ast.select.columns.length === 0 ? '*' : ast.select.columns.join(', ')
231
- const selectStmt = `SELECT ${columnsStmt}`
232
- const fromStmt = `FROM '${ast.tableDef.sqliteDef.name}'`
233
-
234
- const orderByStmt =
235
- ast.orderBy.length > 0
236
- ? `ORDER BY ${ast.orderBy.map(({ col, direction }) => `${col} ${direction}`).join(', ')}`
237
- : ''
238
-
239
- const limitStmt = ast.limit._tag === 'Some' ? `LIMIT ?` : ''
240
- if (ast.limit._tag === 'Some') bindValues.push(ast.limit.value)
241
-
242
- const offsetStmt = ast.offset._tag === 'Some' ? `OFFSET ?` : ''
243
- if (ast.offset._tag === 'Some') bindValues.push(ast.offset.value)
244
-
245
- const query = [selectStmt, fromStmt, whereStmt, orderByStmt, offsetStmt, limitStmt]
246
- .map((_) => _.trim())
247
- .filter((_) => _.length > 0)
248
- .join(' ')
249
-
250
- // TODO bind values
251
- return { query, bindValues }
252
291
  }
253
292
 
254
293
  // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
255
- function assertQueryBuilderAst(ast: QueryBuilderAst): asserts ast is QueryBuilderAst.SelectQuery {
256
- if (ast._tag !== 'SelectQuery') {
257
- throw new Error('Expected SelectQuery but got ' + ast._tag)
294
+ function assertWriteQueryBuilderAst(ast: QueryBuilderAst): asserts ast is QueryBuilderAst.WriteQuery {
295
+ if (ast._tag !== 'InsertQuery' && ast._tag !== 'UpdateQuery' && ast._tag !== 'DeleteQuery') {
296
+ return shouldNeverHappen('Expected WriteQuery but got ' + ast._tag)
258
297
  }
259
298
  }
260
299
 
261
300
  const isRowQuery = (ast: QueryBuilderAst): ast is QueryBuilderAst.RowQuery => ast._tag === 'RowQuery'
262
301
 
263
302
  export const invalidQueryBuilder = (msg?: string) => {
264
- throw new Error('Invalid query builder' + (msg ? `: ${msg}` : ''))
303
+ return shouldNeverHappen('Invalid query builder' + (msg ? `: ${msg}` : ''))
265
304
  }
266
305
 
267
- export const getResultSchema = (qb: QueryBuilder<any, any, any>) => {
306
+ export const getResultSchema = (qb: QueryBuilder<any, any, any>): Schema.Schema<any> => {
268
307
  const queryAst = qb[QueryBuilderAstSymbol]
269
- if (queryAst._tag === 'SelectQuery') {
270
- const arraySchema = Schema.Array(queryAst.resultSchemaSingle)
271
- if (queryAst.pickFirst !== false) {
272
- return arraySchema.pipe(Schema.headOrElse(queryAst.pickFirst.fallback))
308
+ switch (queryAst._tag) {
309
+ case 'SelectQuery': {
310
+ const arraySchema = Schema.Array(queryAst.resultSchemaSingle)
311
+ if (queryAst.pickFirst === false) {
312
+ return arraySchema
313
+ } else if (queryAst.pickFirst === 'no-fallback') {
314
+ // Will throw if the array is empty
315
+ return arraySchema.pipe(Schema.headOrElse())
316
+ } else {
317
+ const fallbackValue = queryAst.pickFirst.fallback()
318
+ return Schema.Union(arraySchema, Schema.Tuple(Schema.Literal(fallbackValue))).pipe(
319
+ Schema.headOrElse(() => fallbackValue),
320
+ )
321
+ }
322
+ }
323
+ case 'CountQuery': {
324
+ return Schema.Struct({ count: Schema.Number }).pipe(Schema.pluck('count'), Schema.Array, Schema.headOrElse())
273
325
  }
326
+ case 'InsertQuery':
327
+ case 'UpdateQuery':
328
+ case 'DeleteQuery': {
329
+ // For write operations with RETURNING clause, we need to return the appropriate schema
330
+ if (queryAst.returning && queryAst.returning.length > 0) {
331
+ // Create a schema for the returned columns
332
+ return queryAst.tableDef.rowSchema.pipe(Schema.pick(...queryAst.returning), Schema.Array)
333
+ }
274
334
 
275
- return arraySchema
276
- } else if (queryAst._tag === 'CountQuery') {
277
- return Schema.Struct({ count: Schema.Number }).pipe(Schema.pluck('count'), Schema.Array, Schema.headOrElse())
278
- } else {
279
- if (queryAst.tableDef.options.isSingleColumn) {
280
- return queryAst.tableDef.schema.pipe(Schema.pluck('value'), Schema.Array, Schema.headOrElse())
281
- } else {
282
- return queryAst.tableDef.schema.pipe(Schema.Array, Schema.headOrElse())
335
+ // For write operations without RETURNING, the result is the number of affected rows
336
+ return Schema.Number
337
+ }
338
+ case 'RowQuery': {
339
+ return queryAst.tableDef.rowSchema.pipe(
340
+ Schema.pluck('value'),
341
+ Schema.annotations({ title: `${queryAst.tableDef.sqliteDef.name}.value` }),
342
+ Schema.Array,
343
+ Schema.headOrElse(),
344
+ )
345
+ }
346
+ default: {
347
+ casesHandled(queryAst)
283
348
  }
284
349
  }
285
350
  }
@@ -7,4 +7,11 @@ export * from './impl.js'
7
7
  * - Close abstraction to SQLite to provide a simple & convenient API with predictable behaviour
8
8
  * - Use table schema definitions to parse, map & validate query results
9
9
  * - Implementation detail: Separate type-level & AST-based runtime implementation
10
+ *
11
+ * Currently not supported (not exhaustive list):
12
+ * - Assumes a `id` column as primary key
13
+ * - Composite primary keys
14
+ *
15
+ * Other known limitations
16
+ * - Doesn't exclude all invalid query patterns on type level `e.g. `db.todos.returning('id')`
10
17
  */
@@ -0,0 +1,114 @@
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 { ApplyEvent } from './leader-thread/mod.js'
6
+ import type { EventDef, EventlogMetaRow, LiveStoreSchema } from './schema/mod.js'
7
+ import { EventId, EVENTLOG_META_TABLE, getEventDef, LiveStoreEvent } from './schema/mod.js'
8
+ import type { PreparedBindValues } from './util.js'
9
+ import { sql } from './util.js'
10
+
11
+ export const rehydrateFromEventlog = ({
12
+ dbEventlog,
13
+ // TODO re-use this db when bringing back the boot in-memory db implementation
14
+ // db,
15
+ schema,
16
+ onProgress,
17
+ applyEvent,
18
+ }: {
19
+ dbEventlog: SqliteDb
20
+ // db: SqliteDb
21
+ schema: LiveStoreSchema
22
+ onProgress: (_: { done: number; total: number }) => Effect.Effect<void>
23
+ applyEvent: ApplyEvent
24
+ }) =>
25
+ Effect.gen(function* () {
26
+ const eventsCount = dbEventlog.select<{ count: number }>(`SELECT COUNT(*) AS count FROM ${EVENTLOG_META_TABLE}`)[0]!
27
+ .count
28
+
29
+ const hashEvent = memoizeByRef((event: EventDef.AnyWithoutFn) => Schema.hash(event.schema))
30
+
31
+ const processEvent = (row: EventlogMetaRow) =>
32
+ Effect.gen(function* () {
33
+ const eventDef = getEventDef(schema, row.name)
34
+
35
+ if (hashEvent(eventDef.eventDef) !== row.schemaHash) {
36
+ yield* Effect.logWarning(`Schema hash mismatch for mutation ${row.name}. Trying to apply mutation anyway.`)
37
+ }
38
+
39
+ const args = JSON.parse(row.argsJson)
40
+
41
+ // Checking whether the schema has changed in an incompatible way
42
+ yield* Schema.decodeUnknown(eventDef.eventDef.schema)(args).pipe(
43
+ Effect.mapError((cause) =>
44
+ UnexpectedError.make({
45
+ cause,
46
+ note: `\
47
+ There was an error during rehydrating from the eventlog while decoding
48
+ the persisted mutation event args for mutation "${row.name}".
49
+ This likely means the schema has changed in an incompatible way.
50
+ `,
51
+ }),
52
+ ),
53
+ )
54
+
55
+ const eventEncoded = LiveStoreEvent.EncodedWithMeta.make({
56
+ id: { global: row.idGlobal, client: row.idClient },
57
+ parentId: { global: row.parentIdGlobal, client: row.parentIdClient },
58
+ name: row.name,
59
+ args,
60
+ clientId: row.clientId,
61
+ sessionId: row.sessionId,
62
+ })
63
+
64
+ yield* applyEvent(eventEncoded, { skipEventlog: true })
65
+ }).pipe(Effect.withSpan(`@livestore/common:rehydrateFromEventlog:processEvent`))
66
+
67
+ const CHUNK_SIZE = 100
68
+
69
+ const stmt = dbEventlog.prepare(sql`\
70
+ SELECT * FROM ${EVENTLOG_META_TABLE}
71
+ WHERE idGlobal > $idGlobal OR (idGlobal = $idGlobal AND idClient > $idClient)
72
+ ORDER BY idGlobal ASC, idClient ASC
73
+ LIMIT ${CHUNK_SIZE}
74
+ `)
75
+
76
+ let processedEvents = 0
77
+
78
+ yield* Stream.unfoldChunk<Chunk.Chunk<EventlogMetaRow> | { _tag: 'Initial ' }, EventlogMetaRow>(
79
+ { _tag: 'Initial ' },
80
+ (item) => {
81
+ // End stream if no more rows
82
+ if (Chunk.isChunk(item) && item.length === 0) return Option.none()
83
+
84
+ const lastId = Chunk.isChunk(item)
85
+ ? Chunk.last(item).pipe(
86
+ Option.map((_) => ({ global: _.idGlobal, client: _.idClient })),
87
+ Option.getOrElse(() => EventId.ROOT),
88
+ )
89
+ : EventId.ROOT
90
+ const nextItem = Chunk.fromIterable(
91
+ stmt.select<EventlogMetaRow>({
92
+ $idGlobal: lastId?.global,
93
+ $idClient: lastId?.client,
94
+ } as any as PreparedBindValues),
95
+ )
96
+ const prevItem = Chunk.isChunk(item) ? item : Chunk.empty()
97
+ return Option.some([prevItem, nextItem])
98
+ },
99
+ ).pipe(
100
+ Stream.bufferChunks({ capacity: 2 }),
101
+ Stream.tap((row) =>
102
+ Effect.gen(function* () {
103
+ yield* processEvent(row)
104
+
105
+ processedEvents++
106
+ yield* onProgress({ done: processedEvents, total: eventsCount })
107
+ }),
108
+ ),
109
+ Stream.runDrain,
110
+ )
111
+ }).pipe(
112
+ Effect.withPerformanceMeasure('@livestore/common:rehydrateFromEventlog'),
113
+ Effect.withSpan('@livestore/common:rehydrateFromEventlog'),
114
+ )