@livestore/common 0.4.0 → 0.5.0-dev.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 (421) 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 +1 -1
  17. package/dist/__tests__/fixture.d.ts.map +1 -1
  18. package/dist/__tests__/fixture.js +3 -3
  19. package/dist/__tests__/fixture.js.map +1 -1
  20. package/dist/adapter-types.d.ts +29 -57
  21. package/dist/adapter-types.d.ts.map +1 -1
  22. package/dist/adapter-types.js +20 -37
  23. package/dist/adapter-types.js.map +1 -1
  24. package/dist/debug-info.d.ts +56 -56
  25. package/dist/debug-info.d.ts.map +1 -1
  26. package/dist/debug-info.js +28 -41
  27. package/dist/debug-info.js.map +1 -1
  28. package/dist/defs.d.ts +9 -9
  29. package/dist/defs.js +2 -2
  30. package/dist/devtools/devtools-compatibility.test.js +1 -0
  31. package/dist/devtools/devtools-compatibility.test.js.map +1 -1
  32. package/dist/devtools/devtools-messages-client-session.d.ts +520 -332
  33. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
  34. package/dist/devtools/devtools-messages-client-session.js +76 -74
  35. package/dist/devtools/devtools-messages-client-session.js.map +1 -1
  36. package/dist/devtools/devtools-messages-common.d.ts +27 -27
  37. package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
  38. package/dist/devtools/devtools-messages-common.js +5 -5
  39. package/dist/devtools/devtools-messages-common.js.map +1 -1
  40. package/dist/devtools/devtools-messages-leader.d.ts +405 -343
  41. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
  42. package/dist/devtools/devtools-messages-leader.js +101 -89
  43. package/dist/devtools/devtools-messages-leader.js.map +1 -1
  44. package/dist/devtools/devtools-sessioninfo.d.ts +18 -19
  45. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
  46. package/dist/devtools/devtools-sessioninfo.js +8 -5
  47. package/dist/devtools/devtools-sessioninfo.js.map +1 -1
  48. package/dist/devtools/mod.d.ts +4 -5
  49. package/dist/devtools/mod.d.ts.map +1 -1
  50. package/dist/devtools/mod.js +9 -5
  51. package/dist/devtools/mod.js.map +1 -1
  52. package/dist/errors.d.ts +45 -69
  53. package/dist/errors.d.ts.map +1 -1
  54. package/dist/errors.js +18 -16
  55. package/dist/errors.js.map +1 -1
  56. package/dist/index.d.ts +4 -1
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +4 -1
  59. package/dist/index.js.map +1 -1
  60. package/dist/leader-thread/LeaderSyncProcessor.d.ts +66 -18
  61. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  62. package/dist/leader-thread/LeaderSyncProcessor.js +519 -461
  63. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  64. package/dist/leader-thread/RejectedPushError.d.ts +67 -36
  65. package/dist/leader-thread/RejectedPushError.d.ts.map +1 -1
  66. package/dist/leader-thread/RejectedPushError.js +24 -5
  67. package/dist/leader-thread/RejectedPushError.js.map +1 -1
  68. package/dist/leader-thread/connection.d.ts +1 -0
  69. package/dist/leader-thread/connection.d.ts.map +1 -1
  70. package/dist/leader-thread/connection.js +9 -8
  71. package/dist/leader-thread/connection.js.map +1 -1
  72. package/dist/leader-thread/eventlog.d.ts +4 -4
  73. package/dist/leader-thread/eventlog.d.ts.map +1 -1
  74. package/dist/leader-thread/eventlog.js +6 -6
  75. package/dist/leader-thread/eventlog.js.map +1 -1
  76. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -1
  77. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  78. package/dist/leader-thread/leader-worker-devtools.js +33 -17
  79. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  80. package/dist/leader-thread/make-leader-thread-layer.d.ts +9 -5
  81. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  82. package/dist/leader-thread/make-leader-thread-layer.js +25 -35
  83. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  84. package/dist/leader-thread/make-leader-thread-layer.test.js +7 -7
  85. package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -1
  86. package/dist/leader-thread/materialize-event.d.ts +2 -1
  87. package/dist/leader-thread/materialize-event.d.ts.map +1 -1
  88. package/dist/leader-thread/materialize-event.js +4 -0
  89. package/dist/leader-thread/materialize-event.js.map +1 -1
  90. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  91. package/dist/leader-thread/recreate-db.js +18 -39
  92. package/dist/leader-thread/recreate-db.js.map +1 -1
  93. package/dist/leader-thread/shutdown-channel.d.ts +2 -6
  94. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  95. package/dist/leader-thread/shutdown-channel.js +2 -3
  96. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  97. package/dist/leader-thread/stream-events.d.ts +4 -7
  98. package/dist/leader-thread/stream-events.d.ts.map +1 -1
  99. package/dist/leader-thread/stream-events.js +13 -16
  100. package/dist/leader-thread/stream-events.js.map +1 -1
  101. package/dist/leader-thread/types.d.ts +32 -69
  102. package/dist/leader-thread/types.d.ts.map +1 -1
  103. package/dist/leader-thread/types.js +5 -5
  104. package/dist/leader-thread/types.js.map +1 -1
  105. package/dist/logging.d.ts +5 -30
  106. package/dist/logging.d.ts.map +1 -1
  107. package/dist/logging.js +1 -32
  108. package/dist/logging.js.map +1 -1
  109. package/dist/make-client-session.d.ts +1 -2
  110. package/dist/make-client-session.d.ts.map +1 -1
  111. package/dist/make-client-session.js +3 -3
  112. package/dist/make-client-session.js.map +1 -1
  113. package/dist/materializer-helper.d.ts +0 -1
  114. package/dist/materializer-helper.d.ts.map +1 -1
  115. package/dist/materializer-helper.js +7 -35
  116. package/dist/materializer-helper.js.map +1 -1
  117. package/dist/otel.d.ts +2 -3
  118. package/dist/otel.d.ts.map +1 -1
  119. package/dist/otel.js +2 -7
  120. package/dist/otel.js.map +1 -1
  121. package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
  122. package/dist/rematerialize-from-eventlog.js +28 -26
  123. package/dist/rematerialize-from-eventlog.js.map +1 -1
  124. package/dist/schema/EventDef/define.d.ts +4 -4
  125. package/dist/schema/EventDef/define.d.ts.map +1 -1
  126. package/dist/schema/EventDef/define.js +5 -5
  127. package/dist/schema/EventDef/define.js.map +1 -1
  128. package/dist/schema/EventDef/define.test.d.ts +2 -0
  129. package/dist/schema/EventDef/define.test.d.ts.map +1 -0
  130. package/dist/schema/EventDef/define.test.js +23 -0
  131. package/dist/schema/EventDef/define.test.js.map +1 -0
  132. package/dist/schema/EventDef/deprecated.d.ts +8 -13
  133. package/dist/schema/EventDef/deprecated.d.ts.map +1 -1
  134. package/dist/schema/EventDef/deprecated.js +12 -13
  135. package/dist/schema/EventDef/deprecated.js.map +1 -1
  136. package/dist/schema/EventDef/deprecated.test.js +1 -1
  137. package/dist/schema/EventDef/deprecated.test.js.map +1 -1
  138. package/dist/schema/EventDef/event-def.d.ts +1 -1
  139. package/dist/schema/EventDef/event-def.d.ts.map +1 -1
  140. package/dist/schema/EventSequenceNumber/client.d.ts +12 -12
  141. package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -1
  142. package/dist/schema/EventSequenceNumber/client.js +8 -9
  143. package/dist/schema/EventSequenceNumber/client.js.map +1 -1
  144. package/dist/schema/EventSequenceNumber/global.d.ts +2 -2
  145. package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -1
  146. package/dist/schema/EventSequenceNumber/global.js +1 -1
  147. package/dist/schema/EventSequenceNumber/global.js.map +1 -1
  148. package/dist/schema/EventSequenceNumber.test.js +5 -5
  149. package/dist/schema/EventSequenceNumber.test.js.map +1 -1
  150. package/dist/schema/LiveStoreEvent/client.d.ts +50 -179
  151. package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -1
  152. package/dist/schema/LiveStoreEvent/client.js +32 -29
  153. package/dist/schema/LiveStoreEvent/client.js.map +1 -1
  154. package/dist/schema/LiveStoreEvent/client.test.js +11 -2
  155. package/dist/schema/LiveStoreEvent/client.test.js.map +1 -1
  156. package/dist/schema/LiveStoreEvent/for-event-def.d.ts +7 -7
  157. package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -1
  158. package/dist/schema/LiveStoreEvent/global.d.ts +6 -6
  159. package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -1
  160. package/dist/schema/LiveStoreEvent/global.js +1 -1
  161. package/dist/schema/LiveStoreEvent/global.js.map +1 -1
  162. package/dist/schema/LiveStoreEvent/input.d.ts +5 -5
  163. package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -1
  164. package/dist/schema/LiveStoreEvent/input.js +3 -3
  165. package/dist/schema/LiveStoreEvent/input.js.map +1 -1
  166. package/dist/schema/mod.d.ts +1 -0
  167. package/dist/schema/mod.d.ts.map +1 -1
  168. package/dist/schema/mod.js +1 -0
  169. package/dist/schema/mod.js.map +1 -1
  170. package/dist/schema/schema.d.ts.map +1 -1
  171. package/dist/schema/schema.js +3 -2
  172. package/dist/schema/schema.js.map +1 -1
  173. package/dist/schema/state/sqlite/client-document-def.d.ts +12 -17
  174. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  175. package/dist/schema/state/sqlite/client-document-def.js +23 -20
  176. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  177. package/dist/schema/state/sqlite/client-document-def.test.js +29 -8
  178. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
  179. package/dist/schema/state/sqlite/column-annotations.d.ts +13 -13
  180. package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
  181. package/dist/schema/state/sqlite/column-annotations.js +13 -15
  182. package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
  183. package/dist/schema/state/sqlite/column-annotations.test.js +19 -43
  184. package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
  185. package/dist/schema/state/sqlite/column-def.d.ts +1 -1
  186. package/dist/schema/state/sqlite/column-def.d.ts.map +1 -1
  187. package/dist/schema/state/sqlite/column-def.js +57 -31
  188. package/dist/schema/state/sqlite/column-def.js.map +1 -1
  189. package/dist/schema/state/sqlite/column-def.test.js +118 -72
  190. package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
  191. package/dist/schema/state/sqlite/column-spec.js.map +1 -1
  192. package/dist/schema/state/sqlite/column-spec.test.js +2 -2
  193. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +2 -2
  194. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -1
  195. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +13 -4
  196. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
  197. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +9 -9
  198. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
  199. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +8 -13
  200. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
  201. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +27 -16
  202. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -1
  203. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +13 -11
  204. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
  205. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +5 -3
  206. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
  207. package/dist/schema/state/sqlite/mod.d.ts +1 -3
  208. package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
  209. package/dist/schema/state/sqlite/mod.js +1 -1
  210. package/dist/schema/state/sqlite/mod.js.map +1 -1
  211. package/dist/schema/state/sqlite/persistence.d.ts +11 -0
  212. package/dist/schema/state/sqlite/persistence.d.ts.map +1 -0
  213. package/dist/schema/state/sqlite/persistence.js +10 -0
  214. package/dist/schema/state/sqlite/persistence.js.map +1 -0
  215. package/dist/schema/state/sqlite/query-builder/api.d.ts +7 -7
  216. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
  217. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
  218. package/dist/schema/state/sqlite/query-builder/astToSql.js +27 -23
  219. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
  220. package/dist/schema/state/sqlite/query-builder/impl.d.ts +3 -1
  221. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
  222. package/dist/schema/state/sqlite/query-builder/impl.js +16 -14
  223. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
  224. package/dist/schema/state/sqlite/query-builder/impl.test.js +362 -596
  225. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  226. package/dist/schema/state/sqlite/schema-helpers.js +1 -1
  227. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
  228. package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts +102 -134
  229. package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts.map +1 -1
  230. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +2 -2
  231. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -1
  232. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +328 -106
  233. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -1
  234. package/dist/schema/state/sqlite/system-tables/state-tables.js +33 -1
  235. package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -1
  236. package/dist/schema/state/sqlite/table-def.d.ts +16 -19
  237. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  238. package/dist/schema/state/sqlite/table-def.js +53 -3
  239. package/dist/schema/state/sqlite/table-def.js.map +1 -1
  240. package/dist/schema/state/sqlite/table-def.test.js +153 -36
  241. package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
  242. package/dist/schema/unknown-events.d.ts.map +1 -1
  243. package/dist/schema/unknown-events.js +2 -1
  244. package/dist/schema/unknown-events.js.map +1 -1
  245. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +2 -2
  246. package/dist/session-id-symbol.d.ts +29 -0
  247. package/dist/session-id-symbol.d.ts.map +1 -0
  248. package/dist/session-id-symbol.js +44 -0
  249. package/dist/session-id-symbol.js.map +1 -0
  250. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  251. package/dist/sql-queries/sql-queries.js +8 -10
  252. package/dist/sql-queries/sql-queries.js.map +1 -1
  253. package/dist/sql-queries/types.d.ts +6 -7
  254. package/dist/sql-queries/types.d.ts.map +1 -1
  255. package/dist/sql-queries/types.js.map +1 -1
  256. package/dist/sqlite-db-helper.d.ts +21 -1
  257. package/dist/sqlite-db-helper.d.ts.map +1 -1
  258. package/dist/sqlite-db-helper.js +37 -2
  259. package/dist/sqlite-db-helper.js.map +1 -1
  260. package/dist/sqlite-types.d.ts +3 -6
  261. package/dist/sqlite-types.d.ts.map +1 -1
  262. package/dist/sqlite-types.js +3 -3
  263. package/dist/sqlite-types.js.map +1 -1
  264. package/dist/sync/ClientSessionSyncProcessor.d.ts +38 -16
  265. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  266. package/dist/sync/ClientSessionSyncProcessor.js +196 -66
  267. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  268. package/dist/sync/errors.d.ts +12 -18
  269. package/dist/sync/errors.d.ts.map +1 -1
  270. package/dist/sync/errors.js +2 -2
  271. package/dist/sync/errors.js.map +1 -1
  272. package/dist/sync/mock-sync-backend.d.ts +2 -3
  273. package/dist/sync/mock-sync-backend.d.ts.map +1 -1
  274. package/dist/sync/mock-sync-backend.js +54 -33
  275. package/dist/sync/mock-sync-backend.js.map +1 -1
  276. package/dist/sync/mock-sync-backend.test.d.ts +2 -0
  277. package/dist/sync/mock-sync-backend.test.d.ts.map +1 -0
  278. package/dist/sync/mock-sync-backend.test.js +49 -0
  279. package/dist/sync/mock-sync-backend.test.js.map +1 -0
  280. package/dist/sync/next/history-dag-common.d.ts +4 -0
  281. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  282. package/dist/sync/next/history-dag-common.js +52 -31
  283. package/dist/sync/next/history-dag-common.js.map +1 -1
  284. package/dist/sync/next/history-dag.d.ts.map +1 -1
  285. package/dist/sync/next/history-dag.js +2 -1
  286. package/dist/sync/next/history-dag.js.map +1 -1
  287. package/dist/sync/next/test/compact-events.calculator.test.js +2 -2
  288. package/dist/sync/next/test/event-fixtures.d.ts +7 -7
  289. package/dist/sync/next/test/event-fixtures.js +1 -1
  290. package/dist/sync/next/test/event-fixtures.js.map +1 -1
  291. package/dist/sync/next/test/history-dag-common.test.d.ts +2 -0
  292. package/dist/sync/next/test/history-dag-common.test.d.ts.map +1 -0
  293. package/dist/sync/next/test/history-dag-common.test.js +73 -0
  294. package/dist/sync/next/test/history-dag-common.test.js.map +1 -0
  295. package/dist/sync/sync-backend-kv.d.ts.map +1 -1
  296. package/dist/sync/sync-backend-kv.js +4 -2
  297. package/dist/sync/sync-backend-kv.js.map +1 -1
  298. package/dist/sync/sync-backend.d.ts +15 -15
  299. package/dist/sync/sync-backend.d.ts.map +1 -1
  300. package/dist/sync/sync-backend.js +9 -5
  301. package/dist/sync/sync-backend.js.map +1 -1
  302. package/dist/sync/sync.d.ts +1 -1
  303. package/dist/sync/sync.d.ts.map +1 -1
  304. package/dist/sync/syncstate.d.ts +97 -173
  305. package/dist/sync/syncstate.d.ts.map +1 -1
  306. package/dist/sync/syncstate.js +34 -37
  307. package/dist/sync/syncstate.js.map +1 -1
  308. package/dist/sync/syncstate.test.js +100 -61
  309. package/dist/sync/syncstate.test.js.map +1 -1
  310. package/dist/sync/transport-chunking.d.ts +15 -16
  311. package/dist/sync/transport-chunking.d.ts.map +1 -1
  312. package/dist/sync/transport-chunking.js +23 -32
  313. package/dist/sync/transport-chunking.js.map +1 -1
  314. package/dist/util.d.ts +11 -4
  315. package/dist/util.d.ts.map +1 -1
  316. package/dist/util.js +19 -2
  317. package/dist/util.js.map +1 -1
  318. package/dist/version.d.ts.map +1 -1
  319. package/dist/version.js.map +1 -1
  320. package/package.json +19 -37
  321. package/src/ClientSessionLeaderThreadProxy.ts +1 -1
  322. package/src/MaterializationJournal.ts +184 -0
  323. package/src/StateHead.ts +80 -0
  324. package/src/WorkerTransportError.ts +4 -4
  325. package/src/__tests__/fixture.ts +3 -3
  326. package/src/adapter-types.ts +24 -61
  327. package/src/debug-info.ts +50 -70
  328. package/src/defs.ts +2 -2
  329. package/src/devtools/devtools-compatibility.test.ts +1 -0
  330. package/src/devtools/devtools-messages-client-session.ts +56 -65
  331. package/src/devtools/devtools-messages-common.ts +12 -11
  332. package/src/devtools/devtools-messages-leader.ts +71 -69
  333. package/src/devtools/devtools-sessioninfo.ts +13 -11
  334. package/src/devtools/mod.ts +4 -5
  335. package/src/errors.ts +46 -34
  336. package/src/index.ts +8 -1
  337. package/src/leader-thread/LeaderSyncProcessor.ts +794 -691
  338. package/src/leader-thread/RejectedPushError.ts +40 -27
  339. package/src/leader-thread/connection.ts +12 -8
  340. package/src/leader-thread/eventlog.ts +7 -7
  341. package/src/leader-thread/leader-worker-devtools.ts +37 -19
  342. package/src/leader-thread/make-leader-thread-layer.test.ts +7 -7
  343. package/src/leader-thread/make-leader-thread-layer.ts +56 -53
  344. package/src/leader-thread/materialize-event.ts +13 -8
  345. package/src/leader-thread/recreate-db.ts +24 -59
  346. package/src/leader-thread/shutdown-channel.ts +3 -14
  347. package/src/leader-thread/stream-events.ts +104 -101
  348. package/src/leader-thread/types.ts +24 -62
  349. package/src/logging.ts +5 -52
  350. package/src/make-client-session.ts +6 -6
  351. package/src/materializer-helper.ts +8 -37
  352. package/src/otel.ts +5 -14
  353. package/src/rematerialize-from-eventlog.ts +97 -94
  354. package/src/schema/EventDef/define.test.ts +28 -0
  355. package/src/schema/EventDef/define.ts +20 -19
  356. package/src/schema/EventDef/deprecated.test.ts +1 -8
  357. package/src/schema/EventDef/deprecated.ts +17 -20
  358. package/src/schema/EventDef/event-def.ts +2 -4
  359. package/src/schema/EventSequenceNumber/client.ts +8 -9
  360. package/src/schema/EventSequenceNumber/global.ts +1 -1
  361. package/src/schema/EventSequenceNumber.test.ts +5 -5
  362. package/src/schema/LiveStoreEvent/client.test.ts +17 -4
  363. package/src/schema/LiveStoreEvent/client.ts +36 -35
  364. package/src/schema/LiveStoreEvent/for-event-def.ts +7 -7
  365. package/src/schema/LiveStoreEvent/global.ts +1 -1
  366. package/src/schema/LiveStoreEvent/input.ts +6 -6
  367. package/src/schema/mod.ts +1 -0
  368. package/src/schema/schema.ts +3 -2
  369. package/src/schema/state/sqlite/client-document-def.test.ts +32 -13
  370. package/src/schema/state/sqlite/client-document-def.ts +95 -80
  371. package/src/schema/state/sqlite/column-annotations.test.ts +26 -45
  372. package/src/schema/state/sqlite/column-annotations.ts +26 -30
  373. package/src/schema/state/sqlite/column-def.test.ts +132 -77
  374. package/src/schema/state/sqlite/column-def.ts +72 -37
  375. package/src/schema/state/sqlite/column-spec.test.ts +2 -2
  376. package/src/schema/state/sqlite/column-spec.ts +3 -2
  377. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +15 -5
  378. package/src/schema/state/sqlite/db-schema/dsl/__snapshots__/field-defs.test.ts.snap +123 -63
  379. package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +35 -16
  380. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +25 -31
  381. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +35 -21
  382. package/src/schema/state/sqlite/mod.ts +2 -4
  383. package/src/schema/state/sqlite/persistence.ts +11 -0
  384. package/src/schema/state/sqlite/query-builder/api.ts +9 -9
  385. package/src/schema/state/sqlite/query-builder/astToSql.ts +31 -26
  386. package/src/schema/state/sqlite/query-builder/impl.test.ts +433 -669
  387. package/src/schema/state/sqlite/query-builder/impl.ts +19 -15
  388. package/src/schema/state/sqlite/schema-helpers.ts +1 -1
  389. package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +2 -2
  390. package/src/schema/state/sqlite/system-tables/state-tables.ts +41 -1
  391. package/src/schema/state/sqlite/table-def.test.ts +204 -66
  392. package/src/schema/state/sqlite/table-def.ts +96 -45
  393. package/src/schema/unknown-events.ts +3 -2
  394. package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +2 -2
  395. package/src/session-id-symbol.ts +59 -0
  396. package/src/sql-queries/sql-queries.ts +8 -12
  397. package/src/sql-queries/types.ts +6 -7
  398. package/src/sqlite-db-helper.ts +64 -2
  399. package/src/sqlite-types.ts +5 -8
  400. package/src/sync/ClientSessionSyncProcessor.ts +303 -119
  401. package/src/sync/errors.ts +14 -12
  402. package/src/sync/mock-sync-backend.test.ts +78 -0
  403. package/src/sync/mock-sync-backend.ts +93 -47
  404. package/src/sync/next/history-dag-common.ts +60 -34
  405. package/src/sync/next/history-dag.ts +4 -1
  406. package/src/sync/next/test/compact-events.calculator.test.ts +2 -2
  407. package/src/sync/next/test/event-fixtures.ts +1 -1
  408. package/src/sync/next/test/history-dag-common.test.ts +87 -0
  409. package/src/sync/sync-backend-kv.ts +4 -2
  410. package/src/sync/sync-backend.ts +15 -15
  411. package/src/sync/sync.ts +1 -1
  412. package/src/sync/syncstate.test.ts +191 -140
  413. package/src/sync/syncstate.ts +63 -53
  414. package/src/sync/transport-chunking.ts +34 -39
  415. package/src/util.ts +18 -9
  416. package/src/version.ts +1 -2
  417. package/dist/sql-queries/misc.d.ts +0 -2
  418. package/dist/sql-queries/misc.d.ts.map +0 -1
  419. package/dist/sql-queries/misc.js +0 -2
  420. package/dist/sql-queries/misc.js.map +0 -1
  421. 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,74 @@ export function table<
281
265
  return tableDef as any
282
266
  }
283
267
 
268
+ const getSqlitePropertySignatures = (schema: Schema.Top): ReadonlyArray<SchemaAST.PropertySignature> => {
269
+ const encodedPropertySignatures = getPropertySignatures(SchemaAST.toEncoded(schema.ast))
270
+ const typePropertySignatures = getPropertySignatures(SchemaAST.toType(schema.ast))
271
+
272
+ return encodedPropertySignatures.map((encodedPropertySignature) => {
273
+ const typePropertySignature = typePropertySignatures.find(
274
+ (propertySignature) => propertySignature.name === encodedPropertySignature.name,
275
+ )
276
+
277
+ if (typePropertySignature === undefined || hasLiveStoreSqliteAnnotation(encodedPropertySignature.type) === true) {
278
+ return encodedPropertySignature
279
+ }
280
+
281
+ return new SchemaAST.PropertySignature(encodedPropertySignature.name, typePropertySignature.type)
282
+ })
283
+ }
284
+
285
+ const getPropertySignatures = (ast: SchemaAST.AST): ReadonlyArray<SchemaAST.PropertySignature> => {
286
+ if (SchemaAST.isObjects(ast) === true) return ast.propertySignatures
287
+
288
+ if (SchemaAST.isUnion(ast) === true) {
289
+ const members = ast.types.map(getPropertySignatures)
290
+ const [head, ...tail] = members
291
+ if (head === undefined) return []
292
+
293
+ return head.flatMap((propertySignature) => {
294
+ const matchingPropertySignatures: Array<SchemaAST.PropertySignature> = []
295
+ for (const propertySignatures of tail) {
296
+ const matchingPropertySignature = propertySignatures.find(
297
+ (memberPropertySignature) => memberPropertySignature.name === propertySignature.name,
298
+ )
299
+ if (matchingPropertySignature === undefined) {
300
+ return []
301
+ }
302
+ matchingPropertySignatures.push(matchingPropertySignature)
303
+ }
304
+
305
+ const propertySignatures = [propertySignature, ...matchingPropertySignatures]
306
+ /**
307
+ * `SchemaAST.optionalKey` became internal in Effect rc.109, so the optional-key marker is
308
+ * applied by constructing the union with an optional `Context`. Equivalent here because the
309
+ * union is freshly built and therefore carries no encoding chain to propagate the marker to.
310
+ */
311
+ const hasOptionalMember =
312
+ propertySignatures.some((memberPropertySignature) => SchemaAST.isOptional(memberPropertySignature.type)) ===
313
+ true
314
+ const keyContext = hasOptionalMember === true ? new SchemaAST.Context(true, false) : undefined
315
+ const union = new SchemaAST.Union(
316
+ propertySignatures.map((memberPropertySignature) => memberPropertySignature.type),
317
+ ast.mode,
318
+ undefined,
319
+ undefined,
320
+ undefined,
321
+ keyContext,
322
+ )
323
+
324
+ return [new SchemaAST.PropertySignature(propertySignature.name, union)]
325
+ })
326
+ }
327
+
328
+ return []
329
+ }
330
+
331
+ const hasLiveStoreSqliteAnnotation = (ast: SchemaAST.AST): boolean => {
332
+ const annotationKeys = [...Object.keys(ast.annotations ?? {}), ...Object.keys(ast.context?.annotations ?? {})]
333
+ return annotationKeys.some((key) => key.startsWith('livestore/state/sqlite/annotations/'))
334
+ }
335
+
284
336
  export namespace FromTable {
285
337
  // TODO this sometimes doesn't preserve the order of columns
286
338
  export type RowDecoded<TTableDef extends TableDefBase> = Types.Simplify<
@@ -297,9 +349,7 @@ export namespace FromTable {
297
349
  }
298
350
 
299
351
  export type RowEncodeNonNullable<TTableDef extends TableDefBase> = {
300
- [K in keyof TTableDef['sqliteDef']['columns']]: Schema.Schema.Encoded<
301
- TTableDef['sqliteDef']['columns'][K]['schema']
302
- >
352
+ [K in keyof TTableDef['sqliteDef']['columns']]: TTableDef['sqliteDef']['columns'][K]['schema']['Encoded']
303
353
  }
304
354
 
305
355
  export type RowEncoded<TTableDef extends TableDefBase> = Types.Simplify<
@@ -308,7 +358,7 @@ export namespace FromTable {
308
358
  >
309
359
 
310
360
  export type RowDecodedAll<TTableDef extends TableDefBase> = {
311
- [K in keyof TTableDef['sqliteDef']['columns']]: Schema.Schema.Type<TTableDef['sqliteDef']['columns'][K]['schema']>
361
+ [K in keyof TTableDef['sqliteDef']['columns']]: TTableDef['sqliteDef']['columns'][K]['schema']['Type']
312
362
  }
313
363
  }
314
364
 
@@ -320,7 +370,7 @@ export namespace FromColumns {
320
370
  >
321
371
 
322
372
  export type RowDecodedAll<TColumns extends SqliteDsl.Columns> = {
323
- [K in keyof TColumns]: Schema.Schema.Type<TColumns[K]['schema']>
373
+ [K in keyof TColumns]: TColumns[K]['schema']['Type']
324
374
  }
325
375
 
326
376
  export type RowEncoded<TColumns extends SqliteDsl.Columns> = Types.Simplify<
@@ -329,7 +379,7 @@ export namespace FromColumns {
329
379
  >
330
380
 
331
381
  export type RowEncodeNonNullable<TColumns extends SqliteDsl.Columns> = {
332
- [K in keyof TColumns]: Schema.Schema.Encoded<TColumns[K]['schema']>
382
+ [K in keyof TColumns]: TColumns[K]['schema']['Encoded']
333
383
  }
334
384
 
335
385
  export type NullableColumnNames<TColumns extends SqliteDsl.Columns> = keyof {
@@ -378,7 +428,8 @@ export declare namespace SchemaToColumns {
378
428
  export type FromTypes<TType, TEncoded> =
379
429
  TEncoded extends Record<string, any>
380
430
  ? {
381
- [K in keyof TEncoded]-?: ColumnDefForType<TEncoded[K],
431
+ [K in keyof TEncoded]-?: ColumnDefForType<
432
+ TEncoded[K],
382
433
  TType extends Record<string, any> ? (K extends keyof TType ? TType[K] : TEncoded[K]) : TEncoded[K]
383
434
  >
384
435
  }
@@ -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,
@@ -49,7 +49,7 @@ describe('migrateTable - quoting and autoincrement', () => {
49
49
  primaryKey: true,
50
50
  autoIncrement: true,
51
51
  default: Option.none(),
52
- schema: Schema.Number,
52
+ schema: Schema.Finite,
53
53
  }),
54
54
  SqliteAst.column({
55
55
  name: 'text',
@@ -67,7 +67,7 @@ describe('migrateTable - quoting and autoincrement', () => {
67
67
  primaryKey: false,
68
68
  autoIncrement: false,
69
69
  default: Option.some(0),
70
- schema: Schema.Number,
70
+ schema: Schema.Finite,
71
71
  }),
72
72
  ],
73
73
  [],
@@ -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(
@@ -303,9 +300,9 @@ Value:`,
303
300
  )
304
301
  // oxlint-disable-next-line eslint(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')
@@ -18,12 +18,12 @@ export interface SqliteDb<TReq = any, TMetadata extends TReq = TReq> {
18
18
  prepare(queryStr: string): PreparedStatement
19
19
  execute(
20
20
  queryStr: string,
21
- bindValues?: PreparedBindValues ,
21
+ bindValues?: PreparedBindValues,
22
22
  options?: { onRowsChanged?: (rowsChanged: number) => void },
23
23
  ): void
24
24
  execute(queryBuilder: QueryBuilder.Any, options?: { onRowsChanged?: (rowsChanged: number) => void }): void
25
25
 
26
- select<T>(queryStr: string, bindValues?: PreparedBindValues ): ReadonlyArray<T>
26
+ select<T>(queryStr: string, bindValues?: PreparedBindValues): ReadonlyArray<T>
27
27
  select<T>(queryBuilder: QueryBuilder<T, any, any>): T
28
28
 
29
29
  export(): Uint8Array<ArrayBuffer>
@@ -67,11 +67,8 @@ export type SqliteDbChangeset = {
67
67
  apply: () => void
68
68
  }
69
69
 
70
- export const PersistenceInfo = Schema.Struct(
71
- {
72
- fileName: Schema.String,
73
- },
74
- { key: Schema.String, value: Schema.Any },
75
- ).annotations({ title: 'LiveStore.PersistenceInfo' })
70
+ export const PersistenceInfo = Schema.StructWithRest(Schema.Struct({ fileName: Schema.String }), [
71
+ Schema.Record(Schema.String, Schema.Any),
72
+ ]).annotate({ title: 'LiveStore.PersistenceInfo' })
76
73
 
77
74
  export type PersistenceInfo<With extends {} = {}> = typeof PersistenceInfo.Type & With