@livestore/common 0.3.0-dev.8 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (480) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/__tests__/fixture.d.ts +83 -221
  3. package/dist/__tests__/fixture.d.ts.map +1 -1
  4. package/dist/__tests__/fixture.js +33 -11
  5. package/dist/__tests__/fixture.js.map +1 -1
  6. package/dist/adapter-types.d.ts +120 -64
  7. package/dist/adapter-types.d.ts.map +1 -1
  8. package/dist/adapter-types.js +39 -8
  9. package/dist/adapter-types.js.map +1 -1
  10. package/dist/bounded-collections.d.ts.map +1 -1
  11. package/dist/debug-info.d.ts +1 -1
  12. package/dist/debug-info.d.ts.map +1 -1
  13. package/dist/debug-info.js +1 -0
  14. package/dist/debug-info.js.map +1 -1
  15. package/dist/devtools/devtools-messages-client-session.d.ts +390 -0
  16. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -0
  17. package/dist/devtools/devtools-messages-client-session.js +97 -0
  18. package/dist/devtools/devtools-messages-client-session.js.map +1 -0
  19. package/dist/devtools/devtools-messages-common.d.ts +68 -0
  20. package/dist/devtools/devtools-messages-common.d.ts.map +1 -0
  21. package/dist/devtools/devtools-messages-common.js +60 -0
  22. package/dist/devtools/devtools-messages-common.js.map +1 -0
  23. package/dist/devtools/devtools-messages-leader.d.ts +394 -0
  24. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -0
  25. package/dist/devtools/devtools-messages-leader.js +147 -0
  26. package/dist/devtools/devtools-messages-leader.js.map +1 -0
  27. package/dist/devtools/devtools-messages.d.ts +3 -580
  28. package/dist/devtools/devtools-messages.d.ts.map +1 -1
  29. package/dist/devtools/devtools-messages.js +3 -174
  30. package/dist/devtools/devtools-messages.js.map +1 -1
  31. package/dist/devtools/devtools-sessioninfo.d.ts +32 -0
  32. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -0
  33. package/dist/devtools/devtools-sessioninfo.js +36 -0
  34. package/dist/devtools/devtools-sessioninfo.js.map +1 -0
  35. package/dist/devtools/mod.d.ts +55 -0
  36. package/dist/devtools/mod.d.ts.map +1 -0
  37. package/dist/devtools/mod.js +33 -0
  38. package/dist/devtools/mod.js.map +1 -0
  39. package/dist/index.d.ts +7 -9
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +7 -9
  42. package/dist/index.js.map +1 -1
  43. package/dist/leader-thread/LeaderSyncProcessor.d.ts +45 -30
  44. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  45. package/dist/leader-thread/LeaderSyncProcessor.js +484 -321
  46. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  47. package/dist/leader-thread/connection.d.ts +34 -6
  48. package/dist/leader-thread/connection.d.ts.map +1 -1
  49. package/dist/leader-thread/connection.js +22 -7
  50. package/dist/leader-thread/connection.js.map +1 -1
  51. package/dist/leader-thread/eventlog.d.ts +27 -0
  52. package/dist/leader-thread/eventlog.d.ts.map +1 -0
  53. package/dist/leader-thread/eventlog.js +119 -0
  54. package/dist/leader-thread/eventlog.js.map +1 -0
  55. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  56. package/dist/leader-thread/leader-worker-devtools.js +155 -80
  57. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  58. package/dist/leader-thread/make-leader-thread-layer.d.ts +22 -9
  59. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  60. package/dist/leader-thread/make-leader-thread-layer.js +67 -45
  61. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  62. package/dist/leader-thread/materialize-event.d.ts +16 -0
  63. package/dist/leader-thread/materialize-event.d.ts.map +1 -0
  64. package/dist/leader-thread/materialize-event.js +109 -0
  65. package/dist/leader-thread/materialize-event.js.map +1 -0
  66. package/dist/leader-thread/mod.d.ts +1 -1
  67. package/dist/leader-thread/mod.d.ts.map +1 -1
  68. package/dist/leader-thread/mod.js +1 -1
  69. package/dist/leader-thread/mod.js.map +1 -1
  70. package/dist/leader-thread/recreate-db.d.ts +4 -2
  71. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  72. package/dist/leader-thread/recreate-db.js +28 -32
  73. package/dist/leader-thread/recreate-db.js.map +1 -1
  74. package/dist/leader-thread/shutdown-channel.d.ts +2 -5
  75. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  76. package/dist/leader-thread/shutdown-channel.js +2 -4
  77. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  78. package/dist/leader-thread/types.d.ts +85 -38
  79. package/dist/leader-thread/types.d.ts.map +1 -1
  80. package/dist/leader-thread/types.js +1 -3
  81. package/dist/leader-thread/types.js.map +1 -1
  82. package/dist/make-client-session.d.ts +23 -0
  83. package/dist/make-client-session.d.ts.map +1 -0
  84. package/dist/make-client-session.js +57 -0
  85. package/dist/make-client-session.js.map +1 -0
  86. package/dist/materializer-helper.d.ts +23 -0
  87. package/dist/materializer-helper.d.ts.map +1 -0
  88. package/dist/materializer-helper.js +86 -0
  89. package/dist/materializer-helper.js.map +1 -0
  90. package/dist/otel.d.ts +2 -0
  91. package/dist/otel.d.ts.map +1 -1
  92. package/dist/otel.js +5 -0
  93. package/dist/otel.js.map +1 -1
  94. package/dist/rematerialize-from-eventlog.d.ts +14 -0
  95. package/dist/rematerialize-from-eventlog.d.ts.map +1 -0
  96. package/dist/rematerialize-from-eventlog.js +64 -0
  97. package/dist/rematerialize-from-eventlog.js.map +1 -0
  98. package/dist/schema/EventDef.d.ts +146 -0
  99. package/dist/schema/EventDef.d.ts.map +1 -0
  100. package/dist/schema/EventDef.js +58 -0
  101. package/dist/schema/EventDef.js.map +1 -0
  102. package/dist/schema/EventSequenceNumber.d.ts +57 -0
  103. package/dist/schema/EventSequenceNumber.d.ts.map +1 -0
  104. package/dist/schema/EventSequenceNumber.js +82 -0
  105. package/dist/schema/EventSequenceNumber.js.map +1 -0
  106. package/dist/schema/EventSequenceNumber.test.d.ts +2 -0
  107. package/dist/schema/EventSequenceNumber.test.d.ts.map +1 -0
  108. package/dist/schema/EventSequenceNumber.test.js +11 -0
  109. package/dist/schema/EventSequenceNumber.test.js.map +1 -0
  110. package/dist/schema/LiveStoreEvent.d.ts +257 -0
  111. package/dist/schema/LiveStoreEvent.d.ts.map +1 -0
  112. package/dist/schema/LiveStoreEvent.js +117 -0
  113. package/dist/schema/LiveStoreEvent.js.map +1 -0
  114. package/dist/schema/events.d.ts +2 -0
  115. package/dist/schema/events.d.ts.map +1 -0
  116. package/dist/schema/events.js +2 -0
  117. package/dist/schema/events.js.map +1 -0
  118. package/dist/schema/mod.d.ts +8 -6
  119. package/dist/schema/mod.d.ts.map +1 -1
  120. package/dist/schema/mod.js +8 -6
  121. package/dist/schema/mod.js.map +1 -1
  122. package/dist/schema/schema.d.ts +50 -32
  123. package/dist/schema/schema.d.ts.map +1 -1
  124. package/dist/schema/schema.js +36 -43
  125. package/dist/schema/schema.js.map +1 -1
  126. package/dist/schema/state/mod.d.ts +3 -0
  127. package/dist/schema/state/mod.d.ts.map +1 -0
  128. package/dist/schema/state/mod.js +3 -0
  129. package/dist/schema/state/mod.js.map +1 -0
  130. package/dist/schema/state/sqlite/client-document-def.d.ts +223 -0
  131. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -0
  132. package/dist/schema/state/sqlite/client-document-def.js +170 -0
  133. package/dist/schema/state/sqlite/client-document-def.js.map +1 -0
  134. package/dist/schema/state/sqlite/client-document-def.test.d.ts +2 -0
  135. package/dist/schema/state/sqlite/client-document-def.test.d.ts.map +1 -0
  136. package/dist/schema/state/sqlite/client-document-def.test.js +201 -0
  137. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -0
  138. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +69 -0
  139. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -0
  140. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +71 -0
  141. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -0
  142. package/dist/schema/state/sqlite/db-schema/ast/validate.d.ts +3 -0
  143. package/dist/schema/state/sqlite/db-schema/ast/validate.d.ts.map +1 -0
  144. package/dist/schema/state/sqlite/db-schema/ast/validate.js +12 -0
  145. package/dist/schema/state/sqlite/db-schema/ast/validate.js.map +1 -0
  146. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +90 -0
  147. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -0
  148. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +87 -0
  149. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -0
  150. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.d.ts +2 -0
  151. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.d.ts.map +1 -0
  152. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +29 -0
  153. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -0
  154. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +90 -0
  155. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -0
  156. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +41 -0
  157. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -0
  158. package/dist/schema/state/sqlite/db-schema/hash.d.ts +2 -0
  159. package/dist/schema/state/sqlite/db-schema/hash.d.ts.map +1 -0
  160. package/dist/schema/state/sqlite/db-schema/hash.js +14 -0
  161. package/dist/schema/state/sqlite/db-schema/hash.js.map +1 -0
  162. package/dist/schema/state/sqlite/db-schema/mod.d.ts +3 -0
  163. package/dist/schema/state/sqlite/db-schema/mod.d.ts.map +1 -0
  164. package/dist/schema/state/sqlite/db-schema/mod.js +3 -0
  165. package/dist/schema/state/sqlite/db-schema/mod.js.map +1 -0
  166. package/dist/schema/state/sqlite/mod.d.ts +17 -0
  167. package/dist/schema/state/sqlite/mod.d.ts.map +1 -0
  168. package/dist/schema/state/sqlite/mod.js +41 -0
  169. package/dist/schema/state/sqlite/mod.js.map +1 -0
  170. package/dist/schema/state/sqlite/query-builder/api.d.ts +294 -0
  171. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -0
  172. package/dist/schema/state/sqlite/query-builder/api.js +6 -0
  173. package/dist/schema/state/sqlite/query-builder/api.js.map +1 -0
  174. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts +7 -0
  175. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -0
  176. package/dist/schema/state/sqlite/query-builder/astToSql.js +190 -0
  177. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -0
  178. package/dist/schema/state/sqlite/query-builder/impl.d.ts +7 -0
  179. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -0
  180. package/dist/schema/state/sqlite/query-builder/impl.js +286 -0
  181. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -0
  182. package/dist/schema/state/sqlite/query-builder/impl.test.d.ts +87 -0
  183. package/dist/schema/state/sqlite/query-builder/impl.test.d.ts.map +1 -0
  184. package/dist/schema/state/sqlite/query-builder/impl.test.js +563 -0
  185. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -0
  186. package/dist/{query-builder → schema/state/sqlite/query-builder}/mod.d.ts +7 -0
  187. package/dist/schema/state/sqlite/query-builder/mod.d.ts.map +1 -0
  188. package/dist/{query-builder → schema/state/sqlite/query-builder}/mod.js +7 -0
  189. package/dist/schema/state/sqlite/query-builder/mod.js.map +1 -0
  190. package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -0
  191. package/dist/schema/{schema-helpers.js → state/sqlite/schema-helpers.js} +1 -1
  192. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -0
  193. package/dist/schema/state/sqlite/system-tables.d.ts +574 -0
  194. package/dist/schema/state/sqlite/system-tables.d.ts.map +1 -0
  195. package/dist/schema/state/sqlite/system-tables.js +88 -0
  196. package/dist/schema/state/sqlite/system-tables.js.map +1 -0
  197. package/dist/schema/state/sqlite/table-def.d.ts +84 -0
  198. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -0
  199. package/dist/schema/state/sqlite/table-def.js +36 -0
  200. package/dist/schema/state/sqlite/table-def.js.map +1 -0
  201. package/dist/schema-management/common.d.ts +7 -7
  202. package/dist/schema-management/common.d.ts.map +1 -1
  203. package/dist/schema-management/common.js.map +1 -1
  204. package/dist/schema-management/migrations.d.ts +6 -6
  205. package/dist/schema-management/migrations.d.ts.map +1 -1
  206. package/dist/schema-management/migrations.js +27 -18
  207. package/dist/schema-management/migrations.js.map +1 -1
  208. package/dist/schema-management/validate-schema.d.ts +8 -0
  209. package/dist/schema-management/validate-schema.d.ts.map +1 -0
  210. package/dist/schema-management/validate-schema.js +39 -0
  211. package/dist/schema-management/validate-schema.js.map +1 -0
  212. package/dist/sql-queries/misc.d.ts.map +1 -1
  213. package/dist/sql-queries/sql-queries.d.ts +1 -1
  214. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  215. package/dist/sql-queries/sql-queries.js.map +1 -1
  216. package/dist/sql-queries/sql-query-builder.d.ts +1 -1
  217. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  218. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  219. package/dist/sql-queries/types.d.ts +2 -1
  220. package/dist/sql-queries/types.d.ts.map +1 -1
  221. package/dist/sql-queries/types.js.map +1 -1
  222. package/dist/sync/ClientSessionSyncProcessor.d.ts +40 -19
  223. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  224. package/dist/sync/ClientSessionSyncProcessor.js +150 -72
  225. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  226. package/dist/sync/next/compact-events.d.ts.map +1 -1
  227. package/dist/sync/next/compact-events.js +38 -35
  228. package/dist/sync/next/compact-events.js.map +1 -1
  229. package/dist/sync/next/facts.d.ts +21 -21
  230. package/dist/sync/next/facts.d.ts.map +1 -1
  231. package/dist/sync/next/facts.js +11 -11
  232. package/dist/sync/next/facts.js.map +1 -1
  233. package/dist/sync/next/history-dag-common.d.ts +9 -7
  234. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  235. package/dist/sync/next/history-dag-common.js +10 -5
  236. package/dist/sync/next/history-dag-common.js.map +1 -1
  237. package/dist/sync/next/history-dag.d.ts +0 -2
  238. package/dist/sync/next/history-dag.d.ts.map +1 -1
  239. package/dist/sync/next/history-dag.js +16 -14
  240. package/dist/sync/next/history-dag.js.map +1 -1
  241. package/dist/sync/next/rebase-events.d.ts +10 -8
  242. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  243. package/dist/sync/next/rebase-events.js +18 -10
  244. package/dist/sync/next/rebase-events.js.map +1 -1
  245. package/dist/sync/next/test/compact-events.calculator.test.js +39 -34
  246. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  247. package/dist/sync/next/test/compact-events.test.js +77 -77
  248. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  249. package/dist/sync/next/test/{mutation-fixtures.d.ts → event-fixtures.d.ts} +35 -25
  250. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -0
  251. package/dist/sync/next/test/{mutation-fixtures.js → event-fixtures.js} +81 -38
  252. package/dist/sync/next/test/event-fixtures.js.map +1 -0
  253. package/dist/sync/next/test/mod.d.ts +1 -1
  254. package/dist/sync/next/test/mod.d.ts.map +1 -1
  255. package/dist/sync/next/test/mod.js +1 -1
  256. package/dist/sync/next/test/mod.js.map +1 -1
  257. package/dist/sync/sync.d.ts +46 -21
  258. package/dist/sync/sync.d.ts.map +1 -1
  259. package/dist/sync/sync.js +10 -6
  260. package/dist/sync/sync.js.map +1 -1
  261. package/dist/sync/syncstate.d.ts +213 -82
  262. package/dist/sync/syncstate.d.ts.map +1 -1
  263. package/dist/sync/syncstate.js +337 -139
  264. package/dist/sync/syncstate.js.map +1 -1
  265. package/dist/sync/syncstate.test.js +309 -286
  266. package/dist/sync/syncstate.test.js.map +1 -1
  267. package/dist/sync/validate-push-payload.d.ts +2 -2
  268. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  269. package/dist/sync/validate-push-payload.js +4 -4
  270. package/dist/sync/validate-push-payload.js.map +1 -1
  271. package/dist/util.d.ts +2 -2
  272. package/dist/util.d.ts.map +1 -1
  273. package/dist/version.d.ts +2 -2
  274. package/dist/version.d.ts.map +1 -1
  275. package/dist/version.js +2 -2
  276. package/dist/version.js.map +1 -1
  277. package/package.json +10 -4
  278. package/src/__tests__/fixture.ts +36 -15
  279. package/src/adapter-types.ts +107 -68
  280. package/src/debug-info.ts +1 -0
  281. package/src/devtools/devtools-messages-client-session.ts +142 -0
  282. package/src/devtools/devtools-messages-common.ts +115 -0
  283. package/src/devtools/devtools-messages-leader.ts +191 -0
  284. package/src/devtools/devtools-messages.ts +3 -246
  285. package/src/devtools/devtools-sessioninfo.ts +101 -0
  286. package/src/devtools/mod.ts +59 -0
  287. package/src/index.ts +7 -9
  288. package/src/leader-thread/LeaderSyncProcessor.ts +738 -477
  289. package/src/leader-thread/connection.ts +54 -9
  290. package/src/leader-thread/eventlog.ts +199 -0
  291. package/src/leader-thread/leader-worker-devtools.ts +227 -104
  292. package/src/leader-thread/make-leader-thread-layer.ts +121 -72
  293. package/src/leader-thread/materialize-event.ts +173 -0
  294. package/src/leader-thread/mod.ts +1 -1
  295. package/src/leader-thread/recreate-db.ts +33 -38
  296. package/src/leader-thread/shutdown-channel.ts +2 -4
  297. package/src/leader-thread/types.ts +94 -48
  298. package/src/make-client-session.ts +136 -0
  299. package/src/materializer-helper.ts +138 -0
  300. package/src/otel.ts +8 -0
  301. package/src/rematerialize-from-eventlog.ts +117 -0
  302. package/src/schema/EventDef.ts +227 -0
  303. package/src/schema/EventSequenceNumber.test.ts +12 -0
  304. package/src/schema/EventSequenceNumber.ts +121 -0
  305. package/src/schema/LiveStoreEvent.ts +240 -0
  306. package/src/schema/events.ts +1 -0
  307. package/src/schema/mod.ts +8 -6
  308. package/src/schema/schema.ts +88 -84
  309. package/src/schema/state/mod.ts +2 -0
  310. package/src/schema/state/sqlite/client-document-def.test.ts +238 -0
  311. package/src/schema/state/sqlite/client-document-def.ts +444 -0
  312. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +142 -0
  313. package/src/schema/state/sqlite/db-schema/ast/validate.ts +13 -0
  314. package/src/schema/state/sqlite/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +206 -0
  315. package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +35 -0
  316. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +242 -0
  317. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +222 -0
  318. package/src/schema/state/sqlite/db-schema/hash.ts +14 -0
  319. package/src/schema/state/sqlite/db-schema/mod.ts +2 -0
  320. package/src/schema/state/sqlite/mod.ts +73 -0
  321. package/src/schema/state/sqlite/query-builder/api.ts +440 -0
  322. package/src/schema/state/sqlite/query-builder/astToSql.ts +232 -0
  323. package/src/schema/state/sqlite/query-builder/impl.test.ts +617 -0
  324. package/src/schema/state/sqlite/query-builder/impl.ts +351 -0
  325. package/src/{query-builder → schema/state/sqlite/query-builder}/mod.ts +7 -0
  326. package/src/schema/{schema-helpers.ts → state/sqlite/schema-helpers.ts} +1 -1
  327. package/src/schema/state/sqlite/system-tables.ts +117 -0
  328. package/src/schema/state/sqlite/table-def.ts +197 -0
  329. package/src/schema-management/common.ts +7 -7
  330. package/src/schema-management/migrations.ts +37 -31
  331. package/src/schema-management/validate-schema.ts +61 -0
  332. package/src/sql-queries/sql-queries.ts +1 -1
  333. package/src/sql-queries/sql-query-builder.ts +1 -2
  334. package/src/sql-queries/types.ts +3 -1
  335. package/src/sync/ClientSessionSyncProcessor.ts +220 -94
  336. package/src/sync/next/compact-events.ts +38 -35
  337. package/src/sync/next/facts.ts +43 -41
  338. package/src/sync/next/history-dag-common.ts +17 -10
  339. package/src/sync/next/history-dag.ts +16 -17
  340. package/src/sync/next/rebase-events.ts +29 -17
  341. package/src/sync/next/test/compact-events.calculator.test.ts +46 -46
  342. package/src/sync/next/test/compact-events.test.ts +79 -79
  343. package/src/sync/next/test/event-fixtures.ts +226 -0
  344. package/src/sync/next/test/mod.ts +1 -1
  345. package/src/sync/sync.ts +46 -21
  346. package/src/sync/syncstate.test.ts +346 -320
  347. package/src/sync/syncstate.ts +422 -230
  348. package/src/sync/validate-push-payload.ts +6 -6
  349. package/src/version.ts +2 -2
  350. package/dist/derived-mutations.d.ts +0 -109
  351. package/dist/derived-mutations.d.ts.map +0 -1
  352. package/dist/derived-mutations.js +0 -54
  353. package/dist/derived-mutations.js.map +0 -1
  354. package/dist/derived-mutations.test.d.ts +0 -2
  355. package/dist/derived-mutations.test.d.ts.map +0 -1
  356. package/dist/derived-mutations.test.js +0 -93
  357. package/dist/derived-mutations.test.js.map +0 -1
  358. package/dist/devtools/devtools-bridge.d.ts +0 -13
  359. package/dist/devtools/devtools-bridge.d.ts.map +0 -1
  360. package/dist/devtools/devtools-bridge.js +0 -2
  361. package/dist/devtools/devtools-bridge.js.map +0 -1
  362. package/dist/devtools/devtools-window-message.d.ts +0 -29
  363. package/dist/devtools/devtools-window-message.d.ts.map +0 -1
  364. package/dist/devtools/devtools-window-message.js +0 -33
  365. package/dist/devtools/devtools-window-message.js.map +0 -1
  366. package/dist/devtools/index.d.ts +0 -42
  367. package/dist/devtools/index.d.ts.map +0 -1
  368. package/dist/devtools/index.js +0 -48
  369. package/dist/devtools/index.js.map +0 -1
  370. package/dist/init-singleton-tables.d.ts +0 -4
  371. package/dist/init-singleton-tables.d.ts.map +0 -1
  372. package/dist/init-singleton-tables.js +0 -16
  373. package/dist/init-singleton-tables.js.map +0 -1
  374. package/dist/leader-thread/apply-mutation.d.ts +0 -11
  375. package/dist/leader-thread/apply-mutation.d.ts.map +0 -1
  376. package/dist/leader-thread/apply-mutation.js +0 -107
  377. package/dist/leader-thread/apply-mutation.js.map +0 -1
  378. package/dist/leader-thread/leader-sync-processor.d.ts +0 -47
  379. package/dist/leader-thread/leader-sync-processor.d.ts.map +0 -1
  380. package/dist/leader-thread/leader-sync-processor.js +0 -430
  381. package/dist/leader-thread/leader-sync-processor.js.map +0 -1
  382. package/dist/leader-thread/mutationlog.d.ts +0 -10
  383. package/dist/leader-thread/mutationlog.d.ts.map +0 -1
  384. package/dist/leader-thread/mutationlog.js +0 -28
  385. package/dist/leader-thread/mutationlog.js.map +0 -1
  386. package/dist/leader-thread/pull-queue-set.d.ts +0 -7
  387. package/dist/leader-thread/pull-queue-set.d.ts.map +0 -1
  388. package/dist/leader-thread/pull-queue-set.js +0 -39
  389. package/dist/leader-thread/pull-queue-set.js.map +0 -1
  390. package/dist/mutation.d.ts +0 -20
  391. package/dist/mutation.d.ts.map +0 -1
  392. package/dist/mutation.js +0 -57
  393. package/dist/mutation.js.map +0 -1
  394. package/dist/query-builder/api.d.ts +0 -190
  395. package/dist/query-builder/api.d.ts.map +0 -1
  396. package/dist/query-builder/api.js +0 -8
  397. package/dist/query-builder/api.js.map +0 -1
  398. package/dist/query-builder/impl.d.ts +0 -12
  399. package/dist/query-builder/impl.d.ts.map +0 -1
  400. package/dist/query-builder/impl.js +0 -244
  401. package/dist/query-builder/impl.js.map +0 -1
  402. package/dist/query-builder/impl.test.d.ts +0 -2
  403. package/dist/query-builder/impl.test.d.ts.map +0 -1
  404. package/dist/query-builder/impl.test.js +0 -212
  405. package/dist/query-builder/impl.test.js.map +0 -1
  406. package/dist/query-builder/mod.d.ts.map +0 -1
  407. package/dist/query-builder/mod.js.map +0 -1
  408. package/dist/query-info.d.ts +0 -38
  409. package/dist/query-info.d.ts.map +0 -1
  410. package/dist/query-info.js +0 -7
  411. package/dist/query-info.js.map +0 -1
  412. package/dist/rehydrate-from-mutationlog.d.ts +0 -14
  413. package/dist/rehydrate-from-mutationlog.d.ts.map +0 -1
  414. package/dist/rehydrate-from-mutationlog.js +0 -66
  415. package/dist/rehydrate-from-mutationlog.js.map +0 -1
  416. package/dist/schema/EventId.d.ts +0 -39
  417. package/dist/schema/EventId.d.ts.map +0 -1
  418. package/dist/schema/EventId.js +0 -38
  419. package/dist/schema/EventId.js.map +0 -1
  420. package/dist/schema/EventId.test.d.ts +0 -2
  421. package/dist/schema/EventId.test.d.ts.map +0 -1
  422. package/dist/schema/EventId.test.js +0 -11
  423. package/dist/schema/EventId.test.js.map +0 -1
  424. package/dist/schema/MutationEvent.d.ts +0 -166
  425. package/dist/schema/MutationEvent.d.ts.map +0 -1
  426. package/dist/schema/MutationEvent.js +0 -72
  427. package/dist/schema/MutationEvent.js.map +0 -1
  428. package/dist/schema/MutationEvent.test.d.ts +0 -2
  429. package/dist/schema/MutationEvent.test.d.ts.map +0 -1
  430. package/dist/schema/MutationEvent.test.js +0 -2
  431. package/dist/schema/MutationEvent.test.js.map +0 -1
  432. package/dist/schema/mutations.d.ts +0 -107
  433. package/dist/schema/mutations.d.ts.map +0 -1
  434. package/dist/schema/mutations.js +0 -42
  435. package/dist/schema/mutations.js.map +0 -1
  436. package/dist/schema/schema-helpers.d.ts.map +0 -1
  437. package/dist/schema/schema-helpers.js.map +0 -1
  438. package/dist/schema/system-tables.d.ts +0 -399
  439. package/dist/schema/system-tables.d.ts.map +0 -1
  440. package/dist/schema/system-tables.js +0 -59
  441. package/dist/schema/system-tables.js.map +0 -1
  442. package/dist/schema/table-def.d.ts +0 -156
  443. package/dist/schema/table-def.d.ts.map +0 -1
  444. package/dist/schema/table-def.js +0 -79
  445. package/dist/schema/table-def.js.map +0 -1
  446. package/dist/schema-management/validate-mutation-defs.d.ts +0 -8
  447. package/dist/schema-management/validate-mutation-defs.d.ts.map +0 -1
  448. package/dist/schema-management/validate-mutation-defs.js +0 -39
  449. package/dist/schema-management/validate-mutation-defs.js.map +0 -1
  450. package/dist/sync/client-session-sync-processor.d.ts +0 -45
  451. package/dist/sync/client-session-sync-processor.d.ts.map +0 -1
  452. package/dist/sync/client-session-sync-processor.js +0 -131
  453. package/dist/sync/client-session-sync-processor.js.map +0 -1
  454. package/dist/sync/next/test/mutation-fixtures.d.ts.map +0 -1
  455. package/dist/sync/next/test/mutation-fixtures.js.map +0 -1
  456. package/src/derived-mutations.test.ts +0 -101
  457. package/src/derived-mutations.ts +0 -170
  458. package/src/devtools/devtools-bridge.ts +0 -14
  459. package/src/devtools/devtools-window-message.ts +0 -27
  460. package/src/devtools/index.ts +0 -48
  461. package/src/init-singleton-tables.ts +0 -24
  462. package/src/leader-thread/apply-mutation.ts +0 -161
  463. package/src/leader-thread/mutationlog.ts +0 -46
  464. package/src/leader-thread/pull-queue-set.ts +0 -58
  465. package/src/mutation.ts +0 -91
  466. package/src/query-builder/api.ts +0 -289
  467. package/src/query-builder/impl.test.ts +0 -239
  468. package/src/query-builder/impl.ts +0 -285
  469. package/src/query-info.ts +0 -78
  470. package/src/rehydrate-from-mutationlog.ts +0 -119
  471. package/src/schema/EventId.test.ts +0 -12
  472. package/src/schema/EventId.ts +0 -60
  473. package/src/schema/MutationEvent.ts +0 -181
  474. package/src/schema/mutations.ts +0 -192
  475. package/src/schema/system-tables.ts +0 -105
  476. package/src/schema/table-def.ts +0 -343
  477. package/src/schema-management/validate-mutation-defs.ts +0 -63
  478. package/src/sync/next/test/mutation-fixtures.ts +0 -224
  479. package/tsconfig.json +0 -11
  480. /package/dist/schema/{schema-helpers.d.ts → state/sqlite/schema-helpers.d.ts} +0 -0
@@ -0,0 +1,351 @@
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) || ast._tag === 'InsertQuery' || ast._tag === 'UpdateQuery' || ast._tag === 'DeleteQuery')
126
+ return invalidQueryBuilder()
127
+
128
+ return makeQueryBuilder(tableDef, {
129
+ _tag: 'CountQuery',
130
+ tableDef,
131
+ where: ast.where,
132
+ resultSchema: Schema.Struct({ count: Schema.Number }).pipe(
133
+ Schema.pluck('count'),
134
+ Schema.Array,
135
+ Schema.headOrElse(),
136
+ ),
137
+ })
138
+ },
139
+ first: (options) => {
140
+ assertSelectQueryBuilderAst(ast)
141
+
142
+ if (ast.limit._tag === 'Some') return invalidQueryBuilder(`.first() can't be called after .limit()`)
143
+
144
+ return makeQueryBuilder(tableDef, {
145
+ ...ast,
146
+ limit: Option.some(1),
147
+ pickFirst:
148
+ options?.fallback !== undefined && options.fallback !== 'throws' ? { fallback: options.fallback } : 'throws',
149
+ })
150
+ },
151
+ // // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
152
+ // getOrCreate() {
153
+ // if (tableDef.options.isClientDocumentTable === false) {
154
+ // return invalidQueryBuilder(`getOrCreate() is not allowed when table is not a client document table`)
155
+ // }
156
+
157
+ // // eslint-disable-next-line prefer-rest-params
158
+ // const params = [...arguments]
159
+
160
+ // let id: string | number
161
+
162
+ // // TODO refactor to handle default id
163
+ // id = params[0] as string | number
164
+ // if (id === undefined) {
165
+ // invalidQueryBuilder(`Id missing for row query on non-singleton table ${tableDef.sqliteDef.name}`)
166
+ // }
167
+
168
+ // // TODO validate all required columns are present and values are matching the schema
169
+ // const insertValues: Record<string, unknown> = params[1]?.insertValues ?? {}
170
+
171
+ // return makeQueryBuilder(tableDef, {
172
+ // _tag: 'RowQuery',
173
+ // id,
174
+ // tableDef,
175
+ // insertValues,
176
+ // }) as any
177
+ // },
178
+ insert: (values) => {
179
+ const filteredValues = Object.fromEntries(Object.entries(values).filter(([, value]) => value !== undefined))
180
+
181
+ return makeQueryBuilder(tableDef, {
182
+ _tag: 'InsertQuery',
183
+ tableDef,
184
+ values: filteredValues,
185
+ onConflict: undefined,
186
+ returning: undefined,
187
+ resultSchema: Schema.Void,
188
+ }) as any
189
+ },
190
+ onConflict: (
191
+ targetOrTargets: string | string[],
192
+ action: 'ignore' | 'replace' | 'update',
193
+ updateValues?: Record<string, unknown>,
194
+ ) => {
195
+ const targets = Array.isArray(targetOrTargets) ? targetOrTargets : [targetOrTargets]
196
+
197
+ assertInsertQueryBuilderAst(ast)
198
+
199
+ const onConflict = Match.value(action).pipe(
200
+ Match.when('ignore', () => ({ targets, action: { _tag: 'ignore' } }) satisfies QueryBuilderAst.OnConflict),
201
+ Match.when('replace', () => ({ targets, action: { _tag: 'replace' } }) satisfies QueryBuilderAst.OnConflict),
202
+ Match.when(
203
+ 'update',
204
+ () => ({ targets, action: { _tag: 'update', update: updateValues! } }) satisfies QueryBuilderAst.OnConflict,
205
+ ),
206
+ Match.exhaustive,
207
+ )
208
+
209
+ return makeQueryBuilder(tableDef, {
210
+ ...ast,
211
+ onConflict,
212
+ }) as any
213
+ },
214
+
215
+ returning: (...columns) => {
216
+ assertWriteQueryBuilderAst(ast)
217
+
218
+ return makeQueryBuilder(tableDef, {
219
+ ...ast,
220
+ returning: columns,
221
+ resultSchema: tableDef.rowSchema.pipe(Schema.pick(...columns), Schema.Array),
222
+ }) as any
223
+ },
224
+
225
+ update: (values) => {
226
+ const filteredValues = Object.fromEntries(Object.entries(values).filter(([, value]) => value !== undefined))
227
+
228
+ return makeQueryBuilder(tableDef, {
229
+ _tag: 'UpdateQuery',
230
+ tableDef,
231
+ values: filteredValues,
232
+ where: [],
233
+ returning: undefined,
234
+ resultSchema: Schema.Void,
235
+ }) as any
236
+ },
237
+
238
+ delete: () => {
239
+ return makeQueryBuilder(tableDef, {
240
+ _tag: 'DeleteQuery',
241
+ tableDef,
242
+ where: [],
243
+ returning: undefined,
244
+ resultSchema: Schema.Void,
245
+ }) as any
246
+ },
247
+ } satisfies QueryBuilder.ApiFull<TResult, TTableDef, never>
248
+
249
+ return {
250
+ [QueryBuilderTypeId]: QueryBuilderTypeId,
251
+ [QueryBuilderAstSymbol]: ast,
252
+ ['ResultType']: 'only-for-type-inference' as TResult,
253
+ asSql: () => astToSql(ast),
254
+ toString: () => {
255
+ try {
256
+ return astToSql(ast).query
257
+ } catch (cause) {
258
+ console.debug(`QueryBuilder.toString(): Error converting query builder to string`, cause, ast)
259
+ return `Error converting query builder to string`
260
+ }
261
+ },
262
+ ...api,
263
+ } satisfies QueryBuilder<TResult, TTableDef>
264
+ }
265
+
266
+ const emptyAst = (tableDef: TableDefBase): QueryBuilderAst.SelectQuery => ({
267
+ _tag: 'SelectQuery',
268
+ columns: [],
269
+ pickFirst: false,
270
+ select: { columns: [] },
271
+ orderBy: [],
272
+ offset: Option.none(),
273
+ limit: Option.none(),
274
+ tableDef,
275
+ where: [],
276
+ resultSchemaSingle: tableDef.rowSchema,
277
+ })
278
+
279
+ // Helper functions
280
+ // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
281
+ function assertSelectQueryBuilderAst(ast: QueryBuilderAst): asserts ast is QueryBuilderAst.SelectQuery {
282
+ if (ast._tag !== 'SelectQuery') {
283
+ return shouldNeverHappen('Expected SelectQuery but got ' + ast._tag)
284
+ }
285
+ }
286
+
287
+ // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
288
+ function assertInsertQueryBuilderAst(ast: QueryBuilderAst): asserts ast is QueryBuilderAst.InsertQuery {
289
+ if (ast._tag !== 'InsertQuery') {
290
+ return shouldNeverHappen('Expected InsertQuery but got ' + ast._tag)
291
+ }
292
+ }
293
+
294
+ // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
295
+ function assertWriteQueryBuilderAst(ast: QueryBuilderAst): asserts ast is QueryBuilderAst.WriteQuery {
296
+ if (ast._tag !== 'InsertQuery' && ast._tag !== 'UpdateQuery' && ast._tag !== 'DeleteQuery') {
297
+ return shouldNeverHappen('Expected WriteQuery but got ' + ast._tag)
298
+ }
299
+ }
300
+
301
+ const isRowQuery = (ast: QueryBuilderAst): ast is QueryBuilderAst.RowQuery => ast._tag === 'RowQuery'
302
+
303
+ export const invalidQueryBuilder = (msg?: string) => {
304
+ return shouldNeverHappen('Invalid query builder' + (msg ? `: ${msg}` : ''))
305
+ }
306
+
307
+ export const getResultSchema = (qb: QueryBuilder<any, any, any>): Schema.Schema<any> => {
308
+ const queryAst = qb[QueryBuilderAstSymbol]
309
+ switch (queryAst._tag) {
310
+ case 'SelectQuery': {
311
+ const arraySchema = Schema.Array(queryAst.resultSchemaSingle)
312
+ if (queryAst.pickFirst === false) {
313
+ return arraySchema
314
+ } else if (queryAst.pickFirst === 'throws') {
315
+ // Will throw if the array is empty
316
+ return arraySchema.pipe(Schema.headOrElse())
317
+ } else {
318
+ const fallbackValue = queryAst.pickFirst.fallback()
319
+ return Schema.Union(arraySchema, Schema.Tuple(Schema.Literal(fallbackValue))).pipe(
320
+ Schema.headOrElse(() => fallbackValue),
321
+ )
322
+ }
323
+ }
324
+ case 'CountQuery': {
325
+ return Schema.Struct({ count: Schema.Number }).pipe(Schema.pluck('count'), Schema.Array, Schema.headOrElse())
326
+ }
327
+ case 'InsertQuery':
328
+ case 'UpdateQuery':
329
+ case 'DeleteQuery': {
330
+ // For write operations with RETURNING clause, we need to return the appropriate schema
331
+ if (queryAst.returning && queryAst.returning.length > 0) {
332
+ // Create a schema for the returned columns
333
+ return queryAst.tableDef.rowSchema.pipe(Schema.pick(...queryAst.returning), Schema.Array)
334
+ }
335
+
336
+ // For write operations without RETURNING, the result is the number of affected rows
337
+ return Schema.Number
338
+ }
339
+ case 'RowQuery': {
340
+ return queryAst.tableDef.rowSchema.pipe(
341
+ Schema.pluck('value'),
342
+ Schema.annotations({ title: `${queryAst.tableDef.sqliteDef.name}.value` }),
343
+ Schema.Array,
344
+ Schema.headOrElse(),
345
+ )
346
+ }
347
+ default: {
348
+ casesHandled(queryAst)
349
+ }
350
+ }
351
+ }
@@ -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,117 @@
1
+ import { Schema } from '@livestore/utils/effect'
2
+
3
+ import * as EventSequenceNumber from '../../EventSequenceNumber.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
+ seqNumGlobal: SqliteDsl.integer({ schema: EventSequenceNumber.GlobalEventSequenceNumber }),
48
+ seqNumClient: SqliteDsl.integer({ schema: EventSequenceNumber.ClientEventSequenceNumber }),
49
+ changeset: SqliteDsl.blob({ nullable: true }),
50
+ debug: SqliteDsl.json({ nullable: true }),
51
+ },
52
+ indexes: [{ columns: ['seqNumGlobal', 'seqNumClient'], 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
+ // TODO get rid of this table in favour of client-only merge generation
60
+ export const leaderMergeCounterTable = table({
61
+ name: LEADER_MERGE_COUNTER_TABLE,
62
+ columns: {
63
+ id: SqliteDsl.integer({ primaryKey: true, schema: Schema.Literal(0) }),
64
+ mergeCounter: SqliteDsl.integer({ primaryKey: true }),
65
+ },
66
+ })
67
+
68
+ export type LeaderMergeCounterRow = typeof leaderMergeCounterTable.Type
69
+
70
+ export const stateSystemTables = [
71
+ schemaMetaTable,
72
+ schemaEventDefsMetaTable,
73
+ sessionChangesetMetaTable,
74
+ leaderMergeCounterTable,
75
+ ]
76
+
77
+ export const isStateSystemTable = (tableName: string) => stateSystemTables.some((_) => _.sqliteDef.name === tableName)
78
+
79
+ /// Eventlog DB
80
+
81
+ export const EVENTLOG_META_TABLE = 'eventlog'
82
+
83
+ export const eventlogMetaTable = table({
84
+ name: EVENTLOG_META_TABLE,
85
+ columns: {
86
+ // TODO Adjust modeling so a global event never needs a client id component
87
+ seqNumGlobal: SqliteDsl.integer({ primaryKey: true, schema: EventSequenceNumber.GlobalEventSequenceNumber }),
88
+ seqNumClient: SqliteDsl.integer({ primaryKey: true, schema: EventSequenceNumber.ClientEventSequenceNumber }),
89
+ parentSeqNumGlobal: SqliteDsl.integer({ schema: EventSequenceNumber.GlobalEventSequenceNumber }),
90
+ parentSeqNumClient: SqliteDsl.integer({ schema: EventSequenceNumber.ClientEventSequenceNumber }),
91
+ name: SqliteDsl.text({}),
92
+ argsJson: SqliteDsl.text({ schema: Schema.parseJson(Schema.Any) }),
93
+ clientId: SqliteDsl.text({}),
94
+ sessionId: SqliteDsl.text({}),
95
+ schemaHash: SqliteDsl.integer({}),
96
+ syncMetadataJson: SqliteDsl.text({ schema: Schema.parseJson(Schema.Option(Schema.JsonValue)) }),
97
+ },
98
+ indexes: [
99
+ { columns: ['seqNumGlobal'], name: 'idx_eventlog_seqNumGlobal' },
100
+ { columns: ['seqNumGlobal', 'seqNumClient'], name: 'idx_eventlog_seqNum' },
101
+ ],
102
+ })
103
+
104
+ export type EventlogMetaRow = typeof eventlogMetaTable.Type
105
+
106
+ export const SYNC_STATUS_TABLE = '__livestore_sync_status'
107
+
108
+ export const syncStatusTable = table({
109
+ name: SYNC_STATUS_TABLE,
110
+ columns: {
111
+ head: SqliteDsl.integer({ primaryKey: true }),
112
+ },
113
+ })
114
+
115
+ export type SyncStatusRow = typeof syncStatusTable.Type
116
+
117
+ 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