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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ClientSessionLeaderThreadProxy.d.ts +20 -12
  3. package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
  4. package/dist/ClientSessionLeaderThreadProxy.js.map +1 -1
  5. package/dist/adapter-types.d.ts +14 -6
  6. package/dist/adapter-types.d.ts.map +1 -1
  7. package/dist/adapter-types.js.map +1 -1
  8. package/dist/debug-info.d.ts.map +1 -1
  9. package/dist/debug-info.js +33 -6
  10. package/dist/debug-info.js.map +1 -1
  11. package/dist/devtools/devtools-messages-client-session.d.ts +28 -23
  12. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
  13. package/dist/devtools/devtools-messages-client-session.js +2 -2
  14. package/dist/devtools/devtools-messages-client-session.js.map +1 -1
  15. package/dist/devtools/devtools-messages-common.d.ts +7 -14
  16. package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
  17. package/dist/devtools/devtools-messages-common.js +1 -6
  18. package/dist/devtools/devtools-messages-common.js.map +1 -1
  19. package/dist/devtools/devtools-messages-leader.d.ts +38 -29
  20. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
  21. package/dist/devtools/devtools-messages-leader.js +9 -8
  22. package/dist/devtools/devtools-messages-leader.js.map +1 -1
  23. package/dist/devtools/devtools-sessioninfo.d.ts +14 -2
  24. package/dist/devtools/devtools-sessioninfo.d.ts.map +1 -1
  25. package/dist/devtools/devtools-sessioninfo.js +7 -4
  26. package/dist/devtools/devtools-sessioninfo.js.map +1 -1
  27. package/dist/devtools/mod.d.ts +13 -2
  28. package/dist/devtools/mod.d.ts.map +1 -1
  29. package/dist/devtools/mod.js +10 -3
  30. package/dist/devtools/mod.js.map +1 -1
  31. package/dist/errors.d.ts +52 -10
  32. package/dist/errors.d.ts.map +1 -1
  33. package/dist/errors.js +25 -6
  34. package/dist/errors.js.map +1 -1
  35. package/dist/index.d.ts +2 -1
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +2 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/leader-thread/LeaderSyncProcessor.d.ts +41 -4
  40. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  41. package/dist/leader-thread/LeaderSyncProcessor.js +158 -75
  42. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  43. package/dist/leader-thread/eventlog.d.ts +21 -22
  44. package/dist/leader-thread/eventlog.d.ts.map +1 -1
  45. package/dist/leader-thread/eventlog.js +77 -20
  46. package/dist/leader-thread/eventlog.js.map +1 -1
  47. package/dist/leader-thread/leader-worker-devtools.d.ts +2 -2
  48. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  49. package/dist/leader-thread/leader-worker-devtools.js +56 -45
  50. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  51. package/dist/leader-thread/make-leader-thread-layer.d.ts +6 -6
  52. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  53. package/dist/leader-thread/make-leader-thread-layer.js +79 -27
  54. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  55. package/dist/leader-thread/make-leader-thread-layer.test.d.ts +2 -0
  56. package/dist/leader-thread/make-leader-thread-layer.test.d.ts.map +1 -0
  57. package/dist/leader-thread/make-leader-thread-layer.test.js +32 -0
  58. package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -0
  59. package/dist/leader-thread/materialize-event.d.ts +3 -3
  60. package/dist/leader-thread/materialize-event.d.ts.map +1 -1
  61. package/dist/leader-thread/materialize-event.js +25 -11
  62. package/dist/leader-thread/materialize-event.js.map +1 -1
  63. package/dist/leader-thread/mod.d.ts +1 -0
  64. package/dist/leader-thread/mod.d.ts.map +1 -1
  65. package/dist/leader-thread/mod.js +1 -0
  66. package/dist/leader-thread/mod.js.map +1 -1
  67. package/dist/leader-thread/recreate-db.d.ts +2 -3
  68. package/dist/leader-thread/recreate-db.d.ts.map +1 -1
  69. package/dist/leader-thread/recreate-db.js +5 -5
  70. package/dist/leader-thread/recreate-db.js.map +1 -1
  71. package/dist/leader-thread/shutdown-channel.d.ts +2 -2
  72. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  73. package/dist/leader-thread/shutdown-channel.js +2 -2
  74. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  75. package/dist/leader-thread/stream-events.d.ts +56 -0
  76. package/dist/leader-thread/stream-events.d.ts.map +1 -0
  77. package/dist/leader-thread/stream-events.js +166 -0
  78. package/dist/leader-thread/stream-events.js.map +1 -0
  79. package/dist/leader-thread/types.d.ts +98 -20
  80. package/dist/leader-thread/types.d.ts.map +1 -1
  81. package/dist/leader-thread/types.js +13 -0
  82. package/dist/leader-thread/types.js.map +1 -1
  83. package/dist/logging.d.ts +40 -0
  84. package/dist/logging.d.ts.map +1 -0
  85. package/dist/logging.js +33 -0
  86. package/dist/logging.js.map +1 -0
  87. package/dist/make-client-session.d.ts +5 -3
  88. package/dist/make-client-session.d.ts.map +1 -1
  89. package/dist/make-client-session.js +5 -2
  90. package/dist/make-client-session.js.map +1 -1
  91. package/dist/materializer-helper.d.ts +6 -6
  92. package/dist/materializer-helper.d.ts.map +1 -1
  93. package/dist/materializer-helper.js +20 -4
  94. package/dist/materializer-helper.js.map +1 -1
  95. package/dist/otel.d.ts +2 -1
  96. package/dist/otel.d.ts.map +1 -1
  97. package/dist/otel.js +5 -0
  98. package/dist/otel.js.map +1 -1
  99. package/dist/rematerialize-from-eventlog.d.ts +2 -2
  100. package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
  101. package/dist/rematerialize-from-eventlog.js +29 -20
  102. package/dist/rematerialize-from-eventlog.js.map +1 -1
  103. package/dist/schema/EventDef/define.d.ts +147 -0
  104. package/dist/schema/EventDef/define.d.ts.map +1 -0
  105. package/dist/schema/EventDef/define.js +139 -0
  106. package/dist/schema/EventDef/define.js.map +1 -0
  107. package/dist/schema/EventDef/event-def.d.ts +106 -0
  108. package/dist/schema/EventDef/event-def.d.ts.map +1 -0
  109. package/dist/schema/EventDef/event-def.js +2 -0
  110. package/dist/schema/EventDef/event-def.js.map +1 -0
  111. package/dist/schema/EventDef/facts.d.ts +118 -0
  112. package/dist/schema/EventDef/facts.d.ts.map +1 -0
  113. package/dist/schema/EventDef/facts.js +53 -0
  114. package/dist/schema/EventDef/facts.js.map +1 -0
  115. package/dist/schema/EventDef/materializer.d.ts +155 -0
  116. package/dist/schema/EventDef/materializer.d.ts.map +1 -0
  117. package/dist/schema/EventDef/materializer.js +83 -0
  118. package/dist/schema/EventDef/materializer.js.map +1 -0
  119. package/dist/schema/EventDef/mod.d.ts +5 -0
  120. package/dist/schema/EventDef/mod.d.ts.map +1 -0
  121. package/dist/schema/EventDef/mod.js +5 -0
  122. package/dist/schema/EventDef/mod.js.map +1 -0
  123. package/dist/schema/EventSequenceNumber/client.d.ts +136 -0
  124. package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -0
  125. package/dist/schema/EventSequenceNumber/client.js +193 -0
  126. package/dist/schema/EventSequenceNumber/client.js.map +1 -0
  127. package/dist/schema/EventSequenceNumber/global.d.ts +15 -0
  128. package/dist/schema/EventSequenceNumber/global.d.ts.map +1 -0
  129. package/dist/schema/EventSequenceNumber/global.js +14 -0
  130. package/dist/schema/EventSequenceNumber/global.js.map +1 -0
  131. package/dist/schema/EventSequenceNumber/mod.d.ts +37 -0
  132. package/dist/schema/EventSequenceNumber/mod.d.ts.map +1 -0
  133. package/dist/schema/EventSequenceNumber/mod.js +37 -0
  134. package/dist/schema/EventSequenceNumber/mod.js.map +1 -0
  135. package/dist/schema/EventSequenceNumber.test.js +43 -43
  136. package/dist/schema/EventSequenceNumber.test.js.map +1 -1
  137. package/dist/schema/{LiveStoreEvent.d.ts → LiveStoreEvent/client.d.ts} +89 -106
  138. package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -0
  139. package/dist/schema/{LiveStoreEvent.js → LiveStoreEvent/client.js} +74 -58
  140. package/dist/schema/LiveStoreEvent/client.js.map +1 -0
  141. package/dist/schema/LiveStoreEvent/for-event-def.d.ts +52 -0
  142. package/dist/schema/LiveStoreEvent/for-event-def.d.ts.map +1 -0
  143. package/dist/schema/LiveStoreEvent/for-event-def.js +2 -0
  144. package/dist/schema/LiveStoreEvent/for-event-def.js.map +1 -0
  145. package/dist/schema/LiveStoreEvent/global.d.ts +36 -0
  146. package/dist/schema/LiveStoreEvent/global.d.ts.map +1 -0
  147. package/dist/schema/LiveStoreEvent/global.js +31 -0
  148. package/dist/schema/LiveStoreEvent/global.js.map +1 -0
  149. package/dist/schema/LiveStoreEvent/input.d.ts +46 -0
  150. package/dist/schema/LiveStoreEvent/input.d.ts.map +1 -0
  151. package/dist/schema/LiveStoreEvent/input.js +26 -0
  152. package/dist/schema/LiveStoreEvent/input.js.map +1 -0
  153. package/dist/schema/LiveStoreEvent/mod.d.ts +5 -0
  154. package/dist/schema/LiveStoreEvent/mod.d.ts.map +1 -0
  155. package/dist/schema/LiveStoreEvent/mod.js +5 -0
  156. package/dist/schema/LiveStoreEvent/mod.js.map +1 -0
  157. package/dist/schema/events.d.ts +1 -1
  158. package/dist/schema/events.d.ts.map +1 -1
  159. package/dist/schema/events.js +1 -1
  160. package/dist/schema/events.js.map +1 -1
  161. package/dist/schema/mod.d.ts +6 -4
  162. package/dist/schema/mod.d.ts.map +1 -1
  163. package/dist/schema/mod.js +5 -4
  164. package/dist/schema/mod.js.map +1 -1
  165. package/dist/schema/schema.d.ts +16 -1
  166. package/dist/schema/schema.d.ts.map +1 -1
  167. package/dist/schema/schema.js +27 -2
  168. package/dist/schema/schema.js.map +1 -1
  169. package/dist/schema/state/sqlite/client-document-def.d.ts +36 -6
  170. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  171. package/dist/schema/state/sqlite/client-document-def.js +97 -6
  172. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  173. package/dist/schema/state/sqlite/client-document-def.test.js +16 -0
  174. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
  175. package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
  176. package/dist/schema/state/sqlite/column-annotations.js +14 -6
  177. package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
  178. package/dist/schema/state/sqlite/column-annotations.test.js +1 -1
  179. package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
  180. package/dist/schema/state/sqlite/column-def.js +69 -22
  181. package/dist/schema/state/sqlite/column-def.js.map +1 -1
  182. package/dist/schema/state/sqlite/column-def.test.js +48 -10
  183. package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
  184. package/dist/schema/state/sqlite/column-spec.d.ts.map +1 -1
  185. package/dist/schema/state/sqlite/column-spec.js +30 -12
  186. package/dist/schema/state/sqlite/column-spec.js.map +1 -1
  187. package/dist/schema/state/sqlite/column-spec.test.js +23 -14
  188. package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
  189. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts +2 -1
  190. package/dist/schema/state/sqlite/db-schema/ast/sqlite.d.ts.map +1 -1
  191. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +23 -6
  192. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
  193. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +14 -8
  194. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
  195. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +5 -3
  196. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
  197. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
  198. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +2 -1
  199. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
  200. package/dist/schema/state/sqlite/mod.d.ts +3 -3
  201. package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
  202. package/dist/schema/state/sqlite/mod.js +3 -3
  203. package/dist/schema/state/sqlite/mod.js.map +1 -1
  204. package/dist/schema/state/sqlite/query-builder/api.d.ts +19 -11
  205. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
  206. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
  207. package/dist/schema/state/sqlite/query-builder/astToSql.js +22 -15
  208. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
  209. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
  210. package/dist/schema/state/sqlite/query-builder/impl.js +6 -3
  211. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
  212. package/dist/schema/state/sqlite/query-builder/impl.test.js +252 -88
  213. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  214. package/dist/schema/state/sqlite/schema-helpers.d.ts +2 -2
  215. package/dist/schema/state/sqlite/schema-helpers.d.ts.map +1 -1
  216. package/dist/schema/state/sqlite/schema-helpers.js +22 -12
  217. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
  218. package/dist/schema/state/sqlite/schema-helpers.test.d.ts +2 -0
  219. package/dist/schema/state/sqlite/schema-helpers.test.d.ts.map +1 -0
  220. package/dist/schema/state/sqlite/schema-helpers.test.js +36 -0
  221. package/dist/schema/state/sqlite/schema-helpers.test.js.map +1 -0
  222. package/dist/schema/state/sqlite/{system-tables.d.ts → system-tables/eventlog-tables.d.ts} +63 -456
  223. package/dist/schema/state/sqlite/system-tables/eventlog-tables.d.ts.map +1 -0
  224. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js +54 -0
  225. package/dist/schema/state/sqlite/system-tables/eventlog-tables.js.map +1 -0
  226. package/dist/schema/state/sqlite/system-tables/mod.d.ts +3 -0
  227. package/dist/schema/state/sqlite/system-tables/mod.d.ts.map +1 -0
  228. package/dist/schema/state/sqlite/system-tables/mod.js +3 -0
  229. package/dist/schema/state/sqlite/system-tables/mod.js.map +1 -0
  230. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts +456 -0
  231. package/dist/schema/state/sqlite/system-tables/state-tables.d.ts.map +1 -0
  232. package/dist/schema/state/sqlite/system-tables/state-tables.js +55 -0
  233. package/dist/schema/state/sqlite/system-tables/state-tables.js.map +1 -0
  234. package/dist/schema/state/sqlite/table-def.d.ts +4 -4
  235. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  236. package/dist/schema/state/sqlite/table-def.js +2 -2
  237. package/dist/schema/state/sqlite/table-def.js.map +1 -1
  238. package/dist/schema/state/sqlite/table-def.test.js +80 -0
  239. package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
  240. package/dist/schema/unknown-events.d.ts +47 -0
  241. package/dist/schema/unknown-events.d.ts.map +1 -0
  242. package/dist/schema/unknown-events.js +69 -0
  243. package/dist/schema/unknown-events.js.map +1 -0
  244. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts +2 -0
  245. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.d.ts.map +1 -0
  246. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +73 -0
  247. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -0
  248. package/dist/schema-management/migrations.d.ts +32 -2
  249. package/dist/schema-management/migrations.d.ts.map +1 -1
  250. package/dist/schema-management/migrations.js +37 -5
  251. package/dist/schema-management/migrations.js.map +1 -1
  252. package/dist/schema-management/validate-schema.d.ts +3 -3
  253. package/dist/schema-management/validate-schema.d.ts.map +1 -1
  254. package/dist/schema-management/validate-schema.js +2 -2
  255. package/dist/schema-management/validate-schema.js.map +1 -1
  256. package/dist/sql-queries/sql-queries.d.ts.map +1 -1
  257. package/dist/sql-queries/sql-queries.js +11 -1
  258. package/dist/sql-queries/sql-queries.js.map +1 -1
  259. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  260. package/dist/sql-queries/sql-query-builder.js +2 -1
  261. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  262. package/dist/sqlite-types.d.ts +3 -3
  263. package/dist/sqlite-types.d.ts.map +1 -1
  264. package/dist/sync/ClientSessionSyncProcessor.d.ts +11 -13
  265. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  266. package/dist/sync/ClientSessionSyncProcessor.js +45 -42
  267. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  268. package/dist/sync/errors.d.ts +66 -0
  269. package/dist/sync/errors.d.ts.map +1 -0
  270. package/dist/sync/errors.js +36 -0
  271. package/dist/sync/errors.js.map +1 -0
  272. package/dist/sync/index.d.ts +3 -0
  273. package/dist/sync/index.d.ts.map +1 -1
  274. package/dist/sync/index.js +3 -0
  275. package/dist/sync/index.js.map +1 -1
  276. package/dist/sync/mock-sync-backend.d.ts +23 -0
  277. package/dist/sync/mock-sync-backend.d.ts.map +1 -0
  278. package/dist/sync/mock-sync-backend.js +114 -0
  279. package/dist/sync/mock-sync-backend.js.map +1 -0
  280. package/dist/sync/next/compact-events.d.ts.map +1 -1
  281. package/dist/sync/next/compact-events.js +6 -7
  282. package/dist/sync/next/compact-events.js.map +1 -1
  283. package/dist/sync/next/facts.d.ts +5 -5
  284. package/dist/sync/next/facts.d.ts.map +1 -1
  285. package/dist/sync/next/facts.js +1 -2
  286. package/dist/sync/next/facts.js.map +1 -1
  287. package/dist/sync/next/history-dag-common.d.ts +54 -15
  288. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  289. package/dist/sync/next/history-dag-common.js +198 -9
  290. package/dist/sync/next/history-dag-common.js.map +1 -1
  291. package/dist/sync/next/history-dag.d.ts.map +1 -1
  292. package/dist/sync/next/history-dag.js +10 -8
  293. package/dist/sync/next/history-dag.js.map +1 -1
  294. package/dist/sync/next/rebase-events.d.ts +5 -5
  295. package/dist/sync/next/rebase-events.d.ts.map +1 -1
  296. package/dist/sync/next/rebase-events.js +5 -5
  297. package/dist/sync/next/rebase-events.js.map +1 -1
  298. package/dist/sync/next/test/event-fixtures.d.ts +2 -2
  299. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
  300. package/dist/sync/next/test/event-fixtures.js +9 -9
  301. package/dist/sync/next/test/event-fixtures.js.map +1 -1
  302. package/dist/sync/sync-backend-kv.d.ts +7 -0
  303. package/dist/sync/sync-backend-kv.d.ts.map +1 -0
  304. package/dist/sync/sync-backend-kv.js +18 -0
  305. package/dist/sync/sync-backend-kv.js.map +1 -0
  306. package/dist/sync/sync-backend.d.ts +105 -0
  307. package/dist/sync/sync-backend.d.ts.map +1 -0
  308. package/dist/sync/sync-backend.js +61 -0
  309. package/dist/sync/sync-backend.js.map +1 -0
  310. package/dist/sync/sync.d.ts +9 -86
  311. package/dist/sync/sync.d.ts.map +1 -1
  312. package/dist/sync/sync.js +2 -27
  313. package/dist/sync/sync.js.map +1 -1
  314. package/dist/sync/syncstate.d.ts +57 -44
  315. package/dist/sync/syncstate.d.ts.map +1 -1
  316. package/dist/sync/syncstate.js +50 -45
  317. package/dist/sync/syncstate.js.map +1 -1
  318. package/dist/sync/syncstate.test.js +83 -46
  319. package/dist/sync/syncstate.test.js.map +1 -1
  320. package/dist/sync/transport-chunking.d.ts +36 -0
  321. package/dist/sync/transport-chunking.d.ts.map +1 -0
  322. package/dist/sync/transport-chunking.js +56 -0
  323. package/dist/sync/transport-chunking.js.map +1 -0
  324. package/dist/sync/validate-push-payload.d.ts +2 -2
  325. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  326. package/dist/sync/validate-push-payload.js +6 -6
  327. package/dist/sync/validate-push-payload.js.map +1 -1
  328. package/dist/testing/event-factory.d.ts +68 -0
  329. package/dist/testing/event-factory.d.ts.map +1 -0
  330. package/dist/testing/event-factory.js +78 -0
  331. package/dist/testing/event-factory.js.map +1 -0
  332. package/dist/testing/mod.d.ts +2 -0
  333. package/dist/testing/mod.d.ts.map +1 -0
  334. package/dist/testing/mod.js +2 -0
  335. package/dist/testing/mod.js.map +1 -0
  336. package/dist/version.d.ts +16 -6
  337. package/dist/version.d.ts.map +1 -1
  338. package/dist/version.js +16 -6
  339. package/dist/version.js.map +1 -1
  340. package/package.json +7 -8
  341. package/src/ClientSessionLeaderThreadProxy.ts +20 -12
  342. package/src/adapter-types.ts +18 -6
  343. package/src/debug-info.ts +37 -6
  344. package/src/devtools/devtools-messages-client-session.ts +2 -2
  345. package/src/devtools/devtools-messages-common.ts +1 -8
  346. package/src/devtools/devtools-messages-leader.ts +9 -8
  347. package/src/devtools/devtools-sessioninfo.ts +8 -5
  348. package/src/devtools/mod.ts +11 -2
  349. package/src/errors.ts +38 -11
  350. package/src/index.ts +2 -1
  351. package/src/leader-thread/LeaderSyncProcessor.ts +277 -105
  352. package/src/leader-thread/eventlog.ts +113 -38
  353. package/src/leader-thread/leader-worker-devtools.ts +86 -55
  354. package/src/leader-thread/make-leader-thread-layer.test.ts +44 -0
  355. package/src/leader-thread/make-leader-thread-layer.ts +156 -37
  356. package/src/leader-thread/materialize-event.ts +37 -12
  357. package/src/leader-thread/mod.ts +1 -0
  358. package/src/leader-thread/recreate-db.ts +15 -7
  359. package/src/leader-thread/shutdown-channel.ts +16 -2
  360. package/src/leader-thread/stream-events.ts +201 -0
  361. package/src/leader-thread/types.ts +70 -20
  362. package/src/logging.ts +62 -0
  363. package/src/make-client-session.ts +9 -3
  364. package/src/materializer-helper.ts +27 -10
  365. package/src/otel.ts +10 -0
  366. package/src/rematerialize-from-eventlog.ts +37 -27
  367. package/src/schema/EventDef/define.ts +201 -0
  368. package/src/schema/EventDef/event-def.ts +120 -0
  369. package/src/schema/EventDef/facts.ts +135 -0
  370. package/src/schema/EventDef/materializer.ts +172 -0
  371. package/src/schema/EventDef/mod.ts +4 -0
  372. package/src/schema/EventSequenceNumber/client.ts +257 -0
  373. package/src/schema/EventSequenceNumber/global.ts +19 -0
  374. package/src/schema/EventSequenceNumber/mod.ts +37 -0
  375. package/src/schema/EventSequenceNumber.test.ts +70 -52
  376. package/src/schema/LiveStoreEvent/client.ts +221 -0
  377. package/src/schema/LiveStoreEvent/for-event-def.ts +60 -0
  378. package/src/schema/LiveStoreEvent/global.ts +45 -0
  379. package/src/schema/LiveStoreEvent/input.ts +63 -0
  380. package/src/schema/LiveStoreEvent/mod.ts +4 -0
  381. package/src/schema/events.ts +1 -1
  382. package/src/schema/mod.ts +6 -4
  383. package/src/schema/schema.ts +39 -3
  384. package/src/schema/state/sqlite/client-document-def.test.ts +19 -2
  385. package/src/schema/state/sqlite/client-document-def.ts +127 -25
  386. package/src/schema/state/sqlite/column-annotations.test.ts +1 -1
  387. package/src/schema/state/sqlite/column-annotations.ts +16 -6
  388. package/src/schema/state/sqlite/column-def.test.ts +62 -10
  389. package/src/schema/state/sqlite/column-def.ts +88 -21
  390. package/src/schema/state/sqlite/column-spec.test.ts +29 -16
  391. package/src/schema/state/sqlite/column-spec.ts +36 -11
  392. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +26 -6
  393. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +29 -12
  394. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +12 -17
  395. package/src/schema/state/sqlite/mod.ts +4 -3
  396. package/src/schema/state/sqlite/query-builder/api.ts +25 -11
  397. package/src/schema/state/sqlite/query-builder/astToSql.ts +23 -14
  398. package/src/schema/state/sqlite/query-builder/impl.test.ts +305 -92
  399. package/src/schema/state/sqlite/query-builder/impl.ts +8 -3
  400. package/src/schema/state/sqlite/schema-helpers.test.ts +44 -0
  401. package/src/schema/state/sqlite/schema-helpers.ts +28 -20
  402. package/src/schema/state/sqlite/system-tables/eventlog-tables.ts +64 -0
  403. package/src/schema/state/sqlite/system-tables/mod.ts +2 -0
  404. package/src/schema/state/sqlite/system-tables/state-tables.ts +69 -0
  405. package/src/schema/state/sqlite/table-def.test.ts +101 -0
  406. package/src/schema/state/sqlite/table-def.ts +8 -6
  407. package/src/schema/unknown-events.ts +131 -0
  408. package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +86 -0
  409. package/src/schema-management/migrations.ts +41 -8
  410. package/src/schema-management/validate-schema.ts +3 -3
  411. package/src/sql-queries/sql-queries.ts +9 -1
  412. package/src/sql-queries/sql-query-builder.ts +2 -1
  413. package/src/sqlite-types.ts +3 -3
  414. package/src/sync/ClientSessionSyncProcessor.ts +69 -62
  415. package/src/sync/errors.ts +38 -0
  416. package/src/sync/index.ts +3 -0
  417. package/src/sync/mock-sync-backend.ts +184 -0
  418. package/src/sync/next/compact-events.ts +6 -7
  419. package/src/sync/next/facts.ts +7 -9
  420. package/src/sync/next/history-dag-common.ts +277 -26
  421. package/src/sync/next/history-dag.ts +16 -10
  422. package/src/sync/next/rebase-events.ts +11 -11
  423. package/src/sync/next/test/event-fixtures.ts +11 -11
  424. package/src/sync/sync-backend-kv.ts +22 -0
  425. package/src/sync/sync-backend.ts +185 -0
  426. package/src/sync/sync.ts +9 -91
  427. package/src/sync/syncstate.test.ts +96 -52
  428. package/src/sync/syncstate.ts +69 -58
  429. package/src/sync/transport-chunking.ts +90 -0
  430. package/src/sync/validate-push-payload.ts +8 -9
  431. package/src/testing/event-factory.ts +131 -0
  432. package/src/testing/mod.ts +1 -0
  433. package/src/version.ts +16 -6
  434. package/dist/schema/EventDef.d.ts +0 -123
  435. package/dist/schema/EventDef.d.ts.map +0 -1
  436. package/dist/schema/EventDef.js +0 -46
  437. package/dist/schema/EventDef.js.map +0 -1
  438. package/dist/schema/EventSequenceNumber.d.ts +0 -80
  439. package/dist/schema/EventSequenceNumber.d.ts.map +0 -1
  440. package/dist/schema/EventSequenceNumber.js +0 -139
  441. package/dist/schema/EventSequenceNumber.js.map +0 -1
  442. package/dist/schema/LiveStoreEvent.d.ts.map +0 -1
  443. package/dist/schema/LiveStoreEvent.js.map +0 -1
  444. package/dist/schema/state/sqlite/system-tables.d.ts.map +0 -1
  445. package/dist/schema/state/sqlite/system-tables.js +0 -79
  446. package/dist/schema/state/sqlite/system-tables.js.map +0 -1
  447. package/dist/schema-management/migrations.test.d.ts +0 -2
  448. package/dist/schema-management/migrations.test.d.ts.map +0 -1
  449. package/dist/schema-management/migrations.test.js +0 -52
  450. package/dist/schema-management/migrations.test.js.map +0 -1
  451. package/dist/sync/next/graphology.d.ts +0 -8
  452. package/dist/sync/next/graphology.d.ts.map +0 -1
  453. package/dist/sync/next/graphology.js +0 -30
  454. package/dist/sync/next/graphology.js.map +0 -1
  455. package/dist/sync/next/graphology_.d.ts +0 -3
  456. package/dist/sync/next/graphology_.d.ts.map +0 -1
  457. package/dist/sync/next/graphology_.js +0 -3
  458. package/dist/sync/next/graphology_.js.map +0 -1
  459. package/src/schema/EventDef.ts +0 -219
  460. package/src/schema/EventSequenceNumber.ts +0 -199
  461. package/src/schema/LiveStoreEvent.ts +0 -287
  462. package/src/schema/state/sqlite/system-tables.ts +0 -104
  463. package/src/sync/next/ambient.d.ts +0 -3
  464. package/src/sync/next/graphology.ts +0 -41
  465. package/src/sync/next/graphology_.ts +0 -2
@@ -1,11 +1,11 @@
1
1
  import { shouldNeverHappen } from '@livestore/utils'
2
2
  import type { Option, Types } from '@livestore/utils/effect'
3
- import { Schema, SchemaAST } from '@livestore/utils/effect'
3
+ import { Schema } from '@livestore/utils/effect'
4
4
 
5
5
  import { SessionIdSymbol } from '../../../adapter-types.ts'
6
6
  import { sql } from '../../../util.ts'
7
- import type { EventDef, Materializer } from '../../EventDef.ts'
8
- import { defineEvent, defineMaterializer } from '../../EventDef.ts'
7
+ import type { EventDef, Materializer } from '../../EventDef/mod.ts'
8
+ import { defineEvent, defineMaterializer } from '../../EventDef/mod.ts'
9
9
  import { SqliteDsl } from './db-schema/mod.ts'
10
10
  import type { QueryBuilder, QueryBuilderAst } from './query-builder/mod.ts'
11
11
  import { QueryBuilderAstSymbol, QueryBuilderTypeId } from './query-builder/mod.ts'
@@ -62,9 +62,16 @@ export const clientDocument = <
62
62
  },
63
63
  } satisfies ClientDocumentTableOptions<TType>
64
64
 
65
+ // Column needs optimistic schema to read historical data formats
66
+ const optimisticColumnSchema = createOptimisticEventSchema({
67
+ valueSchema,
68
+ defaultValue: options.default.value,
69
+ partialSet: false, // Column always stores full documents
70
+ })
71
+
65
72
  const columns = {
66
73
  id: SqliteDsl.text({ primaryKey: true }),
67
- value: SqliteDsl.json({ schema: valueSchema }),
74
+ value: SqliteDsl.json({ schema: optimisticColumnSchema }),
68
75
  }
69
76
 
70
77
  const tableDef = table({ name, columns })
@@ -140,6 +147,105 @@ export const mergeDefaultValues = <T>(defaultValues: T, explicitDefaultValues: T
140
147
  }, {} as any)
141
148
  }
142
149
 
150
+ /**
151
+ * Creates an optimistic schema that accepts historical event formats
152
+ * and transforms them to the current schema, preserving data and intent.
153
+ *
154
+ * Decision Matrix for Schema Changes:
155
+ *
156
+ * | Change Type | Partial Set | Full Set | Strategy |
157
+ * |---------------------|---------------------|----------------------------------|-------------------------|
158
+ * | **Compatible Changes** |
159
+ * | Add optional field | Preserve existing | Preserve existing, new field undefined | Direct decode or merge |
160
+ * | Add required field | Preserve existing | Preserve existing, new field from default | Merge with defaults |
161
+ * | **Incompatible Changes** |
162
+ * | Remove field | Drop removed field | Drop removed field, preserve others | Filter & decode |
163
+ * | Type change | Use default for field | Use default for changed field | Selective merge |
164
+ * | Rename field | Use default | Use default (can't detect rename) | Fall back to default |
165
+ * | **Edge Cases** |
166
+ * | Empty event | Return {} | Return full default | Fallback handling |
167
+ * | Invalid structure | Return {} | Return full default | Fallback handling |
168
+ */
169
+ export const createOptimisticEventSchema = ({
170
+ valueSchema,
171
+ defaultValue,
172
+ partialSet,
173
+ }: {
174
+ valueSchema: Schema.Schema<any, any>
175
+ defaultValue: any
176
+ partialSet: boolean
177
+ }) => {
178
+ const targetSchema = partialSet ? Schema.partial(valueSchema) : valueSchema
179
+
180
+ return Schema.transform(
181
+ Schema.Unknown, // Accept any historical event structure
182
+ targetSchema, // Output current schema
183
+ {
184
+ decode: (eventValue) => {
185
+ // Try direct decode first (for current schema events)
186
+ try {
187
+ return Schema.decodeUnknownSync(targetSchema)(eventValue)
188
+ } catch {
189
+ // Optimistic decoding for historical events
190
+
191
+ // Handle null/undefined/non-object cases
192
+ if (typeof eventValue !== 'object' || eventValue === null) {
193
+ console.warn(`Client document: Non-object event value, using ${partialSet ? 'empty partial' : 'defaults'}`)
194
+ return partialSet ? {} : defaultValue
195
+ }
196
+
197
+ if (partialSet) {
198
+ // For partial sets: only preserve fields that exist in new schema
199
+ const partialResult: Record<string, unknown> = {}
200
+ let hasValidFields = false
201
+
202
+ for (const [key, value] of Object.entries(eventValue as Record<string, unknown>)) {
203
+ if (key in defaultValue) {
204
+ partialResult[key] = value
205
+ hasValidFields = true
206
+ }
207
+ // Drop fields that don't exist in new schema
208
+ }
209
+
210
+ if (hasValidFields) {
211
+ try {
212
+ return Schema.decodeUnknownSync(targetSchema)(partialResult)
213
+ } catch {
214
+ // Even filtered fields don't match schema
215
+ console.warn('Client document: Partial fields incompatible, returning empty partial')
216
+ return {}
217
+ }
218
+ }
219
+ return {}
220
+ } else {
221
+ // Full set: merge old data with new defaults
222
+ const merged: Record<string, unknown> = { ...defaultValue }
223
+
224
+ // Override defaults with valid fields from old event
225
+ for (const [key, value] of Object.entries(eventValue as Record<string, unknown>)) {
226
+ if (key in defaultValue) {
227
+ merged[key] = value
228
+ }
229
+ // Drop fields that don't exist in new schema
230
+ }
231
+
232
+ // Try to decode the merged value
233
+ try {
234
+ return Schema.decodeUnknownSync(valueSchema)(merged)
235
+ } catch {
236
+ // Merged value still doesn't match (e.g., type changes)
237
+ // Fall back to pure defaults
238
+ console.warn('Client document: Could not preserve event data, using defaults')
239
+ return defaultValue
240
+ }
241
+ }
242
+ }
243
+ },
244
+ encode: (value) => value, // Pass-through for encoding
245
+ },
246
+ )
247
+ }
248
+
143
249
  export const deriveEventAndMaterializer = ({
144
250
  name,
145
251
  valueSchema,
@@ -155,7 +261,7 @@ export const deriveEventAndMaterializer = ({
155
261
  name: `${name}Set`,
156
262
  schema: Schema.Struct({
157
263
  id: Schema.Union(Schema.String, Schema.UniqueSymbolFromSelf(SessionIdSymbol)),
158
- value: partialSet ? Schema.partial(valueSchema) : valueSchema,
264
+ value: createOptimisticEventSchema({ valueSchema, defaultValue, partialSet }),
159
265
  }).annotations({ title: `${name}Set:Args` }),
160
266
  clientOnly: true,
161
267
  derived: true,
@@ -167,7 +273,7 @@ export const deriveEventAndMaterializer = ({
167
273
  }
168
274
 
169
275
  // Override the full value if it's not an object or no partial set is allowed
170
- const schemaProps = SchemaAST.getPropertySignatures(valueSchema.ast)
276
+ const schemaProps = Schema.getResolvedPropertySignatures(valueSchema)
171
277
  if (schemaProps.length === 0 || partialSet === false) {
172
278
  const valueColJsonSchema = Schema.parseJson(valueSchema)
173
279
  const encodedInsertValue = Schema.encodeSyncDebug(valueColJsonSchema)(value ?? defaultValue)
@@ -281,8 +387,14 @@ export namespace ClientDocumentTableOptions {
281
387
  }
282
388
  }
283
389
 
390
+ type IsStructLike<T> = T extends {} ? true : false
391
+
284
392
  export type WithDefaults<TInput extends Input<any>> = {
285
- partialSet: TInput['partialSet'] extends false ? false : true
393
+ partialSet: TInput['partialSet'] extends false
394
+ ? false
395
+ : IsStructLike<TInput['default']['value']> extends true
396
+ ? true
397
+ : false
286
398
  default: {
287
399
  id: TInput['default']['id'] extends string | SessionIdSymbol ? TInput['default']['id'] : undefined
288
400
  value: TInput['default']['value']
@@ -401,27 +513,17 @@ export namespace ClientDocumentTableDef {
401
513
  }
402
514
  }
403
515
 
404
- export type GetOptions<TTableDef extends TraitAny> = TTableDef extends ClientDocumentTableDef.Trait<
405
- any,
406
- any,
407
- any,
408
- infer TOptions
409
- >
410
- ? TOptions
411
- : never
516
+ export type GetOptions<TTableDef extends TraitAny> =
517
+ TTableDef extends ClientDocumentTableDef.Trait<any, any, any, infer TOptions> ? TOptions : never
412
518
 
413
519
  export type TraitAny = Trait<any, any, any, any>
414
520
 
415
- export type DefaultIdType<TTableDef extends TraitAny> = TTableDef extends ClientDocumentTableDef.Trait<
416
- any,
417
- any,
418
- any,
419
- infer TOptions
420
- >
421
- ? TOptions['default']['id'] extends SessionIdSymbol | string
422
- ? TOptions['default']['id']
521
+ export type DefaultIdType<TTableDef extends TraitAny> =
522
+ TTableDef extends ClientDocumentTableDef.Trait<any, any, any, infer TOptions>
523
+ ? TOptions['default']['id'] extends SessionIdSymbol | string
524
+ ? TOptions['default']['id']
525
+ : never
423
526
  : never
424
- : never
425
527
 
426
528
  export type SetEventDefLike<
427
529
  TName extends string,
@@ -467,5 +569,5 @@ export namespace ClientDocumentTableDef {
467
569
  ) => QueryBuilder<TType, ClientDocumentTableDef.TableDefBase_<TName, TType>, QueryBuilder.ApiFeature>
468
570
  }
469
571
 
470
- export const ClientDocumentTableDefSymbol = Symbol('ClientDocumentTableDef')
572
+ export const ClientDocumentTableDefSymbol = Symbol.for('livestore.ClientDocumentTableDef')
471
573
  export type ClientDocumentTableDefSymbol = typeof ClientDocumentTableDefSymbol
@@ -65,7 +65,7 @@ describe.concurrent('annotations', () => {
65
65
  })
66
66
 
67
67
  test('Union of same type with compatible column type', () => {
68
- const unionSchema = Schema.Union(Schema.Literal('a'), Schema.Literal('b'))
68
+ const unionSchema = Schema.Literal('a', 'b')
69
69
  expect(() => withColumnType(unionSchema, 'text')).not.toThrow()
70
70
  })
71
71
 
@@ -1,5 +1,5 @@
1
1
  import type { Schema } from '@livestore/utils/effect'
2
- import { dual } from '@livestore/utils/effect'
2
+ import { dual, Option, SchemaAST } from '@livestore/utils/effect'
3
3
  import type { SqliteDsl } from './db-schema/mod.ts'
4
4
 
5
5
  export const PrimaryKeyId = Symbol.for('livestore/state/sqlite/annotations/primary-key')
@@ -32,7 +32,7 @@ Here are the knobs you can turn per-column when you CREATE TABLE (or ALTER TABLE
32
32
  * Adds a primary key annotation to a schema.
33
33
  */
34
34
  export const withPrimaryKey = <T extends Schema.Schema.All>(schema: T) =>
35
- schema.annotations({ [PrimaryKeyId]: true }) as T
35
+ applyAnnotations(schema, { [PrimaryKeyId]: true })
36
36
 
37
37
  /**
38
38
  * Adds a column type annotation to a schema.
@@ -43,19 +43,19 @@ export const withColumnType: {
43
43
  <T extends Schema.Schema.All>(schema: T, type: SqliteDsl.FieldColumnType): T
44
44
  } = dual(2, <T extends Schema.Schema.All>(schema: T, type: SqliteDsl.FieldColumnType) => {
45
45
  validateSchemaColumnTypeCompatibility(schema, type)
46
- return schema.annotations({ [ColumnType]: type }) as T
46
+ return applyAnnotations(schema, { [ColumnType]: type })
47
47
  })
48
48
 
49
49
  /**
50
50
  * Adds an auto-increment annotation to a schema.
51
51
  */
52
52
  export const withAutoIncrement = <T extends Schema.Schema.All>(schema: T) =>
53
- schema.annotations({ [AutoIncrement]: true }) as T
53
+ applyAnnotations(schema, { [AutoIncrement]: true })
54
54
 
55
55
  /**
56
56
  * Adds a unique constraint annotation to a schema.
57
57
  */
58
- export const withUnique = <T extends Schema.Schema.All>(schema: T) => schema.annotations({ [Unique]: true }) as T
58
+ export const withUnique = <T extends Schema.Schema.All>(schema: T) => applyAnnotations(schema, { [Unique]: true })
59
59
 
60
60
  /**
61
61
  * Adds a default value annotation to a schema.
@@ -64,7 +64,7 @@ export const withDefault: {
64
64
  // TODO make type safe
65
65
  <T extends Schema.Schema.All>(schema: T, value: unknown): T
66
66
  (value: unknown): <T extends Schema.Schema.All>(schema: T) => T
67
- } = dual(2, <T extends Schema.Schema.All>(schema: T, value: unknown) => schema.annotations({ [Default]: value }) as T)
67
+ } = dual(2, <T extends Schema.Schema.All>(schema: T, value: unknown) => applyAnnotations(schema, { [Default]: value }))
68
68
 
69
69
  /**
70
70
  * Validates that a schema is compatible with the specified SQLite column type
@@ -75,3 +75,13 @@ const validateSchemaColumnTypeCompatibility = (
75
75
  ): void => {
76
76
  // TODO actually implement this
77
77
  }
78
+
79
+ const applyAnnotations = <T extends Schema.Schema.All>(schema: T, overrides: Record<PropertyKey, unknown>): T => {
80
+ const identifier = SchemaAST.getIdentifierAnnotation(schema.ast)
81
+ const shouldPreserveIdentifier = Option.isSome(identifier) && !(SchemaAST.IdentifierAnnotationId in overrides)
82
+ const annotations: Record<PropertyKey, unknown> = shouldPreserveIdentifier
83
+ ? { ...overrides, [SchemaAST.IdentifierAnnotationId]: identifier.value }
84
+ : overrides
85
+
86
+ return schema.annotations(annotations) as T
87
+ }
@@ -1,5 +1,5 @@
1
1
  import { Schema } from '@livestore/utils/effect'
2
- import { describe, expect, it } from 'vitest'
2
+ import { assert, describe, expect, it } from 'vitest'
3
3
 
4
4
  import * as State from '../mod.ts'
5
5
  import { withAutoIncrement, withColumnType, withDefault, withPrimaryKey, withUnique } from './column-annotations.ts'
@@ -144,11 +144,10 @@ describe('getColumnDefForSchema', () => {
144
144
 
145
145
  it('should map tagged unions to json column', () => {
146
146
  const ResultSchema = Schema.Union(
147
- Schema.Struct({
148
- _tag: Schema.Literal('success'),
147
+ Schema.TaggedStruct('success', {
149
148
  value: Schema.String,
150
149
  }),
151
- Schema.Struct({ _tag: Schema.Literal('error'), error: Schema.String }),
150
+ Schema.TaggedStruct('error', { error: Schema.String }),
152
151
  )
153
152
 
154
153
  const columnDef = State.SQLite.getColumnDefForSchema(ResultSchema)
@@ -273,17 +272,34 @@ describe('getColumnDefForSchema', () => {
273
272
  INACTIVE: 'inactive',
274
273
  })
275
274
 
276
- const StatusUnion = Schema.Union(Schema.Literal('pending'), Schema.Literal('active'), Schema.Literal('inactive'))
275
+ const StatusUnion = Schema.Literal('pending', 'active', 'inactive')
277
276
 
278
277
  expect(State.SQLite.getColumnDefForSchema(StatusEnum).columnType).toBe('text')
279
278
  expect(State.SQLite.getColumnDefForSchema(StatusUnion).columnType).toBe('text')
280
279
  })
280
+
281
+ it('should handle unions of numeric literals as integer column', () => {
282
+ const IntervalSchema = Schema.Literal(1, 5, 15, 30)
283
+
284
+ const columnDef = State.SQLite.getColumnDefForSchema(IntervalSchema)
285
+
286
+ expect(columnDef.columnType).toBe('integer')
287
+ })
288
+
289
+ it('should handle unions of non-integer numeric literals as real column', () => {
290
+ const PercentSchema = Schema.Literal(0.1, 0.2, 0.25)
291
+
292
+ const columnDef = State.SQLite.getColumnDefForSchema(PercentSchema)
293
+
294
+ expect(columnDef.columnType).toBe('real')
295
+ })
281
296
  })
282
297
 
283
298
  describe('binary data', () => {
284
299
  it('should handle Uint8Array as blob column', () => {
285
300
  const columnDef = State.SQLite.getColumnDefForSchema(Schema.Uint8Array)
286
- expect(columnDef.columnType).toBe('text') // Stored as JSON
301
+ expect(columnDef.columnType).toBe('blob')
302
+ expect(columnDef.schema.toString()).toBe('Uint8ArrayFromSelf')
287
303
  })
288
304
  })
289
305
 
@@ -381,6 +397,19 @@ describe('getColumnDefForSchema', () => {
381
397
  expect((table.rowSchema as any).fields.count.toString()).toBe('Int | null')
382
398
  })
383
399
 
400
+ it('should treat unions of string literals as text columns without JSON parsing', () => {
401
+ const schema = Schema.Struct({
402
+ id: Schema.String,
403
+ status: Schema.Literal('idle', 'running', 'stopped'),
404
+ })
405
+
406
+ const table = State.SQLite.table({ name: 'timers', schema })
407
+
408
+ expect(table.sqliteDef.columns.status.columnType).toBe('text')
409
+ expect(table.sqliteDef.columns.status.schema.toString()).toBe('"idle" | "running" | "stopped"')
410
+ expect((table.rowSchema as any).fields.status.toString()).toBe('"idle" | "running" | "stopped"')
411
+ })
412
+
384
413
  it('should handle Schema.NullOr with complex types', () => {
385
414
  const schema = Schema.Struct({
386
415
  data: Schema.NullOr(Schema.Struct({ value: Schema.Number })),
@@ -539,7 +568,7 @@ describe('getColumnDefForSchema', () => {
539
568
 
540
569
  it('should work with column type annotation', () => {
541
570
  const UserSchema = Schema.Struct({
542
- id: Schema.Number.pipe(withColumnType('integer')).pipe(withPrimaryKey),
571
+ id: Schema.Number.pipe(withColumnType('integer'), withPrimaryKey),
543
572
  name: Schema.String,
544
573
  })
545
574
 
@@ -571,7 +600,7 @@ describe('getColumnDefForSchema', () => {
571
600
  describe('withAutoIncrement', () => {
572
601
  it('should add autoIncrement annotation to schema', () => {
573
602
  const UserSchema = Schema.Struct({
574
- id: Schema.Int.pipe(withPrimaryKey).pipe(withAutoIncrement),
603
+ id: Schema.Int.pipe(withPrimaryKey, withAutoIncrement),
575
604
  name: Schema.String,
576
605
  })
577
606
  const userTable = State.SQLite.table({
@@ -623,6 +652,29 @@ describe('getColumnDefForSchema', () => {
623
652
  table2.sqliteDef.columns.count.default._tag === 'Some' && table2.sqliteDef.columns.count.default.value,
624
653
  ).toBe(0)
625
654
  })
655
+
656
+ it('should support thunk defaults without eager evaluation', () => {
657
+ let counter = 0
658
+ const UserSchema = Schema.Struct({
659
+ id: Schema.String.pipe(
660
+ withDefault(() => {
661
+ counter += 1
662
+ return `user-${counter}`
663
+ }),
664
+ ),
665
+ })
666
+
667
+ const table = State.SQLite.table({ name: 'users_with_thunk', schema: UserSchema })
668
+
669
+ expect(counter).toBe(0)
670
+ expect(table.sqliteDef.columns.id.default._tag).toBe('Some')
671
+ if (table.sqliteDef.columns.id.default._tag === 'Some') {
672
+ const defaultThunk = table.sqliteDef.columns.id.default.value
673
+ assert(typeof defaultThunk === 'function')
674
+ expect(defaultThunk()).toBe('user-1')
675
+ expect(defaultThunk()).toBe('user-2')
676
+ }
677
+ })
626
678
  })
627
679
 
628
680
  describe('withUnique', () => {
@@ -668,7 +720,7 @@ describe('getColumnDefForSchema', () => {
668
720
 
669
721
  describe('combined annotations', () => {
670
722
  it('should work with multiple annotations', () => {
671
- const schema = Schema.Uint8ArrayFromBase64.pipe(withColumnType('blob')).pipe(withPrimaryKey)
723
+ const schema = Schema.Uint8ArrayFromBase64.pipe(withColumnType('blob'), withPrimaryKey)
672
724
 
673
725
  const UserSchema = Schema.Struct({
674
726
  id: schema,
@@ -686,7 +738,7 @@ describe('getColumnDefForSchema', () => {
686
738
 
687
739
  it('should combine all annotations', () => {
688
740
  const UserSchema = Schema.Struct({
689
- id: Schema.Int.pipe(withPrimaryKey).pipe(withAutoIncrement),
741
+ id: Schema.Int.pipe(withPrimaryKey, withAutoIncrement),
690
742
  email: Schema.String.pipe(withUnique),
691
743
  status: Schema.String.pipe(withDefault('active')),
692
744
  metadata: Schema.Unknown.pipe(withColumnType('text')),
@@ -179,26 +179,17 @@ const getColumnForSchema = (schema: Schema.Schema.AnyNoContext, nullable = false
179
179
  return SqliteDsl.real({ schema: coreSchema, nullable })
180
180
  }
181
181
 
182
- // Literals based on their type
183
- if (SchemaAST.isLiteral(coreAst)) {
184
- const value = coreAst.literal
185
- if (typeof value === 'boolean') return SqliteDsl.boolean({ nullable })
186
- }
187
-
188
- // Literals based on their encoded type
189
- if (SchemaAST.isLiteral(encodedAst)) {
190
- const value = encodedAst.literal
191
- if (typeof value === 'string') return SqliteDsl.text({ schema: coreSchema, nullable })
192
- if (typeof value === 'number') {
193
- // Check if the original schema is Int
194
- const id = SchemaAST.getIdentifierAnnotation(coreAst).pipe(Option.getOrElse(() => ''))
195
- if (id === 'Int') {
196
- return SqliteDsl.integer({ schema: coreSchema, nullable })
197
- }
198
- return SqliteDsl.real({ schema: coreSchema, nullable })
199
- }
182
+ if (isUint8ArraySchema(coreAst) || isUint8ArraySchema(encodedAst)) {
183
+ return SqliteDsl.blob({ schema: Schema.Uint8ArrayFromSelf as Schema.Schema<Uint8Array<ArrayBuffer>>, nullable })
200
184
  }
201
185
 
186
+ const literalColumn = getLiteralColumnDefinition(encodedAst, coreSchema, nullable, coreAst)
187
+ if (literalColumn) return literalColumn
188
+
189
+ // Fallback to checking the original AST in case the encoded schema differs
190
+ const coreLiteralColumn = getLiteralColumnDefinition(coreAst, coreSchema, nullable, coreAst)
191
+ if (coreLiteralColumn) return coreLiteralColumn
192
+
202
193
  // Everything else needs JSON encoding
203
194
  return SqliteDsl.json({ schema: coreSchema, nullable })
204
195
  }
@@ -206,10 +197,86 @@ const getColumnForSchema = (schema: Schema.Schema.AnyNoContext, nullable = false
206
197
  const stripNullable = (ast: SchemaAST.AST): SchemaAST.AST => {
207
198
  if (!SchemaAST.isUnion(ast)) return ast
208
199
 
209
- // Find non-null/undefined type
210
- const core = ast.types.find(
200
+ // Filter out null/undefined members while preserving any annotations on the union
201
+ const coreTypes = ast.types.filter(
211
202
  (type) => !(SchemaAST.isLiteral(type) && type.literal === null) && !SchemaAST.isUndefinedKeyword(type),
212
203
  )
213
204
 
214
- return core || ast
205
+ if (coreTypes.length === 0 || coreTypes.length === ast.types.length) {
206
+ return ast
207
+ }
208
+
209
+ if (coreTypes.length === 1) {
210
+ return coreTypes[0]!
211
+ }
212
+
213
+ return SchemaAST.Union.make(coreTypes, ast.annotations)
214
+ }
215
+
216
+ const getLiteralColumnDefinition = (
217
+ ast: SchemaAST.AST,
218
+ schema: Schema.Schema.AnyNoContext,
219
+ nullable: boolean,
220
+ sourceAst: SchemaAST.AST,
221
+ ): SqliteDsl.ColumnDefinition.Any | null => {
222
+ const literalValues = extractLiteralValues(ast)
223
+ if (!literalValues) return null
224
+
225
+ const literalType = getLiteralValueType(literalValues)
226
+ switch (literalType) {
227
+ case 'string':
228
+ return SqliteDsl.text({ schema, nullable })
229
+ case 'number': {
230
+ const id = SchemaAST.getIdentifierAnnotation(sourceAst).pipe(Option.getOrElse(() => ''))
231
+ if (id === 'Int' || id === 'DateFromNumber') {
232
+ return SqliteDsl.integer({ schema, nullable })
233
+ }
234
+
235
+ const useIntegerColumn =
236
+ literalValues.length > 1 && literalValues.every((value) => typeof value === 'number' && Number.isInteger(value))
237
+
238
+ return useIntegerColumn ? SqliteDsl.integer({ schema, nullable }) : SqliteDsl.real({ schema, nullable })
239
+ }
240
+ case 'boolean':
241
+ return SqliteDsl.boolean({ nullable })
242
+ case 'bigint':
243
+ return SqliteDsl.integer({ schema, nullable })
244
+ default:
245
+ return null
246
+ }
247
+ }
248
+
249
+ const extractLiteralValues = (ast: SchemaAST.AST): ReadonlyArray<SchemaAST.LiteralValue> | null => {
250
+ if (SchemaAST.isLiteral(ast)) return [ast.literal]
251
+
252
+ if (SchemaAST.isUnion(ast) && ast.types.length > 0 && ast.types.every((type) => SchemaAST.isLiteral(type))) {
253
+ return ast.types.map((type) => (type as SchemaAST.Literal).literal)
254
+ }
255
+
256
+ return null
257
+ }
258
+
259
+ const getLiteralValueType = (
260
+ literals: ReadonlyArray<SchemaAST.LiteralValue>,
261
+ ): 'string' | 'number' | 'boolean' | 'bigint' | null => {
262
+ const literalTypes = new Set(literals.map((value) => (value === null ? 'null' : typeof value)))
263
+ if (literalTypes.size !== 1) return null
264
+
265
+ const [literalType] = literalTypes
266
+ return literalType === 'string' || literalType === 'number' || literalType === 'boolean' || literalType === 'bigint'
267
+ ? literalType
268
+ : null
269
+ }
270
+
271
+ const isUint8ArraySchema = (ast: SchemaAST.AST): boolean => {
272
+ const identifier = SchemaAST.getIdentifierAnnotation(ast)
273
+ if (Option.isSome(identifier) && identifier.value.includes('Uint8Array')) {
274
+ return true
275
+ }
276
+
277
+ if (SchemaAST.isTupleType(ast)) {
278
+ return ast.elements.length === 0 && ast.rest.length === 1 && SchemaAST.isNumberKeyword(ast.rest[0]!.type)
279
+ }
280
+
281
+ return false
215
282
  }
@@ -56,9 +56,9 @@ describe('makeColumnSpec', () => {
56
56
  )
57
57
 
58
58
  const result = makeColumnSpec(table)
59
- expect(result).toMatchInlineSnapshot(`"'order' integer not null , 'group' text "`)
60
- expect(result).toContain("'order'")
61
- expect(result).toContain("'group'")
59
+ expect(result).toMatchInlineSnapshot(`""order" integer not null , "group" text "`)
60
+ expect(result).toContain('"order"')
61
+ expect(result).toContain('"group"')
62
62
  })
63
63
 
64
64
  it('should handle basic columns with primary keys', () => {
@@ -69,8 +69,7 @@ describe('makeColumnSpec', () => {
69
69
  )
70
70
 
71
71
  const result = makeColumnSpec(table)
72
- expect(result).toMatchInlineSnapshot(`"'id' text not null , 'name' text , PRIMARY KEY ('id')"`)
73
- expect(result).toContain("PRIMARY KEY ('id')")
72
+ expect(result).toMatchInlineSnapshot(`""id" text primary key , "name" text "`)
74
73
  })
75
74
 
76
75
  it('should handle multi-column primary keys', () => {
@@ -85,9 +84,9 @@ describe('makeColumnSpec', () => {
85
84
 
86
85
  const result = makeColumnSpec(table)
87
86
  expect(result).toMatchInlineSnapshot(
88
- `"'tenant_id' text not null , 'user_id' text not null , PRIMARY KEY ('tenant_id', 'user_id')"`,
87
+ `""tenant_id" text not null , "user_id" text not null , PRIMARY KEY ("tenant_id", "user_id")"`,
89
88
  )
90
- expect(result).toContain("PRIMARY KEY ('tenant_id', 'user_id')")
89
+ expect(result).toContain('PRIMARY KEY ("tenant_id", "user_id")')
91
90
  })
92
91
 
93
92
  it('should handle auto-increment columns', () => {
@@ -101,9 +100,9 @@ describe('makeColumnSpec', () => {
101
100
  )
102
101
 
103
102
  const result = makeColumnSpec(table)
104
- expect(result).toMatchInlineSnapshot(`"'id' integer not null autoincrement , 'title' text , PRIMARY KEY ('id')"`)
103
+ expect(result).toMatchInlineSnapshot(`""id" integer primary key autoincrement , "title" text "`)
105
104
  expect(result).toContain('autoincrement')
106
- expect(result).toContain("PRIMARY KEY ('id')")
105
+ expect(result).not.toContain("PRIMARY KEY ('id')")
107
106
  })
108
107
 
109
108
  it('should handle columns with default values', () => {
@@ -121,7 +120,7 @@ describe('makeColumnSpec', () => {
121
120
 
122
121
  const result = makeColumnSpec(table)
123
122
  expect(result).toMatchInlineSnapshot(
124
- `"'id' integer not null , 'name' text not null , 'price' real default 0, 'active' integer default true, 'description' text default 'No description', PRIMARY KEY ('id')"`,
123
+ `""id" integer primary key , "name" text not null , "price" real default 0, "active" integer default true, "description" text default 'No description'"`,
125
124
  )
126
125
  expect(result).toContain('default 0')
127
126
  expect(result).toContain('default true')
@@ -141,12 +140,28 @@ describe('makeColumnSpec', () => {
141
140
 
142
141
  const result = makeColumnSpec(table)
143
142
  expect(result).toMatchInlineSnapshot(
144
- `"'id' integer not null , 'created_at' text default CURRENT_TIMESTAMP, 'random_value' real default RANDOM(), PRIMARY KEY ('id')"`,
143
+ `""id" integer primary key , "created_at" text default CURRENT_TIMESTAMP, "random_value" real default RANDOM()"`,
145
144
  )
146
145
  expect(result).toContain('default CURRENT_TIMESTAMP')
147
146
  expect(result).toContain('default RANDOM()')
148
147
  })
149
148
 
149
+ it('should omit default clause for thunk defaults', () => {
150
+ const table = SqliteAst.table(
151
+ 'thunks',
152
+ [
153
+ createColumn('id', 'integer', { nullable: false, primaryKey: true }),
154
+ createColumn('token', 'text', { defaultValue: () => 'dynamic-token' }),
155
+ ],
156
+ [],
157
+ )
158
+
159
+ const result = makeColumnSpec(table)
160
+ expect(result).toMatchInlineSnapshot(`""id" integer primary key , "token" text "`)
161
+ expect(result).not.toContain('dynamic-token')
162
+ expect(result).not.toMatch(/token" text\s+default/i)
163
+ })
164
+
150
165
  it('should handle null default values', () => {
151
166
  const table = SqliteAst.table(
152
167
  'nullable_defaults',
@@ -158,9 +173,7 @@ describe('makeColumnSpec', () => {
158
173
  )
159
174
 
160
175
  const result = makeColumnSpec(table)
161
- expect(result).toMatchInlineSnapshot(
162
- `"'id' integer not null , 'optional_text' text default null, PRIMARY KEY ('id')"`,
163
- )
176
+ expect(result).toMatchInlineSnapshot(`""id" integer primary key , "optional_text" text default null"`)
164
177
  expect(result).toContain('default null')
165
178
  })
166
179
 
@@ -190,7 +203,7 @@ describe('makeColumnSpec', () => {
190
203
 
191
204
  const result = makeColumnSpec(table)
192
205
  expect(result).toMatchInlineSnapshot(
193
- `"'id' integer not null autoincrement , 'name' text not null default 'Unnamed', 'created_at' text not null default CURRENT_TIMESTAMP, 'status' text default 'pending', PRIMARY KEY ('id')"`,
206
+ `""id" integer primary key autoincrement , "name" text not null default 'Unnamed', "created_at" text not null default CURRENT_TIMESTAMP, "status" text default 'pending'"`,
194
207
  )
195
208
  })
196
209
 
@@ -213,7 +226,7 @@ describe('makeColumnSpec', () => {
213
226
  const result = makeColumnSpec(table)
214
227
  // The makeColumnSpec function only generates column specifications, not indexes
215
228
  expect(result).toMatchInlineSnapshot(
216
- `"'id' integer not null autoincrement , 'email' text not null , 'username' text not null , 'created_at' text default CURRENT_TIMESTAMP, PRIMARY KEY ('id')"`,
229
+ `""id" integer primary key autoincrement , "email" text not null , "username" text not null , "created_at" text default CURRENT_TIMESTAMP"`,
217
230
  )
218
231
  // Verify the table has the indexes (even though they're not in the column spec)
219
232
  expect(table.indexes).toHaveLength(3)