@livestore/common 0.4.0-dev.2 → 0.4.0-dev.21

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 (465) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ClientSessionLeaderThreadProxy.d.ts +20 -12
  3. package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
  4. package/dist/ClientSessionLeaderThreadProxy.js.map +1 -1
  5. package/dist/adapter-types.d.ts +14 -6
  6. package/dist/adapter-types.d.ts.map +1 -1
  7. package/dist/adapter-types.js.map +1 -1
  8. package/dist/debug-info.d.ts.map +1 -1
  9. package/dist/debug-info.js +33 -6
  10. package/dist/debug-info.js.map +1 -1
  11. package/dist/devtools/devtools-messages-client-session.d.ts +28 -23
  12. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
  13. package/dist/devtools/devtools-messages-client-session.js +2 -2
  14. package/dist/devtools/devtools-messages-client-session.js.map +1 -1
  15. package/dist/devtools/devtools-messages-common.d.ts +7 -14
  16. package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
  17. package/dist/devtools/devtools-messages-common.js +1 -6
  18. package/dist/devtools/devtools-messages-common.js.map +1 -1
  19. package/dist/devtools/devtools-messages-leader.d.ts +38 -29
  20. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
  21. package/dist/devtools/devtools-messages-leader.js +9 -8
  22. package/dist/devtools/devtools-messages-leader.js.map +1 -1
  23. package/dist/devtools/devtools-sessioninfo.d.ts +14 -2
  24. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
  25. package/dist/devtools/devtools-sessioninfo.js +7 -4
  26. package/dist/devtools/devtools-sessioninfo.js.map +1 -1
  27. package/dist/devtools/mod.d.ts +13 -2
  28. package/dist/devtools/mod.d.ts.map +1 -1
  29. package/dist/devtools/mod.js +10 -3
  30. package/dist/devtools/mod.js.map +1 -1
  31. package/dist/errors.d.ts +52 -10
  32. package/dist/errors.d.ts.map +1 -1
  33. package/dist/errors.js +25 -6
  34. package/dist/errors.js.map +1 -1
  35. package/dist/index.d.ts +2 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +2 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/leader-thread/LeaderSyncProcessor.d.ts +41 -4
  40. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  41. package/dist/leader-thread/LeaderSyncProcessor.js +158 -75
  42. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  43. package/dist/leader-thread/eventlog.d.ts +21 -22
  44. package/dist/leader-thread/eventlog.d.ts.map +1 -1
  45. package/dist/leader-thread/eventlog.js +77 -20
  46. package/dist/leader-thread/eventlog.js.map +1 -1
  47. package/dist/leader-thread/leader-worker-devtools.d.ts +2 -2
  48. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  49. package/dist/leader-thread/leader-worker-devtools.js +56 -45
  50. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  51. package/dist/leader-thread/make-leader-thread-layer.d.ts +6 -6
  52. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  53. package/dist/leader-thread/make-leader-thread-layer.js +79 -27
  54. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  55. package/dist/leader-thread/make-leader-thread-layer.test.d.ts +2 -0
  56. package/dist/leader-thread/make-leader-thread-layer.test.d.ts.map +1 -0
  57. package/dist/leader-thread/make-leader-thread-layer.test.js +32 -0
  58. package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -0
  59. package/dist/leader-thread/materialize-event.d.ts +3 -3
  60. package/dist/leader-thread/materialize-event.d.ts.map +1 -1
  61. package/dist/leader-thread/materialize-event.js +25 -11
  62. package/dist/leader-thread/materialize-event.js.map +1 -1
  63. package/dist/leader-thread/mod.d.ts +1 -0
  64. package/dist/leader-thread/mod.d.ts.map +1 -1
  65. package/dist/leader-thread/mod.js +1 -0
  66. package/dist/leader-thread/mod.js.map +1 -1
  67. package/dist/leader-thread/recreate-db.d.ts +2 -3
  68. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  69. package/dist/leader-thread/recreate-db.js +5 -5
  70. package/dist/leader-thread/recreate-db.js.map +1 -1
  71. package/dist/leader-thread/shutdown-channel.d.ts +2 -2
  72. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  73. package/dist/leader-thread/shutdown-channel.js +2 -2
  74. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  75. package/dist/leader-thread/stream-events.d.ts +56 -0
  76. package/dist/leader-thread/stream-events.d.ts.map +1 -0
  77. package/dist/leader-thread/stream-events.js +166 -0
  78. package/dist/leader-thread/stream-events.js.map +1 -0
  79. package/dist/leader-thread/types.d.ts +98 -20
  80. package/dist/leader-thread/types.d.ts.map +1 -1
  81. package/dist/leader-thread/types.js +13 -0
  82. package/dist/leader-thread/types.js.map +1 -1
  83. package/dist/logging.d.ts +40 -0
  84. package/dist/logging.d.ts.map +1 -0
  85. package/dist/logging.js +33 -0
  86. package/dist/logging.js.map +1 -0
  87. package/dist/make-client-session.d.ts +5 -3
  88. package/dist/make-client-session.d.ts.map +1 -1
  89. package/dist/make-client-session.js +5 -2
  90. package/dist/make-client-session.js.map +1 -1
  91. package/dist/materializer-helper.d.ts +6 -6
  92. package/dist/materializer-helper.d.ts.map +1 -1
  93. package/dist/materializer-helper.js +20 -4
  94. package/dist/materializer-helper.js.map +1 -1
  95. package/dist/otel.d.ts +2 -1
  96. package/dist/otel.d.ts.map +1 -1
  97. package/dist/otel.js +5 -0
  98. package/dist/otel.js.map +1 -1
  99. package/dist/rematerialize-from-eventlog.d.ts +2 -2
  100. package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
  101. package/dist/rematerialize-from-eventlog.js +29 -20
  102. package/dist/rematerialize-from-eventlog.js.map +1 -1
  103. package/dist/schema/EventDef/define.d.ts +147 -0
  104. package/dist/schema/EventDef/define.d.ts.map +1 -0
  105. package/dist/schema/EventDef/define.js +139 -0
  106. package/dist/schema/EventDef/define.js.map +1 -0
  107. package/dist/schema/EventDef/event-def.d.ts +106 -0
  108. package/dist/schema/EventDef/event-def.d.ts.map +1 -0
  109. package/dist/schema/EventDef/event-def.js +2 -0
  110. package/dist/schema/EventDef/event-def.js.map +1 -0
  111. package/dist/schema/EventDef/facts.d.ts +118 -0
  112. package/dist/schema/EventDef/facts.d.ts.map +1 -0
  113. package/dist/schema/EventDef/facts.js +53 -0
  114. package/dist/schema/EventDef/facts.js.map +1 -0
  115. package/dist/schema/EventDef/materializer.d.ts +155 -0
  116. package/dist/schema/EventDef/materializer.d.ts.map +1 -0
  117. package/dist/schema/EventDef/materializer.js +83 -0
  118. package/dist/schema/EventDef/materializer.js.map +1 -0
  119. package/dist/schema/EventDef/mod.d.ts +5 -0
  120. package/dist/schema/EventDef/mod.d.ts.map +1 -0
  121. package/dist/schema/EventDef/mod.js +5 -0
  122. package/dist/schema/EventDef/mod.js.map +1 -0
  123. package/dist/schema/EventSequenceNumber/client.d.ts +136 -0
  124. package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -0
  125. package/dist/schema/EventSequenceNumber/client.js +193 -0
  126. package/dist/schema/EventSequenceNumber/client.js.map +1 -0
  127. package/dist/schema/EventSequenceNumber/global.d.ts +15 -0
  128. package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -0
  129. package/dist/schema/EventSequenceNumber/global.js +14 -0
  130. package/dist/schema/EventSequenceNumber/global.js.map +1 -0
  131. package/dist/schema/EventSequenceNumber/mod.d.ts +37 -0
  132. package/dist/schema/EventSequenceNumber/mod.d.ts.map +1 -0
  133. package/dist/schema/EventSequenceNumber/mod.js +37 -0
  134. package/dist/schema/EventSequenceNumber/mod.js.map +1 -0
  135. package/dist/schema/EventSequenceNumber.test.js +43 -43
  136. package/dist/schema/EventSequenceNumber.test.js.map +1 -1
  137. package/dist/schema/{LiveStoreEvent.d.ts → LiveStoreEvent/client.d.ts} +89 -106
  138. package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -0
  139. package/dist/schema/{LiveStoreEvent.js → LiveStoreEvent/client.js} +74 -58
  140. package/dist/schema/LiveStoreEvent/client.js.map +1 -0
  141. package/dist/schema/LiveStoreEvent/for-event-def.d.ts +52 -0
  142. package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -0
  143. package/dist/schema/LiveStoreEvent/for-event-def.js +2 -0
  144. package/dist/schema/LiveStoreEvent/for-event-def.js.map +1 -0
  145. package/dist/schema/LiveStoreEvent/global.d.ts +36 -0
  146. package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -0
  147. package/dist/schema/LiveStoreEvent/global.js +31 -0
  148. package/dist/schema/LiveStoreEvent/global.js.map +1 -0
  149. package/dist/schema/LiveStoreEvent/input.d.ts +46 -0
  150. package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -0
  151. package/dist/schema/LiveStoreEvent/input.js +26 -0
  152. package/dist/schema/LiveStoreEvent/input.js.map +1 -0
  153. package/dist/schema/LiveStoreEvent/mod.d.ts +5 -0
  154. package/dist/schema/LiveStoreEvent/mod.d.ts.map +1 -0
  155. package/dist/schema/LiveStoreEvent/mod.js +5 -0
  156. package/dist/schema/LiveStoreEvent/mod.js.map +1 -0
  157. package/dist/schema/events.d.ts +1 -1
  158. package/dist/schema/events.d.ts.map +1 -1
  159. package/dist/schema/events.js +1 -1
  160. package/dist/schema/events.js.map +1 -1
  161. package/dist/schema/mod.d.ts +6 -4
  162. package/dist/schema/mod.d.ts.map +1 -1
  163. package/dist/schema/mod.js +5 -4
  164. package/dist/schema/mod.js.map +1 -1
  165. package/dist/schema/schema.d.ts +16 -1
  166. package/dist/schema/schema.d.ts.map +1 -1
  167. package/dist/schema/schema.js +27 -2
  168. package/dist/schema/schema.js.map +1 -1
  169. package/dist/schema/state/sqlite/client-document-def.d.ts +36 -6
  170. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  171. package/dist/schema/state/sqlite/client-document-def.js +97 -6
  172. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  173. package/dist/schema/state/sqlite/client-document-def.test.js +16 -0
  174. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
  175. package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
  176. package/dist/schema/state/sqlite/column-annotations.js +14 -6
  177. package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
  178. package/dist/schema/state/sqlite/column-annotations.test.js +1 -1
  179. package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
  180. package/dist/schema/state/sqlite/column-def.js +69 -22
  181. package/dist/schema/state/sqlite/column-def.js.map +1 -1
  182. package/dist/schema/state/sqlite/column-def.test.js +48 -10
  183. package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
  184. package/dist/schema/state/sqlite/column-spec.d.ts.map +1 -1
  185. package/dist/schema/state/sqlite/column-spec.js +30 -12
  186. package/dist/schema/state/sqlite/column-spec.js.map +1 -1
  187. package/dist/schema/state/sqlite/column-spec.test.js +23 -14
  188. package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
  189. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +2 -1
  190. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -1
  191. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +23 -6
  192. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
  193. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +14 -8
  194. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
  195. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +5 -3
  196. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
  197. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
  198. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +2 -1
  199. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
  200. package/dist/schema/state/sqlite/mod.d.ts +3 -3
  201. package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
  202. package/dist/schema/state/sqlite/mod.js +3 -3
  203. package/dist/schema/state/sqlite/mod.js.map +1 -1
  204. package/dist/schema/state/sqlite/query-builder/api.d.ts +19 -11
  205. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
  206. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
  207. package/dist/schema/state/sqlite/query-builder/astToSql.js +22 -15
  208. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
  209. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
  210. package/dist/schema/state/sqlite/query-builder/impl.js +6 -3
  211. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
  212. package/dist/schema/state/sqlite/query-builder/impl.test.js +252 -88
  213. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  214. package/dist/schema/state/sqlite/schema-helpers.d.ts +2 -2
  215. package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -1
  216. package/dist/schema/state/sqlite/schema-helpers.js +22 -12
  217. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
  218. package/dist/schema/state/sqlite/schema-helpers.test.d.ts +2 -0
  219. package/dist/schema/state/sqlite/schema-helpers.test.d.ts.map +1 -0
  220. package/dist/schema/state/sqlite/schema-helpers.test.js +36 -0
  221. package/dist/schema/state/sqlite/schema-helpers.test.js.map +1 -0
  222. package/dist/schema/state/sqlite/{system-tables.d.ts → system-tables/eventlog-tables.d.ts} +63 -456
  223. package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts.map +1 -0
  224. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +54 -0
  225. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -0
  226. package/dist/schema/state/sqlite/system-tables/mod.d.ts +3 -0
  227. package/dist/schema/state/sqlite/system-tables/mod.d.ts.map +1 -0
  228. package/dist/schema/state/sqlite/system-tables/mod.js +3 -0
  229. package/dist/schema/state/sqlite/system-tables/mod.js.map +1 -0
  230. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +456 -0
  231. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -0
  232. package/dist/schema/state/sqlite/system-tables/state-tables.js +55 -0
  233. package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -0
  234. package/dist/schema/state/sqlite/table-def.d.ts +4 -4
  235. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  236. package/dist/schema/state/sqlite/table-def.js +2 -2
  237. package/dist/schema/state/sqlite/table-def.js.map +1 -1
  238. package/dist/schema/state/sqlite/table-def.test.js +80 -0
  239. package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
  240. package/dist/schema/unknown-events.d.ts +47 -0
  241. package/dist/schema/unknown-events.d.ts.map +1 -0
  242. package/dist/schema/unknown-events.js +69 -0
  243. package/dist/schema/unknown-events.js.map +1 -0
  244. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts +2 -0
  245. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts.map +1 -0
  246. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +73 -0
  247. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -0
  248. package/dist/schema-management/migrations.d.ts +32 -2
  249. package/dist/schema-management/migrations.d.ts.map +1 -1
  250. package/dist/schema-management/migrations.js +37 -5
  251. package/dist/schema-management/migrations.js.map +1 -1
  252. package/dist/schema-management/validate-schema.d.ts +3 -3
  253. package/dist/schema-management/validate-schema.d.ts.map +1 -1
  254. package/dist/schema-management/validate-schema.js +2 -2
  255. package/dist/schema-management/validate-schema.js.map +1 -1
  256. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  257. package/dist/sql-queries/sql-queries.js +11 -1
  258. package/dist/sql-queries/sql-queries.js.map +1 -1
  259. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  260. package/dist/sql-queries/sql-query-builder.js +2 -1
  261. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  262. package/dist/sqlite-types.d.ts +3 -3
  263. package/dist/sqlite-types.d.ts.map +1 -1
  264. package/dist/sync/ClientSessionSyncProcessor.d.ts +11 -13
  265. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  266. package/dist/sync/ClientSessionSyncProcessor.js +45 -42
  267. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  268. package/dist/sync/errors.d.ts +66 -0
  269. package/dist/sync/errors.d.ts.map +1 -0
  270. package/dist/sync/errors.js +36 -0
  271. package/dist/sync/errors.js.map +1 -0
  272. package/dist/sync/index.d.ts +3 -0
  273. package/dist/sync/index.d.ts.map +1 -1
  274. package/dist/sync/index.js +3 -0
  275. package/dist/sync/index.js.map +1 -1
  276. package/dist/sync/mock-sync-backend.d.ts +23 -0
  277. package/dist/sync/mock-sync-backend.d.ts.map +1 -0
  278. package/dist/sync/mock-sync-backend.js +114 -0
  279. package/dist/sync/mock-sync-backend.js.map +1 -0
  280. package/dist/sync/next/compact-events.d.ts.map +1 -1
  281. package/dist/sync/next/compact-events.js +6 -7
  282. package/dist/sync/next/compact-events.js.map +1 -1
  283. package/dist/sync/next/facts.d.ts +5 -5
  284. package/dist/sync/next/facts.d.ts.map +1 -1
  285. package/dist/sync/next/facts.js +1 -2
  286. package/dist/sync/next/facts.js.map +1 -1
  287. package/dist/sync/next/history-dag-common.d.ts +54 -15
  288. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  289. package/dist/sync/next/history-dag-common.js +198 -9
  290. package/dist/sync/next/history-dag-common.js.map +1 -1
  291. package/dist/sync/next/history-dag.d.ts.map +1 -1
  292. package/dist/sync/next/history-dag.js +10 -8
  293. package/dist/sync/next/history-dag.js.map +1 -1
  294. package/dist/sync/next/rebase-events.d.ts +5 -5
  295. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  296. package/dist/sync/next/rebase-events.js +5 -5
  297. package/dist/sync/next/rebase-events.js.map +1 -1
  298. package/dist/sync/next/test/event-fixtures.d.ts +2 -2
  299. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
  300. package/dist/sync/next/test/event-fixtures.js +9 -9
  301. package/dist/sync/next/test/event-fixtures.js.map +1 -1
  302. package/dist/sync/sync-backend-kv.d.ts +7 -0
  303. package/dist/sync/sync-backend-kv.d.ts.map +1 -0
  304. package/dist/sync/sync-backend-kv.js +18 -0
  305. package/dist/sync/sync-backend-kv.js.map +1 -0
  306. package/dist/sync/sync-backend.d.ts +105 -0
  307. package/dist/sync/sync-backend.d.ts.map +1 -0
  308. package/dist/sync/sync-backend.js +61 -0
  309. package/dist/sync/sync-backend.js.map +1 -0
  310. package/dist/sync/sync.d.ts +9 -86
  311. package/dist/sync/sync.d.ts.map +1 -1
  312. package/dist/sync/sync.js +2 -27
  313. package/dist/sync/sync.js.map +1 -1
  314. package/dist/sync/syncstate.d.ts +57 -44
  315. package/dist/sync/syncstate.d.ts.map +1 -1
  316. package/dist/sync/syncstate.js +50 -45
  317. package/dist/sync/syncstate.js.map +1 -1
  318. package/dist/sync/syncstate.test.js +83 -46
  319. package/dist/sync/syncstate.test.js.map +1 -1
  320. package/dist/sync/transport-chunking.d.ts +36 -0
  321. package/dist/sync/transport-chunking.d.ts.map +1 -0
  322. package/dist/sync/transport-chunking.js +56 -0
  323. package/dist/sync/transport-chunking.js.map +1 -0
  324. package/dist/sync/validate-push-payload.d.ts +2 -2
  325. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  326. package/dist/sync/validate-push-payload.js +6 -6
  327. package/dist/sync/validate-push-payload.js.map +1 -1
  328. package/dist/testing/event-factory.d.ts +68 -0
  329. package/dist/testing/event-factory.d.ts.map +1 -0
  330. package/dist/testing/event-factory.js +78 -0
  331. package/dist/testing/event-factory.js.map +1 -0
  332. package/dist/testing/mod.d.ts +2 -0
  333. package/dist/testing/mod.d.ts.map +1 -0
  334. package/dist/testing/mod.js +2 -0
  335. package/dist/testing/mod.js.map +1 -0
  336. package/dist/version.d.ts +16 -6
  337. package/dist/version.d.ts.map +1 -1
  338. package/dist/version.js +16 -6
  339. package/dist/version.js.map +1 -1
  340. package/package.json +7 -8
  341. package/src/ClientSessionLeaderThreadProxy.ts +20 -12
  342. package/src/adapter-types.ts +18 -6
  343. package/src/debug-info.ts +37 -6
  344. package/src/devtools/devtools-messages-client-session.ts +2 -2
  345. package/src/devtools/devtools-messages-common.ts +1 -8
  346. package/src/devtools/devtools-messages-leader.ts +9 -8
  347. package/src/devtools/devtools-sessioninfo.ts +8 -5
  348. package/src/devtools/mod.ts +11 -2
  349. package/src/errors.ts +38 -11
  350. package/src/index.ts +2 -1
  351. package/src/leader-thread/LeaderSyncProcessor.ts +277 -105
  352. package/src/leader-thread/eventlog.ts +113 -38
  353. package/src/leader-thread/leader-worker-devtools.ts +86 -55
  354. package/src/leader-thread/make-leader-thread-layer.test.ts +44 -0
  355. package/src/leader-thread/make-leader-thread-layer.ts +156 -37
  356. package/src/leader-thread/materialize-event.ts +37 -12
  357. package/src/leader-thread/mod.ts +1 -0
  358. package/src/leader-thread/recreate-db.ts +15 -7
  359. package/src/leader-thread/shutdown-channel.ts +16 -2
  360. package/src/leader-thread/stream-events.ts +201 -0
  361. package/src/leader-thread/types.ts +70 -20
  362. package/src/logging.ts +62 -0
  363. package/src/make-client-session.ts +9 -3
  364. package/src/materializer-helper.ts +27 -10
  365. package/src/otel.ts +10 -0
  366. package/src/rematerialize-from-eventlog.ts +37 -27
  367. package/src/schema/EventDef/define.ts +201 -0
  368. package/src/schema/EventDef/event-def.ts +120 -0
  369. package/src/schema/EventDef/facts.ts +135 -0
  370. package/src/schema/EventDef/materializer.ts +172 -0
  371. package/src/schema/EventDef/mod.ts +4 -0
  372. package/src/schema/EventSequenceNumber/client.ts +257 -0
  373. package/src/schema/EventSequenceNumber/global.ts +19 -0
  374. package/src/schema/EventSequenceNumber/mod.ts +37 -0
  375. package/src/schema/EventSequenceNumber.test.ts +70 -52
  376. package/src/schema/LiveStoreEvent/client.ts +221 -0
  377. package/src/schema/LiveStoreEvent/for-event-def.ts +60 -0
  378. package/src/schema/LiveStoreEvent/global.ts +45 -0
  379. package/src/schema/LiveStoreEvent/input.ts +63 -0
  380. package/src/schema/LiveStoreEvent/mod.ts +4 -0
  381. package/src/schema/events.ts +1 -1
  382. package/src/schema/mod.ts +6 -4
  383. package/src/schema/schema.ts +39 -3
  384. package/src/schema/state/sqlite/client-document-def.test.ts +19 -2
  385. package/src/schema/state/sqlite/client-document-def.ts +127 -25
  386. package/src/schema/state/sqlite/column-annotations.test.ts +1 -1
  387. package/src/schema/state/sqlite/column-annotations.ts +16 -6
  388. package/src/schema/state/sqlite/column-def.test.ts +62 -10
  389. package/src/schema/state/sqlite/column-def.ts +88 -21
  390. package/src/schema/state/sqlite/column-spec.test.ts +29 -16
  391. package/src/schema/state/sqlite/column-spec.ts +36 -11
  392. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +26 -6
  393. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +29 -12
  394. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +12 -17
  395. package/src/schema/state/sqlite/mod.ts +4 -3
  396. package/src/schema/state/sqlite/query-builder/api.ts +25 -11
  397. package/src/schema/state/sqlite/query-builder/astToSql.ts +23 -14
  398. package/src/schema/state/sqlite/query-builder/impl.test.ts +305 -92
  399. package/src/schema/state/sqlite/query-builder/impl.ts +8 -3
  400. package/src/schema/state/sqlite/schema-helpers.test.ts +44 -0
  401. package/src/schema/state/sqlite/schema-helpers.ts +28 -20
  402. package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +64 -0
  403. package/src/schema/state/sqlite/system-tables/mod.ts +2 -0
  404. package/src/schema/state/sqlite/system-tables/state-tables.ts +69 -0
  405. package/src/schema/state/sqlite/table-def.test.ts +101 -0
  406. package/src/schema/state/sqlite/table-def.ts +8 -6
  407. package/src/schema/unknown-events.ts +131 -0
  408. package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +86 -0
  409. package/src/schema-management/migrations.ts +41 -8
  410. package/src/schema-management/validate-schema.ts +3 -3
  411. package/src/sql-queries/sql-queries.ts +9 -1
  412. package/src/sql-queries/sql-query-builder.ts +2 -1
  413. package/src/sqlite-types.ts +3 -3
  414. package/src/sync/ClientSessionSyncProcessor.ts +69 -62
  415. package/src/sync/errors.ts +38 -0
  416. package/src/sync/index.ts +3 -0
  417. package/src/sync/mock-sync-backend.ts +184 -0
  418. package/src/sync/next/compact-events.ts +6 -7
  419. package/src/sync/next/facts.ts +7 -9
  420. package/src/sync/next/history-dag-common.ts +277 -26
  421. package/src/sync/next/history-dag.ts +16 -10
  422. package/src/sync/next/rebase-events.ts +11 -11
  423. package/src/sync/next/test/event-fixtures.ts +11 -11
  424. package/src/sync/sync-backend-kv.ts +22 -0
  425. package/src/sync/sync-backend.ts +185 -0
  426. package/src/sync/sync.ts +9 -91
  427. package/src/sync/syncstate.test.ts +96 -52
  428. package/src/sync/syncstate.ts +69 -58
  429. package/src/sync/transport-chunking.ts +90 -0
  430. package/src/sync/validate-push-payload.ts +8 -9
  431. package/src/testing/event-factory.ts +131 -0
  432. package/src/testing/mod.ts +1 -0
  433. package/src/version.ts +16 -6
  434. package/dist/schema/EventDef.d.ts +0 -123
  435. package/dist/schema/EventDef.d.ts.map +0 -1
  436. package/dist/schema/EventDef.js +0 -46
  437. package/dist/schema/EventDef.js.map +0 -1
  438. package/dist/schema/EventSequenceNumber.d.ts +0 -80
  439. package/dist/schema/EventSequenceNumber.d.ts.map +0 -1
  440. package/dist/schema/EventSequenceNumber.js +0 -139
  441. package/dist/schema/EventSequenceNumber.js.map +0 -1
  442. package/dist/schema/LiveStoreEvent.d.ts.map +0 -1
  443. package/dist/schema/LiveStoreEvent.js.map +0 -1
  444. package/dist/schema/state/sqlite/system-tables.d.ts.map +0 -1
  445. package/dist/schema/state/sqlite/system-tables.js +0 -79
  446. package/dist/schema/state/sqlite/system-tables.js.map +0 -1
  447. package/dist/schema-management/migrations.test.d.ts +0 -2
  448. package/dist/schema-management/migrations.test.d.ts.map +0 -1
  449. package/dist/schema-management/migrations.test.js +0 -52
  450. package/dist/schema-management/migrations.test.js.map +0 -1
  451. package/dist/sync/next/graphology.d.ts +0 -8
  452. package/dist/sync/next/graphology.d.ts.map +0 -1
  453. package/dist/sync/next/graphology.js +0 -30
  454. package/dist/sync/next/graphology.js.map +0 -1
  455. package/dist/sync/next/graphology_.d.ts +0 -3
  456. package/dist/sync/next/graphology_.d.ts.map +0 -1
  457. package/dist/sync/next/graphology_.js +0 -3
  458. package/dist/sync/next/graphology_.js.map +0 -1
  459. package/src/schema/EventDef.ts +0 -219
  460. package/src/schema/EventSequenceNumber.ts +0 -199
  461. package/src/schema/LiveStoreEvent.ts +0 -287
  462. package/src/schema/state/sqlite/system-tables.ts +0 -104
  463. package/src/sync/next/ambient.d.ts +0 -3
  464. package/src/sync/next/graphology.ts +0 -41
  465. package/src/sync/next/graphology_.ts +0 -2
@@ -10,33 +10,58 @@ import { type SqliteAst, SqliteDsl } from './db-schema/mod.ts'
10
10
  * ```
11
11
  */
12
12
  export const makeColumnSpec = (tableAst: SqliteAst.Table) => {
13
- const primaryKeys = tableAst.columns.filter((_) => _.primaryKey).map((_) => `'${_.name}'`)
14
- const columnDefStrs = tableAst.columns.map(toSqliteColumnSpec)
13
+ const pkColumns = tableAst.columns.filter((_) => _.primaryKey)
14
+ const hasSinglePk = pkColumns.length === 1
15
+ const pkColumn = hasSinglePk ? pkColumns[0] : undefined
15
16
 
16
- if (primaryKeys.length > 0) {
17
- columnDefStrs.push(`PRIMARY KEY (${primaryKeys.join(', ')})`)
17
+ // Build column definitions, handling the special SQLite rule that AUTOINCREMENT
18
+ // is only valid on a single column declared as INTEGER PRIMARY KEY (column-level).
19
+ const columnDefStrs = tableAst.columns.map((column) =>
20
+ toSqliteColumnSpec(column, {
21
+ inlinePrimaryKey: hasSinglePk && column === pkColumn && column.primaryKey === true,
22
+ }),
23
+ )
24
+
25
+ // For composite primary keys, add a table-level PRIMARY KEY clause.
26
+ if (pkColumns.length > 1) {
27
+ const quotedPkCols = pkColumns.map((_) => `"${_.name}"`)
28
+ columnDefStrs.push(`PRIMARY KEY (${quotedPkCols.join(', ')})`)
18
29
  }
19
30
 
20
31
  return columnDefStrs.join(', ')
21
32
  }
22
33
 
23
34
  /** NOTE primary keys are applied on a table level not on a column level to account for multi-column primary keys */
24
- const toSqliteColumnSpec = (column: SqliteAst.Column) => {
35
+ const toSqliteColumnSpec = (column: SqliteAst.Column, opts: { inlinePrimaryKey: boolean }) => {
25
36
  const columnTypeStr = column.type._tag
26
- const nullableStr = column.nullable === false ? 'not null' : ''
27
- const autoIncrementStr = column.autoIncrement ? 'autoincrement' : ''
37
+ // When PRIMARY KEY is declared inline, NOT NULL is implied and should not be emitted,
38
+ // and AUTOINCREMENT must immediately follow PRIMARY KEY within the same constraint.
39
+ const nullableStr = opts.inlinePrimaryKey ? '' : column.nullable === false ? 'not null' : ''
40
+
41
+ // Only include AUTOINCREMENT when it's valid: single-column INTEGER PRIMARY KEY
42
+ const includeAutoIncrement = opts.inlinePrimaryKey && column.type._tag === 'integer' && column.autoIncrement === true
43
+
44
+ const pkStr = opts.inlinePrimaryKey ? 'primary key' : ''
45
+ const autoIncrementStr = includeAutoIncrement ? 'autoincrement' : ''
46
+
28
47
  const defaultValueStr = (() => {
29
48
  if (column.default._tag === 'None') return ''
30
49
 
31
- if (column.default.value === null) return 'default null'
32
- if (SqliteDsl.isSqlDefaultValue(column.default.value)) return `default ${column.default.value.sql}`
50
+ const defaultValue = column.default.value
51
+ if (SqliteDsl.isDefaultThunk(defaultValue)) return ''
52
+
53
+ const resolvedDefault = SqliteDsl.resolveColumnDefault(defaultValue)
54
+
55
+ if (resolvedDefault === null) return 'default null'
56
+ if (SqliteDsl.isSqlDefaultValue(resolvedDefault)) return `default ${resolvedDefault.sql}`
33
57
 
34
58
  const encodeValue = Schema.encodeSync(column.schema)
35
- const encodedDefaultValue = encodeValue(column.default.value)
59
+ const encodedDefaultValue = encodeValue(resolvedDefault)
36
60
 
37
61
  if (columnTypeStr === 'text') return `default '${encodedDefaultValue}'`
38
62
  return `default ${encodedDefaultValue}`
39
63
  })()
40
64
 
41
- return `'${column.name}' ${columnTypeStr} ${nullableStr} ${autoIncrementStr} ${defaultValueStr}`
65
+ // Ensure order: PRIMARY KEY [AUTOINCREMENT] [NOT NULL] ...
66
+ return `"${column.name}" ${columnTypeStr} ${pkStr} ${autoIncrementStr} ${nullableStr} ${defaultValueStr}`
42
67
  }
@@ -1,4 +1,5 @@
1
- import { type Option, Schema } from '@livestore/utils/effect'
1
+ import { omitUndefineds } from '@livestore/utils'
2
+ import { type Option, Schema, SchemaAST } from '@livestore/utils/effect'
2
3
 
3
4
  import { hashCode } from '../hash.ts'
4
5
 
@@ -45,9 +46,7 @@ export const index = (
45
46
  ): Index => ({
46
47
  _tag: 'index',
47
48
  columns,
48
- name,
49
- unique,
50
- primaryKey,
49
+ ...omitUndefineds({ name, unique, primaryKey }),
51
50
  })
52
51
 
53
52
  export type ForeignKey = {
@@ -85,7 +84,19 @@ export type DbSchema = {
85
84
  export const dbSchema = (tables: Table[]): DbSchema => ({ _tag: 'dbSchema', tables })
86
85
 
87
86
  /**
88
- * NOTE we're only including SQLite-relevant information in the hash (which excludes the schema mapping)
87
+ * Helper to detect if a column is a JSON column (has parseJson transformation)
88
+ */
89
+ const isJsonColumn = (column: Column): boolean => {
90
+ if (column.type._tag !== 'text') return false
91
+
92
+ // Check if the schema AST is a parseJson transformation
93
+ const ast = column.schema.ast
94
+ return ast._tag === 'Transformation' && ast.annotations.schemaId === SchemaAST.ParseJsonSchemaId
95
+ }
96
+
97
+ /**
98
+ * NOTE we're now including JSON schema information for JSON columns
99
+ * to detect client document schema changes
89
100
  */
90
101
  export const hash = (obj: Table | Column | Index | ForeignKey | DbSchema): number =>
91
102
  hashCode(JSON.stringify(trimInfoForHasing(obj)))
@@ -101,7 +112,7 @@ const trimInfoForHasing = (obj: Table | Column | Index | ForeignKey | DbSchema):
101
112
  }
102
113
  }
103
114
  case 'column': {
104
- return {
115
+ const baseInfo: Record<string, any> = {
105
116
  _tag: 'column',
106
117
  name: obj.name,
107
118
  type: obj.type._tag,
@@ -110,6 +121,15 @@ const trimInfoForHasing = (obj: Table | Column | Index | ForeignKey | DbSchema):
110
121
  autoIncrement: obj.autoIncrement,
111
122
  default: obj.default,
112
123
  }
124
+
125
+ // NEW: Include schema hash for JSON columns
126
+ // This ensures that changes to the JSON schema are detected
127
+ if (isJsonColumn(obj) && obj.schema) {
128
+ // Use Effect's Schema.hash for consistent hashing
129
+ baseInfo.jsonSchemaHash = Schema.hash(obj.schema)
130
+ }
131
+
132
+ return baseInfo
113
133
  }
114
134
  case 'index': {
115
135
  return {
@@ -1,10 +1,27 @@
1
1
  import { casesHandled } from '@livestore/utils'
2
2
  import { Option, Schema } from '@livestore/utils/effect'
3
3
 
4
+ export type SqlDefaultValue = {
5
+ readonly sql: string
6
+ }
7
+
8
+ export const isSqlDefaultValue = (value: unknown): value is SqlDefaultValue => {
9
+ return typeof value === 'object' && value !== null && 'sql' in value && typeof (value as any).sql === 'string'
10
+ }
11
+
12
+ export type ColumnDefaultThunk<T> = () => T
13
+
14
+ export const isDefaultThunk = (value: unknown): value is ColumnDefaultThunk<unknown> => typeof value === 'function'
15
+
16
+ export type ColumnDefaultValue<T> = T | null | ColumnDefaultThunk<T | null> | SqlDefaultValue
17
+
18
+ export const resolveColumnDefault = <T>(value: ColumnDefaultValue<T>): T | null | SqlDefaultValue =>
19
+ isDefaultThunk(value) ? (value as ColumnDefaultThunk<T | null>)() : value
20
+
4
21
  export type ColumnDefinition<TEncoded, TDecoded> = {
5
22
  readonly columnType: FieldColumnType
6
23
  readonly schema: Schema.Schema<TDecoded, TEncoded>
7
- readonly default: Option.Option<TEncoded>
24
+ readonly default: Option.Option<ColumnDefaultValue<TDecoded>>
8
25
  /** @default false */
9
26
  readonly nullable: boolean
10
27
  /** @default false */
@@ -27,9 +44,17 @@ export const isColumnDefinition = (value: unknown): value is ColumnDefinition.An
27
44
  )
28
45
  }
29
46
 
47
+ type MaybeNull<T, TNullable extends boolean> = T | (TNullable extends true ? null : never)
48
+
49
+ type ColumnDefaultArg<T, TNullable extends boolean> =
50
+ | MaybeNull<T, TNullable>
51
+ | ColumnDefaultThunk<MaybeNull<T, TNullable>>
52
+ | SqlDefaultValue
53
+ | NoDefault
54
+
30
55
  export type ColumnDefinitionInput = {
31
56
  readonly schema?: Schema.Schema<unknown>
32
- readonly default?: unknown | NoDefault
57
+ readonly default?: ColumnDefaultArg<unknown, boolean>
33
58
  readonly nullable?: boolean
34
59
  readonly primaryKey?: boolean
35
60
  readonly autoIncrement?: boolean
@@ -38,14 +63,6 @@ export type ColumnDefinitionInput = {
38
63
  export const NoDefault = Symbol.for('NoDefault')
39
64
  export type NoDefault = typeof NoDefault
40
65
 
41
- export type SqlDefaultValue = {
42
- readonly sql: string
43
- }
44
-
45
- export const isSqlDefaultValue = (value: unknown): value is SqlDefaultValue => {
46
- return typeof value === 'object' && value !== null && 'sql' in value && typeof value.sql === 'string'
47
- }
48
-
49
66
  export type ColDefFn<TColumnType extends FieldColumnType> = {
50
67
  (): {
51
68
  columnType: TColumnType
@@ -59,7 +76,7 @@ export type ColDefFn<TColumnType extends FieldColumnType> = {
59
76
  TEncoded extends DefaultEncodedForColumnType<TColumnType>,
60
77
  TDecoded = DefaultEncodedForColumnType<TColumnType>,
61
78
  const TNullable extends boolean = false,
62
- const TDefault extends TDecoded | SqlDefaultValue | NoDefault | (TNullable extends true ? null : never) = NoDefault,
79
+ const TDefault extends ColumnDefaultArg<NoInfer<TDecoded>, TNullable> = NoDefault,
63
80
  const TPrimaryKey extends boolean = false,
64
81
  const TAutoIncrement extends boolean = false,
65
82
  >(args: {
@@ -132,7 +149,7 @@ export type SpecializedColDefFn<
132
149
  <
133
150
  TDecoded = TBaseDecoded,
134
151
  const TNullable extends boolean = false,
135
- const TDefault extends TDecoded | NoDefault | (TNullable extends true ? null : never) = NoDefault,
152
+ const TDefault extends ColumnDefaultArg<NoInfer<TDecoded>, TNullable> = NoDefault,
136
153
  const TPrimaryKey extends boolean = false,
137
154
  const TAutoIncrement extends boolean = false,
138
155
  >(
@@ -1,4 +1,5 @@
1
1
  import type { Nullable } from '@livestore/utils'
2
+ import { omitUndefineds } from '@livestore/utils'
2
3
  import type { Option, Types } from '@livestore/utils/effect'
3
4
  import { Schema } from '@livestore/utils/effect'
4
5
 
@@ -19,13 +20,12 @@ export type DbSchemaInput = Record<string, TableDefinition<any, any>> | Readonly
19
20
  * - array: we use the table name of each array item (= table definition) as the object key
20
21
  * - object: we discard the keys of the input object and use the table name of each object value (= table definition) as the new object key
21
22
  */
22
- export type DbSchemaFromInputSchema<TSchemaInput extends DbSchemaInput> = TSchemaInput extends ReadonlyArray<
23
- TableDefinition<any, any>
24
- >
25
- ? { [K in TSchemaInput[number] as K['name']]: K }
26
- : TSchemaInput extends Record<string, TableDefinition<any, any>>
27
- ? { [K in keyof TSchemaInput as TSchemaInput[K]['name']]: TSchemaInput[K] }
28
- : never
23
+ export type DbSchemaFromInputSchema<TSchemaInput extends DbSchemaInput> =
24
+ TSchemaInput extends ReadonlyArray<TableDefinition<any, any>>
25
+ ? { [K in TSchemaInput[number] as K['name']]: K }
26
+ : TSchemaInput extends Record<string, TableDefinition<any, any>>
27
+ ? { [K in keyof TSchemaInput as TSchemaInput[K]['name']]: TSchemaInput[K] }
28
+ : never
29
29
 
30
30
  // TODO ensure via runtime check (possibly even via type-level check) that all index names are unique
31
31
  export const makeDbSchema = <TDbSchemaInput extends DbSchemaInput>(
@@ -46,7 +46,7 @@ export const table = <TTableName extends string, TColumns extends Columns, TInde
46
46
  indexes: indexesToAst(indexes ?? []),
47
47
  }
48
48
 
49
- return { name, columns, indexes, ast }
49
+ return { name, columns, ...omitUndefineds({ indexes }), ast }
50
50
  }
51
51
 
52
52
  export type AnyIfConstained<In, Out> = '__constrained' extends keyof In ? any : Out
@@ -115,12 +115,8 @@ export type TableDefinition<TName extends string, TColumns extends Columns> = {
115
115
 
116
116
  export type Columns = Record<string, ColumnDefinition<any, any>>
117
117
 
118
- export type IsSingleColumn<TColumns extends Columns | ColumnDefinition<any, any>> = TColumns extends ColumnDefinition<
119
- any,
120
- any
121
- >
122
- ? true
123
- : false
118
+ export type IsSingleColumn<TColumns extends Columns | ColumnDefinition<any, any>> =
119
+ TColumns extends ColumnDefinition<any, any> ? true : false
124
120
 
125
121
  /**
126
122
  * NOTE this is only needed to avoid a TS limitation where `StructSchemaForColumns` in the default case
@@ -213,9 +209,8 @@ export namespace FromColumns {
213
209
 
214
210
  export type RequiredInsertColumnNames<TColumns extends Columns> = keyof RequiredInsertColumns<TColumns>
215
211
 
216
- export type RequiresInsertValues<TColumns extends Columns> = RequiredInsertColumnNames<TColumns> extends never
217
- ? false
218
- : true
212
+ export type RequiresInsertValues<TColumns extends Columns> =
213
+ RequiredInsertColumnNames<TColumns> extends never ? false : true
219
214
 
220
215
  export type InsertRowDecoded<TColumns extends Columns> = Types.Simplify<
221
216
  Pick<RowDecodedAll<TColumns>, RequiredInsertColumnNames<TColumns>> &
@@ -1,19 +1,20 @@
1
1
  import { shouldNeverHappen } from '@livestore/utils'
2
2
 
3
3
  import type { MigrationOptions } from '../../../adapter-types.ts'
4
- import type { Materializer } from '../../EventDef.ts'
4
+ import type { Materializer } from '../../EventDef/mod.ts'
5
5
  import type { InternalState } from '../../schema.ts'
6
6
  import { ClientDocumentTableDefSymbol, tableIsClientDocumentTable } from './client-document-def.ts'
7
7
  import { SqliteAst } from './db-schema/mod.ts'
8
- import { stateSystemTables } from './system-tables.ts'
8
+ import { stateSystemTables } from './system-tables/state-tables.ts'
9
9
  import type { TableDef, TableDefBase } from './table-def.ts'
10
10
 
11
- export * from '../../EventDef.ts'
11
+ export * from '../../EventDef/mod.ts'
12
12
  export {
13
13
  type ClientDocumentTableDef,
14
14
  ClientDocumentTableDefSymbol,
15
15
  type ClientDocumentTableOptions,
16
16
  clientDocument,
17
+ createOptimisticEventSchema,
17
18
  tableIsClientDocumentTable,
18
19
  } from './client-document-def.ts'
19
20
  export * from './column-annotations.ts'
@@ -3,7 +3,7 @@ import { type Option, Predicate, type Schema } from '@livestore/utils/effect'
3
3
 
4
4
  import type { SessionIdSymbol } from '../../../../adapter-types.ts'
5
5
  import type { SqlValue } from '../../../../util.ts'
6
- import type { ClientDocumentTableDef } from '../client-document-def.ts'
6
+ import type { ClientDocumentTableDef, ClientDocumentTableDefSymbol } from '../client-document-def.ts'
7
7
  import type { SqliteDsl } from '../db-schema/mod.ts'
8
8
  import type { TableDefBase } from '../table-def.ts'
9
9
 
@@ -242,7 +242,12 @@ export namespace QueryBuilder {
242
242
  ): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
243
243
  <TColName extends keyof TTableDef['sqliteDef']['columns']>(
244
244
  col: TColName,
245
- op: QueryBuilder.WhereOps,
245
+ op: QueryBuilder.WhereOps.MultiValue,
246
+ value: ReadonlyArray<TTableDef['sqliteDef']['columns'][TColName]['schema']['Type']>,
247
+ ): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
248
+ <TColName extends keyof TTableDef['sqliteDef']['columns']>(
249
+ col: TColName,
250
+ op: QueryBuilder.WhereOps.SingleValue,
246
251
  value: TTableDef['sqliteDef']['columns'][TColName]['schema']['Type'],
247
252
  ): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
248
253
  }
@@ -347,22 +352,26 @@ export namespace QueryBuilder {
347
352
  >
348
353
 
349
354
  /**
350
- * Example: If the row already exists, it will be ignored.
355
+ * Upsert: insert a row, or handle conflicts on existing rows.
356
+ * Equivalent to SQLite's `INSERT ... ON CONFLICT` clause.
357
+ *
358
+ * Actions:
359
+ * - `'ignore'`: Skip the insert if a row with the same key exists
360
+ * - `'replace'`: Delete the existing row and insert the new one
361
+ * - `'update'`: Update specific columns on the existing row
362
+ *
351
363
  * ```ts
364
+ * // Ignore: skip if row exists
352
365
  * db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'ignore')
353
- * ```
354
366
  *
355
- * Example: If the row already exists, it will be replaced.
356
- * ```ts
367
+ * // Replace: delete existing row and insert new one
357
368
  * db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'replace')
358
- * ```
359
369
  *
360
- * Example: If the row already exists, it will be updated.
361
- * ```ts
370
+ * // Update: merge specific columns into existing row
362
371
  * db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'update', { text: 'Buy soy milk' })
363
372
  * ```
364
373
  *
365
- * NOTE This API doesn't yet support composite primary keys.
374
+ * NOTE: Composite primary keys are not yet supported.
366
375
  */
367
376
  readonly onConflict: {
368
377
  <TTarget extends SingleOrReadonlyArray<keyof TTableDef['sqliteDef']['columns']>>(
@@ -437,7 +446,12 @@ export namespace QueryBuilder {
437
446
 
438
447
  export namespace RowQuery {
439
448
  export type GetOrCreateOptions<TTableDef extends ClientDocumentTableDef.TraitAny> = {
440
- default: Partial<TTableDef['Value']>
449
+ /**
450
+ * Default value to use instead of the default value from the table definition
451
+ */
452
+ default: TTableDef[ClientDocumentTableDefSymbol]['options']['partialSet'] extends false
453
+ ? TTableDef['Value']
454
+ : Partial<TTableDef['Value']>
441
455
  }
442
456
 
443
457
  // TODO get rid of this
@@ -7,6 +7,8 @@ import type { State } from '../../../mod.ts'
7
7
  import type { QueryBuilderAst } from './api.ts'
8
8
 
9
9
  // Helper functions for SQL generation
10
+ const quoteIdentifier = (identifier: string): string => `"${identifier.replace(/"/g, '""')}"`
11
+
10
12
  const formatWhereClause = (
11
13
  whereConditions: ReadonlyArray<QueryBuilderAst.Where>,
12
14
  tableDef: State.SQLite.TableDefBase,
@@ -16,13 +18,15 @@ const formatWhereClause = (
16
18
 
17
19
  const whereClause = whereConditions
18
20
  .map(({ col, op, value }) => {
21
+ const quotedCol = quoteIdentifier(col)
22
+
19
23
  // Handle NULL values
20
24
  if (value === null) {
21
25
  if (op !== '=' && op !== '!=') {
22
26
  throw new Error(`Unsupported operator for NULL value: ${op}`)
23
27
  }
24
28
  const opStmt = op === '=' ? 'IS' : 'IS NOT'
25
- return `${col} ${opStmt} NULL`
29
+ return `${quotedCol} ${opStmt} NULL`
26
30
  }
27
31
 
28
32
  // Get column definition and encode value
@@ -48,11 +52,11 @@ const formatWhereClause = (
48
52
  const encodedValues = value.map((v) => Schema.encodeSync(colDef.schema)(v)) as SqlValue[]
49
53
  bindValues.push(...encodedValues)
50
54
  const placeholders = encodedValues.map(() => '?').join(', ')
51
- return `${col} ${op} (${placeholders})`
55
+ return `${quotedCol} ${op} (${placeholders})`
52
56
  } else {
53
57
  const encodedValue = Schema.encodeSync(colDef.schema)(value)
54
58
  bindValues.push(encodedValue as SqlValue)
55
- return `${col} ${op} ?`
59
+ return `${quotedCol} ${op} ?`
56
60
  }
57
61
  })
58
62
  .join(' AND ')
@@ -62,7 +66,7 @@ const formatWhereClause = (
62
66
 
63
67
  const formatReturningClause = (returning?: string[]): string => {
64
68
  if (!returning || returning.length === 0) return ''
65
- return ` RETURNING ${returning.join(', ')}`
69
+ return ` RETURNING ${returning.map(quoteIdentifier).join(', ')}`
66
70
  }
67
71
 
68
72
  export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: SqlValue[]; usedTables: Set<string> } => {
@@ -72,6 +76,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
72
76
  // INSERT query
73
77
  if (ast._tag === 'InsertQuery') {
74
78
  const columns = Object.keys(ast.values)
79
+ const quotedColumns = columns.map(quoteIdentifier)
75
80
  const placeholders = columns.map(() => '?').join(', ')
76
81
  const encodedValues = Schema.encodeSync(ast.tableDef.insertSchema)(ast.values)
77
82
 
@@ -91,7 +96,8 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
91
96
  // For REPLACE, the conflict target is implied and no further clause is needed
92
97
  } else {
93
98
  // Build the ON CONFLICT clause for IGNORE or UPDATE
94
- conflictClause = ` ON CONFLICT (${ast.onConflict.targets.join(', ')}) `
99
+ const conflictTargets = ast.onConflict.targets.map(quoteIdentifier).join(', ')
100
+ conflictClause = ` ON CONFLICT (${conflictTargets}) `
95
101
  if (ast.onConflict.action._tag === 'ignore') {
96
102
  conflictClause += 'DO NOTHING'
97
103
  } else {
@@ -105,8 +111,9 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
105
111
  const updates = updateCols
106
112
  .map((col) => {
107
113
  const value = updateValues[col]
114
+ const quotedCol = quoteIdentifier(col)
108
115
  // If the value is undefined, use excluded.col
109
- return value === undefined ? `${col} = excluded.${col}` : `${col} = ?`
116
+ return value === undefined ? `${quotedCol} = excluded.${quotedCol}` : `${quotedCol} = ?`
110
117
  })
111
118
  .join(', ')
112
119
 
@@ -129,7 +136,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
129
136
  }
130
137
 
131
138
  // Construct the main query part
132
- let query = `${insertVerb} INTO '${ast.tableDef.sqliteDef.name}' (${columns.join(', ')}) VALUES (${placeholders})`
139
+ let query = `${insertVerb} INTO '${ast.tableDef.sqliteDef.name}' (${quotedColumns.join(', ')}) VALUES (${placeholders})`
133
140
 
134
141
  // Append the conflict clause if it was generated (i.e., not for REPLACE)
135
142
  query += conflictClause
@@ -157,7 +164,9 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
157
164
  bindValues.push(encodedValues[col] as SqlValue)
158
165
  })
159
166
 
160
- let query = `UPDATE '${ast.tableDef.sqliteDef.name}' SET ${setColumns.map((col) => `${col} = ?`).join(', ')}`
167
+ let query = `UPDATE '${ast.tableDef.sqliteDef.name}' SET ${setColumns
168
+ .map((col) => `${quoteIdentifier(col)} = ?`)
169
+ .join(', ')}`
161
170
 
162
171
  const whereClause = formatWhereClause(ast.where, ast.tableDef, bindValues)
163
172
  if (whereClause) query += ` ${whereClause}`
@@ -201,31 +210,31 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
201
210
  const encodedId = ast.id === SessionIdSymbol ? ast.id : Schema.encodeSync(idColDef.schema)(ast.id)
202
211
 
203
212
  return {
204
- query: `SELECT * FROM '${ast.tableDef.sqliteDef.name}' WHERE id = ?`,
213
+ query: `SELECT * FROM '${ast.tableDef.sqliteDef.name}' WHERE ${quoteIdentifier('id')} = ?`,
205
214
  bindValues: [encodedId as SqlValue],
206
215
  usedTables,
207
216
  }
208
217
  }
209
218
 
210
219
  // SELECT query
211
- const columnsStmt = ast.select.columns.length === 0 ? '*' : ast.select.columns.join(', ')
220
+ const columnsStmt = ast.select.columns.length === 0 ? '*' : ast.select.columns.map(quoteIdentifier).join(', ')
212
221
  const selectStmt = `SELECT ${columnsStmt}`
213
222
  const fromStmt = `FROM '${ast.tableDef.sqliteDef.name}'`
214
223
  const whereStmt = formatWhereClause(ast.where, ast.tableDef, bindValues)
215
224
 
216
225
  const orderByStmt =
217
226
  ast.orderBy.length > 0
218
- ? `ORDER BY ${ast.orderBy.map(({ col, direction }) => `${col} ${direction}`).join(', ')}`
227
+ ? `ORDER BY ${ast.orderBy.map(({ col, direction }) => `${quoteIdentifier(col)} ${direction}`).join(', ')}`
219
228
  : ''
220
229
 
221
230
  const limitStmt = ast.limit._tag === 'Some' ? `LIMIT ?` : ''
222
231
  const offsetStmt = ast.offset._tag === 'Some' ? `OFFSET ?` : ''
223
232
 
224
- // Push offset and limit values in the correct order matching the query string
225
- if (ast.offset._tag === 'Some') bindValues.push(ast.offset.value)
233
+ // Push limit and offset values in the correct order matching the query string
226
234
  if (ast.limit._tag === 'Some') bindValues.push(ast.limit.value)
235
+ if (ast.offset._tag === 'Some') bindValues.push(ast.offset.value)
227
236
 
228
- const query = [selectStmt, fromStmt, whereStmt, orderByStmt, offsetStmt, limitStmt]
237
+ const query = [selectStmt, fromStmt, whereStmt, orderByStmt, limitStmt, offsetStmt]
229
238
  .map((clause) => clause.trim())
230
239
  .filter((clause) => clause.length > 0)
231
240
  .join(' ')