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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/__tests__/fixture.d.ts +83 -221
  3. package/dist/__tests__/fixture.d.ts.map +1 -1
  4. package/dist/__tests__/fixture.js +33 -11
  5. package/dist/__tests__/fixture.js.map +1 -1
  6. package/dist/adapter-types.d.ts +132 -75
  7. package/dist/adapter-types.d.ts.map +1 -1
  8. package/dist/adapter-types.js +36 -7
  9. package/dist/adapter-types.js.map +1 -1
  10. package/dist/bounded-collections.d.ts.map +1 -1
  11. package/dist/debug-info.d.ts +1 -1
  12. package/dist/debug-info.d.ts.map +1 -1
  13. package/dist/debug-info.js +1 -0
  14. package/dist/debug-info.js.map +1 -1
  15. package/dist/devtools/devtools-messages-client-session.d.ts +390 -0
  16. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -0
  17. package/dist/devtools/devtools-messages-client-session.js +97 -0
  18. package/dist/devtools/devtools-messages-client-session.js.map +1 -0
  19. package/dist/devtools/devtools-messages-common.d.ts +68 -0
  20. package/dist/devtools/devtools-messages-common.d.ts.map +1 -0
  21. package/dist/devtools/devtools-messages-common.js +60 -0
  22. package/dist/devtools/devtools-messages-common.js.map +1 -0
  23. package/dist/devtools/devtools-messages-leader.d.ts +394 -0
  24. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -0
  25. package/dist/devtools/devtools-messages-leader.js +147 -0
  26. package/dist/devtools/devtools-messages-leader.js.map +1 -0
  27. package/dist/devtools/devtools-messages.d.ts +3 -592
  28. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  29. package/dist/devtools/devtools-messages.js +3 -171
  30. package/dist/devtools/devtools-messages.js.map +1 -1
  31. package/dist/devtools/devtools-sessioninfo.d.ts +32 -0
  32. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -0
  33. package/dist/devtools/devtools-sessioninfo.js +36 -0
  34. package/dist/devtools/devtools-sessioninfo.js.map +1 -0
  35. package/dist/devtools/mod.d.ts +55 -0
  36. package/dist/devtools/mod.d.ts.map +1 -0
  37. package/dist/devtools/mod.js +33 -0
  38. package/dist/devtools/mod.js.map +1 -0
  39. package/dist/index.d.ts +7 -13
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +7 -9
  42. package/dist/index.js.map +1 -1
  43. package/dist/leader-thread/LeaderSyncProcessor.d.ts +62 -0
  44. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -0
  45. package/dist/leader-thread/LeaderSyncProcessor.js +593 -0
  46. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -0
  47. package/dist/leader-thread/connection.d.ts +34 -6
  48. package/dist/leader-thread/connection.d.ts.map +1 -1
  49. package/dist/leader-thread/connection.js +22 -7
  50. package/dist/leader-thread/connection.js.map +1 -1
  51. package/dist/leader-thread/eventlog.d.ts +27 -0
  52. package/dist/leader-thread/eventlog.d.ts.map +1 -0
  53. package/dist/leader-thread/eventlog.js +119 -0
  54. package/dist/leader-thread/eventlog.js.map +1 -0
  55. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  56. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  57. package/dist/leader-thread/leader-worker-devtools.js +165 -134
  58. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  59. package/dist/leader-thread/make-leader-thread-layer.d.ts +26 -12
  60. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  61. package/dist/leader-thread/make-leader-thread-layer.js +76 -48
  62. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  63. package/dist/leader-thread/materialize-event.d.ts +16 -0
  64. package/dist/leader-thread/materialize-event.d.ts.map +1 -0
  65. package/dist/leader-thread/materialize-event.js +105 -0
  66. package/dist/leader-thread/materialize-event.js.map +1 -0
  67. package/dist/leader-thread/mod.d.ts +1 -1
  68. package/dist/leader-thread/mod.d.ts.map +1 -1
  69. package/dist/leader-thread/mod.js +1 -1
  70. package/dist/leader-thread/mod.js.map +1 -1
  71. package/dist/leader-thread/recreate-db.d.ts +4 -2
  72. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  73. package/dist/leader-thread/recreate-db.js +33 -31
  74. package/dist/leader-thread/recreate-db.js.map +1 -1
  75. package/dist/leader-thread/shutdown-channel.d.ts +2 -5
  76. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  77. package/dist/leader-thread/shutdown-channel.js +2 -4
  78. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  79. package/dist/leader-thread/types.d.ts +89 -40
  80. package/dist/leader-thread/types.d.ts.map +1 -1
  81. package/dist/leader-thread/types.js +1 -3
  82. package/dist/leader-thread/types.js.map +1 -1
  83. package/dist/make-client-session.d.ts +21 -0
  84. package/dist/make-client-session.d.ts.map +1 -0
  85. package/dist/make-client-session.js +51 -0
  86. package/dist/make-client-session.js.map +1 -0
  87. package/dist/materializer-helper.d.ts +23 -0
  88. package/dist/materializer-helper.d.ts.map +1 -0
  89. package/dist/materializer-helper.js +84 -0
  90. package/dist/materializer-helper.js.map +1 -0
  91. package/dist/otel.d.ts +2 -0
  92. package/dist/otel.d.ts.map +1 -1
  93. package/dist/otel.js +5 -0
  94. package/dist/otel.js.map +1 -1
  95. package/dist/rematerialize-from-eventlog.d.ts +14 -0
  96. package/dist/rematerialize-from-eventlog.d.ts.map +1 -0
  97. package/dist/rematerialize-from-eventlog.js +64 -0
  98. package/dist/rematerialize-from-eventlog.js.map +1 -0
  99. package/dist/schema/EventDef.d.ts +146 -0
  100. package/dist/schema/EventDef.d.ts.map +1 -0
  101. package/dist/schema/EventDef.js +58 -0
  102. package/dist/schema/EventDef.js.map +1 -0
  103. package/dist/schema/EventId.d.ts +35 -15
  104. package/dist/schema/EventId.d.ts.map +1 -1
  105. package/dist/schema/EventId.js +57 -11
  106. package/dist/schema/EventId.js.map +1 -1
  107. package/dist/schema/EventId.test.d.ts +2 -0
  108. package/dist/schema/EventId.test.d.ts.map +1 -0
  109. package/dist/schema/EventId.test.js +11 -0
  110. package/dist/schema/EventId.test.js.map +1 -0
  111. package/dist/schema/LiveStoreEvent.d.ts +255 -0
  112. package/dist/schema/LiveStoreEvent.d.ts.map +1 -0
  113. package/dist/schema/LiveStoreEvent.js +118 -0
  114. package/dist/schema/LiveStoreEvent.js.map +1 -0
  115. package/dist/schema/events.d.ts +2 -0
  116. package/dist/schema/events.d.ts.map +1 -0
  117. package/dist/schema/events.js +2 -0
  118. package/dist/schema/events.js.map +1 -0
  119. package/dist/schema/mod.d.ts +7 -5
  120. package/dist/schema/mod.d.ts.map +1 -1
  121. package/dist/schema/mod.js +7 -5
  122. package/dist/schema/mod.js.map +1 -1
  123. package/dist/schema/schema.d.ts +48 -30
  124. package/dist/schema/schema.d.ts.map +1 -1
  125. package/dist/schema/schema.js +36 -43
  126. package/dist/schema/schema.js.map +1 -1
  127. package/dist/schema/state/mod.d.ts +3 -0
  128. package/dist/schema/state/mod.d.ts.map +1 -0
  129. package/dist/schema/state/mod.js +3 -0
  130. package/dist/schema/state/mod.js.map +1 -0
  131. package/dist/schema/state/sqlite/client-document-def.d.ts +223 -0
  132. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -0
  133. package/dist/schema/state/sqlite/client-document-def.js +170 -0
  134. package/dist/schema/state/sqlite/client-document-def.js.map +1 -0
  135. package/dist/schema/state/sqlite/client-document-def.test.d.ts +2 -0
  136. package/dist/schema/state/sqlite/client-document-def.test.d.ts.map +1 -0
  137. package/dist/schema/state/sqlite/client-document-def.test.js +201 -0
  138. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -0
  139. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +69 -0
  140. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -0
  141. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +71 -0
  142. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -0
  143. package/dist/schema/state/sqlite/db-schema/ast/validate.d.ts +3 -0
  144. package/dist/schema/state/sqlite/db-schema/ast/validate.d.ts.map +1 -0
  145. package/dist/schema/state/sqlite/db-schema/ast/validate.js +12 -0
  146. package/dist/schema/state/sqlite/db-schema/ast/validate.js.map +1 -0
  147. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +90 -0
  148. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -0
  149. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +87 -0
  150. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -0
  151. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.d.ts +2 -0
  152. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.d.ts.map +1 -0
  153. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +29 -0
  154. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -0
  155. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +90 -0
  156. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -0
  157. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +41 -0
  158. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -0
  159. package/dist/schema/state/sqlite/db-schema/hash.d.ts +2 -0
  160. package/dist/schema/state/sqlite/db-schema/hash.d.ts.map +1 -0
  161. package/dist/schema/state/sqlite/db-schema/hash.js +14 -0
  162. package/dist/schema/state/sqlite/db-schema/hash.js.map +1 -0
  163. package/dist/schema/state/sqlite/db-schema/mod.d.ts +3 -0
  164. package/dist/schema/state/sqlite/db-schema/mod.d.ts.map +1 -0
  165. package/dist/schema/state/sqlite/db-schema/mod.js +3 -0
  166. package/dist/schema/state/sqlite/db-schema/mod.js.map +1 -0
  167. package/dist/schema/state/sqlite/mod.d.ts +17 -0
  168. package/dist/schema/state/sqlite/mod.d.ts.map +1 -0
  169. package/dist/schema/state/sqlite/mod.js +41 -0
  170. package/dist/schema/state/sqlite/mod.js.map +1 -0
  171. package/dist/schema/state/sqlite/query-builder/api.d.ts +294 -0
  172. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -0
  173. package/dist/schema/state/sqlite/query-builder/api.js +6 -0
  174. package/dist/schema/state/sqlite/query-builder/api.js.map +1 -0
  175. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts +7 -0
  176. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -0
  177. package/dist/schema/state/sqlite/query-builder/astToSql.js +190 -0
  178. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -0
  179. package/dist/schema/state/sqlite/query-builder/impl.d.ts +7 -0
  180. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -0
  181. package/dist/schema/state/sqlite/query-builder/impl.js +286 -0
  182. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -0
  183. package/dist/schema/state/sqlite/query-builder/impl.test.d.ts +87 -0
  184. package/dist/schema/state/sqlite/query-builder/impl.test.d.ts.map +1 -0
  185. package/dist/schema/state/sqlite/query-builder/impl.test.js +554 -0
  186. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -0
  187. package/dist/{query-builder → schema/state/sqlite/query-builder}/mod.d.ts +7 -0
  188. package/dist/schema/state/sqlite/query-builder/mod.d.ts.map +1 -0
  189. package/dist/{query-builder → schema/state/sqlite/query-builder}/mod.js +7 -0
  190. package/dist/schema/state/sqlite/query-builder/mod.js.map +1 -0
  191. package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -0
  192. package/dist/schema/{schema-helpers.js → state/sqlite/schema-helpers.js} +1 -1
  193. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -0
  194. package/dist/schema/state/sqlite/system-tables.d.ts +574 -0
  195. package/dist/schema/state/sqlite/system-tables.d.ts.map +1 -0
  196. package/dist/schema/state/sqlite/system-tables.js +87 -0
  197. package/dist/schema/state/sqlite/system-tables.js.map +1 -0
  198. package/dist/schema/state/sqlite/table-def.d.ts +84 -0
  199. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -0
  200. package/dist/schema/state/sqlite/table-def.js +36 -0
  201. package/dist/schema/state/sqlite/table-def.js.map +1 -0
  202. package/dist/schema-management/common.d.ts +7 -7
  203. package/dist/schema-management/common.d.ts.map +1 -1
  204. package/dist/schema-management/common.js.map +1 -1
  205. package/dist/schema-management/migrations.d.ts +6 -6
  206. package/dist/schema-management/migrations.d.ts.map +1 -1
  207. package/dist/schema-management/migrations.js +33 -24
  208. package/dist/schema-management/migrations.js.map +1 -1
  209. package/dist/schema-management/validate-schema.d.ts +8 -0
  210. package/dist/schema-management/validate-schema.d.ts.map +1 -0
  211. package/dist/schema-management/validate-schema.js +39 -0
  212. package/dist/schema-management/validate-schema.js.map +1 -0
  213. package/dist/sql-queries/misc.d.ts.map +1 -1
  214. package/dist/sql-queries/sql-queries.d.ts +1 -1
  215. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  216. package/dist/sql-queries/sql-queries.js.map +1 -1
  217. package/dist/sql-queries/sql-query-builder.d.ts +1 -1
  218. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  219. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  220. package/dist/sql-queries/types.d.ts +2 -1
  221. package/dist/sql-queries/types.d.ts.map +1 -1
  222. package/dist/sql-queries/types.js.map +1 -1
  223. package/dist/sync/ClientSessionSyncProcessor.d.ts +66 -0
  224. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -0
  225. package/dist/sync/ClientSessionSyncProcessor.js +209 -0
  226. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -0
  227. package/dist/sync/index.d.ts +1 -1
  228. package/dist/sync/index.d.ts.map +1 -1
  229. package/dist/sync/index.js +1 -1
  230. package/dist/sync/index.js.map +1 -1
  231. package/dist/sync/next/compact-events.d.ts.map +1 -1
  232. package/dist/sync/next/facts.d.ts +19 -19
  233. package/dist/sync/next/facts.d.ts.map +1 -1
  234. package/dist/sync/next/facts.js +3 -3
  235. package/dist/sync/next/facts.js.map +1 -1
  236. package/dist/sync/next/history-dag-common.d.ts +6 -7
  237. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  238. package/dist/sync/next/history-dag-common.js +4 -2
  239. package/dist/sync/next/history-dag-common.js.map +1 -1
  240. package/dist/sync/next/history-dag.d.ts.map +1 -1
  241. package/dist/sync/next/history-dag.js +2 -2
  242. package/dist/sync/next/history-dag.js.map +1 -1
  243. package/dist/sync/next/rebase-events.d.ts +10 -8
  244. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  245. package/dist/sync/next/rebase-events.js +11 -8
  246. package/dist/sync/next/rebase-events.js.map +1 -1
  247. package/dist/sync/next/test/compact-events.calculator.test.js +38 -33
  248. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  249. package/dist/sync/next/test/compact-events.test.js +76 -76
  250. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  251. package/dist/sync/next/test/{mutation-fixtures.d.ts → event-fixtures.d.ts} +25 -25
  252. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -0
  253. package/dist/sync/next/test/{mutation-fixtures.js → event-fixtures.js} +67 -36
  254. package/dist/sync/next/test/event-fixtures.js.map +1 -0
  255. package/dist/sync/next/test/mod.d.ts +1 -1
  256. package/dist/sync/next/test/mod.d.ts.map +1 -1
  257. package/dist/sync/next/test/mod.js +1 -1
  258. package/dist/sync/next/test/mod.js.map +1 -1
  259. package/dist/sync/sync.d.ts +55 -20
  260. package/dist/sync/sync.d.ts.map +1 -1
  261. package/dist/sync/sync.js +7 -3
  262. package/dist/sync/sync.js.map +1 -1
  263. package/dist/sync/syncstate.d.ts +213 -82
  264. package/dist/sync/syncstate.d.ts.map +1 -1
  265. package/dist/sync/syncstate.js +319 -120
  266. package/dist/sync/syncstate.js.map +1 -1
  267. package/dist/sync/syncstate.test.js +295 -275
  268. package/dist/sync/syncstate.test.js.map +1 -1
  269. package/dist/sync/validate-push-payload.d.ts +2 -2
  270. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  271. package/dist/sync/validate-push-payload.js +2 -2
  272. package/dist/sync/validate-push-payload.js.map +1 -1
  273. package/dist/util.d.ts +2 -2
  274. package/dist/util.d.ts.map +1 -1
  275. package/dist/version.d.ts +1 -1
  276. package/dist/version.d.ts.map +1 -1
  277. package/dist/version.js +1 -1
  278. package/dist/version.js.map +1 -1
  279. package/package.json +13 -6
  280. package/src/__tests__/fixture.ts +36 -15
  281. package/src/adapter-types.ts +116 -83
  282. package/src/debug-info.ts +1 -0
  283. package/src/devtools/devtools-messages-client-session.ts +142 -0
  284. package/src/devtools/devtools-messages-common.ts +115 -0
  285. package/src/devtools/devtools-messages-leader.ts +191 -0
  286. package/src/devtools/devtools-messages.ts +3 -243
  287. package/src/devtools/devtools-sessioninfo.ts +101 -0
  288. package/src/devtools/mod.ts +59 -0
  289. package/src/index.ts +7 -15
  290. package/src/leader-thread/LeaderSyncProcessor.ts +933 -0
  291. package/src/leader-thread/connection.ts +54 -9
  292. package/src/leader-thread/eventlog.ts +194 -0
  293. package/src/leader-thread/leader-worker-devtools.ts +235 -191
  294. package/src/leader-thread/make-leader-thread-layer.ts +138 -78
  295. package/src/leader-thread/materialize-event.ts +169 -0
  296. package/src/leader-thread/mod.ts +1 -1
  297. package/src/leader-thread/recreate-db.ts +38 -39
  298. package/src/leader-thread/shutdown-channel.ts +2 -4
  299. package/src/leader-thread/types.ts +98 -53
  300. package/src/make-client-session.ts +119 -0
  301. package/src/materializer-helper.ts +135 -0
  302. package/src/otel.ts +8 -0
  303. package/src/rematerialize-from-eventlog.ts +117 -0
  304. package/src/schema/EventDef.ts +227 -0
  305. package/src/schema/EventId.test.ts +12 -0
  306. package/src/schema/EventId.ts +75 -15
  307. package/src/schema/LiveStoreEvent.ts +239 -0
  308. package/src/schema/events.ts +1 -0
  309. package/src/schema/mod.ts +7 -5
  310. package/src/schema/schema.ts +85 -81
  311. package/src/schema/state/mod.ts +2 -0
  312. package/src/schema/state/sqlite/client-document-def.test.ts +238 -0
  313. package/src/schema/state/sqlite/client-document-def.ts +444 -0
  314. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +142 -0
  315. package/src/schema/state/sqlite/db-schema/ast/validate.ts +13 -0
  316. package/src/schema/state/sqlite/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +206 -0
  317. package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +35 -0
  318. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +242 -0
  319. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +222 -0
  320. package/src/schema/state/sqlite/db-schema/hash.ts +14 -0
  321. package/src/schema/state/sqlite/db-schema/mod.ts +2 -0
  322. package/src/schema/state/sqlite/mod.ts +73 -0
  323. package/src/schema/state/sqlite/query-builder/api.ts +440 -0
  324. package/src/schema/state/sqlite/query-builder/astToSql.ts +232 -0
  325. package/src/schema/state/sqlite/query-builder/impl.test.ts +608 -0
  326. package/src/schema/state/sqlite/query-builder/impl.ts +350 -0
  327. package/src/{query-builder → schema/state/sqlite/query-builder}/mod.ts +7 -0
  328. package/src/schema/{schema-helpers.ts → state/sqlite/schema-helpers.ts} +1 -1
  329. package/src/schema/state/sqlite/system-tables.ts +116 -0
  330. package/src/schema/state/sqlite/table-def.ts +197 -0
  331. package/src/schema-management/common.ts +7 -7
  332. package/src/schema-management/migrations.ts +43 -37
  333. package/src/schema-management/validate-schema.ts +61 -0
  334. package/src/sql-queries/sql-queries.ts +1 -1
  335. package/src/sql-queries/sql-query-builder.ts +1 -2
  336. package/src/sql-queries/types.ts +3 -1
  337. package/src/sync/ClientSessionSyncProcessor.ts +332 -0
  338. package/src/sync/index.ts +1 -1
  339. package/src/sync/next/facts.ts +32 -33
  340. package/src/sync/next/history-dag-common.ts +9 -5
  341. package/src/sync/next/history-dag.ts +2 -2
  342. package/src/sync/next/rebase-events.ts +22 -16
  343. package/src/sync/next/test/compact-events.calculator.test.ts +45 -45
  344. package/src/sync/next/test/compact-events.test.ts +78 -78
  345. package/src/sync/next/test/event-fixtures.ts +219 -0
  346. package/src/sync/next/test/mod.ts +1 -1
  347. package/src/sync/sync.ts +51 -19
  348. package/src/sync/syncstate.test.ts +335 -308
  349. package/src/sync/syncstate.ts +394 -212
  350. package/src/sync/validate-push-payload.ts +7 -4
  351. package/src/version.ts +1 -1
  352. package/dist/derived-mutations.d.ts +0 -109
  353. package/dist/derived-mutations.d.ts.map +0 -1
  354. package/dist/derived-mutations.js +0 -54
  355. package/dist/derived-mutations.js.map +0 -1
  356. package/dist/derived-mutations.test.d.ts +0 -2
  357. package/dist/derived-mutations.test.d.ts.map +0 -1
  358. package/dist/derived-mutations.test.js +0 -93
  359. package/dist/derived-mutations.test.js.map +0 -1
  360. package/dist/devtools/devtools-bridge.d.ts +0 -12
  361. package/dist/devtools/devtools-bridge.d.ts.map +0 -1
  362. package/dist/devtools/devtools-bridge.js +0 -2
  363. package/dist/devtools/devtools-bridge.js.map +0 -1
  364. package/dist/devtools/devtools-window-message.d.ts +0 -29
  365. package/dist/devtools/devtools-window-message.d.ts.map +0 -1
  366. package/dist/devtools/devtools-window-message.js +0 -33
  367. package/dist/devtools/devtools-window-message.js.map +0 -1
  368. package/dist/devtools/index.d.ts +0 -42
  369. package/dist/devtools/index.d.ts.map +0 -1
  370. package/dist/devtools/index.js +0 -48
  371. package/dist/devtools/index.js.map +0 -1
  372. package/dist/init-singleton-tables.d.ts +0 -4
  373. package/dist/init-singleton-tables.d.ts.map +0 -1
  374. package/dist/init-singleton-tables.js +0 -16
  375. package/dist/init-singleton-tables.js.map +0 -1
  376. package/dist/leader-thread/apply-mutation.d.ts +0 -8
  377. package/dist/leader-thread/apply-mutation.d.ts.map +0 -1
  378. package/dist/leader-thread/apply-mutation.js +0 -95
  379. package/dist/leader-thread/apply-mutation.js.map +0 -1
  380. package/dist/leader-thread/leader-sync-processor.d.ts +0 -47
  381. package/dist/leader-thread/leader-sync-processor.d.ts.map +0 -1
  382. package/dist/leader-thread/leader-sync-processor.js +0 -422
  383. package/dist/leader-thread/leader-sync-processor.js.map +0 -1
  384. package/dist/leader-thread/mutationlog.d.ts +0 -23
  385. package/dist/leader-thread/mutationlog.d.ts.map +0 -1
  386. package/dist/leader-thread/mutationlog.js +0 -27
  387. package/dist/leader-thread/mutationlog.js.map +0 -1
  388. package/dist/leader-thread/pull-queue-set.d.ts +0 -7
  389. package/dist/leader-thread/pull-queue-set.d.ts.map +0 -1
  390. package/dist/leader-thread/pull-queue-set.js +0 -39
  391. package/dist/leader-thread/pull-queue-set.js.map +0 -1
  392. package/dist/mutation.d.ts +0 -13
  393. package/dist/mutation.d.ts.map +0 -1
  394. package/dist/mutation.js +0 -57
  395. package/dist/mutation.js.map +0 -1
  396. package/dist/query-builder/api.d.ts +0 -190
  397. package/dist/query-builder/api.d.ts.map +0 -1
  398. package/dist/query-builder/api.js +0 -8
  399. package/dist/query-builder/api.js.map +0 -1
  400. package/dist/query-builder/impl.d.ts +0 -12
  401. package/dist/query-builder/impl.d.ts.map +0 -1
  402. package/dist/query-builder/impl.js +0 -244
  403. package/dist/query-builder/impl.js.map +0 -1
  404. package/dist/query-builder/impl.test.d.ts +0 -2
  405. package/dist/query-builder/impl.test.d.ts.map +0 -1
  406. package/dist/query-builder/impl.test.js +0 -212
  407. package/dist/query-builder/impl.test.js.map +0 -1
  408. package/dist/query-builder/mod.d.ts.map +0 -1
  409. package/dist/query-builder/mod.js.map +0 -1
  410. package/dist/query-info.d.ts +0 -38
  411. package/dist/query-info.d.ts.map +0 -1
  412. package/dist/query-info.js +0 -7
  413. package/dist/query-info.js.map +0 -1
  414. package/dist/rehydrate-from-mutationlog.d.ts +0 -14
  415. package/dist/rehydrate-from-mutationlog.d.ts.map +0 -1
  416. package/dist/rehydrate-from-mutationlog.js +0 -72
  417. package/dist/rehydrate-from-mutationlog.js.map +0 -1
  418. package/dist/schema/MutationEvent.d.ts +0 -191
  419. package/dist/schema/MutationEvent.d.ts.map +0 -1
  420. package/dist/schema/MutationEvent.js +0 -56
  421. package/dist/schema/MutationEvent.js.map +0 -1
  422. package/dist/schema/mutations.d.ts +0 -107
  423. package/dist/schema/mutations.d.ts.map +0 -1
  424. package/dist/schema/mutations.js +0 -42
  425. package/dist/schema/mutations.js.map +0 -1
  426. package/dist/schema/schema-helpers.d.ts.map +0 -1
  427. package/dist/schema/schema-helpers.js.map +0 -1
  428. package/dist/schema/system-tables.d.ts +0 -399
  429. package/dist/schema/system-tables.d.ts.map +0 -1
  430. package/dist/schema/system-tables.js +0 -51
  431. package/dist/schema/system-tables.js.map +0 -1
  432. package/dist/schema/table-def.d.ts +0 -156
  433. package/dist/schema/table-def.d.ts.map +0 -1
  434. package/dist/schema/table-def.js +0 -79
  435. package/dist/schema/table-def.js.map +0 -1
  436. package/dist/schema-management/validate-mutation-defs.d.ts +0 -8
  437. package/dist/schema-management/validate-mutation-defs.d.ts.map +0 -1
  438. package/dist/schema-management/validate-mutation-defs.js +0 -39
  439. package/dist/schema-management/validate-mutation-defs.js.map +0 -1
  440. package/dist/sync/client-session-sync-processor.d.ts +0 -45
  441. package/dist/sync/client-session-sync-processor.d.ts.map +0 -1
  442. package/dist/sync/client-session-sync-processor.js +0 -131
  443. package/dist/sync/client-session-sync-processor.js.map +0 -1
  444. package/dist/sync/next/test/mutation-fixtures.d.ts.map +0 -1
  445. package/dist/sync/next/test/mutation-fixtures.js.map +0 -1
  446. package/src/derived-mutations.test.ts +0 -101
  447. package/src/derived-mutations.ts +0 -166
  448. package/src/devtools/devtools-bridge.ts +0 -13
  449. package/src/devtools/devtools-window-message.ts +0 -27
  450. package/src/devtools/index.ts +0 -48
  451. package/src/init-singleton-tables.ts +0 -24
  452. package/src/leader-thread/apply-mutation.ts +0 -143
  453. package/src/leader-thread/leader-sync-processor.ts +0 -666
  454. package/src/leader-thread/mutationlog.ts +0 -42
  455. package/src/leader-thread/pull-queue-set.ts +0 -58
  456. package/src/mutation.ts +0 -81
  457. package/src/query-builder/api.ts +0 -289
  458. package/src/query-builder/impl.test.ts +0 -239
  459. package/src/query-builder/impl.ts +0 -285
  460. package/src/query-info.ts +0 -78
  461. package/src/rehydrate-from-mutationlog.ts +0 -127
  462. package/src/schema/MutationEvent.ts +0 -161
  463. package/src/schema/mutations.ts +0 -192
  464. package/src/schema/system-tables.ts +0 -97
  465. package/src/schema/table-def.ts +0 -343
  466. package/src/schema-management/validate-mutation-defs.ts +0 -63
  467. package/src/sync/client-session-sync-processor.ts +0 -207
  468. package/src/sync/next/test/mutation-fixtures.ts +0 -231
  469. package/tsconfig.json +0 -11
  470. /package/dist/schema/{schema-helpers.d.ts → state/sqlite/schema-helpers.d.ts} +0 -0
@@ -0,0 +1,350 @@
1
+ import { casesHandled, shouldNeverHappen } from '@livestore/utils'
2
+ import { Match, Option, Predicate, Schema } from '@livestore/utils/effect'
3
+
4
+ import type { TableDefBase } from '../table-def.js'
5
+ import type { QueryBuilder, QueryBuilderAst } from './api.js'
6
+ import { QueryBuilderAstSymbol, QueryBuilderTypeId } from './api.js'
7
+ import { astToSql } from './astToSql.js'
8
+ export const makeQueryBuilder = <TResult, TTableDef extends TableDefBase>(
9
+ tableDef: TTableDef,
10
+ ast: QueryBuilderAst = emptyAst(tableDef),
11
+ ): QueryBuilder<TResult, TTableDef, never> => {
12
+ const api = {
13
+ // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
14
+ select() {
15
+ assertSelectQueryBuilderAst(ast)
16
+
17
+ // eslint-disable-next-line prefer-rest-params
18
+ const params = [...arguments]
19
+
20
+ // Pluck if there's only one column selected
21
+ if (params.length === 1) {
22
+ const [col] = params as any as [string]
23
+ return makeQueryBuilder(tableDef, {
24
+ ...ast,
25
+ resultSchemaSingle: ast.resultSchemaSingle.pipe(Schema.pluck(col)),
26
+ select: { columns: [col] },
27
+ })
28
+ }
29
+
30
+ const columns = params as unknown as ReadonlyArray<string>
31
+
32
+ return makeQueryBuilder(tableDef, {
33
+ ...ast,
34
+ resultSchemaSingle:
35
+ columns.length === 0 ? ast.resultSchemaSingle : ast.resultSchemaSingle.pipe(Schema.pick(...columns)),
36
+ select: { columns },
37
+ }) as any
38
+ },
39
+ // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
40
+ where: function () {
41
+ if (ast._tag === 'InsertQuery') return invalidQueryBuilder('Cannot use where with insert')
42
+ if (ast._tag === 'RowQuery') return invalidQueryBuilder('Cannot use where with row')
43
+
44
+ if (arguments.length === 1) {
45
+ // eslint-disable-next-line prefer-rest-params
46
+ const params = arguments[0]
47
+ const newOps = Object.entries(params)
48
+ .filter(([, value]) => value !== undefined)
49
+ .map<QueryBuilderAst.Where>(([col, value]) =>
50
+ Predicate.hasProperty(value, 'op') && Predicate.hasProperty(value, 'value')
51
+ ? ({ col, op: value.op, value: value.value } as any)
52
+ : { col, op: '=', value },
53
+ )
54
+
55
+ switch (ast._tag) {
56
+ case 'CountQuery':
57
+ case 'SelectQuery':
58
+ case 'UpdateQuery':
59
+ case 'DeleteQuery': {
60
+ return makeQueryBuilder(tableDef, {
61
+ ...ast,
62
+ where: [...ast.where, ...newOps],
63
+ }) as any
64
+ }
65
+ default: {
66
+ return casesHandled(ast)
67
+ }
68
+ }
69
+ }
70
+
71
+ // eslint-disable-next-line prefer-rest-params
72
+ const [col, opOrValue, valueOrUndefined] = arguments
73
+ const op = valueOrUndefined === undefined ? '=' : opOrValue
74
+ const value = valueOrUndefined === undefined ? opOrValue : valueOrUndefined
75
+
76
+ switch (ast._tag) {
77
+ case 'CountQuery':
78
+ case 'SelectQuery':
79
+ case 'UpdateQuery':
80
+ case 'DeleteQuery': {
81
+ return makeQueryBuilder(tableDef, {
82
+ ...ast,
83
+ where: [...ast.where, { col, op, value }],
84
+ }) as any
85
+ }
86
+ default: {
87
+ return casesHandled(ast)
88
+ }
89
+ }
90
+ },
91
+ // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
92
+ orderBy() {
93
+ assertSelectQueryBuilderAst(ast)
94
+
95
+ if (arguments.length === 0 || arguments.length > 2) return invalidQueryBuilder()
96
+
97
+ if (arguments.length === 1) {
98
+ // eslint-disable-next-line prefer-rest-params
99
+ const params = arguments[0] as QueryBuilder.OrderByParams<TTableDef>
100
+ return makeQueryBuilder(tableDef, {
101
+ ...ast,
102
+ orderBy: [...ast.orderBy, ...params],
103
+ })
104
+ }
105
+
106
+ // eslint-disable-next-line prefer-rest-params
107
+ const [col, direction] = arguments as any as [keyof TTableDef['sqliteDef']['columns'] & string, 'asc' | 'desc']
108
+
109
+ return makeQueryBuilder(tableDef, {
110
+ ...ast,
111
+ orderBy: [...ast.orderBy, { col, direction }],
112
+ }) as any
113
+ },
114
+ limit: (limit) => {
115
+ assertSelectQueryBuilderAst(ast)
116
+
117
+ return makeQueryBuilder(tableDef, { ...ast, limit: Option.some(limit) })
118
+ },
119
+ offset: (offset) => {
120
+ assertSelectQueryBuilderAst(ast)
121
+
122
+ return makeQueryBuilder(tableDef, { ...ast, offset: Option.some(offset) })
123
+ },
124
+ count: () => {
125
+ if (isRowQuery(ast)) return invalidQueryBuilder()
126
+
127
+ return makeQueryBuilder(tableDef, {
128
+ _tag: 'CountQuery',
129
+ tableDef,
130
+ where: [],
131
+ resultSchema: Schema.Struct({ count: Schema.Number }).pipe(
132
+ Schema.pluck('count'),
133
+ Schema.Array,
134
+ Schema.headOrElse(),
135
+ ),
136
+ })
137
+ },
138
+ first: (options) => {
139
+ assertSelectQueryBuilderAst(ast)
140
+
141
+ if (ast.limit._tag === 'Some') return invalidQueryBuilder(`.first() can't be called after .limit()`)
142
+
143
+ return makeQueryBuilder(tableDef, {
144
+ ...ast,
145
+ limit: Option.some(1),
146
+ pickFirst:
147
+ options?.fallback !== undefined && options.fallback !== 'throws' ? { fallback: options.fallback } : 'throws',
148
+ })
149
+ },
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))
179
+
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
+ )
207
+
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
+ },
223
+
224
+ update: (values) => {
225
+ const filteredValues = Object.fromEntries(Object.entries(values).filter(([, value]) => value !== undefined))
226
+
227
+ return makeQueryBuilder(tableDef, {
228
+ _tag: 'UpdateQuery',
229
+ tableDef,
230
+ values: filteredValues,
231
+ where: [],
232
+ returning: undefined,
233
+ resultSchema: Schema.Void,
234
+ }) as any
235
+ },
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>
247
+
248
+ return {
249
+ [QueryBuilderTypeId]: QueryBuilderTypeId,
250
+ [QueryBuilderAstSymbol]: ast,
251
+ ['ResultType']: 'only-for-type-inference' as TResult,
252
+ asSql: () => astToSql(ast),
253
+ toString: () => {
254
+ try {
255
+ return astToSql(ast).query
256
+ } catch (cause) {
257
+ console.debug(`QueryBuilder.toString(): Error converting query builder to string`, cause, ast)
258
+ return `Error converting query builder to string`
259
+ }
260
+ },
261
+ ...api,
262
+ } satisfies QueryBuilder<TResult, TTableDef>
263
+ }
264
+
265
+ const emptyAst = (tableDef: 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)
283
+ }
284
+ }
285
+
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)
290
+ }
291
+ }
292
+
293
+ // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
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)
297
+ }
298
+ }
299
+
300
+ const isRowQuery = (ast: QueryBuilderAst): ast is QueryBuilderAst.RowQuery => ast._tag === 'RowQuery'
301
+
302
+ export const invalidQueryBuilder = (msg?: string) => {
303
+ return shouldNeverHappen('Invalid query builder' + (msg ? `: ${msg}` : ''))
304
+ }
305
+
306
+ export const getResultSchema = (qb: QueryBuilder<any, any, any>): Schema.Schema<any> => {
307
+ const queryAst = qb[QueryBuilderAstSymbol]
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 === 'throws') {
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())
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
+ }
334
+
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)
348
+ }
349
+ }
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
  */
@@ -1,7 +1,7 @@
1
- import { SqliteDsl } from '@livestore/db-schema'
2
1
  import { shouldNeverHappen } from '@livestore/utils'
3
2
  import { pipe, ReadonlyRecord, Schema } from '@livestore/utils/effect'
4
3
 
4
+ import { SqliteDsl } from './db-schema/mod.js'
5
5
  import type { TableDef, TableDefBase } from './table-def.js'
6
6
 
7
7
  export const getDefaultValuesEncoded = <TTableDef extends TableDef>(
@@ -0,0 +1,116 @@
1
+ import { Schema } from '@livestore/utils/effect'
2
+
3
+ import * as EventId from '../../EventId.js'
4
+ import { SqliteDsl } from './db-schema/mod.js'
5
+ import { table } from './table-def.js'
6
+
7
+ /// Read model DB
8
+
9
+ export const SCHEMA_META_TABLE = '__livestore_schema'
10
+
11
+ export const schemaMetaTable = table({
12
+ name: SCHEMA_META_TABLE,
13
+ columns: {
14
+ tableName: SqliteDsl.text({ primaryKey: true }),
15
+ schemaHash: SqliteDsl.integer({ nullable: false }),
16
+ /** ISO date format */
17
+ updatedAt: SqliteDsl.text({ nullable: false }),
18
+ },
19
+ })
20
+
21
+ export type SchemaMetaRow = typeof schemaMetaTable.Type
22
+
23
+ export const SCHEMA_EVENT_DEFS_META_TABLE = '__livestore_schema_event_defs'
24
+
25
+ export const schemaEventDefsMetaTable = table({
26
+ name: SCHEMA_EVENT_DEFS_META_TABLE,
27
+ columns: {
28
+ eventName: SqliteDsl.text({ primaryKey: true }),
29
+ schemaHash: SqliteDsl.integer({ nullable: false }),
30
+ /** ISO date format */
31
+ updatedAt: SqliteDsl.text({ nullable: false }),
32
+ },
33
+ })
34
+
35
+ export type SchemaEventDefsMetaRow = typeof schemaEventDefsMetaTable.Type
36
+
37
+ /**
38
+ * Table which stores SQLite changeset blobs which is used for rolling back
39
+ * read-model state during rebasing.
40
+ */
41
+ export const SESSION_CHANGESET_META_TABLE = '__livestore_session_changeset'
42
+
43
+ export const sessionChangesetMetaTable = table({
44
+ name: SESSION_CHANGESET_META_TABLE,
45
+ columns: {
46
+ // TODO bring back primary key
47
+ idGlobal: SqliteDsl.integer({ schema: EventId.GlobalEventId }),
48
+ idClient: SqliteDsl.integer({ schema: EventId.ClientEventId }),
49
+ changeset: SqliteDsl.blob({ nullable: true }),
50
+ debug: SqliteDsl.json({ nullable: true }),
51
+ },
52
+ indexes: [{ columns: ['idGlobal', 'idClient'], name: 'idx_session_changeset_id' }],
53
+ })
54
+
55
+ export type SessionChangesetMetaRow = typeof sessionChangesetMetaTable.Type
56
+
57
+ export const LEADER_MERGE_COUNTER_TABLE = '__livestore_leader_merge_counter'
58
+
59
+ export const leaderMergeCounterTable = table({
60
+ name: LEADER_MERGE_COUNTER_TABLE,
61
+ columns: {
62
+ id: SqliteDsl.integer({ primaryKey: true, schema: Schema.Literal(0) }),
63
+ mergeCounter: SqliteDsl.integer({ primaryKey: true }),
64
+ },
65
+ })
66
+
67
+ export type LeaderMergeCounterRow = typeof leaderMergeCounterTable.Type
68
+
69
+ export const stateSystemTables = [
70
+ schemaMetaTable,
71
+ schemaEventDefsMetaTable,
72
+ sessionChangesetMetaTable,
73
+ leaderMergeCounterTable,
74
+ ]
75
+
76
+ export const isStateSystemTable = (tableName: string) => stateSystemTables.some((_) => _.sqliteDef.name === tableName)
77
+
78
+ /// Eventlog DB
79
+
80
+ export const EVENTLOG_META_TABLE = 'eventlog'
81
+
82
+ export const eventlogMetaTable = table({
83
+ name: EVENTLOG_META_TABLE,
84
+ columns: {
85
+ // TODO Adjust modeling so a global event never needs a client id component
86
+ idGlobal: SqliteDsl.integer({ primaryKey: true, schema: EventId.GlobalEventId }),
87
+ idClient: SqliteDsl.integer({ primaryKey: true, schema: EventId.ClientEventId }),
88
+ parentIdGlobal: SqliteDsl.integer({ schema: EventId.GlobalEventId }),
89
+ parentIdClient: SqliteDsl.integer({ schema: EventId.ClientEventId }),
90
+ name: SqliteDsl.text({}),
91
+ argsJson: SqliteDsl.text({ schema: Schema.parseJson(Schema.Any) }),
92
+ clientId: SqliteDsl.text({}),
93
+ sessionId: SqliteDsl.text({}),
94
+ schemaHash: SqliteDsl.integer({}),
95
+ syncMetadataJson: SqliteDsl.text({ schema: Schema.parseJson(Schema.Option(Schema.JsonValue)) }),
96
+ },
97
+ indexes: [
98
+ { columns: ['idGlobal'], name: 'idx_eventlog_idGlobal' },
99
+ { columns: ['idGlobal', 'idClient'], name: 'idx_eventlog_id' },
100
+ ],
101
+ })
102
+
103
+ export type EventlogMetaRow = typeof eventlogMetaTable.Type
104
+
105
+ export const SYNC_STATUS_TABLE = '__livestore_sync_status'
106
+
107
+ export const syncStatusTable = table({
108
+ name: SYNC_STATUS_TABLE,
109
+ columns: {
110
+ head: SqliteDsl.integer({ primaryKey: true }),
111
+ },
112
+ })
113
+
114
+ export type SyncStatusRow = typeof syncStatusTable.Type
115
+
116
+ export const eventlogSystemTables = [eventlogMetaTable, syncStatusTable]
@@ -0,0 +1,197 @@
1
+ import { type Nullable } from '@livestore/utils'
2
+ import type { Schema, Types } from '@livestore/utils/effect'
3
+
4
+ import { SqliteDsl } from './db-schema/mod.js'
5
+ import type { QueryBuilder } from './query-builder/mod.js'
6
+ import { makeQueryBuilder, QueryBuilderAstSymbol, QueryBuilderTypeId } from './query-builder/mod.js'
7
+
8
+ export const { blob, boolean, column, datetime, integer, isColumnDefinition, json, real, text } = SqliteDsl
9
+
10
+ export type StateType = 'singleton' | 'dynamic'
11
+
12
+ export type DefaultSqliteTableDef = SqliteDsl.TableDefinition<string, SqliteDsl.Columns>
13
+ export type DefaultSqliteTableDefConstrained = SqliteDsl.TableDefinition<string, SqliteDsl.ConstraintColumns>
14
+
15
+ // TODO use to hide table def internals
16
+ export const TableDefInternalsSymbol = Symbol('TableDefInternals')
17
+ export type TableDefInternalsSymbol = typeof TableDefInternalsSymbol
18
+
19
+ export type TableDefBase<
20
+ TSqliteDef extends DefaultSqliteTableDef = DefaultSqliteTableDefConstrained,
21
+ TOptions extends TableOptions = TableOptions,
22
+ > = {
23
+ sqliteDef: TSqliteDef
24
+ options: TOptions
25
+ // Derived from `sqliteDef`, so only exposed for convenience
26
+ rowSchema: SqliteDsl.StructSchemaForColumns<TSqliteDef['columns']>
27
+ insertSchema: SqliteDsl.InsertStructSchemaForColumns<TSqliteDef['columns']>
28
+ }
29
+
30
+ export type TableDef<
31
+ TSqliteDef extends DefaultSqliteTableDef = DefaultSqliteTableDefConstrained,
32
+ TOptions extends TableOptions = TableOptions,
33
+ // NOTE we're not using `SqliteDsl.StructSchemaForColumns<TSqliteDef['columns']>`
34
+ // as we don't want the alias type for users to show up, so we're redefining it here
35
+ TSchema = Schema.Schema<
36
+ SqliteDsl.AnyIfConstained<
37
+ TSqliteDef['columns'],
38
+ { readonly [K in keyof TSqliteDef['columns']]: TSqliteDef['columns'][K]['schema']['Type'] }
39
+ >,
40
+ SqliteDsl.AnyIfConstained<
41
+ TSqliteDef['columns'],
42
+ { readonly [K in keyof TSqliteDef['columns']]: TSqliteDef['columns'][K]['schema']['Encoded'] }
43
+ >
44
+ >,
45
+ > = {
46
+ sqliteDef: TSqliteDef
47
+ options: TOptions
48
+ // Derived from `sqliteDef`, so only exposed for convenience
49
+ rowSchema: TSchema
50
+ insertSchema: SqliteDsl.InsertStructSchemaForColumns<TSqliteDef['columns']>
51
+ // query: QueryBuilder<ReadonlyArray<Schema.Schema.Type<TSchema>>, TableDefBase<TSqliteDef & {}, TOptions>>
52
+ readonly Type: Schema.Schema.Type<TSchema>
53
+ readonly Encoded: Schema.Schema.Encoded<TSchema>
54
+ } & QueryBuilder<ReadonlyArray<Schema.Schema.Type<TSchema>>, TableDefBase<TSqliteDef & {}, TOptions>>
55
+
56
+ export type TableOptionsInput = Partial<{
57
+ indexes: SqliteDsl.Index[]
58
+ }>
59
+
60
+ export namespace TableDef {
61
+ export type Any = TableDef<any, any>
62
+ }
63
+
64
+ export type TableOptions = {
65
+ /** Derived based on whether the table definition has one or more columns (besides the `id` column) */
66
+ readonly isClientDocumentTable: boolean
67
+ }
68
+
69
+ export const table = <
70
+ TName extends string,
71
+ TColumns extends SqliteDsl.Columns | SqliteDsl.ColumnDefinition<any, any>,
72
+ const TOptionsInput extends TableOptionsInput = TableOptionsInput,
73
+ >(
74
+ args: {
75
+ name: TName
76
+ columns: TColumns
77
+ } & Partial<TOptionsInput>,
78
+ ): TableDef<SqliteTableDefForInput<TName, TColumns>, WithDefaults<TColumns>> => {
79
+ const { name, columns: columnOrColumns, ...options } = args
80
+ const tablePath = name
81
+
82
+ const options_: TableOptions = {
83
+ isClientDocumentTable: false,
84
+ }
85
+
86
+ const columns = (
87
+ SqliteDsl.isColumnDefinition(columnOrColumns) ? { value: columnOrColumns } : columnOrColumns
88
+ ) as SqliteDsl.Columns
89
+
90
+ const sqliteDef = SqliteDsl.table(tablePath, columns, options?.indexes ?? [])
91
+
92
+ const rowSchema = SqliteDsl.structSchemaForTable(sqliteDef)
93
+ const insertSchema = SqliteDsl.insertStructSchemaForTable(sqliteDef)
94
+ const tableDef = {
95
+ sqliteDef,
96
+ options: options_,
97
+ rowSchema,
98
+ insertSchema,
99
+ } satisfies TableDefBase
100
+
101
+ const query = makeQueryBuilder(tableDef)
102
+ // tableDef.query = query
103
+
104
+ // NOTE we're currently patching the existing tableDef object
105
+ // as it's being used as part of the query builder API
106
+ for (const key of Object.keys(query)) {
107
+ // @ts-expect-error TODO properly implement this
108
+ tableDef[key] = query[key]
109
+ }
110
+
111
+ // @ts-expect-error TODO properly type this
112
+ tableDef[QueryBuilderAstSymbol] = query[QueryBuilderAstSymbol]
113
+ // @ts-expect-error TODO properly type this
114
+ tableDef[QueryBuilderTypeId] = query[QueryBuilderTypeId]
115
+
116
+ return tableDef as any
117
+ }
118
+
119
+ export namespace FromTable {
120
+ // TODO this sometimes doesn't preserve the order of columns
121
+ export type RowDecoded<TTableDef extends TableDefBase> = Types.Simplify<
122
+ Nullable<Pick<RowDecodedAll<TTableDef>, NullableColumnNames<TTableDef>>> &
123
+ Omit<RowDecodedAll<TTableDef>, NullableColumnNames<TTableDef>>
124
+ >
125
+
126
+ export type NullableColumnNames<TTableDef extends TableDefBase> = FromColumns.NullableColumnNames<
127
+ TTableDef['sqliteDef']['columns']
128
+ >
129
+
130
+ export type Columns<TTableDef extends TableDefBase> = {
131
+ [K in keyof TTableDef['sqliteDef']['columns']]: TTableDef['sqliteDef']['columns'][K]['columnType']
132
+ }
133
+
134
+ export type RowEncodeNonNullable<TTableDef extends TableDefBase> = {
135
+ [K in keyof TTableDef['sqliteDef']['columns']]: Schema.Schema.Encoded<
136
+ TTableDef['sqliteDef']['columns'][K]['schema']
137
+ >
138
+ }
139
+
140
+ export type RowEncoded<TTableDef extends TableDefBase> = Types.Simplify<
141
+ Nullable<Pick<RowEncodeNonNullable<TTableDef>, NullableColumnNames<TTableDef>>> &
142
+ Omit<RowEncodeNonNullable<TTableDef>, NullableColumnNames<TTableDef>>
143
+ >
144
+
145
+ export type RowDecodedAll<TTableDef extends TableDefBase> = {
146
+ [K in keyof TTableDef['sqliteDef']['columns']]: Schema.Schema.Type<TTableDef['sqliteDef']['columns'][K]['schema']>
147
+ }
148
+ }
149
+
150
+ export namespace FromColumns {
151
+ // TODO this sometimes doesn't preserve the order of columns
152
+ export type RowDecoded<TColumns extends SqliteDsl.Columns> = Types.Simplify<
153
+ Nullable<Pick<RowDecodedAll<TColumns>, NullableColumnNames<TColumns>>> &
154
+ Omit<RowDecodedAll<TColumns>, NullableColumnNames<TColumns>>
155
+ >
156
+
157
+ export type RowDecodedAll<TColumns extends SqliteDsl.Columns> = {
158
+ [K in keyof TColumns]: Schema.Schema.Type<TColumns[K]['schema']>
159
+ }
160
+
161
+ export type RowEncoded<TColumns extends SqliteDsl.Columns> = Types.Simplify<
162
+ Nullable<Pick<RowEncodeNonNullable<TColumns>, NullableColumnNames<TColumns>>> &
163
+ Omit<RowEncodeNonNullable<TColumns>, NullableColumnNames<TColumns>>
164
+ >
165
+
166
+ export type RowEncodeNonNullable<TColumns extends SqliteDsl.Columns> = {
167
+ [K in keyof TColumns]: Schema.Schema.Encoded<TColumns[K]['schema']>
168
+ }
169
+
170
+ export type NullableColumnNames<TColumns extends SqliteDsl.Columns> = keyof {
171
+ [K in keyof TColumns as TColumns[K]['default'] extends true ? K : never]: {}
172
+ }
173
+
174
+ export type RequiredInsertColumnNames<TColumns extends SqliteDsl.Columns> =
175
+ SqliteDsl.FromColumns.RequiredInsertColumnNames<TColumns>
176
+
177
+ export type InsertRowDecoded<TColumns extends SqliteDsl.Columns> = SqliteDsl.FromColumns.InsertRowDecoded<TColumns>
178
+ }
179
+
180
+ type SqliteTableDefForInput<
181
+ TName extends string,
182
+ TColumns extends SqliteDsl.Columns | SqliteDsl.ColumnDefinition<any, any>,
183
+ > = SqliteDsl.TableDefinition<TName, PrettifyFlat<ToColumns<TColumns>>>
184
+
185
+ type WithDefaults<TColumns extends SqliteDsl.Columns | SqliteDsl.ColumnDefinition<any, any>> = {
186
+ isClientDocumentTable: false
187
+ requiredInsertColumnNames: SqliteDsl.FromColumns.RequiredInsertColumnNames<ToColumns<TColumns>>
188
+ }
189
+
190
+ export type PrettifyFlat<T> = T extends infer U ? { [K in keyof U]: U[K] } : never
191
+
192
+ type ToColumns<TColumns extends SqliteDsl.Columns | SqliteDsl.ColumnDefinition<any, any>> =
193
+ TColumns extends SqliteDsl.Columns
194
+ ? TColumns
195
+ : TColumns extends SqliteDsl.ColumnDefinition<any, any>
196
+ ? { value: TColumns }
197
+ : never