@livestore/common 0.4.0 → 0.5.0-dev.1

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 (501) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ClientSessionLeaderThreadProxy.d.ts +1 -1
  3. package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
  4. package/dist/MaterializationJournal.d.ts +44 -0
  5. package/dist/MaterializationJournal.d.ts.map +1 -0
  6. package/dist/MaterializationJournal.js +112 -0
  7. package/dist/MaterializationJournal.js.map +1 -0
  8. package/dist/StateHead.d.ts +26 -0
  9. package/dist/StateHead.d.ts.map +1 -0
  10. package/dist/StateHead.js +50 -0
  11. package/dist/StateHead.js.map +1 -0
  12. package/dist/WorkerTransportError.d.ts +3 -3
  13. package/dist/WorkerTransportError.d.ts.map +1 -1
  14. package/dist/WorkerTransportError.js +3 -3
  15. package/dist/WorkerTransportError.js.map +1 -1
  16. package/dist/__tests__/fixture.d.ts +8 -8
  17. package/dist/__tests__/fixture.d.ts.map +1 -1
  18. package/dist/__tests__/fixture.js +4 -4
  19. package/dist/__tests__/fixture.js.map +1 -1
  20. package/dist/adapter-types.d.ts +33 -57
  21. package/dist/adapter-types.d.ts.map +1 -1
  22. package/dist/adapter-types.js +24 -41
  23. package/dist/adapter-types.js.map +1 -1
  24. package/dist/bounded-collections.d.ts.map +1 -1
  25. package/dist/bounded-collections.js.map +1 -1
  26. package/dist/debug-info.d.ts +56 -56
  27. package/dist/debug-info.d.ts.map +1 -1
  28. package/dist/debug-info.js +32 -44
  29. package/dist/debug-info.js.map +1 -1
  30. package/dist/defs.d.ts +9 -9
  31. package/dist/defs.js +2 -2
  32. package/dist/devtools/devtools-compatibility.test.js +2 -1
  33. package/dist/devtools/devtools-compatibility.test.js.map +1 -1
  34. package/dist/devtools/devtools-messages-client-session.d.ts +522 -334
  35. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
  36. package/dist/devtools/devtools-messages-client-session.js +80 -78
  37. package/dist/devtools/devtools-messages-client-session.js.map +1 -1
  38. package/dist/devtools/devtools-messages-common.d.ts +27 -27
  39. package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
  40. package/dist/devtools/devtools-messages-common.js +6 -6
  41. package/dist/devtools/devtools-messages-common.js.map +1 -1
  42. package/dist/devtools/devtools-messages-leader.d.ts +410 -348
  43. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
  44. package/dist/devtools/devtools-messages-leader.js +105 -93
  45. package/dist/devtools/devtools-messages-leader.js.map +1 -1
  46. package/dist/devtools/devtools-messages.js +3 -3
  47. package/dist/devtools/devtools-sessioninfo.d.ts +18 -19
  48. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
  49. package/dist/devtools/devtools-sessioninfo.js +8 -5
  50. package/dist/devtools/devtools-sessioninfo.js.map +1 -1
  51. package/dist/devtools/mod.d.ts +4 -5
  52. package/dist/devtools/mod.d.ts.map +1 -1
  53. package/dist/devtools/mod.js +12 -8
  54. package/dist/devtools/mod.js.map +1 -1
  55. package/dist/errors.d.ts +45 -69
  56. package/dist/errors.d.ts.map +1 -1
  57. package/dist/errors.js +19 -17
  58. package/dist/errors.js.map +1 -1
  59. package/dist/index.d.ts +4 -1
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +22 -19
  62. package/dist/index.js.map +1 -1
  63. package/dist/leader-thread/LeaderSyncProcessor.d.ts +87 -18
  64. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  65. package/dist/leader-thread/LeaderSyncProcessor.js +548 -480
  66. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  67. package/dist/leader-thread/RejectedPushError.d.ts +72 -41
  68. package/dist/leader-thread/RejectedPushError.d.ts.map +1 -1
  69. package/dist/leader-thread/RejectedPushError.js +25 -6
  70. package/dist/leader-thread/RejectedPushError.js.map +1 -1
  71. package/dist/leader-thread/connection.d.ts +1 -0
  72. package/dist/leader-thread/connection.d.ts.map +1 -1
  73. package/dist/leader-thread/connection.js +11 -10
  74. package/dist/leader-thread/connection.js.map +1 -1
  75. package/dist/leader-thread/eventlog.d.ts +15 -5
  76. package/dist/leader-thread/eventlog.d.ts.map +1 -1
  77. package/dist/leader-thread/eventlog.js +19 -19
  78. package/dist/leader-thread/eventlog.js.map +1 -1
  79. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  80. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  81. package/dist/leader-thread/leader-worker-devtools.js +36 -20
  82. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  83. package/dist/leader-thread/make-leader-thread-layer.d.ts +15 -5
  84. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  85. package/dist/leader-thread/make-leader-thread-layer.js +62 -58
  86. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  87. package/dist/leader-thread/make-leader-thread-layer.test.js +9 -9
  88. package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -1
  89. package/dist/leader-thread/materialize-event.d.ts +2 -1
  90. package/dist/leader-thread/materialize-event.d.ts.map +1 -1
  91. package/dist/leader-thread/materialize-event.js +12 -8
  92. package/dist/leader-thread/materialize-event.js.map +1 -1
  93. package/dist/leader-thread/mod.js +9 -9
  94. package/dist/leader-thread/recreate-db.d.ts +5 -1
  95. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  96. package/dist/leader-thread/recreate-db.js +34 -59
  97. package/dist/leader-thread/recreate-db.js.map +1 -1
  98. package/dist/leader-thread/shutdown-channel.d.ts +2 -6
  99. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  100. package/dist/leader-thread/shutdown-channel.js +2 -3
  101. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  102. package/dist/leader-thread/stream-events.d.ts +4 -7
  103. package/dist/leader-thread/stream-events.d.ts.map +1 -1
  104. package/dist/leader-thread/stream-events.js +16 -21
  105. package/dist/leader-thread/stream-events.js.map +1 -1
  106. package/dist/leader-thread/types.d.ts +38 -73
  107. package/dist/leader-thread/types.d.ts.map +1 -1
  108. package/dist/leader-thread/types.js +10 -6
  109. package/dist/leader-thread/types.js.map +1 -1
  110. package/dist/logging.d.ts +5 -30
  111. package/dist/logging.d.ts.map +1 -1
  112. package/dist/logging.js +1 -32
  113. package/dist/logging.js.map +1 -1
  114. package/dist/make-client-session.d.ts +2 -3
  115. package/dist/make-client-session.d.ts.map +1 -1
  116. package/dist/make-client-session.js +5 -5
  117. package/dist/make-client-session.js.map +1 -1
  118. package/dist/materializer-helper.d.ts +0 -1
  119. package/dist/materializer-helper.d.ts.map +1 -1
  120. package/dist/materializer-helper.js +9 -37
  121. package/dist/materializer-helper.js.map +1 -1
  122. package/dist/otel.d.ts +2 -3
  123. package/dist/otel.d.ts.map +1 -1
  124. package/dist/otel.js +2 -7
  125. package/dist/otel.js.map +1 -1
  126. package/dist/rematerialize-from-eventlog.d.ts +3 -1
  127. package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
  128. package/dist/rematerialize-from-eventlog.js +42 -33
  129. package/dist/rematerialize-from-eventlog.js.map +1 -1
  130. package/dist/schema/EventDef/define.d.ts +6 -6
  131. package/dist/schema/EventDef/define.d.ts.map +1 -1
  132. package/dist/schema/EventDef/define.js +5 -5
  133. package/dist/schema/EventDef/define.js.map +1 -1
  134. package/dist/schema/EventDef/define.test.d.ts +2 -0
  135. package/dist/schema/EventDef/define.test.d.ts.map +1 -0
  136. package/dist/schema/EventDef/define.test.js +23 -0
  137. package/dist/schema/EventDef/define.test.js.map +1 -0
  138. package/dist/schema/EventDef/deprecated.d.ts +8 -13
  139. package/dist/schema/EventDef/deprecated.d.ts.map +1 -1
  140. package/dist/schema/EventDef/deprecated.js +12 -13
  141. package/dist/schema/EventDef/deprecated.js.map +1 -1
  142. package/dist/schema/EventDef/deprecated.test.js +3 -3
  143. package/dist/schema/EventDef/deprecated.test.js.map +1 -1
  144. package/dist/schema/EventDef/event-def.d.ts +1 -1
  145. package/dist/schema/EventDef/event-def.d.ts.map +1 -1
  146. package/dist/schema/EventDef/facts.d.ts.map +1 -1
  147. package/dist/schema/EventDef/materializer.d.ts +2 -2
  148. package/dist/schema/EventDef/materializer.d.ts.map +1 -1
  149. package/dist/schema/EventDef/mod.js +5 -5
  150. package/dist/schema/EventSequenceNumber/client.d.ts +12 -17
  151. package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -1
  152. package/dist/schema/EventSequenceNumber/client.js +20 -24
  153. package/dist/schema/EventSequenceNumber/client.js.map +1 -1
  154. package/dist/schema/EventSequenceNumber/global.d.ts +2 -2
  155. package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -1
  156. package/dist/schema/EventSequenceNumber/global.js +1 -1
  157. package/dist/schema/EventSequenceNumber/global.js.map +1 -1
  158. package/dist/schema/EventSequenceNumber/mod.js +2 -2
  159. package/dist/schema/EventSequenceNumber.test.js +6 -6
  160. package/dist/schema/EventSequenceNumber.test.js.map +1 -1
  161. package/dist/schema/LiveStoreEvent/client.d.ts +58 -187
  162. package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -1
  163. package/dist/schema/LiveStoreEvent/client.js +33 -30
  164. package/dist/schema/LiveStoreEvent/client.js.map +1 -1
  165. package/dist/schema/LiveStoreEvent/client.test.js +13 -4
  166. package/dist/schema/LiveStoreEvent/client.test.js.map +1 -1
  167. package/dist/schema/LiveStoreEvent/for-event-def.d.ts +7 -7
  168. package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -1
  169. package/dist/schema/LiveStoreEvent/global.d.ts +6 -6
  170. package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -1
  171. package/dist/schema/LiveStoreEvent/global.js +2 -2
  172. package/dist/schema/LiveStoreEvent/global.js.map +1 -1
  173. package/dist/schema/LiveStoreEvent/input.d.ts +6 -6
  174. package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -1
  175. package/dist/schema/LiveStoreEvent/input.js +3 -3
  176. package/dist/schema/LiveStoreEvent/input.js.map +1 -1
  177. package/dist/schema/LiveStoreEvent/mod.js +4 -4
  178. package/dist/schema/events.js +1 -1
  179. package/dist/schema/mod.d.ts +1 -0
  180. package/dist/schema/mod.d.ts.map +1 -1
  181. package/dist/schema/mod.js +11 -10
  182. package/dist/schema/mod.js.map +1 -1
  183. package/dist/schema/schema.d.ts +1 -1
  184. package/dist/schema/schema.d.ts.map +1 -1
  185. package/dist/schema/schema.js +6 -5
  186. package/dist/schema/schema.js.map +1 -1
  187. package/dist/schema/state/mod.js +2 -2
  188. package/dist/schema/state/sqlite/client-document-def.d.ts +13 -18
  189. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  190. package/dist/schema/state/sqlite/client-document-def.js +30 -27
  191. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  192. package/dist/schema/state/sqlite/client-document-def.test.js +53 -18
  193. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
  194. package/dist/schema/state/sqlite/column-annotations.d.ts +13 -13
  195. package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
  196. package/dist/schema/state/sqlite/column-annotations.js +13 -15
  197. package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
  198. package/dist/schema/state/sqlite/column-annotations.test.js +19 -43
  199. package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
  200. package/dist/schema/state/sqlite/column-def.d.ts +1 -1
  201. package/dist/schema/state/sqlite/column-def.d.ts.map +1 -1
  202. package/dist/schema/state/sqlite/column-def.js +73 -33
  203. package/dist/schema/state/sqlite/column-def.js.map +1 -1
  204. package/dist/schema/state/sqlite/column-def.test.js +176 -75
  205. package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
  206. package/dist/schema/state/sqlite/column-spec.d.ts.map +1 -1
  207. package/dist/schema/state/sqlite/column-spec.js +1 -1
  208. package/dist/schema/state/sqlite/column-spec.js.map +1 -1
  209. package/dist/schema/state/sqlite/column-spec.test.js +4 -4
  210. package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
  211. package/dist/schema/state/sqlite/db-schema/ast/fingerprint-digest.d.ts +3 -0
  212. package/dist/schema/state/sqlite/db-schema/ast/fingerprint-digest.d.ts.map +1 -0
  213. package/dist/schema/state/sqlite/db-schema/ast/fingerprint-digest.js +5 -0
  214. package/dist/schema/state/sqlite/db-schema/ast/fingerprint-digest.js.map +1 -0
  215. package/dist/schema/state/sqlite/db-schema/ast/fingerprint.d.ts +5 -0
  216. package/dist/schema/state/sqlite/db-schema/ast/fingerprint.d.ts.map +1 -0
  217. package/dist/schema/state/sqlite/db-schema/ast/fingerprint.js +183 -0
  218. package/dist/schema/state/sqlite/db-schema/ast/fingerprint.js.map +1 -0
  219. package/dist/schema/state/sqlite/db-schema/ast/fingerprint.test.d.ts +2 -0
  220. package/dist/schema/state/sqlite/db-schema/ast/fingerprint.test.d.ts.map +1 -0
  221. package/dist/schema/state/sqlite/db-schema/ast/fingerprint.test.js +142 -0
  222. package/dist/schema/state/sqlite/db-schema/ast/fingerprint.test.js.map +1 -0
  223. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +3 -8
  224. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -1
  225. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +1 -73
  226. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
  227. package/dist/schema/state/sqlite/db-schema/ast/validate.d.ts.map +1 -1
  228. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +9 -9
  229. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
  230. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +9 -13
  231. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
  232. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +28 -17
  233. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -1
  234. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +13 -11
  235. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
  236. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +6 -4
  237. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
  238. package/dist/schema/state/sqlite/db-schema/has-json-string-encoding.d.ts +3 -0
  239. package/dist/schema/state/sqlite/db-schema/has-json-string-encoding.d.ts.map +1 -0
  240. package/dist/schema/state/sqlite/db-schema/has-json-string-encoding.js +6 -0
  241. package/dist/schema/state/sqlite/db-schema/has-json-string-encoding.js.map +1 -0
  242. package/dist/schema/state/sqlite/db-schema/mod.js +2 -2
  243. package/dist/schema/state/sqlite/mod.d.ts +1 -3
  244. package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
  245. package/dist/schema/state/sqlite/mod.js +11 -10
  246. package/dist/schema/state/sqlite/mod.js.map +1 -1
  247. package/dist/schema/state/sqlite/persistence.d.ts +11 -0
  248. package/dist/schema/state/sqlite/persistence.d.ts.map +1 -0
  249. package/dist/schema/state/sqlite/persistence.js +10 -0
  250. package/dist/schema/state/sqlite/persistence.js.map +1 -0
  251. package/dist/schema/state/sqlite/query-builder/api.d.ts +7 -7
  252. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
  253. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
  254. package/dist/schema/state/sqlite/query-builder/astToSql.js +22 -23
  255. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
  256. package/dist/schema/state/sqlite/query-builder/impl.d.ts +1 -1
  257. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
  258. package/dist/schema/state/sqlite/query-builder/impl.js +18 -16
  259. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
  260. package/dist/schema/state/sqlite/query-builder/impl.test.js +364 -598
  261. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  262. package/dist/schema/state/sqlite/query-builder/mod.js +2 -2
  263. package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -1
  264. package/dist/schema/state/sqlite/schema-helpers.js +2 -2
  265. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
  266. package/dist/schema/state/sqlite/schema-helpers.test.js +2 -2
  267. package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts +102 -134
  268. package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts.map +1 -1
  269. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +5 -5
  270. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -1
  271. package/dist/schema/state/sqlite/system-tables/mod.js +2 -2
  272. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +380 -115
  273. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -1
  274. package/dist/schema/state/sqlite/system-tables/state-tables.js +47 -6
  275. package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -1
  276. package/dist/schema/state/sqlite/table-def.d.ts +17 -20
  277. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  278. package/dist/schema/state/sqlite/table-def.js +72 -6
  279. package/dist/schema/state/sqlite/table-def.js.map +1 -1
  280. package/dist/schema/state/sqlite/table-def.test.js +207 -37
  281. package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
  282. package/dist/schema/unknown-events.d.ts.map +1 -1
  283. package/dist/schema/unknown-events.js +3 -2
  284. package/dist/schema/unknown-events.js.map +1 -1
  285. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +28 -6
  286. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -1
  287. package/dist/schema-management/common.d.ts.map +1 -1
  288. package/dist/schema-management/common.js +2 -2
  289. package/dist/schema-management/migrations.d.ts +4 -4
  290. package/dist/schema-management/migrations.d.ts.map +1 -1
  291. package/dist/schema-management/migrations.js +9 -9
  292. package/dist/schema-management/migrations.js.map +1 -1
  293. package/dist/schema-management/validate-schema.d.ts.map +1 -1
  294. package/dist/schema-management/validate-schema.js +1 -1
  295. package/dist/session-id-symbol.d.ts +29 -0
  296. package/dist/session-id-symbol.d.ts.map +1 -0
  297. package/dist/session-id-symbol.js +44 -0
  298. package/dist/session-id-symbol.js.map +1 -0
  299. package/dist/sql-queries/index.js +3 -3
  300. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  301. package/dist/sql-queries/sql-queries.js +11 -13
  302. package/dist/sql-queries/sql-queries.js.map +1 -1
  303. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  304. package/dist/sql-queries/sql-query-builder.js +1 -1
  305. package/dist/sql-queries/types.d.ts +6 -7
  306. package/dist/sql-queries/types.d.ts.map +1 -1
  307. package/dist/sql-queries/types.js.map +1 -1
  308. package/dist/sqlite-db-helper.d.ts +23 -3
  309. package/dist/sqlite-db-helper.d.ts.map +1 -1
  310. package/dist/sqlite-db-helper.js +39 -4
  311. package/dist/sqlite-db-helper.js.map +1 -1
  312. package/dist/sqlite-types.d.ts +3 -6
  313. package/dist/sqlite-types.d.ts.map +1 -1
  314. package/dist/sqlite-types.js +3 -3
  315. package/dist/sqlite-types.js.map +1 -1
  316. package/dist/sync/ClientSessionSyncProcessor.d.ts +41 -19
  317. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  318. package/dist/sync/ClientSessionSyncProcessor.js +200 -70
  319. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  320. package/dist/sync/errors.d.ts +12 -18
  321. package/dist/sync/errors.d.ts.map +1 -1
  322. package/dist/sync/errors.js +3 -3
  323. package/dist/sync/errors.js.map +1 -1
  324. package/dist/sync/index.js +6 -6
  325. package/dist/sync/mock-sync-backend.d.ts +2 -3
  326. package/dist/sync/mock-sync-backend.d.ts.map +1 -1
  327. package/dist/sync/mock-sync-backend.js +58 -37
  328. package/dist/sync/mock-sync-backend.js.map +1 -1
  329. package/dist/sync/mock-sync-backend.test.d.ts +2 -0
  330. package/dist/sync/mock-sync-backend.test.d.ts.map +1 -0
  331. package/dist/sync/mock-sync-backend.test.js +49 -0
  332. package/dist/sync/mock-sync-backend.test.js.map +1 -0
  333. package/dist/sync/next/compact-events.d.ts.map +1 -1
  334. package/dist/sync/next/compact-events.js +3 -3
  335. package/dist/sync/next/facts.d.ts.map +1 -1
  336. package/dist/sync/next/facts.js +1 -1
  337. package/dist/sync/next/history-dag-common.d.ts +5 -1
  338. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  339. package/dist/sync/next/history-dag-common.js +53 -32
  340. package/dist/sync/next/history-dag-common.js.map +1 -1
  341. package/dist/sync/next/history-dag.d.ts.map +1 -1
  342. package/dist/sync/next/history-dag.js +5 -4
  343. package/dist/sync/next/history-dag.js.map +1 -1
  344. package/dist/sync/next/mod.js +5 -5
  345. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  346. package/dist/sync/next/rebase-events.js +2 -2
  347. package/dist/sync/next/test/compact-events.calculator.test.js +6 -6
  348. package/dist/sync/next/test/compact-events.test.js +4 -4
  349. package/dist/sync/next/test/event-fixtures.d.ts +8 -8
  350. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
  351. package/dist/sync/next/test/event-fixtures.js +6 -6
  352. package/dist/sync/next/test/event-fixtures.js.map +1 -1
  353. package/dist/sync/next/test/history-dag-common.test.d.ts +2 -0
  354. package/dist/sync/next/test/history-dag-common.test.d.ts.map +1 -0
  355. package/dist/sync/next/test/history-dag-common.test.js +73 -0
  356. package/dist/sync/next/test/history-dag-common.test.js.map +1 -0
  357. package/dist/sync/next/test/mod.js +1 -1
  358. package/dist/sync/sync-backend-kv.d.ts.map +1 -1
  359. package/dist/sync/sync-backend-kv.js +5 -3
  360. package/dist/sync/sync-backend-kv.js.map +1 -1
  361. package/dist/sync/sync-backend.d.ts +15 -15
  362. package/dist/sync/sync-backend.d.ts.map +1 -1
  363. package/dist/sync/sync-backend.js +10 -6
  364. package/dist/sync/sync-backend.js.map +1 -1
  365. package/dist/sync/sync.d.ts +1 -1
  366. package/dist/sync/sync.d.ts.map +1 -1
  367. package/dist/sync/sync.js +2 -2
  368. package/dist/sync/syncstate.d.ts +100 -176
  369. package/dist/sync/syncstate.d.ts.map +1 -1
  370. package/dist/sync/syncstate.js +36 -39
  371. package/dist/sync/syncstate.js.map +1 -1
  372. package/dist/sync/syncstate.test.js +103 -64
  373. package/dist/sync/syncstate.test.js.map +1 -1
  374. package/dist/sync/transport-chunking.d.ts +15 -16
  375. package/dist/sync/transport-chunking.d.ts.map +1 -1
  376. package/dist/sync/transport-chunking.js +23 -32
  377. package/dist/sync/transport-chunking.js.map +1 -1
  378. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  379. package/dist/sync/validate-push-payload.js +2 -2
  380. package/dist/testing/event-factory.d.ts.map +1 -1
  381. package/dist/testing/event-factory.js +2 -2
  382. package/dist/testing/event-factory.js.map +1 -1
  383. package/dist/testing/mod.js +1 -1
  384. package/dist/util.d.ts +11 -4
  385. package/dist/util.d.ts.map +1 -1
  386. package/dist/util.js +20 -2
  387. package/dist/util.js.map +1 -1
  388. package/dist/version.d.ts.map +1 -1
  389. package/dist/version.js.map +1 -1
  390. package/package.json +40 -57
  391. package/src/ClientSessionLeaderThreadProxy.ts +1 -1
  392. package/src/MaterializationJournal.ts +184 -0
  393. package/src/StateHead.ts +80 -0
  394. package/src/WorkerTransportError.ts +4 -4
  395. package/src/__tests__/fixture.ts +3 -3
  396. package/src/adapter-types.ts +28 -61
  397. package/src/debug-info.ts +53 -70
  398. package/src/defs.ts +2 -2
  399. package/src/devtools/devtools-compatibility.test.ts +1 -0
  400. package/src/devtools/devtools-messages-client-session.ts +56 -65
  401. package/src/devtools/devtools-messages-common.ts +12 -11
  402. package/src/devtools/devtools-messages-leader.ts +71 -69
  403. package/src/devtools/devtools-sessioninfo.ts +13 -11
  404. package/src/devtools/mod.ts +4 -5
  405. package/src/errors.ts +46 -34
  406. package/src/index.ts +8 -1
  407. package/src/leader-thread/LeaderSyncProcessor.ts +777 -650
  408. package/src/leader-thread/RejectedPushError.ts +40 -27
  409. package/src/leader-thread/connection.ts +12 -8
  410. package/src/leader-thread/eventlog.ts +20 -12
  411. package/src/leader-thread/leader-worker-devtools.ts +38 -20
  412. package/src/leader-thread/make-leader-thread-layer.test.ts +7 -7
  413. package/src/leader-thread/make-leader-thread-layer.ts +100 -71
  414. package/src/leader-thread/materialize-event.ts +13 -8
  415. package/src/leader-thread/recreate-db.ts +41 -75
  416. package/src/leader-thread/shutdown-channel.ts +3 -14
  417. package/src/leader-thread/stream-events.ts +102 -101
  418. package/src/leader-thread/types.ts +29 -62
  419. package/src/logging.ts +5 -52
  420. package/src/make-client-session.ts +6 -6
  421. package/src/materializer-helper.ts +7 -36
  422. package/src/otel.ts +5 -14
  423. package/src/rematerialize-from-eventlog.ts +116 -98
  424. package/src/schema/EventDef/define.test.ts +28 -0
  425. package/src/schema/EventDef/define.ts +20 -19
  426. package/src/schema/EventDef/deprecated.test.ts +1 -8
  427. package/src/schema/EventDef/deprecated.ts +17 -20
  428. package/src/schema/EventDef/event-def.ts +2 -4
  429. package/src/schema/EventSequenceNumber/client.ts +20 -24
  430. package/src/schema/EventSequenceNumber/global.ts +1 -1
  431. package/src/schema/EventSequenceNumber.test.ts +5 -5
  432. package/src/schema/LiveStoreEvent/client.test.ts +17 -4
  433. package/src/schema/LiveStoreEvent/client.ts +36 -35
  434. package/src/schema/LiveStoreEvent/for-event-def.ts +7 -7
  435. package/src/schema/LiveStoreEvent/global.ts +1 -1
  436. package/src/schema/LiveStoreEvent/input.ts +6 -6
  437. package/src/schema/mod.ts +1 -0
  438. package/src/schema/schema.ts +4 -3
  439. package/src/schema/state/sqlite/client-document-def.test.ts +55 -20
  440. package/src/schema/state/sqlite/client-document-def.ts +95 -80
  441. package/src/schema/state/sqlite/column-annotations.test.ts +26 -45
  442. package/src/schema/state/sqlite/column-annotations.ts +26 -30
  443. package/src/schema/state/sqlite/column-def.test.ts +213 -77
  444. package/src/schema/state/sqlite/column-def.ts +87 -37
  445. package/src/schema/state/sqlite/column-spec.test.ts +2 -2
  446. package/src/schema/state/sqlite/column-spec.ts +3 -2
  447. package/src/schema/state/sqlite/db-schema/ast/fingerprint-digest.ts +6 -0
  448. package/src/schema/state/sqlite/db-schema/ast/fingerprint.test.ts +209 -0
  449. package/src/schema/state/sqlite/db-schema/ast/fingerprint.ts +225 -0
  450. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +2 -81
  451. package/src/schema/state/sqlite/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +123 -63
  452. package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +35 -16
  453. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +26 -31
  454. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +35 -21
  455. package/src/schema/state/sqlite/db-schema/has-json-string-encoding.ts +9 -0
  456. package/src/schema/state/sqlite/mod.ts +4 -5
  457. package/src/schema/state/sqlite/persistence.ts +11 -0
  458. package/src/schema/state/sqlite/query-builder/api.ts +9 -9
  459. package/src/schema/state/sqlite/query-builder/astToSql.ts +24 -26
  460. package/src/schema/state/sqlite/query-builder/impl.test.ts +433 -669
  461. package/src/schema/state/sqlite/query-builder/impl.ts +19 -15
  462. package/src/schema/state/sqlite/schema-helpers.ts +1 -1
  463. package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +2 -2
  464. package/src/schema/state/sqlite/system-tables/state-tables.ts +54 -3
  465. package/src/schema/state/sqlite/table-def.test.ts +270 -66
  466. package/src/schema/state/sqlite/table-def.ts +112 -45
  467. package/src/schema/unknown-events.ts +3 -2
  468. package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +35 -4
  469. package/src/schema-management/migrations.ts +7 -6
  470. package/src/session-id-symbol.ts +59 -0
  471. package/src/sql-queries/sql-queries.ts +9 -13
  472. package/src/sql-queries/types.ts +6 -7
  473. package/src/sqlite-db-helper.ts +64 -2
  474. package/src/sqlite-types.ts +5 -8
  475. package/src/sync/ClientSessionSyncProcessor.ts +303 -119
  476. package/src/sync/errors.ts +14 -12
  477. package/src/sync/mock-sync-backend.test.ts +78 -0
  478. package/src/sync/mock-sync-backend.ts +93 -47
  479. package/src/sync/next/history-dag-common.ts +60 -34
  480. package/src/sync/next/history-dag.ts +4 -1
  481. package/src/sync/next/test/compact-events.calculator.test.ts +2 -2
  482. package/src/sync/next/test/event-fixtures.ts +1 -1
  483. package/src/sync/next/test/history-dag-common.test.ts +87 -0
  484. package/src/sync/sync-backend-kv.ts +4 -2
  485. package/src/sync/sync-backend.ts +15 -15
  486. package/src/sync/sync.ts +1 -1
  487. package/src/sync/syncstate.test.ts +191 -140
  488. package/src/sync/syncstate.ts +63 -53
  489. package/src/sync/transport-chunking.ts +34 -39
  490. package/src/util.ts +19 -9
  491. package/src/version.ts +1 -2
  492. package/dist/schema/state/sqlite/db-schema/hash.d.ts +0 -2
  493. package/dist/schema/state/sqlite/db-schema/hash.d.ts.map +0 -1
  494. package/dist/schema/state/sqlite/db-schema/hash.js +0 -15
  495. package/dist/schema/state/sqlite/db-schema/hash.js.map +0 -1
  496. package/dist/sql-queries/misc.d.ts +0 -2
  497. package/dist/sql-queries/misc.d.ts.map +0 -1
  498. package/dist/sql-queries/misc.js +0 -2
  499. package/dist/sql-queries/misc.js.map +0 -1
  500. package/src/schema/state/sqlite/db-schema/hash.ts +0 -13
  501. package/src/sql-queries/misc.ts +0 -2
@@ -1,5 +1,6 @@
1
1
  import { type Nullable, shouldNeverHappen } from '@livestore/utils'
2
- import { Option, Schema, SchemaAST, type Types } from '@livestore/utils/effect'
2
+ import type { Schema } from '@livestore/utils/effect'
3
+ import { SchemaAST, type Types } from '@livestore/utils/effect'
3
4
 
4
5
  import { getColumnDefForSchema, schemaFieldsToColumns } from './column-def.ts'
5
6
  import { SqliteDsl } from './db-schema/mod.ts'
@@ -38,29 +39,17 @@ export type TableDef<
38
39
  // https://github.com/livestorejs/livestore/issues/382
39
40
  TSqliteDef extends DefaultSqliteTableDef = DefaultSqliteTableDefConstrained,
40
41
  TOptions extends TableOptions = TableOptions,
41
- // NOTE we're not using `SqliteDsl.StructSchemaForColumns<TSqliteDef['columns']>`
42
- // as we don't want the alias type for users to show up, so we're redefining it here
43
- // TODO adjust this to `TSchema = Schema.TypeLiteral<` but requires some advance type-level work
44
- TSchema = Schema.Schema<
45
- SqliteDsl.AnyIfConstained<
46
- TSqliteDef['columns'],
47
- { readonly [K in keyof TSqliteDef['columns']]: TSqliteDef['columns'][K]['schema']['Type'] }
48
- >,
49
- SqliteDsl.AnyIfConstained<
50
- TSqliteDef['columns'],
51
- { readonly [K in keyof TSqliteDef['columns']]: TSqliteDef['columns'][K]['schema']['Encoded'] }
52
- >
53
- >,
42
+ TSchema extends Schema.Top = Schema.Struct<SqliteDsl.StructFieldsForColumns<TSqliteDef['columns']>>,
54
43
  > = {
55
44
  sqliteDef: TSqliteDef
56
45
  options: TOptions
57
46
  // Derived from `sqliteDef`, so only exposed for convenience
58
47
  rowSchema: TSchema
59
48
  insertSchema: SqliteDsl.InsertStructSchemaForColumns<TSqliteDef['columns']>
60
- // query: QueryBuilder<ReadonlyArray<Schema.Schema.Type<TSchema>>, TableDefBase<TSqliteDef & {}, TOptions>>
61
- readonly Type: Schema.Schema.Type<TSchema>
62
- readonly Encoded: Schema.Schema.Encoded<TSchema>
63
- } & QueryBuilder<ReadonlyArray<Schema.Schema.Type<TSchema>>, TableDefBase<TSqliteDef & {}, TOptions>>
49
+ // query: QueryBuilder<ReadonlyArray<TSchema['Type']>>, TableDefBase<TSqliteDef & {}, TOptions>>
50
+ readonly Type: TSchema['Type']
51
+ readonly Encoded: TSchema['Encoded']
52
+ } & QueryBuilder<ReadonlyArray<TSchema['Type']>, TableDefBase<TSqliteDef & {}, TOptions>>
64
53
 
65
54
  export type TableOptionsInput = Partial<{
66
55
  indexes: SqliteDsl.Index[]
@@ -114,7 +103,7 @@ export type TableOptions = {
114
103
  * })
115
104
  *
116
105
  * // Option 2: With name from schema annotation (title or identifier)
117
- * const AnnotatedUserSchema = UserSchema.annotations({ title: 'users' })
106
+ * const AnnotatedUserSchema = UserSchema.annotate({ title: 'users' })
118
107
  * const usersTable2 = State.SQLite.table({
119
108
  * schema: AnnotatedUserSchema,
120
109
  * })
@@ -127,7 +116,7 @@ export type TableOptions = {
127
116
  * title: Schema.String,
128
117
  * authorId: Schema.String,
129
118
  * createdAt: Schema.Date,
130
- * }).annotations({ identifier: 'posts' })
119
+ * }).annotate({ identifier: 'posts' })
131
120
  *
132
121
  * const postsTable = State.SQLite.table({
133
122
  * schema: PostSchema,
@@ -161,24 +150,21 @@ export function table<
161
150
  // Overload 2: With schema and explicit name
162
151
  export function table<
163
152
  TName extends string,
164
- TSchema extends Schema.Schema.AnyNoContext,
153
+ TSchema extends Schema.Top,
165
154
  const TOptionsInput extends TableOptionsInput = TableOptionsInput,
166
155
  >(
167
156
  args: {
168
157
  name: TName
169
158
  schema: TSchema
170
159
  } & Partial<TOptionsInput>,
171
- ): TableDef<SqliteTableDefForSchemaInput<TName, Schema.Schema.Type<TSchema>, Schema.Schema.Encoded<TSchema>, TSchema>>
160
+ ): TableDef<SqliteTableDefForSchemaInput<TName, TSchema['Type'], TSchema['Encoded'], TSchema>>
172
161
 
173
162
  // Overload 3: With schema and no name (uses schema annotations)
174
- export function table<
175
- TSchema extends Schema.Schema.AnyNoContext,
176
- const TOptionsInput extends TableOptionsInput = TableOptionsInput,
177
- >(
163
+ export function table<TSchema extends Schema.Top, const TOptionsInput extends TableOptionsInput = TableOptionsInput>(
178
164
  args: {
179
165
  schema: TSchema
180
166
  } & Partial<TOptionsInput>,
181
- ): TableDef<SqliteTableDefForSchemaInput<string, Schema.Schema.Type<TSchema>, Schema.Schema.Encoded<TSchema>, TSchema>>
167
+ ): TableDef<SqliteTableDefForSchemaInput<string, TSchema['Type'], TSchema['Encoded'], TSchema>>
182
168
 
183
169
  // Implementation
184
170
  export function table<
@@ -193,10 +179,10 @@ export function table<
193
179
  }
194
180
  | {
195
181
  name: TName
196
- schema: Schema.Schema.AnyNoContext
182
+ schema: Schema.Top
197
183
  }
198
184
  | {
199
- schema: Schema.Schema.AnyNoContext
185
+ schema: Schema.Top
200
186
  }
201
187
  ) &
202
188
  Partial<TOptionsInput>,
@@ -213,7 +199,7 @@ export function table<
213
199
  columns = SqliteDsl.isColumnDefinition(columnOrColumns) === true ? { value: columnOrColumns } : columnOrColumns
214
200
  additionalIndexes = []
215
201
  } else if ('schema' in args) {
216
- const result = schemaFieldsToColumns(Schema.getResolvedPropertySignatures(args.schema))
202
+ const result = args.schema.pipe(getSqlitePropertySignatures, schemaFieldsToColumns)
217
203
  columns = result.columns
218
204
 
219
205
  // We'll set tableName first, then use it for index names
@@ -224,14 +210,12 @@ export function table<
224
210
  tempTableName = args.name
225
211
  } else {
226
212
  // Use title or identifier, with preference for title
227
- tempTableName = SchemaAST.getTitleAnnotation(args.schema.ast).pipe(
228
- Option.orElse(() => SchemaAST.getIdentifierAnnotation(args.schema.ast)),
229
- Option.getOrElse(() =>
230
- shouldNeverHappen(
231
- 'When using schema without explicit name, the schema must have a title or identifier annotation',
232
- ),
233
- ),
234
- )
213
+ tempTableName =
214
+ SchemaAST.resolveTitle(args.schema.ast) ??
215
+ SchemaAST.resolveIdentifier(args.schema.ast) ??
216
+ shouldNeverHappen(
217
+ 'When using schema without explicit name, the schema must have a title or identifier annotation',
218
+ )
235
219
  }
236
220
 
237
221
  tableName = tempTableName
@@ -281,6 +265,90 @@ export function table<
281
265
  return tableDef as any
282
266
  }
283
267
 
268
+ /**
269
+ * The encoded side of the schema decides which columns exist (a transformation may flatten a nested
270
+ * type into columns). Where the schema itself declares a property of the same name, that property's
271
+ * own AST becomes the column schema: it still carries the field's encoding, so a codec such as
272
+ * `Schema.DateFromString` or `Schema.DateFromMillis` stores its encoded form and decodes back to
273
+ * its type. Substituting the type-side AST instead would strip that encoding and leave a `Date`
274
+ * with nothing SQLite can store natively, which is how date columns ended up JSON-encoded and
275
+ * unreadable.
276
+ */
277
+ const getSqlitePropertySignatures = (schema: Schema.Top): ReadonlyArray<SchemaAST.PropertySignature> => {
278
+ const encodedPropertySignatures = getPropertySignatures(SchemaAST.toEncoded(schema.ast))
279
+ const ownPropertySignatures = getPropertySignatures(schema.ast)
280
+
281
+ return encodedPropertySignatures.map((encodedPropertySignature) => {
282
+ const ownPropertySignature = ownPropertySignatures.find(
283
+ (propertySignature) => propertySignature.name === encodedPropertySignature.name,
284
+ )
285
+
286
+ if (ownPropertySignature === undefined || hasLiveStoreSqliteAnnotation(encodedPropertySignature.type) === true) {
287
+ return encodedPropertySignature
288
+ }
289
+
290
+ return ownPropertySignature
291
+ })
292
+ }
293
+
294
+ const getPropertySignatures = (ast: SchemaAST.AST): ReadonlyArray<SchemaAST.PropertySignature> => {
295
+ if (SchemaAST.isObjects(ast) === true) return ast.propertySignatures
296
+
297
+ // Class declarations encode through their fields object. Inspect that first
298
+ // link before toEncoded strips the individual field codecs.
299
+ if (SchemaAST.isDeclaration(ast) === true) {
300
+ const fieldsAst = ast.encoding?.[0]?.to
301
+ if (fieldsAst !== undefined) return getPropertySignatures(fieldsAst)
302
+ }
303
+
304
+ if (SchemaAST.isUnion(ast) === true) {
305
+ const members = ast.types.map(getPropertySignatures)
306
+ const [head, ...tail] = members
307
+ if (head === undefined) return []
308
+
309
+ return head.flatMap((propertySignature) => {
310
+ const matchingPropertySignatures: Array<SchemaAST.PropertySignature> = []
311
+ for (const propertySignatures of tail) {
312
+ const matchingPropertySignature = propertySignatures.find(
313
+ (memberPropertySignature) => memberPropertySignature.name === propertySignature.name,
314
+ )
315
+ if (matchingPropertySignature === undefined) {
316
+ return []
317
+ }
318
+ matchingPropertySignatures.push(matchingPropertySignature)
319
+ }
320
+
321
+ const propertySignatures = [propertySignature, ...matchingPropertySignatures]
322
+ /**
323
+ * `SchemaAST.optionalKey` became internal in Effect rc.109, so the optional-key marker is
324
+ * applied by constructing the union with an optional `Context`. Equivalent here because the
325
+ * union is freshly built and therefore carries no encoding chain to propagate the marker to.
326
+ */
327
+ const hasOptionalMember =
328
+ propertySignatures.some((memberPropertySignature) => SchemaAST.isOptional(memberPropertySignature.type)) ===
329
+ true
330
+ const keyContext = hasOptionalMember === true ? new SchemaAST.Context(true, false) : undefined
331
+ const union = new SchemaAST.Union(
332
+ propertySignatures.map((memberPropertySignature) => memberPropertySignature.type),
333
+ ast.options,
334
+ undefined,
335
+ undefined,
336
+ undefined,
337
+ keyContext,
338
+ )
339
+
340
+ return [new SchemaAST.PropertySignature(propertySignature.name, union)]
341
+ })
342
+ }
343
+
344
+ return []
345
+ }
346
+
347
+ const hasLiveStoreSqliteAnnotation = (ast: SchemaAST.AST): boolean => {
348
+ const annotationKeys = [...Object.keys(ast.annotations ?? {}), ...Object.keys(ast.context?.annotations ?? {})]
349
+ return annotationKeys.some((key) => key.startsWith('livestore/state/sqlite/annotations/'))
350
+ }
351
+
284
352
  export namespace FromTable {
285
353
  // TODO this sometimes doesn't preserve the order of columns
286
354
  export type RowDecoded<TTableDef extends TableDefBase> = Types.Simplify<
@@ -297,9 +365,7 @@ export namespace FromTable {
297
365
  }
298
366
 
299
367
  export type RowEncodeNonNullable<TTableDef extends TableDefBase> = {
300
- [K in keyof TTableDef['sqliteDef']['columns']]: Schema.Schema.Encoded<
301
- TTableDef['sqliteDef']['columns'][K]['schema']
302
- >
368
+ [K in keyof TTableDef['sqliteDef']['columns']]: TTableDef['sqliteDef']['columns'][K]['schema']['Encoded']
303
369
  }
304
370
 
305
371
  export type RowEncoded<TTableDef extends TableDefBase> = Types.Simplify<
@@ -308,7 +374,7 @@ export namespace FromTable {
308
374
  >
309
375
 
310
376
  export type RowDecodedAll<TTableDef extends TableDefBase> = {
311
- [K in keyof TTableDef['sqliteDef']['columns']]: Schema.Schema.Type<TTableDef['sqliteDef']['columns'][K]['schema']>
377
+ [K in keyof TTableDef['sqliteDef']['columns']]: TTableDef['sqliteDef']['columns'][K]['schema']['Type']
312
378
  }
313
379
  }
314
380
 
@@ -320,7 +386,7 @@ export namespace FromColumns {
320
386
  >
321
387
 
322
388
  export type RowDecodedAll<TColumns extends SqliteDsl.Columns> = {
323
- [K in keyof TColumns]: Schema.Schema.Type<TColumns[K]['schema']>
389
+ [K in keyof TColumns]: TColumns[K]['schema']['Type']
324
390
  }
325
391
 
326
392
  export type RowEncoded<TColumns extends SqliteDsl.Columns> = Types.Simplify<
@@ -329,7 +395,7 @@ export namespace FromColumns {
329
395
  >
330
396
 
331
397
  export type RowEncodeNonNullable<TColumns extends SqliteDsl.Columns> = {
332
- [K in keyof TColumns]: Schema.Schema.Encoded<TColumns[K]['schema']>
398
+ [K in keyof TColumns]: TColumns[K]['schema']['Encoded']
333
399
  }
334
400
 
335
401
  export type NullableColumnNames<TColumns extends SqliteDsl.Columns> = keyof {
@@ -378,7 +444,8 @@ export declare namespace SchemaToColumns {
378
444
  export type FromTypes<TType, TEncoded> =
379
445
  TEncoded extends Record<string, any>
380
446
  ? {
381
- [K in keyof TEncoded]-?: ColumnDefForType<TEncoded[K],
447
+ [K in keyof TEncoded]-?: ColumnDefForType<
448
+ TEncoded[K],
382
449
  TType extends Record<string, any> ? (K extends keyof TType ? TType[K] : TEncoded[K]) : TEncoded[K]
383
450
  >
384
451
  }
@@ -72,8 +72,9 @@ const handleUnknownEvent = ({
72
72
  case 'callback': {
73
73
  const callback = config.onUnknownEvent
74
74
 
75
- yield* Effect.tryAll<void>(() => callback(context, error)).pipe(
76
- Effect.catchAll((cause) =>
75
+ // @effect-diagnostics-next-line anyUnknownInErrorContext:off -- user callback errors are immediately handled and logged below
76
+ yield* Effect.trySyncOrPromiseOrEffect(() => callback(context, error)).pipe(
77
+ Effect.catch((cause) =>
77
78
  Effect.logWarning('@livestore/common:schema:unknown-event:callback-error', {
78
79
  event: context.event,
79
80
  reason: context.reason,
@@ -2,13 +2,16 @@ import { describe, expect, it } from 'vitest'
2
2
 
3
3
  import { Effect, Option, Schema } from '@livestore/utils/effect'
4
4
 
5
+ import { fingerprint } from '../../schema/state/sqlite/db-schema/ast/fingerprint.ts'
5
6
  import { SqliteAst } from '../../schema/state/sqlite/db-schema/mod.ts'
7
+ import { schemaMetaTable } from '../../schema/state/sqlite/system-tables/state-tables.ts'
6
8
  import type { PreparedStatement, SqliteDb } from '../../sqlite-types.ts'
7
9
  import type { PreparedBindValues } from '../../util.ts'
8
10
  import { migrateTable } from '../migrations.ts'
9
11
 
10
12
  const makeStubDb = () => {
11
13
  const executed: string[] = []
14
+ const bindings: Array<PreparedBindValues | undefined> = []
12
15
 
13
16
  const db: SqliteDb = {
14
17
  _tag: 'SqliteDb',
@@ -16,8 +19,9 @@ const makeStubDb = () => {
16
19
  debug: { head: 0 as any },
17
20
  prepare: (queryStr: string): PreparedStatement => ({
18
21
  sql: queryStr,
19
- execute: (_bind: PreparedBindValues | undefined) => {
22
+ execute: (bind: PreparedBindValues | undefined) => {
20
23
  executed.push(queryStr)
24
+ bindings.push(bind)
21
25
  },
22
26
  select: <T>(_bind: PreparedBindValues | undefined) => [] as unknown as ReadonlyArray<T>,
23
27
  finalize: () => {},
@@ -32,7 +36,7 @@ const makeStubDb = () => {
32
36
  makeChangeset: () => ({ invert: () => ({ invert: () => ({}) as any, apply: () => {} }) as any, apply: () => {} }),
33
37
  }
34
38
 
35
- return { db, executed }
39
+ return { db, executed, bindings }
36
40
  }
37
41
 
38
42
  describe('migrateTable - quoting and autoincrement', () => {
@@ -49,7 +53,7 @@ describe('migrateTable - quoting and autoincrement', () => {
49
53
  primaryKey: true,
50
54
  autoIncrement: true,
51
55
  default: Option.none(),
52
- schema: Schema.Number,
56
+ schema: Schema.Finite,
53
57
  }),
54
58
  SqliteAst.column({
55
59
  name: 'text',
@@ -67,7 +71,7 @@ describe('migrateTable - quoting and autoincrement', () => {
67
71
  primaryKey: false,
68
72
  autoIncrement: false,
69
73
  default: Option.some(0),
70
- schema: Schema.Number,
74
+ schema: Schema.Finite,
71
75
  }),
72
76
  ],
73
77
  [],
@@ -85,4 +89,31 @@ describe('migrateTable - quoting and autoincrement', () => {
85
89
  expect(createStmt!).not.toContain("PRIMARY KEY ('id')")
86
90
  expect(createStmt!).not.toMatch(/'todos'|'id'|'text'/)
87
91
  })
92
+
93
+ it('persists full textual table fingerprints', () => {
94
+ const { db, bindings } = makeStubDb()
95
+ const table = SqliteAst.table(
96
+ 'todos',
97
+ [
98
+ SqliteAst.column({
99
+ name: 'id',
100
+ type: { _tag: 'text' },
101
+ nullable: false,
102
+ primaryKey: true,
103
+ autoIncrement: false,
104
+ default: Option.none(),
105
+ schema: Schema.String,
106
+ }),
107
+ ],
108
+ [],
109
+ )
110
+
111
+ migrateTable({ db, tableAst: table, behaviour: 'create-if-not-exists' }).pipe(Effect.runSync)
112
+
113
+ const schemaMetaBinding = bindings.find(
114
+ (binding) => binding !== undefined && Array.isArray(binding) === false && '$schemaHash' in binding,
115
+ )
116
+ expect(schemaMetaBinding).toMatchObject({ $schemaHash: fingerprint(table) })
117
+ expect(schemaMetaTable.sqliteDef.ast.columns.find((column) => column.name === 'schemaHash')?.type._tag).toBe('text')
118
+ })
88
119
  })
@@ -8,7 +8,7 @@
8
8
  * - EVENTLOG TABLES (NEVER modify): Changes cause data loss - need manual versioning!
9
9
  *
10
10
  * How it works:
11
- * 1. Each table's schema is hashed using SqliteAst.hash()
11
+ * 1. Each table's schema is fingerprinted
12
12
  * 2. Hashes are stored in SCHEMA_META_TABLE after successful migrations
13
13
  * 3. On app start, current schema hashes are compared with stored hashes
14
14
  * 4. Mismatches trigger migrations:
@@ -37,7 +37,8 @@ import type { MigrationsReport, MigrationsReportEntry } from '../defs.ts'
37
37
  import type { UnknownError } from '../errors.ts'
38
38
  import type { LiveStoreSchema } from '../schema/mod.ts'
39
39
  import { makeColumnSpec } from '../schema/state/sqlite/column-spec.ts'
40
- import { SqliteAst } from '../schema/state/sqlite/db-schema/mod.ts'
40
+ import { fingerprint } from '../schema/state/sqlite/db-schema/ast/fingerprint.ts'
41
+ import type { SqliteAst } from '../schema/state/sqlite/db-schema/mod.ts'
41
42
  import type { SchemaEventDefsMetaRow, SchemaMetaRow } from '../schema/state/sqlite/system-tables/state-tables.ts'
42
43
  import {
43
44
  isStateSystemTable,
@@ -114,14 +115,14 @@ export const migrateDb = ({
114
115
  ...Array.from(schema.state.sqlite.tables.values()).filter((_) => !isStateSystemTable(_.sqliteDef.name)),
115
116
  ]
116
117
 
117
- const tablesToMigrate = new Set<{ tableAst: SqliteAst.Table; schemaHash: number }>()
118
+ const tablesToMigrate = new Set<{ tableAst: SqliteAst.Table; schemaHash: string }>()
118
119
 
119
120
  const migrationsReportEntries: MigrationsReportEntry[] = []
120
121
  for (const tableDef of tableDefs) {
121
122
  const tableAst = tableDef.sqliteDef.ast
122
123
  const tableName = tableAst.name
123
124
  const dbSchemaHash = dbSchemaHashByTable[tableName]
124
- const schemaHash = SqliteAst.hash(tableAst)
125
+ const schemaHash = fingerprint(tableAst)
125
126
 
126
127
  if (schemaHash !== dbSchemaHash) {
127
128
  tablesToMigrate.add({ tableAst, schemaHash })
@@ -151,13 +152,13 @@ export const migrateDb = ({
151
152
  export const migrateTable = ({
152
153
  db,
153
154
  tableAst,
154
- schemaHash = SqliteAst.hash(tableAst),
155
+ schemaHash = fingerprint(tableAst),
155
156
  behaviour,
156
157
  skipMetaTable = false,
157
158
  }: {
158
159
  db: SqliteDb
159
160
  tableAst: SqliteAst.Table
160
- schemaHash?: number
161
+ schemaHash?: string
161
162
  behaviour: 'drop-and-recreate' | 'create-if-not-exists'
162
163
  skipMetaTable?: boolean
163
164
  }) =>
@@ -0,0 +1,59 @@
1
+ /**
2
+ * SessionIdSymbol is a user-facing placeholder for "the current client session".
3
+ * User code can keep using the same event/query object across sessions, while the
4
+ * storage and eventlog layers require concrete string ids. Resolving the symbol at
5
+ * those boundaries preserves the symbolic API without mutating caller-owned values.
6
+ *
7
+ * @module
8
+ */
9
+ import { Predicate } from '@livestore/utils/effect'
10
+
11
+ import type { Bindable, SqlValue } from './util.ts'
12
+
13
+ /**
14
+ * Can be used in queries to refer to the current session id.
15
+ * Will be replaced with the actual session id at runtime.
16
+ *
17
+ * In client document table:
18
+ * ```ts
19
+ * const uiState = State.SQLite.clientDocument({
20
+ * name: 'ui_state',
21
+ * schema: Schema.Struct({
22
+ * theme: Schema.Literals(['dark', 'light', 'system']),
23
+ * user: Schema.String,
24
+ * showToolbar: Schema.Boolean,
25
+ * }),
26
+ * default: { value: defaultFrontendState, id: SessionIdSymbol },
27
+ * })
28
+ * ```
29
+ *
30
+ * Or in a client document query:
31
+ * ```ts
32
+ * const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
33
+ * ```
34
+ */
35
+ export const SessionIdSymbol = Symbol.for('@livestore/session-id')
36
+ export type SessionIdSymbol = typeof SessionIdSymbol
37
+
38
+ export type BindableWithSessionIdSymbol =
39
+ | ReadonlyArray<SqlValue | SessionIdSymbol>
40
+ | Record<string, SqlValue | SessionIdSymbol>
41
+
42
+ export const resolveSessionIdSymbolInBindValues = (
43
+ bindValues: BindableWithSessionIdSymbol,
44
+ sessionId: string,
45
+ ): Bindable => {
46
+ return Array.isArray(bindValues) === true
47
+ ? bindValues.map((value) => (value === SessionIdSymbol ? sessionId : value))
48
+ : (Object.fromEntries(
49
+ Object.entries(bindValues).map(([key, value]) => [key, value === SessionIdSymbol ? sessionId : value]),
50
+ ) as Record<string, SqlValue>)
51
+ }
52
+
53
+ export const resolveSessionIdSymbolInEventArgs = (args: unknown, sessionId: string): unknown => {
54
+ if (Predicate.hasProperty(args, 'id') === false) {
55
+ return args
56
+ }
57
+
58
+ return args.id === SessionIdSymbol ? { ...args, id: sessionId } : args
59
+ }
@@ -1,9 +1,8 @@
1
1
  import { shouldNeverHappen } from '@livestore/utils'
2
- import { pipe, ReadonlyArray, Schema, TreeFormatter } from '@livestore/utils/effect'
2
+ import { pipe, ReadonlyArray, ReadonlyRecord, Result, Schema, SchemaIssue } from '@livestore/utils/effect'
3
3
 
4
4
  import type { SqliteDsl } from '../schema/state/sqlite/db-schema/mod.ts'
5
5
  import { sql } from '../util.ts'
6
- import { objectEntries } from './misc.ts'
7
6
  import * as ClientTypes from './types.ts'
8
7
 
9
8
  export type BindValues = {
@@ -106,7 +105,6 @@ export const insertRows = <TColumns extends SqliteDsl.Columns>({
106
105
 
107
106
  const bindValues = valuesArray.reduce(
108
107
  (acc, values, itemIndex) => ({
109
- // biome-ignore lint/performance/noAccumulatingSpread: TODO improve this some day
110
108
  ...acc,
111
109
  ...makeBindValues({ columns, values, variablePrefix: `item_${itemIndex}_` }),
112
110
  }),
@@ -279,15 +277,14 @@ export const makeBindValues = <TColumns extends SqliteDsl.Columns, TKeys extends
279
277
  skipNil?: boolean
280
278
  }): Record<string, any> => {
281
279
  const codecMap = pipe(
282
- columns,
283
- objectEntries,
280
+ ReadonlyRecord.toEntries(columns),
284
281
  ReadonlyArray.map(([columnName, columnDef]) => [
285
282
  columnName,
286
283
  (value: any) => {
287
284
  if (columnDef.nullable === true && (value === null || value === undefined)) return null
288
- const res = Schema.encodeEither(columnDef.schema)(value)
289
- if (res._tag === 'Left') {
290
- const parseErrorStr = TreeFormatter.formatErrorSync(res.left)
285
+ const res = Schema.encodeResult(columnDef.schema)(value)
286
+ if (Result.isFailure(res) === true) {
287
+ const parseErrorStr = SchemaIssue.makeFormatterDefault()(res.failure.issue)
291
288
  const expectedSchemaStr = String(columnDef.schema.ast)
292
289
 
293
290
  console.error(
@@ -301,11 +298,11 @@ Error: ${parseErrorStr}
301
298
  Value:`,
302
299
  value,
303
300
  )
304
- // oxlint-disable-next-line eslint(no-debugger) -- intentional breakpoint for SQL decode errors
301
+ // oxlint-disable-next-line no-debugger -- intentional breakpoint for SQL decode errors
305
302
  debugger
306
- throw res.left
303
+ throw res.failure
307
304
  } else {
308
- return res.right
305
+ return res.success
309
306
  }
310
307
  },
311
308
  ]),
@@ -363,8 +360,7 @@ const buildWhereSql = <TColumns extends SqliteDsl.Columns>({
363
360
  }
364
361
 
365
362
  return pipe(
366
- where,
367
- objectEntries,
363
+ ReadonlyRecord.toEntries(where),
368
364
  ReadonlyArray.map(([columnName, value]) => `${columnName} ${getWhereOp(columnName, value)}`),
369
365
  ReadonlyArray.join(' AND '),
370
366
  )
@@ -1,16 +1,15 @@
1
- import type { Prettify } from '@livestore/utils'
2
- import type { Schema } from '@livestore/utils/effect'
1
+ import type { Schema, Types } from '@livestore/utils/effect'
3
2
 
4
3
  import type { SqliteDsl } from '../schema/state/sqlite/db-schema/mod.ts'
5
4
 
6
5
  export type DecodedValuesForTableAll<TSchema extends SqliteDsl.DbSchema, TTableName extends keyof TSchema> = {
7
- [K in keyof GetColumns<TSchema, TTableName>]: Schema.Schema.Type<GetColumn<TSchema, TTableName, K>['schema']>
6
+ [K in keyof GetColumns<TSchema, TTableName>]: GetColumn<TSchema, TTableName, K>['schema']['Type']
8
7
  }
9
8
 
10
9
  export type DecodedValuesForTablePretty<
11
10
  TSchema extends SqliteDsl.DbSchema,
12
11
  TTableName extends keyof TSchema,
13
- > = Prettify<DecodedValuesForTable<TSchema, TTableName>>
12
+ > = Types.Simplify<DecodedValuesForTable<TSchema, TTableName>>
14
13
 
15
14
  export type DecodedValuesForTable<TSchema extends SqliteDsl.DbSchema, TTableName extends keyof TSchema> = Partial<
16
15
  Pick<DecodedValuesForTableAll<TSchema, TTableName>, GetNullableColumnNamesForTable<TSchema, TTableName>>
@@ -40,7 +39,7 @@ export const isValidWhereOp = (op: string): op is WhereOp => {
40
39
  }
41
40
 
42
41
  export type EncodedValuesForTableAll<TSchema extends SqliteDsl.DbSchema, TTableName extends keyof TSchema> = {
43
- [K in keyof GetColumns<TSchema, TTableName>]: Schema.Schema.Type<GetColumn<TSchema, TTableName, K>['schema']>
42
+ [K in keyof GetColumns<TSchema, TTableName>]: GetColumn<TSchema, TTableName, K>['schema']['Type']
44
43
  }
45
44
 
46
45
  export type EncodedValuesForTable<TSchema extends SqliteDsl.DbSchema, TTableName extends keyof TSchema> = Partial<
@@ -69,7 +68,7 @@ export type GetColumn<
69
68
  > = TSchema[TTableName]['columns'][TColumnName]
70
69
 
71
70
  export type DecodedValuesForColumnsAll<TColumns extends SqliteDsl.Columns> = {
72
- [K in keyof TColumns]: Schema.Schema.Type<TColumns[K]['schema']>
71
+ [K in keyof TColumns]: TColumns[K]['schema']['Type']
73
72
  }
74
73
 
75
74
  export type DecodedValuesForColumns<TColumns extends SqliteDsl.Columns> = Partial<
@@ -78,7 +77,7 @@ export type DecodedValuesForColumns<TColumns extends SqliteDsl.Columns> = Partia
78
77
  Omit<DecodedValuesForColumnsAll<TColumns>, GetNullableColumnNames<TColumns>>
79
78
 
80
79
  export type EncodedValuesForColumnsAll<TColumns extends SqliteDsl.Columns> = {
81
- [K in keyof TColumns]: Schema.Schema.Encoded<TColumns[K]['schema']>
80
+ [K in keyof TColumns]: TColumns[K]['schema']['Encoded']
82
81
  }
83
82
 
84
83
  export type EncodedValuesForColumns<TColumns extends SqliteDsl.Columns> = Partial<
@@ -1,4 +1,4 @@
1
- import { Schema } from '@livestore/utils/effect'
1
+ import { Effect, Exit, Function, Schema } from '@livestore/utils/effect'
2
2
 
3
3
  import { type SqliteDb, SqliteError } from './adapter-types.ts'
4
4
  import { getResultSchema, isQueryBuilder } from './schema/state/sqlite/query-builder/mod.ts'
@@ -33,13 +33,75 @@ export const makeSelect = <T>(
33
33
  const { query, bindValues } = queryStrOrQueryBuilder.asSql()
34
34
  const resultSchema = getResultSchema(queryStrOrQueryBuilder)
35
35
  const results = select(query, bindValues as unknown as PreparedBindValues)
36
- return Schema.decodeSync(resultSchema)(results)
36
+ return Schema.decodeUnknownSync(resultSchema)(results)
37
37
  } else {
38
38
  return select(queryStrOrQueryBuilder, maybeBindValues)
39
39
  }
40
40
  }
41
41
  }
42
42
 
43
+ /**
44
+ * Runs an Effect inside an SQLite savepoint.
45
+ *
46
+ * @remarks
47
+ *
48
+ * This starts a savepoint before running `effect`, releases the savepoint on
49
+ * success, and rolls back to the savepoint before re-emitting the original
50
+ * failure on failure.
51
+ *
52
+ * Use this for atomic DB updates that need to compose with callers that may
53
+ * already have an open transaction.
54
+ *
55
+ * @see {@link https://sqlite.org/lang_savepoint.html | SQLite savepoint documentation}
56
+ * @see {@link https://sqlite.org/lang_transaction.html | SQLite transaction documentation}
57
+ */
58
+ export const withSavepoint: {
59
+ (db: SqliteDb): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E | SqliteError, R>
60
+ <A, E, R>(self: Effect.Effect<A, E, R>, db: SqliteDb): Effect.Effect<A, E | SqliteError, R>
61
+ } = Function.dual(
62
+ 2,
63
+ <A, E, R>(self: Effect.Effect<A, E, R>, db: SqliteDb): Effect.Effect<A, E | SqliteError, R> =>
64
+ Effect.uninterruptibleMask((restore) =>
65
+ Effect.sync(generateSavepointName).pipe(
66
+ Effect.flatMap((savepointName) => {
67
+ const savepointSql = `SAVEPOINT ${savepointName}`
68
+ const releaseSql = `RELEASE SAVEPOINT ${savepointName}`
69
+
70
+ return executeSavepointSql(db, savepointSql).pipe(
71
+ // Cleanup is installed only after SQLite successfully creates the savepoint.
72
+ Effect.andThen(
73
+ restore(self).pipe(
74
+ Effect.exit,
75
+ Effect.flatMap((exit) => {
76
+ const cleanup =
77
+ Exit.isSuccess(exit) === true
78
+ ? executeSavepointSql(db, releaseSql)
79
+ : executeSavepointSql(db, `ROLLBACK TO SAVEPOINT ${savepointName}`).pipe(
80
+ Effect.andThen(executeSavepointSql(db, releaseSql)),
81
+ )
82
+
83
+ // Cleanup failures supersede the wrapped exit because the connection state is uncertain.
84
+ return cleanup.pipe(Effect.andThen(exit))
85
+ }),
86
+ ),
87
+ ),
88
+ )
89
+ }),
90
+ ),
91
+ ),
92
+ )
93
+
94
+ let nextSavepointId = 0
95
+
96
+ /** Uses a reserved prefix and process-local counter to avoid caller-controlled or reused identifiers. */
97
+ const generateSavepointName = () => `livestore_savepoint_${nextSavepointId++}`
98
+
99
+ const executeSavepointSql = (db: SqliteDb, sql: string): Effect.Effect<void, SqliteError> =>
100
+ Effect.try({
101
+ try: () => db.execute(sql),
102
+ catch: (cause) => new SqliteError({ cause, query: { sql, bindValues: [] } }),
103
+ })
104
+
43
105
  export const validateSnapshot = (snapshot: Uint8Array) => {
44
106
  const headerBytes = new TextDecoder().decode(snapshot.slice(0, 16))
45
107
  const hasValidHeader = headerBytes.startsWith('SQLite format 3')