@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,6 +1,5 @@
1
- /** biome-ignore-all lint/complexity/noArguments: using arguments is fine here */
2
1
  import { casesHandled, shouldNeverHappen } from '@livestore/utils'
3
- import { Match, Option, Predicate, Schema } from '@livestore/utils/effect'
2
+ import { Match, Option, Predicate, Schema, Struct } from '@livestore/utils/effect'
4
3
 
5
4
  import type { TableDefBase } from '../table-def.ts'
6
5
  import type { QueryBuilder, QueryBuilderAst } from './api.ts'
@@ -22,7 +21,7 @@ export const makeQueryBuilder = <TResult, TTableDef extends TableDefBase>(
22
21
  const [col] = params as any as [string]
23
22
  return makeQueryBuilder(tableDef, {
24
23
  ...ast,
25
- resultSchemaSingle: ast.resultSchemaSingle.pipe(Schema.pluck(col)),
24
+ resultSchemaSingle: ast.tableDef.rowSchema.pipe(Schema.pluck(col)),
26
25
  select: { columns: [col] },
27
26
  })
28
27
  }
@@ -34,7 +33,7 @@ export const makeQueryBuilder = <TResult, TTableDef extends TableDefBase>(
34
33
  return makeQueryBuilder(tableDef, {
35
34
  ...ast,
36
35
  resultSchemaSingle:
37
- columns.length === 0 ? ast.resultSchemaSingle : ast.resultSchemaSingle.pipe(Schema.pick(...columns)),
36
+ columns.length === 0 ? ast.resultSchemaSingle : ast.tableDef.rowSchema.mapFields(Struct.pick(columns)),
38
37
  select: { columns },
39
38
  }) as any
40
39
  },
@@ -48,8 +47,8 @@ export const makeQueryBuilder = <TResult, TTableDef extends TableDefBase>(
48
47
  .filter(([, value]) => value !== undefined)
49
48
  .map<QueryBuilderAst.Where>(([col, value]) =>
50
49
  Predicate.hasProperty(value, 'op') === true && Predicate.hasProperty(value, 'value') === true
51
- // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- where clause construction; shape validated at runtime
52
- ? ({ col, op: value.op, value: value.value } as any)
50
+ ? // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- where clause construction; shape validated at runtime
51
+ ({ col, op: value.op, value: value.value } as any)
53
52
  : { col, op: '=', value },
54
53
  )
55
54
 
@@ -125,14 +124,19 @@ export const makeQueryBuilder = <TResult, TTableDef extends TableDefBase>(
125
124
  return makeQueryBuilder(tableDef, { ...ast, offset: Option.some(offset) })
126
125
  },
127
126
  count: () => {
128
- if (isRowQuery(ast) === true || ast._tag === 'InsertQuery' || ast._tag === 'UpdateQuery' || ast._tag === 'DeleteQuery')
127
+ if (
128
+ isRowQuery(ast) === true ||
129
+ ast._tag === 'InsertQuery' ||
130
+ ast._tag === 'UpdateQuery' ||
131
+ ast._tag === 'DeleteQuery'
132
+ )
129
133
  return invalidQueryBuilder()
130
134
 
131
135
  return makeQueryBuilder(tableDef, {
132
136
  _tag: 'CountQuery',
133
137
  tableDef,
134
138
  where: ast.where,
135
- resultSchema: Schema.Struct({ count: Schema.Number }).pipe(
139
+ resultSchema: Schema.Struct({ count: Schema.Finite }).pipe(
136
140
  Schema.pluck('count'),
137
141
  Schema.Array,
138
142
  Schema.headOrElse(),
@@ -223,7 +227,7 @@ export const makeQueryBuilder = <TResult, TTableDef extends TableDefBase>(
223
227
  return makeQueryBuilder(tableDef, {
224
228
  ...ast,
225
229
  returning: columns,
226
- resultSchema: tableDef.rowSchema.pipe(Schema.pick(...columns), Schema.Array),
230
+ resultSchema: tableDef.rowSchema.mapFields(Struct.pick(columns)).pipe(Schema.Array),
227
231
  }) as any
228
232
  },
229
233
 
@@ -316,7 +320,7 @@ export const invalidQueryBuilder = (msg?: string) => {
316
320
  return shouldNeverHappen(`Invalid query builder${msg !== undefined ? `: ${msg}` : ''}`)
317
321
  }
318
322
 
319
- export const getResultSchema = (qb: QueryBuilder<any, any, any>): Schema.Schema<any> => {
323
+ export const getResultSchema = (qb: QueryBuilder<any, any, any>) => {
320
324
  const queryAst = qb[QueryBuilderAstSymbol]
321
325
  switch (queryAst._tag) {
322
326
  case 'SelectQuery': {
@@ -331,13 +335,13 @@ export const getResultSchema = (qb: QueryBuilder<any, any, any>): Schema.Schema<
331
335
  return arraySchema.pipe(Schema.headOrElse())
332
336
  } else {
333
337
  const fallbackValue = queryAst.pickFirst.fallback()
334
- return Schema.Union(arraySchema, Schema.Tuple(Schema.Literal(fallbackValue))).pipe(
338
+ return Schema.Array(Schema.Union([queryAst.resultSchemaSingle, Schema.Literal(fallbackValue)])).pipe(
335
339
  Schema.headOrElse(() => fallbackValue),
336
340
  )
337
341
  }
338
342
  }
339
343
  case 'CountQuery': {
340
- return Schema.Struct({ count: Schema.Number }).pipe(Schema.pluck('count'), Schema.Array, Schema.headOrElse())
344
+ return Schema.Struct({ count: Schema.Finite }).pipe(Schema.pluck('count'), Schema.Array, Schema.headOrElse())
341
345
  }
342
346
  case 'InsertQuery':
343
347
  case 'UpdateQuery':
@@ -345,16 +349,16 @@ export const getResultSchema = (qb: QueryBuilder<any, any, any>): Schema.Schema<
345
349
  // For write operations with RETURNING clause, we need to return the appropriate schema
346
350
  if (queryAst.returning !== undefined && queryAst.returning.length > 0) {
347
351
  // Create a schema for the returned columns
348
- return queryAst.tableDef.rowSchema.pipe(Schema.pick(...queryAst.returning), Schema.Array)
352
+ return queryAst.tableDef.rowSchema.mapFields(Struct.pick(queryAst.returning)).pipe(Schema.Array)
349
353
  }
350
354
 
351
355
  // For write operations without RETURNING, the result is the number of affected rows
352
- return Schema.Number
356
+ return Schema.Finite
353
357
  }
354
358
  case 'RowQuery': {
355
359
  return queryAst.tableDef.rowSchema.pipe(
356
360
  Schema.pluck('value'),
357
- Schema.annotations({ title: `${queryAst.tableDef.sqliteDef.name}.value` }),
361
+ Schema.annotate({ title: `${queryAst.tableDef.sqliteDef.name}.value` }),
358
362
  Schema.Array,
359
363
  Schema.headOrElse(),
360
364
  )
@@ -52,6 +52,6 @@ export const getDefaultValuesDecoded = <TTableDef extends TableDefBase>(
52
52
  const defaultValue = column!.default.value
53
53
  const resolvedDefault = SqliteDsl.resolveColumnDefault(defaultValue)
54
54
 
55
- return Schema.validateSync(column!.schema)(resolvedDefault)
55
+ return Schema.decodeSync(Schema.toType(column!.schema))(resolvedDefault)
56
56
  }),
57
57
  )
@@ -30,11 +30,11 @@ export const eventlogMetaTable = table({
30
30
  parentSeqNumRebaseGeneration: SqliteDsl.integer({}),
31
31
  /** Event definition name */
32
32
  name: SqliteDsl.text({}),
33
- argsJson: SqliteDsl.text({ schema: Schema.parseJson(Schema.Any) }),
33
+ argsJson: SqliteDsl.text({ schema: Schema.fromJsonString(Schema.Any) }),
34
34
  clientId: SqliteDsl.text({}),
35
35
  sessionId: SqliteDsl.text({}),
36
36
  schemaHash: SqliteDsl.integer({}),
37
- syncMetadataJson: SqliteDsl.text({ schema: Schema.parseJson(Schema.Option(Schema.JsonValue)) }),
37
+ syncMetadataJson: SqliteDsl.text({ schema: Schema.fromJsonString(Schema.toCodecJson(Schema.Option(Schema.Json))) }),
38
38
  },
39
39
  indexes: [
40
40
  { columns: ['seqNumGlobal'], name: 'idx_eventlog_seqNumGlobal' },
@@ -43,6 +43,27 @@ export const schemaEventDefsMetaTable = table({
43
43
 
44
44
  export type SchemaEventDefsMetaRow = typeof schemaEventDefsMetaTable.Type
45
45
 
46
+ export const STATE_HEAD_META_TABLE = '__livestore_state_head'
47
+
48
+ /**
49
+ * Single-row marker for the latest event sequence number reflected by the state DB.
50
+ *
51
+ * @remarks
52
+ * This is separate from the session changeset table because confirmed changesets
53
+ * can be removed after they are no longer needed for rollback.
54
+ */
55
+ export const stateHeadMetaTable = table({
56
+ name: STATE_HEAD_META_TABLE,
57
+ columns: {
58
+ id: SqliteDsl.integer({ primaryKey: true }),
59
+ seqNumGlobal: SqliteDsl.integer({ schema: EventSequenceNumber.Global.Schema }),
60
+ seqNumClient: SqliteDsl.integer({ schema: EventSequenceNumber.Client.Schema }),
61
+ seqNumRebaseGeneration: SqliteDsl.integer({}),
62
+ },
63
+ })
64
+
65
+ export type StateHeadMetaRow = typeof stateHeadMetaTable.Type
66
+
46
67
  /**
47
68
  * Table which stores SQLite changeset blobs which is used for rolling back
48
69
  * read-model state during rebasing.
@@ -64,6 +85,25 @@ export const sessionChangesetMetaTable = table({
64
85
 
65
86
  export type SessionChangesetMetaRow = typeof sessionChangesetMetaTable.Type
66
87
 
67
- export const stateSystemTables = [schemaMetaTable, schemaEventDefsMetaTable, sessionChangesetMetaTable] as const
88
+ // TODO: Rename the physical table once legacy session changeset consumers have been migrated.
89
+ export const MATERIALIZATION_JOURNAL_META_TABLE = SESSION_CHANGESET_META_TABLE
90
+
91
+ /**
92
+ * Materialization journal used to roll back state database changes during rebasing.
93
+ *
94
+ * @remarks
95
+ * This aliases the legacy table definition until all session changeset consumers
96
+ * have adopted the journal service.
97
+ */
98
+ export const materializationJournalMetaTable = sessionChangesetMetaTable
99
+
100
+ export type MaterializationJournalMetaRow = SessionChangesetMetaRow
101
+
102
+ export const stateSystemTables = [
103
+ schemaMetaTable,
104
+ schemaEventDefsMetaTable,
105
+ stateHeadMetaTable,
106
+ sessionChangesetMetaTable,
107
+ ] as const
68
108
 
69
109
  export const isStateSystemTable = (tableName: string) => stateSystemTables.some((_) => _.sqliteDef.name === tableName)
@@ -1,8 +1,8 @@
1
- import { objectToString } from '@livestore/utils'
2
-
3
- import { Schema } from '@livestore/utils/effect'
1
+ import { TestSchema } from 'effect/testing'
4
2
  import { describe, expect, expectTypeOf, it } from 'vitest'
5
3
 
4
+ import { Schema, SchemaAST, SchemaTransformation } from '@livestore/utils/effect'
5
+
6
6
  import { State } from '../../mod.ts'
7
7
 
8
8
  describe('table function overloads', () => {
@@ -11,7 +11,7 @@ describe('table function overloads', () => {
11
11
  id: Schema.String,
12
12
  text: Schema.String,
13
13
  completed: Schema.Boolean,
14
- }).annotations({ title: 'todos' })
14
+ }).annotate({ title: 'todos' })
15
15
 
16
16
  const todosTable = State.SQLite.table({
17
17
  schema: TodoSchema,
@@ -25,7 +25,7 @@ describe('table function overloads', () => {
25
25
  id: Schema.String,
26
26
  text: Schema.String,
27
27
  completed: Schema.Boolean,
28
- }).annotations({ identifier: 'TodoItem' })
28
+ }).annotate({ identifier: 'TodoItem' })
29
29
 
30
30
  const todosTable = State.SQLite.table({ schema: TodoSchema })
31
31
 
@@ -37,7 +37,7 @@ describe('table function overloads', () => {
37
37
  id: Schema.String,
38
38
  text: Schema.String,
39
39
  completed: Schema.Boolean,
40
- }).annotations({
40
+ }).annotate({
41
41
  title: 'todos',
42
42
  identifier: 'TodoItem',
43
43
  })
@@ -59,7 +59,7 @@ describe('table function overloads', () => {
59
59
  )
60
60
  })
61
61
 
62
- it('should work with columns parameter', () => {
62
+ it('should work with columns parameter', async () => {
63
63
  const todosTable = State.SQLite.table({
64
64
  name: 'todos',
65
65
  columns: {
@@ -74,7 +74,6 @@ describe('table function overloads', () => {
74
74
  },
75
75
  })
76
76
 
77
- expect((todosTable.rowSchema as any).fields.completed.toString()).toMatchInlineSnapshot(`"(number <-> boolean)"`)
78
77
  expect(todosTable.sqliteDef.name).toBe('todos')
79
78
  expect(todosTable.sqliteDef.columns).toHaveProperty('id')
80
79
  expect(todosTable.sqliteDef.columns).toHaveProperty('text')
@@ -82,15 +81,42 @@ describe('table function overloads', () => {
82
81
  expect(todosTable.sqliteDef.columns).toHaveProperty('optionalComplex')
83
82
 
84
83
  expect(todosTable.sqliteDef.columns.optionalBoolean.nullable).toBe(true)
85
- expect(objectToString(todosTable.sqliteDef.columns.optionalBoolean.schema)).toBe('(number <-> boolean) | null')
86
- expect((todosTable.rowSchema as any).fields.optionalBoolean.toString()).toBe('(number <-> boolean) | null')
84
+ expect(Schema.encodeSync(todosTable.sqliteDef.columns.optionalBoolean.schema)(false)).toBe(0)
87
85
 
88
86
  expect(todosTable.sqliteDef.columns.optionalComplex.nullable).toBe(true)
89
- expect(objectToString(todosTable.sqliteDef.columns.optionalComplex.schema)).toBe(
90
- '(parseJson <-> { readonly color: string } | undefined) | null',
87
+
88
+ const asserts = new TestSchema.Asserts(todosTable.rowSchema)
89
+ await asserts.decoding().succeed(
90
+ {
91
+ id: 'todo-1',
92
+ text: 'Buy milk',
93
+ completed: 1,
94
+ optionalBoolean: null,
95
+ optionalComplex: JSON.stringify({ color: 'red' }),
96
+ },
97
+ {
98
+ id: 'todo-1',
99
+ text: 'Buy milk',
100
+ completed: true,
101
+ optionalBoolean: null,
102
+ optionalComplex: { color: 'red' },
103
+ },
91
104
  )
92
- expect((todosTable.rowSchema as any).fields.optionalComplex.toString()).toBe(
93
- '(parseJson <-> { readonly color: string } | undefined) | null',
105
+ await asserts.decoding().succeed(
106
+ {
107
+ id: 'todo-1',
108
+ text: 'Buy milk',
109
+ completed: 0,
110
+ optionalBoolean: null,
111
+ optionalComplex: null,
112
+ },
113
+ {
114
+ id: 'todo-1',
115
+ text: 'Buy milk',
116
+ completed: false,
117
+ optionalBoolean: null,
118
+ optionalComplex: null,
119
+ },
94
120
  )
95
121
  })
96
122
 
@@ -205,32 +231,33 @@ describe('table function overloads', () => {
205
231
  contactEmail: Schema.String.pipe(State.SQLite.withUnique),
206
232
  })
207
233
 
208
- const Nested = Schema.transform(
209
- Flat,
210
- Schema.Struct({
211
- id: Schema.String,
212
- contact: Schema.Struct({
213
- firstName: Schema.String,
214
- lastName: Schema.String,
215
- email: Schema.String,
216
- }),
217
- }),
218
- {
219
- decode: ({ id, contactFirstName, contactLastName, contactEmail }) => ({
220
- id,
221
- contact: {
222
- firstName: contactFirstName,
223
- lastName: contactLastName,
224
- email: contactEmail,
225
- },
234
+ const Nested = Flat.pipe(
235
+ Schema.decodeTo(
236
+ Schema.Struct({
237
+ id: Schema.String,
238
+ contact: Schema.Struct({
239
+ firstName: Schema.String,
240
+ lastName: Schema.String,
241
+ email: Schema.String,
242
+ }),
226
243
  }),
227
- encode: ({ id, contact }) => ({
228
- id,
229
- contactFirstName: contact.firstName,
230
- contactLastName: contact.lastName,
231
- contactEmail: contact.email,
244
+ SchemaTransformation.transform({
245
+ decode: ({ id, contactFirstName, contactLastName, contactEmail }) => ({
246
+ id,
247
+ contact: {
248
+ firstName: contactFirstName,
249
+ lastName: contactLastName,
250
+ email: contactEmail,
251
+ },
252
+ }),
253
+ encode: ({ id, contact }) => ({
254
+ id,
255
+ contactFirstName: contact.firstName,
256
+ contactLastName: contact.lastName,
257
+ contactEmail: contact.email,
258
+ }),
232
259
  }),
233
- },
260
+ ),
234
261
  )
235
262
 
236
263
  const contactsTable = State.SQLite.table({
@@ -266,13 +293,13 @@ describe('table function overloads', () => {
266
293
  expect(todosTable.sqliteDef.name).toBe('TodoItem')
267
294
  })
268
295
 
269
- it('should properly infer types from schema', () => {
296
+ it('should properly infer types from schema', async () => {
270
297
  const UserSchema = Schema.Struct({
271
298
  id: Schema.String,
272
299
  name: Schema.String,
273
300
  age: Schema.Int,
274
301
  active: Schema.Boolean,
275
- metadata: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Unknown })),
302
+ metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
276
303
  })
277
304
 
278
305
  const userTable = State.SQLite.table({
@@ -297,13 +324,6 @@ describe('table function overloads', () => {
297
324
  type ActiveColumn = typeof userTable.sqliteDef.columns.active
298
325
  type MetadataColumn = typeof userTable.sqliteDef.columns.metadata
299
326
 
300
- // Should derive proper column schema
301
- expect((userTable.rowSchema as any).fields.age.toString()).toMatchInlineSnapshot(`"Int"`)
302
- expect((userTable.rowSchema as any).fields.active.toString()).toMatchInlineSnapshot(`"(number <-> boolean)"`)
303
- expect((userTable.rowSchema as any).fields.metadata.toString()).toMatchInlineSnapshot(
304
- `"(parseJson <-> { readonly [x: string]: unknown }) | null"`,
305
- )
306
-
307
327
  // These should compile without errors
308
328
  const _idCheck: IdColumn['schema']['Type'] = 'string'
309
329
  const _nameCheck: NameColumn['schema']['Type'] = 'string'
@@ -318,6 +338,28 @@ describe('table function overloads', () => {
318
338
  expect(userTable.sqliteDef.columns.active.columnType).toBe('integer')
319
339
  expect(userTable.sqliteDef.columns.metadata.columnType).toBe('text')
320
340
  expect(userTable.sqliteDef.columns.metadata.nullable).toBe(true)
341
+
342
+ const asserts = new TestSchema.Asserts(userTable.rowSchema)
343
+ await asserts.decoding().succeed(
344
+ {
345
+ id: 'test-id',
346
+ name: 'John',
347
+ age: 30,
348
+ active: 1,
349
+ metadata: JSON.stringify({ key1: 'value1', key2: 123 }),
350
+ },
351
+ {
352
+ id: 'test-id',
353
+ name: 'John',
354
+ age: 30,
355
+ active: true,
356
+ metadata: { key1: 'value1', key2: 123 },
357
+ },
358
+ )
359
+ const activeAsserts = new TestSchema.Asserts(userTable.sqliteDef.columns.active.schema)
360
+ const metadataAsserts = new TestSchema.Asserts(userTable.sqliteDef.columns.metadata.schema)
361
+ await activeAsserts.decoding().succeed(0, false)
362
+ await metadataAsserts.decoding().succeed(null)
321
363
  })
322
364
 
323
365
  it('should allow omitting nullable fields in insert()', () => {
@@ -347,41 +389,117 @@ describe('table function overloads', () => {
347
389
  .toBeCallableWith({ id: '1', undefined: undefined, null: null, undefinedOrString: undefined })
348
390
  .toBeCallableWith({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string' })
349
391
  .toBeCallableWith({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: null })
350
- .toBeCallableWith({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: 'string' })
351
- .toBeCallableWith({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: 'string', optionalString: 'string' })
352
- .toBeCallableWith({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: 'string', optionalString: 'string', optionalNullOrString: null })
353
- .toBeCallableWith({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: 'string', optionalString: 'string', optionalNullOrString: 'string' })
392
+ .toBeCallableWith({
393
+ id: '1',
394
+ undefined: undefined,
395
+ null: null,
396
+ undefinedOrString: 'string',
397
+ nullOrString: 'string',
398
+ })
399
+ .toBeCallableWith({
400
+ id: '1',
401
+ undefined: undefined,
402
+ null: null,
403
+ undefinedOrString: 'string',
404
+ nullOrString: 'string',
405
+ optionalString: 'string',
406
+ })
407
+ .toBeCallableWith({
408
+ id: '1',
409
+ undefined: undefined,
410
+ null: null,
411
+ undefinedOrString: 'string',
412
+ nullOrString: 'string',
413
+ optionalString: 'string',
414
+ optionalNullOrString: null,
415
+ })
416
+ .toBeCallableWith({
417
+ id: '1',
418
+ undefined: undefined,
419
+ null: null,
420
+ undefinedOrString: 'string',
421
+ nullOrString: 'string',
422
+ optionalString: 'string',
423
+ optionalNullOrString: 'string',
424
+ })
354
425
 
355
426
  expect(() => usersTable.insert({ id: '1' }).asSql()).not.toThrow()
356
427
  expect(() => usersTable.insert({ id: '1', undefined: undefined }).asSql()).not.toThrow()
357
428
  expect(() => usersTable.insert({ id: '1', undefined: undefined, null: null }).asSql()).not.toThrow()
358
- expect(() => usersTable.insert({ id: '1', undefined: undefined, null: null, undefinedOrString: undefined }).asSql()).not.toThrow()
359
- expect(() => usersTable.insert({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string' }).asSql()).not.toThrow()
360
- expect(() => usersTable.insert({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: null }).asSql()).not.toThrow()
361
- expect(() => usersTable.insert({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: 'string' }).asSql()).not.toThrow()
362
- expect(() => usersTable.insert({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: 'string', optionalString: 'string' }).asSql()).not.toThrow()
363
- expect(() => usersTable.insert({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: 'string', optionalString: 'string', optionalNullOrString: null }).asSql()).not.toThrow()
364
- expect(() => usersTable.insert({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: 'string', optionalString: 'string', optionalNullOrString: 'string' }).asSql()).not.toThrow()
429
+ expect(() =>
430
+ usersTable.insert({ id: '1', undefined: undefined, null: null, undefinedOrString: undefined }).asSql(),
431
+ ).not.toThrow()
432
+ expect(() =>
433
+ usersTable.insert({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string' }).asSql(),
434
+ ).not.toThrow()
435
+ expect(() =>
436
+ usersTable
437
+ .insert({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: null })
438
+ .asSql(),
439
+ ).not.toThrow()
440
+ expect(() =>
441
+ usersTable
442
+ .insert({ id: '1', undefined: undefined, null: null, undefinedOrString: 'string', nullOrString: 'string' })
443
+ .asSql(),
444
+ ).not.toThrow()
445
+ expect(() =>
446
+ usersTable
447
+ .insert({
448
+ id: '1',
449
+ undefined: undefined,
450
+ null: null,
451
+ undefinedOrString: 'string',
452
+ nullOrString: 'string',
453
+ optionalString: 'string',
454
+ })
455
+ .asSql(),
456
+ ).not.toThrow()
457
+ expect(() =>
458
+ usersTable
459
+ .insert({
460
+ id: '1',
461
+ undefined: undefined,
462
+ null: null,
463
+ undefinedOrString: 'string',
464
+ nullOrString: 'string',
465
+ optionalString: 'string',
466
+ optionalNullOrString: null,
467
+ })
468
+ .asSql(),
469
+ ).not.toThrow()
470
+ expect(() =>
471
+ usersTable
472
+ .insert({
473
+ id: '1',
474
+ undefined: undefined,
475
+ null: null,
476
+ undefinedOrString: 'string',
477
+ nullOrString: 'string',
478
+ optionalString: 'string',
479
+ optionalNullOrString: 'string',
480
+ })
481
+ .asSql(),
482
+ ).not.toThrow()
365
483
  })
366
484
 
367
485
  it('supports discriminated unions with parsed JSON payloads', () => {
368
486
  const CircleDataSchema = Schema.Struct({
369
- radius: Schema.Number,
487
+ radius: Schema.Finite,
370
488
  })
371
489
  const CircleSchema = Schema.Struct({
372
490
  kind: Schema.Literal('circle'),
373
- data: Schema.parseJson(CircleDataSchema),
491
+ data: Schema.fromJsonString(CircleDataSchema),
374
492
  })
375
493
 
376
494
  const SquareDataSchema = Schema.Struct({
377
- sideLength: Schema.Number,
495
+ sideLength: Schema.Finite,
378
496
  })
379
497
  const SquareSchema = Schema.Struct({
380
498
  kind: Schema.Literal('square'),
381
- data: Schema.parseJson(SquareDataSchema),
499
+ data: Schema.fromJsonString(SquareDataSchema),
382
500
  })
383
501
 
384
- const ShapeSchema = Schema.Union(CircleSchema, SquareSchema)
502
+ const ShapeSchema = Schema.Union([CircleSchema, SquareSchema])
385
503
 
386
504
  const shapes = State.SQLite.table({
387
505
  name: 'shapes',
@@ -389,9 +507,7 @@ describe('table function overloads', () => {
389
507
  })
390
508
 
391
509
  expect(shapes.sqliteDef.columns.kind.columnType).toBe('text')
392
-
393
- const kindSchema = objectToString(shapes.sqliteDef.columns.kind.schema)
394
- expect(kindSchema).toContain('"circle" | "square"')
510
+ expect(SchemaAST.isUnion(Schema.toEncoded(shapes.sqliteDef.columns.kind.schema).ast)).toBe(true)
395
511
 
396
512
  expect(() =>
397
513
  shapes
@@ -411,4 +527,26 @@ describe('table function overloads', () => {
411
527
  .asSql(),
412
528
  ).not.toThrow()
413
529
  })
530
+
531
+ it('treats optional common union fields as nullable columns', () => {
532
+ const StateSchema = Schema.Union([
533
+ Schema.Struct({
534
+ kind: Schema.Literal('empty'),
535
+ note: Schema.optional(Schema.String),
536
+ }),
537
+ Schema.Struct({
538
+ kind: Schema.Literal('ready'),
539
+ note: Schema.optional(Schema.String),
540
+ }),
541
+ ])
542
+
543
+ const states = State.SQLite.table({
544
+ name: 'states',
545
+ schema: StateSchema,
546
+ })
547
+
548
+ expect(states.sqliteDef.columns.kind.columnType).toBe('text')
549
+ expect(states.sqliteDef.columns.note.columnType).toBe('text')
550
+ expect(states.sqliteDef.columns.note.nullable).toBe(true)
551
+ })
414
552
  })