@livestore/common 0.4.0-dev.9 → 0.4.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 (513) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ClientSessionLeaderThreadProxy.d.ts +27 -12
  3. package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
  4. package/dist/ClientSessionLeaderThreadProxy.js.map +1 -1
  5. package/dist/WorkerTransportError.d.ts +11 -0
  6. package/dist/WorkerTransportError.d.ts.map +1 -0
  7. package/dist/WorkerTransportError.js +11 -0
  8. package/dist/WorkerTransportError.js.map +1 -0
  9. package/dist/adapter-types.d.ts +37 -7
  10. package/dist/adapter-types.d.ts.map +1 -1
  11. package/dist/adapter-types.js +27 -1
  12. package/dist/adapter-types.js.map +1 -1
  13. package/dist/bounded-collections.d.ts.map +1 -1
  14. package/dist/bounded-collections.js +6 -4
  15. package/dist/bounded-collections.js.map +1 -1
  16. package/dist/debug-info.d.ts.map +1 -1
  17. package/dist/debug-info.js +33 -6
  18. package/dist/debug-info.js.map +1 -1
  19. package/dist/devtools/devtools-compatibility.test.d.ts +2 -0
  20. package/dist/devtools/devtools-compatibility.test.d.ts.map +1 -0
  21. package/dist/devtools/devtools-compatibility.test.js +15 -0
  22. package/dist/devtools/devtools-compatibility.test.js.map +1 -0
  23. package/dist/devtools/devtools-messages-client-session.d.ts +55 -24
  24. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
  25. package/dist/devtools/devtools-messages-client-session.js +22 -5
  26. package/dist/devtools/devtools-messages-client-session.js.map +1 -1
  27. package/dist/devtools/devtools-messages-common.d.ts +11 -14
  28. package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
  29. package/dist/devtools/devtools-messages-common.js +7 -9
  30. package/dist/devtools/devtools-messages-common.js.map +1 -1
  31. package/dist/devtools/devtools-messages-leader.d.ts +65 -30
  32. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
  33. package/dist/devtools/devtools-messages-leader.js +29 -11
  34. package/dist/devtools/devtools-messages-leader.js.map +1 -1
  35. package/dist/devtools/devtools-sessioninfo.d.ts +14 -2
  36. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
  37. package/dist/devtools/devtools-sessioninfo.js +7 -4
  38. package/dist/devtools/devtools-sessioninfo.js.map +1 -1
  39. package/dist/devtools/mod.d.ts +13 -2
  40. package/dist/devtools/mod.d.ts.map +1 -1
  41. package/dist/devtools/mod.js +10 -3
  42. package/dist/devtools/mod.js.map +1 -1
  43. package/dist/errors.d.ts +48 -18
  44. package/dist/errors.d.ts.map +1 -1
  45. package/dist/errors.js +20 -12
  46. package/dist/errors.js.map +1 -1
  47. package/dist/index.d.ts +4 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +4 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/leader-thread/LeaderSyncProcessor.d.ts +53 -6
  52. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  53. package/dist/leader-thread/LeaderSyncProcessor.js +325 -257
  54. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  55. package/dist/leader-thread/RejectedPushError.d.ts +107 -0
  56. package/dist/leader-thread/RejectedPushError.d.ts.map +1 -0
  57. package/dist/leader-thread/RejectedPushError.js +78 -0
  58. package/dist/leader-thread/RejectedPushError.js.map +1 -0
  59. package/dist/leader-thread/connection.js +1 -1
  60. package/dist/leader-thread/connection.js.map +1 -1
  61. package/dist/leader-thread/eventlog.d.ts +19 -14
  62. package/dist/leader-thread/eventlog.d.ts.map +1 -1
  63. package/dist/leader-thread/eventlog.js +78 -18
  64. package/dist/leader-thread/eventlog.js.map +1 -1
  65. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -2
  66. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  67. package/dist/leader-thread/leader-worker-devtools.js +90 -58
  68. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  69. package/dist/leader-thread/make-leader-thread-layer.d.ts +15 -7
  70. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  71. package/dist/leader-thread/make-leader-thread-layer.js +49 -17
  72. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  73. package/dist/leader-thread/make-leader-thread-layer.test.d.ts +2 -0
  74. package/dist/leader-thread/make-leader-thread-layer.test.d.ts.map +1 -0
  75. package/dist/leader-thread/make-leader-thread-layer.test.js +32 -0
  76. package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -0
  77. package/dist/leader-thread/materialize-event.d.ts +1 -1
  78. package/dist/leader-thread/materialize-event.d.ts.map +1 -1
  79. package/dist/leader-thread/materialize-event.js +28 -9
  80. package/dist/leader-thread/materialize-event.js.map +1 -1
  81. package/dist/leader-thread/mod.d.ts +1 -0
  82. package/dist/leader-thread/mod.d.ts.map +1 -1
  83. package/dist/leader-thread/mod.js +1 -0
  84. package/dist/leader-thread/mod.js.map +1 -1
  85. package/dist/leader-thread/recreate-db.d.ts +2 -2
  86. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  87. package/dist/leader-thread/recreate-db.js +6 -6
  88. package/dist/leader-thread/recreate-db.js.map +1 -1
  89. package/dist/leader-thread/shutdown-channel.d.ts +2 -2
  90. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  91. package/dist/leader-thread/shutdown-channel.js +2 -2
  92. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  93. package/dist/leader-thread/stream-events.d.ts +56 -0
  94. package/dist/leader-thread/stream-events.d.ts.map +1 -0
  95. package/dist/leader-thread/stream-events.js +167 -0
  96. package/dist/leader-thread/stream-events.js.map +1 -0
  97. package/dist/leader-thread/types.d.ts +95 -17
  98. package/dist/leader-thread/types.d.ts.map +1 -1
  99. package/dist/leader-thread/types.js +13 -0
  100. package/dist/leader-thread/types.js.map +1 -1
  101. package/dist/logging.d.ts +40 -0
  102. package/dist/logging.d.ts.map +1 -0
  103. package/dist/logging.js +33 -0
  104. package/dist/logging.js.map +1 -0
  105. package/dist/make-client-session.d.ts +5 -3
  106. package/dist/make-client-session.d.ts.map +1 -1
  107. package/dist/make-client-session.js +7 -4
  108. package/dist/make-client-session.js.map +1 -1
  109. package/dist/materializer-helper.d.ts +6 -6
  110. package/dist/materializer-helper.d.ts.map +1 -1
  111. package/dist/materializer-helper.js +18 -8
  112. package/dist/materializer-helper.js.map +1 -1
  113. package/dist/otel.d.ts +2 -1
  114. package/dist/otel.d.ts.map +1 -1
  115. package/dist/otel.js +7 -2
  116. package/dist/otel.js.map +1 -1
  117. package/dist/rematerialize-from-eventlog.d.ts +3 -3
  118. package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
  119. package/dist/rematerialize-from-eventlog.js +40 -29
  120. package/dist/rematerialize-from-eventlog.js.map +1 -1
  121. package/dist/schema/EventDef/define.d.ts +161 -0
  122. package/dist/schema/EventDef/define.d.ts.map +1 -0
  123. package/dist/schema/EventDef/define.js +140 -0
  124. package/dist/schema/EventDef/define.js.map +1 -0
  125. package/dist/schema/EventDef/deprecated.d.ts +99 -0
  126. package/dist/schema/EventDef/deprecated.d.ts.map +1 -0
  127. package/dist/schema/EventDef/deprecated.js +144 -0
  128. package/dist/schema/EventDef/deprecated.js.map +1 -0
  129. package/dist/schema/EventDef/deprecated.test.d.ts +2 -0
  130. package/dist/schema/EventDef/deprecated.test.d.ts.map +1 -0
  131. package/dist/schema/EventDef/deprecated.test.js +95 -0
  132. package/dist/schema/EventDef/deprecated.test.js.map +1 -0
  133. package/dist/schema/EventDef/event-def.d.ts +110 -0
  134. package/dist/schema/EventDef/event-def.d.ts.map +1 -0
  135. package/dist/schema/EventDef/event-def.js +2 -0
  136. package/dist/schema/EventDef/event-def.js.map +1 -0
  137. package/dist/schema/EventDef/facts.d.ts +118 -0
  138. package/dist/schema/EventDef/facts.d.ts.map +1 -0
  139. package/dist/schema/EventDef/facts.js +53 -0
  140. package/dist/schema/EventDef/facts.js.map +1 -0
  141. package/dist/schema/EventDef/materializer.d.ts +155 -0
  142. package/dist/schema/EventDef/materializer.d.ts.map +1 -0
  143. package/dist/schema/EventDef/materializer.js +83 -0
  144. package/dist/schema/EventDef/materializer.js.map +1 -0
  145. package/dist/schema/EventDef/mod.d.ts +6 -0
  146. package/dist/schema/EventDef/mod.d.ts.map +1 -0
  147. package/dist/schema/EventDef/mod.js +6 -0
  148. package/dist/schema/EventDef/mod.js.map +1 -0
  149. package/dist/schema/EventSequenceNumber/client.d.ts +136 -0
  150. package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -0
  151. package/dist/schema/EventSequenceNumber/client.js +193 -0
  152. package/dist/schema/EventSequenceNumber/client.js.map +1 -0
  153. package/dist/schema/EventSequenceNumber/global.d.ts +15 -0
  154. package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -0
  155. package/dist/schema/EventSequenceNumber/global.js +14 -0
  156. package/dist/schema/EventSequenceNumber/global.js.map +1 -0
  157. package/dist/schema/EventSequenceNumber/mod.d.ts +37 -0
  158. package/dist/schema/EventSequenceNumber/mod.d.ts.map +1 -0
  159. package/dist/schema/EventSequenceNumber/mod.js +37 -0
  160. package/dist/schema/EventSequenceNumber/mod.js.map +1 -0
  161. package/dist/schema/EventSequenceNumber.test.js +44 -44
  162. package/dist/schema/EventSequenceNumber.test.js.map +1 -1
  163. package/dist/schema/{LiveStoreEvent.d.ts → LiveStoreEvent/client.d.ts} +102 -111
  164. package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -0
  165. package/dist/schema/LiveStoreEvent/client.js +176 -0
  166. package/dist/schema/LiveStoreEvent/client.js.map +1 -0
  167. package/dist/schema/LiveStoreEvent/client.test.d.ts +2 -0
  168. package/dist/schema/LiveStoreEvent/client.test.d.ts.map +1 -0
  169. package/dist/schema/LiveStoreEvent/client.test.js +111 -0
  170. package/dist/schema/LiveStoreEvent/client.test.js.map +1 -0
  171. package/dist/schema/LiveStoreEvent/for-event-def.d.ts +52 -0
  172. package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -0
  173. package/dist/schema/LiveStoreEvent/for-event-def.js +2 -0
  174. package/dist/schema/LiveStoreEvent/for-event-def.js.map +1 -0
  175. package/dist/schema/LiveStoreEvent/global.d.ts +36 -0
  176. package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -0
  177. package/dist/schema/LiveStoreEvent/global.js +31 -0
  178. package/dist/schema/LiveStoreEvent/global.js.map +1 -0
  179. package/dist/schema/LiveStoreEvent/input.d.ts +46 -0
  180. package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -0
  181. package/dist/schema/LiveStoreEvent/input.js +26 -0
  182. package/dist/schema/LiveStoreEvent/input.js.map +1 -0
  183. package/dist/schema/LiveStoreEvent/mod.d.ts +5 -0
  184. package/dist/schema/LiveStoreEvent/mod.d.ts.map +1 -0
  185. package/dist/schema/LiveStoreEvent/mod.js +5 -0
  186. package/dist/schema/LiveStoreEvent/mod.js.map +1 -0
  187. package/dist/schema/events.d.ts +1 -1
  188. package/dist/schema/events.d.ts.map +1 -1
  189. package/dist/schema/events.js +1 -1
  190. package/dist/schema/events.js.map +1 -1
  191. package/dist/schema/mod.d.ts +6 -4
  192. package/dist/schema/mod.d.ts.map +1 -1
  193. package/dist/schema/mod.js +5 -4
  194. package/dist/schema/mod.js.map +1 -1
  195. package/dist/schema/schema.d.ts +16 -1
  196. package/dist/schema/schema.d.ts.map +1 -1
  197. package/dist/schema/schema.js +32 -4
  198. package/dist/schema/schema.js.map +1 -1
  199. package/dist/schema/state/sqlite/client-document-def.d.ts +2 -1
  200. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  201. package/dist/schema/state/sqlite/client-document-def.js +36 -15
  202. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  203. package/dist/schema/state/sqlite/client-document-def.test.js +121 -2
  204. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
  205. package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
  206. package/dist/schema/state/sqlite/column-annotations.js +1 -1
  207. package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
  208. package/dist/schema/state/sqlite/column-annotations.test.js +2 -2
  209. package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
  210. package/dist/schema/state/sqlite/column-def.d.ts.map +1 -1
  211. package/dist/schema/state/sqlite/column-def.js +96 -47
  212. package/dist/schema/state/sqlite/column-def.js.map +1 -1
  213. package/dist/schema/state/sqlite/column-def.test.js +51 -12
  214. package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
  215. package/dist/schema/state/sqlite/column-spec.d.ts.map +1 -1
  216. package/dist/schema/state/sqlite/column-spec.js +30 -12
  217. package/dist/schema/state/sqlite/column-spec.js.map +1 -1
  218. package/dist/schema/state/sqlite/column-spec.test.js +24 -15
  219. package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
  220. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +2 -2
  221. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
  222. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +16 -10
  223. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
  224. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +15 -4
  225. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
  226. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +1 -1
  227. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -1
  228. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +1 -1
  229. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
  230. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +1 -1
  231. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
  232. package/dist/schema/state/sqlite/mod.d.ts +2 -2
  233. package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
  234. package/dist/schema/state/sqlite/mod.js +5 -7
  235. package/dist/schema/state/sqlite/mod.js.map +1 -1
  236. package/dist/schema/state/sqlite/query-builder/api.d.ts +51 -22
  237. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
  238. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
  239. package/dist/schema/state/sqlite/query-builder/astToSql.js +99 -22
  240. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
  241. package/dist/schema/state/sqlite/query-builder/impl.d.ts +1 -1
  242. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
  243. package/dist/schema/state/sqlite/query-builder/impl.js +28 -15
  244. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
  245. package/dist/schema/state/sqlite/query-builder/impl.test.js +231 -93
  246. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  247. package/dist/schema/state/sqlite/schema-helpers.d.ts +2 -2
  248. package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -1
  249. package/dist/schema/state/sqlite/schema-helpers.js +24 -14
  250. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
  251. package/dist/schema/state/sqlite/schema-helpers.test.d.ts +2 -0
  252. package/dist/schema/state/sqlite/schema-helpers.test.d.ts.map +1 -0
  253. package/dist/schema/state/sqlite/schema-helpers.test.js +36 -0
  254. package/dist/schema/state/sqlite/schema-helpers.test.js.map +1 -0
  255. package/dist/schema/state/sqlite/{system-tables.d.ts → system-tables/eventlog-tables.d.ts} +21 -450
  256. package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts.map +1 -0
  257. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +54 -0
  258. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -0
  259. package/dist/schema/state/sqlite/system-tables/mod.d.ts +3 -0
  260. package/dist/schema/state/sqlite/system-tables/mod.d.ts.map +1 -0
  261. package/dist/schema/state/sqlite/system-tables/mod.js +3 -0
  262. package/dist/schema/state/sqlite/system-tables/mod.js.map +1 -0
  263. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +456 -0
  264. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -0
  265. package/dist/schema/state/sqlite/system-tables/state-tables.js +55 -0
  266. package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -0
  267. package/dist/schema/state/sqlite/table-def.d.ts +5 -3
  268. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  269. package/dist/schema/state/sqlite/table-def.js +1 -1
  270. package/dist/schema/state/sqlite/table-def.js.map +1 -1
  271. package/dist/schema/state/sqlite/table-def.test.js +92 -3
  272. package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
  273. package/dist/schema/unknown-events.d.ts +47 -0
  274. package/dist/schema/unknown-events.d.ts.map +1 -0
  275. package/dist/schema/unknown-events.js +69 -0
  276. package/dist/schema/unknown-events.js.map +1 -0
  277. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts +2 -0
  278. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts.map +1 -0
  279. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +73 -0
  280. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -0
  281. package/dist/schema-management/common.js +2 -2
  282. package/dist/schema-management/common.js.map +1 -1
  283. package/dist/schema-management/migrations.d.ts +32 -2
  284. package/dist/schema-management/migrations.d.ts.map +1 -1
  285. package/dist/schema-management/migrations.js +38 -6
  286. package/dist/schema-management/migrations.js.map +1 -1
  287. package/dist/schema-management/validate-schema.d.ts +3 -3
  288. package/dist/schema-management/validate-schema.d.ts.map +1 -1
  289. package/dist/schema-management/validate-schema.js +2 -2
  290. package/dist/schema-management/validate-schema.js.map +1 -1
  291. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  292. package/dist/sql-queries/sql-queries.js +18 -6
  293. package/dist/sql-queries/sql-queries.js.map +1 -1
  294. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  295. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  296. package/dist/sqlite-db-helper.js +3 -3
  297. package/dist/sqlite-db-helper.js.map +1 -1
  298. package/dist/sqlite-types.d.ts +5 -5
  299. package/dist/sqlite-types.d.ts.map +1 -1
  300. package/dist/sqlite-types.js.map +1 -1
  301. package/dist/sync/ClientSessionSyncProcessor.d.ts +12 -12
  302. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  303. package/dist/sync/ClientSessionSyncProcessor.js +99 -114
  304. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  305. package/dist/sync/errors.d.ts +0 -33
  306. package/dist/sync/errors.d.ts.map +1 -1
  307. package/dist/sync/errors.js +5 -22
  308. package/dist/sync/errors.js.map +1 -1
  309. package/dist/sync/index.d.ts +2 -0
  310. package/dist/sync/index.d.ts.map +1 -1
  311. package/dist/sync/index.js +2 -0
  312. package/dist/sync/index.js.map +1 -1
  313. package/dist/sync/mock-sync-backend.d.ts +10 -8
  314. package/dist/sync/mock-sync-backend.d.ts.map +1 -1
  315. package/dist/sync/mock-sync-backend.js +71 -69
  316. package/dist/sync/mock-sync-backend.js.map +1 -1
  317. package/dist/sync/next/compact-events.d.ts.map +1 -1
  318. package/dist/sync/next/compact-events.js +11 -12
  319. package/dist/sync/next/compact-events.js.map +1 -1
  320. package/dist/sync/next/facts.d.ts +5 -5
  321. package/dist/sync/next/facts.d.ts.map +1 -1
  322. package/dist/sync/next/facts.js +7 -8
  323. package/dist/sync/next/facts.js.map +1 -1
  324. package/dist/sync/next/history-dag-common.d.ts +54 -15
  325. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  326. package/dist/sync/next/history-dag-common.js +198 -9
  327. package/dist/sync/next/history-dag-common.js.map +1 -1
  328. package/dist/sync/next/history-dag.d.ts.map +1 -1
  329. package/dist/sync/next/history-dag.js +11 -11
  330. package/dist/sync/next/history-dag.js.map +1 -1
  331. package/dist/sync/next/rebase-events.d.ts +5 -5
  332. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  333. package/dist/sync/next/rebase-events.js +6 -6
  334. package/dist/sync/next/rebase-events.js.map +1 -1
  335. package/dist/sync/next/test/compact-events.calculator.test.js +2 -2
  336. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  337. package/dist/sync/next/test/compact-events.test.d.ts.map +1 -1
  338. package/dist/sync/next/test/compact-events.test.js +2 -2
  339. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  340. package/dist/sync/next/test/event-fixtures.d.ts +2 -2
  341. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
  342. package/dist/sync/next/test/event-fixtures.js +11 -11
  343. package/dist/sync/next/test/event-fixtures.js.map +1 -1
  344. package/dist/sync/sync-backend-kv.d.ts +3 -3
  345. package/dist/sync/sync-backend-kv.d.ts.map +1 -1
  346. package/dist/sync/sync-backend-kv.js +3 -3
  347. package/dist/sync/sync-backend-kv.js.map +1 -1
  348. package/dist/sync/sync-backend.d.ts +33 -13
  349. package/dist/sync/sync-backend.d.ts.map +1 -1
  350. package/dist/sync/sync-backend.js +38 -1
  351. package/dist/sync/sync-backend.js.map +1 -1
  352. package/dist/sync/sync.d.ts +23 -2
  353. package/dist/sync/sync.d.ts.map +1 -1
  354. package/dist/sync/syncstate.d.ts +55 -55
  355. package/dist/sync/syncstate.d.ts.map +1 -1
  356. package/dist/sync/syncstate.js +80 -98
  357. package/dist/sync/syncstate.js.map +1 -1
  358. package/dist/sync/syncstate.test.js +221 -132
  359. package/dist/sync/syncstate.test.js.map +1 -1
  360. package/dist/sync/transport-chunking.d.ts +36 -0
  361. package/dist/sync/transport-chunking.d.ts.map +1 -0
  362. package/dist/sync/transport-chunking.js +56 -0
  363. package/dist/sync/transport-chunking.js.map +1 -0
  364. package/dist/sync/validate-push-payload.d.ts +2 -2
  365. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  366. package/dist/sync/validate-push-payload.js +4 -6
  367. package/dist/sync/validate-push-payload.js.map +1 -1
  368. package/dist/testing/event-factory.d.ts +3 -3
  369. package/dist/testing/event-factory.d.ts.map +1 -1
  370. package/dist/testing/event-factory.js +5 -7
  371. package/dist/testing/event-factory.js.map +1 -1
  372. package/dist/util.js +2 -2
  373. package/dist/util.js.map +1 -1
  374. package/dist/version.d.ts +24 -5
  375. package/dist/version.d.ts.map +1 -1
  376. package/dist/version.js +25 -8
  377. package/dist/version.js.map +1 -1
  378. package/package.json +67 -15
  379. package/src/ClientSessionLeaderThreadProxy.ts +27 -12
  380. package/src/WorkerTransportError.ts +12 -0
  381. package/src/adapter-types.ts +50 -7
  382. package/src/bounded-collections.ts +6 -5
  383. package/src/debug-info.ts +37 -6
  384. package/src/devtools/devtools-compatibility.test.ts +18 -0
  385. package/src/devtools/devtools-messages-client-session.ts +22 -4
  386. package/src/devtools/devtools-messages-common.ts +7 -12
  387. package/src/devtools/devtools-messages-leader.ts +29 -10
  388. package/src/devtools/devtools-sessioninfo.ts +8 -5
  389. package/src/devtools/mod.ts +11 -2
  390. package/src/errors.ts +32 -24
  391. package/src/index.ts +4 -1
  392. package/src/leader-thread/LeaderSyncProcessor.ts +523 -373
  393. package/src/leader-thread/RejectedPushError.ts +106 -0
  394. package/src/leader-thread/connection.ts +1 -1
  395. package/src/leader-thread/eventlog.ts +112 -39
  396. package/src/leader-thread/leader-worker-devtools.ts +201 -120
  397. package/src/leader-thread/make-leader-thread-layer.test.ts +44 -0
  398. package/src/leader-thread/make-leader-thread-layer.ts +125 -40
  399. package/src/leader-thread/materialize-event.ts +40 -10
  400. package/src/leader-thread/mod.ts +1 -0
  401. package/src/leader-thread/recreate-db.ts +7 -7
  402. package/src/leader-thread/shutdown-channel.ts +4 -8
  403. package/src/leader-thread/stream-events.ts +206 -0
  404. package/src/leader-thread/types.ts +68 -18
  405. package/src/logging.ts +62 -0
  406. package/src/make-client-session.ts +11 -5
  407. package/src/materializer-helper.ts +27 -16
  408. package/src/otel.ts +13 -2
  409. package/src/rematerialize-from-eventlog.ts +61 -51
  410. package/src/schema/EventDef/define.ts +217 -0
  411. package/src/schema/EventDef/deprecated.test.ts +129 -0
  412. package/src/schema/EventDef/deprecated.ts +175 -0
  413. package/src/schema/EventDef/event-def.ts +125 -0
  414. package/src/schema/EventDef/facts.ts +135 -0
  415. package/src/schema/EventDef/materializer.ts +172 -0
  416. package/src/schema/EventDef/mod.ts +5 -0
  417. package/src/schema/EventSequenceNumber/client.ts +257 -0
  418. package/src/schema/EventSequenceNumber/global.ts +19 -0
  419. package/src/schema/EventSequenceNumber/mod.ts +37 -0
  420. package/src/schema/EventSequenceNumber.test.ts +72 -53
  421. package/src/schema/LiveStoreEvent/client.test.ts +129 -0
  422. package/src/schema/LiveStoreEvent/client.ts +235 -0
  423. package/src/schema/LiveStoreEvent/for-event-def.ts +60 -0
  424. package/src/schema/LiveStoreEvent/global.ts +45 -0
  425. package/src/schema/LiveStoreEvent/input.ts +63 -0
  426. package/src/schema/LiveStoreEvent/mod.ts +4 -0
  427. package/src/schema/events.ts +1 -1
  428. package/src/schema/mod.ts +6 -4
  429. package/src/schema/schema.ts +46 -5
  430. package/src/schema/state/sqlite/client-document-def.test.ts +144 -5
  431. package/src/schema/state/sqlite/client-document-def.ts +47 -34
  432. package/src/schema/state/sqlite/column-annotations.test.ts +3 -2
  433. package/src/schema/state/sqlite/column-annotations.ts +2 -1
  434. package/src/schema/state/sqlite/column-def.test.ts +66 -12
  435. package/src/schema/state/sqlite/column-def.ts +119 -47
  436. package/src/schema/state/sqlite/column-spec.test.ts +32 -17
  437. package/src/schema/state/sqlite/column-spec.ts +37 -11
  438. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +2 -2
  439. package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +2 -1
  440. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +41 -15
  441. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +13 -19
  442. package/src/schema/state/sqlite/mod.ts +7 -8
  443. package/src/schema/state/sqlite/query-builder/api.ts +55 -17
  444. package/src/schema/state/sqlite/query-builder/astToSql.ts +110 -21
  445. package/src/schema/state/sqlite/query-builder/impl.test.ts +267 -93
  446. package/src/schema/state/sqlite/query-builder/impl.ts +26 -13
  447. package/src/schema/state/sqlite/schema-helpers.test.ts +44 -0
  448. package/src/schema/state/sqlite/schema-helpers.ts +30 -22
  449. package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +64 -0
  450. package/src/schema/state/sqlite/system-tables/mod.ts +2 -0
  451. package/src/schema/state/sqlite/system-tables/state-tables.ts +69 -0
  452. package/src/schema/state/sqlite/table-def.test.ts +114 -3
  453. package/src/schema/state/sqlite/table-def.ts +16 -22
  454. package/src/schema/unknown-events.ts +131 -0
  455. package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +88 -0
  456. package/src/schema-management/common.ts +2 -2
  457. package/src/schema-management/migrations.ts +42 -9
  458. package/src/schema-management/validate-schema.ts +3 -3
  459. package/src/sql-queries/sql-queries.ts +18 -6
  460. package/src/sql-queries/sql-query-builder.ts +1 -0
  461. package/src/sqlite-db-helper.ts +3 -3
  462. package/src/sqlite-types.ts +6 -5
  463. package/src/sync/ClientSessionSyncProcessor.ts +152 -142
  464. package/src/sync/errors.ts +12 -24
  465. package/src/sync/index.ts +2 -0
  466. package/src/sync/mock-sync-backend.ts +146 -104
  467. package/src/sync/next/compact-events.ts +10 -11
  468. package/src/sync/next/facts.ts +13 -14
  469. package/src/sync/next/history-dag-common.ts +280 -26
  470. package/src/sync/next/history-dag.ts +17 -13
  471. package/src/sync/next/rebase-events.ts +12 -12
  472. package/src/sync/next/test/compact-events.calculator.test.ts +3 -2
  473. package/src/sync/next/test/compact-events.test.ts +4 -3
  474. package/src/sync/next/test/event-fixtures.ts +13 -13
  475. package/src/sync/sync-backend-kv.ts +4 -3
  476. package/src/sync/sync-backend.ts +66 -17
  477. package/src/sync/sync.ts +24 -2
  478. package/src/sync/syncstate.test.ts +583 -419
  479. package/src/sync/syncstate.ts +127 -122
  480. package/src/sync/transport-chunking.ts +90 -0
  481. package/src/sync/validate-push-payload.ts +6 -8
  482. package/src/testing/event-factory.ts +10 -12
  483. package/src/util.ts +2 -2
  484. package/src/version.ts +33 -8
  485. package/dist/schema/EventDef.d.ts +0 -126
  486. package/dist/schema/EventDef.d.ts.map +0 -1
  487. package/dist/schema/EventDef.js +0 -46
  488. package/dist/schema/EventDef.js.map +0 -1
  489. package/dist/schema/EventSequenceNumber.d.ts +0 -80
  490. package/dist/schema/EventSequenceNumber.d.ts.map +0 -1
  491. package/dist/schema/EventSequenceNumber.js +0 -139
  492. package/dist/schema/EventSequenceNumber.js.map +0 -1
  493. package/dist/schema/LiveStoreEvent.d.ts.map +0 -1
  494. package/dist/schema/LiveStoreEvent.js +0 -147
  495. package/dist/schema/LiveStoreEvent.js.map +0 -1
  496. package/dist/schema/state/sqlite/system-tables.d.ts.map +0 -1
  497. package/dist/schema/state/sqlite/system-tables.js +0 -81
  498. package/dist/schema/state/sqlite/system-tables.js.map +0 -1
  499. package/dist/sync/next/graphology.d.ts +0 -8
  500. package/dist/sync/next/graphology.d.ts.map +0 -1
  501. package/dist/sync/next/graphology.js +0 -30
  502. package/dist/sync/next/graphology.js.map +0 -1
  503. package/dist/sync/next/graphology_.d.ts +0 -3
  504. package/dist/sync/next/graphology_.d.ts.map +0 -1
  505. package/dist/sync/next/graphology_.js +0 -3
  506. package/dist/sync/next/graphology_.js.map +0 -1
  507. package/src/schema/EventDef.ts +0 -222
  508. package/src/schema/EventSequenceNumber.ts +0 -199
  509. package/src/schema/LiveStoreEvent.ts +0 -286
  510. package/src/schema/state/sqlite/system-tables.ts +0 -106
  511. package/src/sync/next/ambient.d.ts +0 -3
  512. package/src/sync/next/graphology.ts +0 -41
  513. package/src/sync/next/graphology_.ts +0 -2
@@ -1,12 +1,30 @@
1
1
  import { casesHandled } from '@livestore/utils'
2
2
  import { Option, Schema } from '@livestore/utils/effect'
3
3
 
4
- export type ColumnDefinition<TEncoded, TDecoded> = {
4
+ export type SqlDefaultValue = {
5
+ readonly sql: string
6
+ }
7
+
8
+ export const isSqlDefaultValue = (value: unknown): value is SqlDefaultValue => {
9
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- type guard property access after structural check
10
+ return typeof value === 'object' && value !== null && 'sql' in value && typeof (value as any).sql === 'string'
11
+ }
12
+
13
+ export type ColumnDefaultThunk<T> = () => T
14
+
15
+ export const isDefaultThunk = (value: unknown): value is ColumnDefaultThunk<unknown> => typeof value === 'function'
16
+
17
+ export type ColumnDefaultValue<T> = T | null | ColumnDefaultThunk<T | null> | SqlDefaultValue
18
+
19
+ export const resolveColumnDefault = <T>(value: ColumnDefaultValue<T>): T | null | SqlDefaultValue =>
20
+ isDefaultThunk(value) === true ? value() : value
21
+
22
+ export type ColumnDefinition<TEncoded, TDecoded, TNullable extends boolean = boolean> = {
5
23
  readonly columnType: FieldColumnType
6
24
  readonly schema: Schema.Schema<TDecoded, TEncoded>
7
- readonly default: Option.Option<TEncoded>
25
+ readonly default: Option.Option<ColumnDefaultValue<TDecoded>>
8
26
  /** @default false */
9
- readonly nullable: boolean
27
+ readonly nullable: TNullable
10
28
  /** @default false */
11
29
  readonly primaryKey: boolean
12
30
  /** @default false */
@@ -23,13 +41,22 @@ export const isColumnDefinition = (value: unknown): value is ColumnDefinition.An
23
41
  typeof value === 'object' &&
24
42
  value !== null &&
25
43
  'columnType' in value &&
44
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- type guard narrowing; columnType checked to be in valid set
26
45
  validColumnTypes.includes(value.columnType as any)
27
46
  )
28
47
  }
29
48
 
49
+ type MaybeNull<T, TNullable extends boolean> = T | (TNullable extends true ? null : never)
50
+
51
+ type ColumnDefaultArg<T, TNullable extends boolean> =
52
+ | MaybeNull<T, TNullable>
53
+ | ColumnDefaultThunk<MaybeNull<T, TNullable>>
54
+ | SqlDefaultValue
55
+ | NoDefault
56
+
30
57
  export type ColumnDefinitionInput = {
31
58
  readonly schema?: Schema.Schema<unknown>
32
- readonly default?: unknown | NoDefault
59
+ readonly default?: ColumnDefaultArg<unknown, boolean>
33
60
  readonly nullable?: boolean
34
61
  readonly primaryKey?: boolean
35
62
  readonly autoIncrement?: boolean
@@ -38,14 +65,6 @@ export type ColumnDefinitionInput = {
38
65
  export const NoDefault = Symbol.for('NoDefault')
39
66
  export type NoDefault = typeof NoDefault
40
67
 
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
68
  export type ColDefFn<TColumnType extends FieldColumnType> = {
50
69
  (): {
51
70
  columnType: TColumnType
@@ -59,7 +78,7 @@ export type ColDefFn<TColumnType extends FieldColumnType> = {
59
78
  TEncoded extends DefaultEncodedForColumnType<TColumnType>,
60
79
  TDecoded = DefaultEncodedForColumnType<TColumnType>,
61
80
  const TNullable extends boolean = false,
62
- const TDefault extends TDecoded | SqlDefaultValue | NoDefault | (TNullable extends true ? null : never) = NoDefault,
81
+ const TDefault extends ColumnDefaultArg<NoInfer<TDecoded>, TNullable> = NoDefault,
63
82
  const TPrimaryKey extends boolean = false,
64
83
  const TAutoIncrement extends boolean = false,
65
84
  >(args: {
@@ -88,6 +107,7 @@ const makeColDef =
88
107
  const schema = nullable === true ? Schema.NullOr(schemaWithoutNull) : schemaWithoutNull
89
108
  const default_ = def?.default === undefined || def.default === NoDefault ? Option.none() : Option.some(def.default)
90
109
 
110
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- column factory return type uses complex conditional generics; consumer type safety enforced by ColDefFn signature
91
111
  return {
92
112
  columnType,
93
113
  schema,
@@ -132,7 +152,7 @@ export type SpecializedColDefFn<
132
152
  <
133
153
  TDecoded = TBaseDecoded,
134
154
  const TNullable extends boolean = false,
135
- const TDefault extends TDecoded | NoDefault | (TNullable extends true ? null : never) = NoDefault,
155
+ const TDefault extends ColumnDefaultArg<NoInfer<TDecoded>, TNullable> = NoDefault,
136
156
  const TPrimaryKey extends boolean = false,
137
157
  const TAutoIncrement extends boolean = false,
138
158
  >(
@@ -183,10 +203,12 @@ type MakeSpecializedColDefFn = {
183
203
 
184
204
  const makeSpecializedColDef: MakeSpecializedColDefFn = (columnType, opts) => (def?: ColumnDefinitionInput) => {
185
205
  const nullable = def?.nullable ?? false
206
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- schema type variance; custom schema compatibility checked at call site
186
207
  const schemaWithoutNull = opts._tag === 'baseSchemaFn' ? opts.baseSchemaFn(def?.schema as any) : opts.baseSchema
187
208
  const schema = nullable === true ? Schema.NullOr(schemaWithoutNull) : schemaWithoutNull
188
209
  const default_ = def?.default === undefined || def.default === NoDefault ? Option.none() : Option.some(def.default)
189
210
 
211
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- specialized column factory return type uses complex conditional generics; consumer type safety enforced by SpecializedColDefFn signature
190
212
  return {
191
213
  columnType,
192
214
  schema,
@@ -219,7 +241,7 @@ export const boolean: SpecializedColDefFn<'integer', false, boolean> = makeSpeci
219
241
  _tag: 'baseSchema',
220
242
  baseSchema: Schema.transform(Schema.Number, Schema.Boolean, {
221
243
  decode: (_) => _ === 1,
222
- encode: (_) => (_ ? 1 : 0),
244
+ encode: (_) => (_ === true ? 1 : 0),
223
245
  }),
224
246
  })
225
247
 
@@ -242,15 +264,19 @@ export const defaultSchemaForColumnType = <TColumnType extends FieldColumnType>(
242
264
 
243
265
  switch (columnType) {
244
266
  case 'text': {
267
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
245
268
  return Schema.String as any as Schema.Schema<T>
246
269
  }
247
270
  case 'integer': {
271
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
248
272
  return Schema.Number as any as Schema.Schema<T>
249
273
  }
250
274
  case 'real': {
275
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
251
276
  return Schema.Number as any as Schema.Schema<T>
252
277
  }
253
278
  case 'blob': {
279
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
254
280
  return Schema.Uint8ArrayFromSelf as any as Schema.Schema<T>
255
281
  }
256
282
  default: {
@@ -20,19 +20,18 @@ export type DbSchemaInput = Record<string, TableDefinition<any, any>> | Readonly
20
20
  * - array: we use the table name of each array item (= table definition) as the object key
21
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
22
22
  */
23
- export type DbSchemaFromInputSchema<TSchemaInput extends DbSchemaInput> = TSchemaInput extends ReadonlyArray<
24
- TableDefinition<any, any>
25
- >
26
- ? { [K in TSchemaInput[number] as K['name']]: K }
27
- : TSchemaInput extends Record<string, TableDefinition<any, any>>
28
- ? { [K in keyof TSchemaInput as TSchemaInput[K]['name']]: TSchemaInput[K] }
29
- : 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
30
29
 
31
30
  // TODO ensure via runtime check (possibly even via type-level check) that all index names are unique
32
31
  export const makeDbSchema = <TDbSchemaInput extends DbSchemaInput>(
33
32
  schema: TDbSchemaInput,
34
33
  ): DbSchemaFromInputSchema<TDbSchemaInput> => {
35
- return Array.isArray(schema) ? Object.fromEntries(schema.map((_) => [_.name, _])) : (schema as any)
34
+ return Array.isArray(schema) === true ? Object.fromEntries(schema.map((_) => [_.name, _])) : (schema as any)
36
35
  }
37
36
 
38
37
  export const table = <TTableName extends string, TColumns extends Columns, TIndexes extends Index[]>(
@@ -77,6 +76,7 @@ export const insertStructSchemaForTable = <TTableDefinition extends TableDefinit
77
76
  Object.fromEntries(
78
77
  tableDef.ast.columns.map((column) => [
79
78
  column.name,
79
+
80
80
  column.nullable === true || column.default._tag === 'Some' ? Schema.optional(column.schema) : column.schema,
81
81
  ]),
82
82
  ),
@@ -116,12 +116,8 @@ export type TableDefinition<TName extends string, TColumns extends Columns> = {
116
116
 
117
117
  export type Columns = Record<string, ColumnDefinition<any, any>>
118
118
 
119
- export type IsSingleColumn<TColumns extends Columns | ColumnDefinition<any, any>> = TColumns extends ColumnDefinition<
120
- any,
121
- any
122
- >
123
- ? true
124
- : false
119
+ export type IsSingleColumn<TColumns extends Columns | ColumnDefinition<any, any>> =
120
+ TColumns extends ColumnDefinition<any, any> ? true : false
125
121
 
126
122
  /**
127
123
  * NOTE this is only needed to avoid a TS limitation where `StructSchemaForColumns` in the default case
@@ -200,8 +196,7 @@ export namespace FromColumns {
200
196
  }
201
197
 
202
198
  export type NullableColumnNames<TColumns extends Columns> = keyof {
203
- // TODO double check why there is a `true` in the type
204
- [K in keyof TColumns as TColumns[K] extends ColumnDefinition<any, true> ? K : never]: {}
199
+ [K in keyof TColumns as TColumns[K]['nullable'] extends true ? K : never]: {}
205
200
  }
206
201
 
207
202
  export type RequiredInsertColumns<TColumns extends Columns> = {
@@ -214,9 +209,8 @@ export namespace FromColumns {
214
209
 
215
210
  export type RequiredInsertColumnNames<TColumns extends Columns> = keyof RequiredInsertColumns<TColumns>
216
211
 
217
- export type RequiresInsertValues<TColumns extends Columns> = RequiredInsertColumnNames<TColumns> extends never
218
- ? false
219
- : true
212
+ export type RequiresInsertValues<TColumns extends Columns> =
213
+ RequiredInsertColumnNames<TColumns> extends never ? false : true
220
214
 
221
215
  export type InsertRowDecoded<TColumns extends Columns> = Types.Simplify<
222
216
  Pick<RowDecodedAll<TColumns>, RequiredInsertColumnNames<TColumns>> &
@@ -1,14 +1,14 @@
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,
@@ -22,16 +22,15 @@ export * from './column-spec.ts'
22
22
  export * from './table-def.ts'
23
23
 
24
24
  export const makeState = <TStateInput extends InputState>(inputSchema: TStateInput): InternalState => {
25
- const inputTables: ReadonlyArray<TableDef> = Array.isArray(inputSchema.tables)
26
- ? inputSchema.tables
27
- : Object.values(inputSchema.tables)
25
+ const inputTables: ReadonlyArray<TableDef> =
26
+ Array.isArray(inputSchema.tables) === true ? inputSchema.tables : Object.values(inputSchema.tables)
28
27
 
29
28
  const tables = new Map<string, TableDef.Any>()
30
29
 
31
30
  for (const tableDef of inputTables) {
32
31
  const sqliteDef = tableDef.sqliteDef
33
32
  // TODO validate tables (e.g. index names are unique)
34
- if (tables.has(sqliteDef.ast.name)) {
33
+ if (tables.has(sqliteDef.ast.name) === true) {
35
34
  shouldNeverHappen(`Duplicate table name: ${sqliteDef.ast.name}. Please use unique names for tables.`)
36
35
  }
37
36
  tables.set(sqliteDef.ast.name, tableDef)
@@ -48,7 +47,7 @@ export const makeState = <TStateInput extends InputState>(inputSchema: TStateInp
48
47
  }
49
48
 
50
49
  for (const tableDef of inputTables) {
51
- if (tableIsClientDocumentTable(tableDef)) {
50
+ if (tableIsClientDocumentTable(tableDef) === true) {
52
51
  materializers.set(
53
52
  tableDef[ClientDocumentTableDefSymbol].derived.setEventDef.name,
54
53
  tableDef[ClientDocumentTableDefSymbol].derived.setMaterializer,
@@ -128,15 +128,25 @@ export type QueryBuilder<
128
128
 
129
129
  export namespace QueryBuilder {
130
130
  export type Any = QueryBuilder<any, any, any>
131
- export type WhereOps = WhereOps.Equality | WhereOps.Order | WhereOps.Like | WhereOps.In
131
+ export type WhereOps = WhereOps.Equality | WhereOps.Order | WhereOps.Like | WhereOps.In | WhereOps.JsonArray
132
132
 
133
133
  export namespace WhereOps {
134
134
  export type Equality = '=' | '!='
135
135
  export type Order = '<' | '>' | '<=' | '>='
136
136
  export type Like = 'LIKE' | 'NOT LIKE' | 'ILIKE' | 'NOT ILIKE'
137
137
  export type In = 'IN' | 'NOT IN'
138
+ /**
139
+ * Operators for checking if a JSON array column contains a value.
140
+ *
141
+ * ⚠️ **Performance note**: These operators use SQLite's `json_each()` table-valued function
142
+ * which **cannot be indexed** and requires a full table scan. For large tables with frequent
143
+ * lookups, consider denormalizing the data into a separate indexed table.
144
+ *
145
+ * @see https://sqlite.org/json1.html#jeach
146
+ */
147
+ export type JsonArray = 'JSON_CONTAINS' | 'JSON_NOT_CONTAINS'
138
148
 
139
- export type SingleValue = Equality | Order | Like
149
+ export type SingleValue = Equality | Order | Like | JsonArray
140
150
  export type MultiValue = In
141
151
  }
142
152
 
@@ -155,14 +165,26 @@ export namespace QueryBuilder {
155
165
  | 'returning'
156
166
  | 'onConflict'
157
167
 
168
+ /** Extracts the element type from an array type, or returns never if not an array */
169
+ type ArrayElement<T> = T extends ReadonlyArray<infer E> ? E : never
170
+
158
171
  export type WhereParams<TTableDef extends TableDefBase> = Partial<{
159
172
  [K in keyof TTableDef['sqliteDef']['columns']]:
160
173
  | TTableDef['sqliteDef']['columns'][K]['schema']['Type']
161
- | { op: QueryBuilder.WhereOps.SingleValue; value: TTableDef['sqliteDef']['columns'][K]['schema']['Type'] }
174
+ | {
175
+ op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>
176
+ value: TTableDef['sqliteDef']['columns'][K]['schema']['Type']
177
+ }
162
178
  | {
163
179
  op: QueryBuilder.WhereOps.MultiValue
164
180
  value: ReadonlyArray<TTableDef['sqliteDef']['columns'][K]['schema']['Type']>
165
181
  }
182
+ | (ArrayElement<TTableDef['sqliteDef']['columns'][K]['schema']['Type']> extends never
183
+ ? never
184
+ : {
185
+ op: QueryBuilder.WhereOps.JsonArray
186
+ value: ArrayElement<TTableDef['sqliteDef']['columns'][K]['schema']['Type']>
187
+ })
166
188
  | undefined
167
189
  }>
168
190
 
@@ -208,9 +230,8 @@ export namespace QueryBuilder {
208
230
  /** Select multiple columns */
209
231
  <TColumns extends keyof TTableDef['sqliteDef']['columns'] & string>(
210
232
  ...columns: TColumns[]
211
- // TODO also support arbitrary SQL selects
212
- // params: QueryBuilderSelectParams,
213
- ): QueryBuilder<
233
+ )// params: QueryBuilderSelectParams, // TODO also support arbitrary SQL selects
234
+ : QueryBuilder<
214
235
  ReadonlyArray<{
215
236
  readonly [K in TColumns]: TTableDef['sqliteDef']['columns'][K]['schema']['Type']
216
237
  }>,
@@ -242,7 +263,12 @@ export namespace QueryBuilder {
242
263
  ): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
243
264
  <TColName extends keyof TTableDef['sqliteDef']['columns']>(
244
265
  col: TColName,
245
- op: QueryBuilder.WhereOps,
266
+ op: QueryBuilder.WhereOps.MultiValue,
267
+ value: ReadonlyArray<TTableDef['sqliteDef']['columns'][TColName]['schema']['Type']>,
268
+ ): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
269
+ <TColName extends keyof TTableDef['sqliteDef']['columns']>(
270
+ col: TColName,
271
+ op: QueryBuilder.WhereOps.SingleValue,
246
272
  value: TTableDef['sqliteDef']['columns'][TColName]['schema']['Type'],
247
273
  ): QueryBuilder<TResult, TTableDef, TWithout | 'row' | 'select'>
248
274
  }
@@ -331,12 +357,20 @@ export namespace QueryBuilder {
331
357
  >
332
358
 
333
359
  /**
334
- * Insert a new row into the table
360
+ * Insert a new row into the table.
361
+ *
362
+ * @remarks
363
+ *
364
+ * Follows SQL semantics: nullable columns and columns with defaults are omittable.
365
+ * `NullOr(S)` and `optional(NullOr(S))` both produce nullable columns, so both are omittable.
366
+ *
367
+ * @example
335
368
  *
336
- * Example:
337
369
  * ```ts
338
370
  * db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' })
339
371
  * ```
372
+ *
373
+ * @param values - The row values to insert.
340
374
  */
341
375
  readonly insert: (
342
376
  values: TTableDef['insertSchema']['Type'],
@@ -347,22 +381,26 @@ export namespace QueryBuilder {
347
381
  >
348
382
 
349
383
  /**
350
- * Example: If the row already exists, it will be ignored.
384
+ * Upsert: insert a row, or handle conflicts on existing rows.
385
+ * Equivalent to SQLite's `INSERT ... ON CONFLICT` clause.
386
+ *
387
+ * Actions:
388
+ * - `'ignore'`: Skip the insert if a row with the same key exists
389
+ * - `'replace'`: Delete the existing row and insert the new one
390
+ * - `'update'`: Update specific columns on the existing row
391
+ *
351
392
  * ```ts
393
+ * // Ignore: skip if row exists
352
394
  * db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'ignore')
353
- * ```
354
395
  *
355
- * Example: If the row already exists, it will be replaced.
356
- * ```ts
396
+ * // Replace: delete existing row and insert new one
357
397
  * db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'replace')
358
- * ```
359
398
  *
360
- * Example: If the row already exists, it will be updated.
361
- * ```ts
399
+ * // Update: merge specific columns into existing row
362
400
  * db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' }).onConflict('id', 'update', { text: 'Buy soy milk' })
363
401
  * ```
364
402
  *
365
- * NOTE This API doesn't yet support composite primary keys.
403
+ * NOTE: Composite primary keys are not yet supported.
366
404
  */
367
405
  readonly onConflict: {
368
406
  <TTarget extends SingleOrReadonlyArray<keyof TTableDef['sqliteDef']['columns']>>(
@@ -1,12 +1,77 @@
1
1
  import { shouldNeverHappen } from '@livestore/utils'
2
- import { Schema } from '@livestore/utils/effect'
2
+ import { Schema, SchemaAST } from '@livestore/utils/effect'
3
3
 
4
4
  import { SessionIdSymbol } from '../../../../adapter-types.ts'
5
5
  import type { SqlValue } from '../../../../util.ts'
6
6
  import type { State } from '../../../mod.ts'
7
7
  import type { QueryBuilderAst } from './api.ts'
8
8
 
9
+ /**
10
+ * Extracts array element schema from a JSON array transformation AST.
11
+ * Returns the element schema, or undefined if not a JSON array transformation.
12
+ */
13
+ const extractArrayElementFromTransformation = (ast: SchemaAST.AST): Schema.Schema.Any | undefined => {
14
+ if (SchemaAST.isTransformation(ast) === false) return undefined
15
+
16
+ const toAst = ast.to
17
+ // Check if the "to" side is a TupleType (Effect's internal representation of Array)
18
+ if (SchemaAST.isTupleType(toAst) === false) return undefined
19
+
20
+ // For Schema.Array, rest contains { type: AST } elements - get the first one's type
21
+ const restElement = toAst.rest[0]
22
+ if (restElement === undefined) return undefined
23
+
24
+ return Schema.make(restElement.type)
25
+ }
26
+
27
+ /**
28
+ * For JSON array columns, extracts the element schema from Schema.parseJson(Schema.Array(ElementSchema)).
29
+ * Also handles nullable JSON arrays (Schema.NullOr(Schema.parseJson(Schema.Array(...)))).
30
+ * Returns the element schema, or undefined if the column is not a JSON array.
31
+ */
32
+ const getJsonArrayElementSchema = (colSchema: Schema.Schema.Any): Schema.Schema.Any | undefined => {
33
+ const ast = colSchema.ast
34
+
35
+ // Case 1: Direct transformation (non-nullable JSON array)
36
+ // Schema.parseJson(Schema.Array(ElementSchema)) creates a Transformation AST
37
+ if (SchemaAST.isTransformation(ast) === true) {
38
+ return extractArrayElementFromTransformation(ast)
39
+ }
40
+
41
+ // Case 2: Nullable JSON array - Schema.NullOr wraps the parseJson in a Union
42
+ // Structure: Union([Transformation (JSON array), Literal (null)])
43
+ if (SchemaAST.isUnion(ast) === true) {
44
+ for (const member of ast.types) {
45
+ const result = extractArrayElementFromTransformation(member)
46
+ if (result !== undefined) return result
47
+ }
48
+ }
49
+
50
+ return undefined
51
+ }
52
+
53
+ /**
54
+ * Encodes a JSON array element to the representation returned by SQLite's json_each().
55
+ * Objects/arrays are stringified so they match json_each's TEXT representation.
56
+ */
57
+ const encodeJsonArrayElementValue = (elementSchema: Schema.Schema.Any, value: unknown): SqlValue => {
58
+ const encoded = Schema.encodeSync(elementSchema as Schema.Schema<unknown, SqlValue>)(value)
59
+
60
+ if (encoded === null) return null
61
+ if (typeof encoded === 'object') {
62
+ // Objects and arrays need to be JSON-stringified to match json_each() output
63
+ return JSON.stringify(encoded)
64
+ }
65
+ if (typeof encoded === 'boolean') {
66
+ return encoded === true ? 1 : 0
67
+ }
68
+
69
+ return encoded
70
+ }
71
+
9
72
  // Helper functions for SQL generation
73
+ const quoteIdentifier = (identifier: string): string => `"${identifier.replace(/"/g, '""')}"`
74
+
10
75
  const formatWhereClause = (
11
76
  whereConditions: ReadonlyArray<QueryBuilderAst.Where>,
12
77
  tableDef: State.SQLite.TableDefBase,
@@ -16,13 +81,15 @@ const formatWhereClause = (
16
81
 
17
82
  const whereClause = whereConditions
18
83
  .map(({ col, op, value }) => {
84
+ const quotedCol = quoteIdentifier(col)
85
+
19
86
  // Handle NULL values
20
87
  if (value === null) {
21
88
  if (op !== '=' && op !== '!=') {
22
89
  throw new Error(`Unsupported operator for NULL value: ${op}`)
23
90
  }
24
91
  const opStmt = op === '=' ? 'IS' : 'IS NOT'
25
- return `${col} ${opStmt} NULL`
92
+ return `${quotedCol} ${opStmt} NULL`
26
93
  }
27
94
 
28
95
  // Get column definition and encode value
@@ -31,12 +98,29 @@ const formatWhereClause = (
31
98
  throw new Error(`Column ${col} not found`)
32
99
  }
33
100
 
101
+ // Handle JSON array containment operators
102
+ if (op === 'JSON_CONTAINS' || op === 'JSON_NOT_CONTAINS') {
103
+ const elementSchema = getJsonArrayElementSchema(colDef.schema)
104
+ if (elementSchema === undefined) {
105
+ throw new Error(
106
+ `${op} operator can only be used on JSON array columns, but column "${col}" is not a JSON array`,
107
+ )
108
+ }
109
+
110
+ const existsOp = op === 'JSON_CONTAINS' ? 'EXISTS' : 'NOT EXISTS'
111
+ // Encode the element value using the element schema
112
+ // Objects are JSON-stringified to match json_each() output
113
+ const encodedValue = encodeJsonArrayElementValue(elementSchema, value)
114
+ bindValues.push(encodedValue)
115
+ return `${existsOp} (SELECT 1 FROM json_each(${quotedCol}) WHERE value = ?)`
116
+ }
117
+
34
118
  // Handle array values for IN/NOT IN operators
35
119
  const isArray = op === 'IN' || op === 'NOT IN'
36
120
 
37
- if (isArray) {
121
+ if (isArray === true) {
38
122
  // Verify value is an array
39
- if (!Array.isArray(value)) {
123
+ if (Array.isArray(value) === false) {
40
124
  return shouldNeverHappen(`Expected array value for ${op} operator but got`, value)
41
125
  }
42
126
 
@@ -48,11 +132,11 @@ const formatWhereClause = (
48
132
  const encodedValues = value.map((v) => Schema.encodeSync(colDef.schema)(v)) as SqlValue[]
49
133
  bindValues.push(...encodedValues)
50
134
  const placeholders = encodedValues.map(() => '?').join(', ')
51
- return `${col} ${op} (${placeholders})`
135
+ return `${quotedCol} ${op} (${placeholders})`
52
136
  } else {
53
137
  const encodedValue = Schema.encodeSync(colDef.schema)(value)
54
138
  bindValues.push(encodedValue as SqlValue)
55
- return `${col} ${op} ?`
139
+ return `${quotedCol} ${op} ?`
56
140
  }
57
141
  })
58
142
  .join(' AND ')
@@ -61,8 +145,8 @@ const formatWhereClause = (
61
145
  }
62
146
 
63
147
  const formatReturningClause = (returning?: string[]): string => {
64
- if (!returning || returning.length === 0) return ''
65
- return ` RETURNING ${returning.join(', ')}`
148
+ if (returning == null || returning.length === 0) return ''
149
+ return ` RETURNING ${returning.map(quoteIdentifier).join(', ')}`
66
150
  }
67
151
 
68
152
  export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: SqlValue[]; usedTables: Set<string> } => {
@@ -72,6 +156,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
72
156
  // INSERT query
73
157
  if (ast._tag === 'InsertQuery') {
74
158
  const columns = Object.keys(ast.values)
159
+ const quotedColumns = columns.map(quoteIdentifier)
75
160
  const placeholders = columns.map(() => '?').join(', ')
76
161
  const encodedValues = Schema.encodeSync(ast.tableDef.insertSchema)(ast.values)
77
162
 
@@ -84,14 +169,15 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
84
169
  let conflictClause = '' // Store the ON CONFLICT clause separately
85
170
 
86
171
  // Handle ON CONFLICT clause
87
- if (ast.onConflict) {
172
+ if (ast.onConflict !== undefined) {
88
173
  // Handle REPLACE specifically as it changes the INSERT verb
89
174
  if (ast.onConflict.action._tag === 'replace') {
90
175
  insertVerb = 'INSERT OR REPLACE'
91
176
  // For REPLACE, the conflict target is implied and no further clause is needed
92
177
  } else {
93
178
  // Build the ON CONFLICT clause for IGNORE or UPDATE
94
- conflictClause = ` ON CONFLICT (${ast.onConflict.targets.join(', ')}) `
179
+ const conflictTargets = ast.onConflict.targets.map(quoteIdentifier).join(', ')
180
+ conflictClause = ` ON CONFLICT (${conflictTargets}) `
95
181
  if (ast.onConflict.action._tag === 'ignore') {
96
182
  conflictClause += 'DO NOTHING'
97
183
  } else {
@@ -105,8 +191,9 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
105
191
  const updates = updateCols
106
192
  .map((col) => {
107
193
  const value = updateValues[col]
194
+ const quotedCol = quoteIdentifier(col)
108
195
  // If the value is undefined, use excluded.col
109
- return value === undefined ? `${col} = excluded.${col}` : `${col} = ?`
196
+ return value === undefined ? `${quotedCol} = excluded.${quotedCol}` : `${quotedCol} = ?`
110
197
  })
111
198
  .join(', ')
112
199
 
@@ -129,7 +216,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
129
216
  }
130
217
 
131
218
  // Construct the main query part
132
- let query = `${insertVerb} INTO '${ast.tableDef.sqliteDef.name}' (${columns.join(', ')}) VALUES (${placeholders})`
219
+ let query = `${insertVerb} INTO '${ast.tableDef.sqliteDef.name}' (${quotedColumns.join(', ')}) VALUES (${placeholders})`
133
220
 
134
221
  // Append the conflict clause if it was generated (i.e., not for REPLACE)
135
222
  query += conflictClause
@@ -157,10 +244,12 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
157
244
  bindValues.push(encodedValues[col] as SqlValue)
158
245
  })
159
246
 
160
- let query = `UPDATE '${ast.tableDef.sqliteDef.name}' SET ${setColumns.map((col) => `${col} = ?`).join(', ')}`
247
+ let query = `UPDATE '${ast.tableDef.sqliteDef.name}' SET ${setColumns
248
+ .map((col) => `${quoteIdentifier(col)} = ?`)
249
+ .join(', ')}`
161
250
 
162
251
  const whereClause = formatWhereClause(ast.where, ast.tableDef, bindValues)
163
- if (whereClause) query += ` ${whereClause}`
252
+ if (whereClause !== undefined) query += ` ${whereClause}`
164
253
 
165
254
  query += formatReturningClause(ast.returning)
166
255
  return { query, bindValues, usedTables }
@@ -171,7 +260,7 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
171
260
  let query = `DELETE FROM '${ast.tableDef.sqliteDef.name}'`
172
261
 
173
262
  const whereClause = formatWhereClause(ast.where, ast.tableDef, bindValues)
174
- if (whereClause) query += ` ${whereClause}`
263
+ if (whereClause !== undefined) query += ` ${whereClause}`
175
264
 
176
265
  query += formatReturningClause(ast.returning)
177
266
  return { query, bindValues, usedTables }
@@ -201,31 +290,31 @@ export const astToSql = (ast: QueryBuilderAst): { query: string; bindValues: Sql
201
290
  const encodedId = ast.id === SessionIdSymbol ? ast.id : Schema.encodeSync(idColDef.schema)(ast.id)
202
291
 
203
292
  return {
204
- query: `SELECT * FROM '${ast.tableDef.sqliteDef.name}' WHERE id = ?`,
293
+ query: `SELECT * FROM '${ast.tableDef.sqliteDef.name}' WHERE ${quoteIdentifier('id')} = ?`,
205
294
  bindValues: [encodedId as SqlValue],
206
295
  usedTables,
207
296
  }
208
297
  }
209
298
 
210
299
  // SELECT query
211
- const columnsStmt = ast.select.columns.length === 0 ? '*' : ast.select.columns.join(', ')
300
+ const columnsStmt = ast.select.columns.length === 0 ? '*' : ast.select.columns.map(quoteIdentifier).join(', ')
212
301
  const selectStmt = `SELECT ${columnsStmt}`
213
302
  const fromStmt = `FROM '${ast.tableDef.sqliteDef.name}'`
214
303
  const whereStmt = formatWhereClause(ast.where, ast.tableDef, bindValues)
215
304
 
216
305
  const orderByStmt =
217
306
  ast.orderBy.length > 0
218
- ? `ORDER BY ${ast.orderBy.map(({ col, direction }) => `${col} ${direction}`).join(', ')}`
307
+ ? `ORDER BY ${ast.orderBy.map(({ col, direction }) => `${quoteIdentifier(col)} ${direction}`).join(', ')}`
219
308
  : ''
220
309
 
221
310
  const limitStmt = ast.limit._tag === 'Some' ? `LIMIT ?` : ''
222
311
  const offsetStmt = ast.offset._tag === 'Some' ? `OFFSET ?` : ''
223
312
 
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)
313
+ // Push limit and offset values in the correct order matching the query string
226
314
  if (ast.limit._tag === 'Some') bindValues.push(ast.limit.value)
315
+ if (ast.offset._tag === 'Some') bindValues.push(ast.offset.value)
227
316
 
228
- const query = [selectStmt, fromStmt, whereStmt, orderByStmt, offsetStmt, limitStmt]
317
+ const query = [selectStmt, fromStmt, whereStmt, orderByStmt, limitStmt, offsetStmt]
229
318
  .map((clause) => clause.trim())
230
319
  .filter((clause) => clause.length > 0)
231
320
  .join(' ')