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

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 (344) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/ClientSessionLeaderThreadProxy.d.ts +16 -9
  3. package/dist/ClientSessionLeaderThreadProxy.d.ts.map +1 -1
  4. package/dist/ClientSessionLeaderThreadProxy.js.map +1 -1
  5. package/dist/WorkerTransportError.d.ts +11 -0
  6. package/dist/WorkerTransportError.d.ts.map +1 -0
  7. package/dist/WorkerTransportError.js +11 -0
  8. package/dist/WorkerTransportError.js.map +1 -0
  9. package/dist/adapter-types.d.ts +26 -3
  10. package/dist/adapter-types.d.ts.map +1 -1
  11. package/dist/adapter-types.js +27 -1
  12. package/dist/adapter-types.js.map +1 -1
  13. package/dist/bounded-collections.d.ts.map +1 -1
  14. package/dist/bounded-collections.js +6 -4
  15. package/dist/bounded-collections.js.map +1 -1
  16. package/dist/debug-info.js +4 -4
  17. package/dist/debug-info.js.map +1 -1
  18. package/dist/devtools/devtools-messages-client-session.d.ts +42 -22
  19. package/dist/devtools/devtools-messages-client-session.d.ts.map +1 -1
  20. package/dist/devtools/devtools-messages-client-session.js +12 -1
  21. package/dist/devtools/devtools-messages-client-session.js.map +1 -1
  22. package/dist/devtools/devtools-messages-common.d.ts +12 -6
  23. package/dist/devtools/devtools-messages-common.d.ts.map +1 -1
  24. package/dist/devtools/devtools-messages-common.js +8 -3
  25. package/dist/devtools/devtools-messages-common.js.map +1 -1
  26. package/dist/devtools/devtools-messages-leader.d.ts +45 -25
  27. package/dist/devtools/devtools-messages-leader.d.ts.map +1 -1
  28. package/dist/devtools/devtools-messages-leader.js +12 -1
  29. package/dist/devtools/devtools-messages-leader.js.map +1 -1
  30. package/dist/devtools/mod.js +1 -1
  31. package/dist/devtools/mod.js.map +1 -1
  32. package/dist/errors.d.ts +15 -15
  33. package/dist/errors.d.ts.map +1 -1
  34. package/dist/errors.js +11 -11
  35. package/dist/errors.js.map +1 -1
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +2 -0
  39. package/dist/index.js.map +1 -1
  40. package/dist/leader-thread/LeaderSyncProcessor.d.ts +20 -6
  41. package/dist/leader-thread/LeaderSyncProcessor.d.ts.map +1 -1
  42. package/dist/leader-thread/LeaderSyncProcessor.js +283 -253
  43. package/dist/leader-thread/LeaderSyncProcessor.js.map +1 -1
  44. package/dist/leader-thread/RejectedPushError.d.ts +107 -0
  45. package/dist/leader-thread/RejectedPushError.d.ts.map +1 -0
  46. package/dist/leader-thread/RejectedPushError.js +78 -0
  47. package/dist/leader-thread/RejectedPushError.js.map +1 -0
  48. package/dist/leader-thread/connection.js +1 -1
  49. package/dist/leader-thread/connection.js.map +1 -1
  50. package/dist/leader-thread/eventlog.d.ts.map +1 -1
  51. package/dist/leader-thread/eventlog.js +12 -11
  52. package/dist/leader-thread/eventlog.js.map +1 -1
  53. package/dist/leader-thread/leader-worker-devtools.d.ts +1 -2
  54. package/dist/leader-thread/leader-worker-devtools.d.ts.map +1 -1
  55. package/dist/leader-thread/leader-worker-devtools.js +34 -14
  56. package/dist/leader-thread/leader-worker-devtools.js.map +1 -1
  57. package/dist/leader-thread/make-leader-thread-layer.d.ts +12 -5
  58. package/dist/leader-thread/make-leader-thread-layer.d.ts.map +1 -1
  59. package/dist/leader-thread/make-leader-thread-layer.js +12 -11
  60. package/dist/leader-thread/make-leader-thread-layer.js.map +1 -1
  61. package/dist/leader-thread/make-leader-thread-layer.test.js +1 -1
  62. package/dist/leader-thread/make-leader-thread-layer.test.js.map +1 -1
  63. package/dist/leader-thread/materialize-event.d.ts.map +1 -1
  64. package/dist/leader-thread/materialize-event.js +7 -4
  65. package/dist/leader-thread/materialize-event.js.map +1 -1
  66. package/dist/leader-thread/recreate-db.js +1 -1
  67. package/dist/leader-thread/recreate-db.js.map +1 -1
  68. package/dist/leader-thread/shutdown-channel.d.ts +2 -2
  69. package/dist/leader-thread/shutdown-channel.d.ts.map +1 -1
  70. package/dist/leader-thread/shutdown-channel.js +2 -2
  71. package/dist/leader-thread/shutdown-channel.js.map +1 -1
  72. package/dist/leader-thread/stream-events.d.ts.map +1 -1
  73. package/dist/leader-thread/stream-events.js +4 -3
  74. package/dist/leader-thread/stream-events.js.map +1 -1
  75. package/dist/leader-thread/types.d.ts +7 -6
  76. package/dist/leader-thread/types.d.ts.map +1 -1
  77. package/dist/leader-thread/types.js.map +1 -1
  78. package/dist/logging.js +4 -4
  79. package/dist/logging.js.map +1 -1
  80. package/dist/make-client-session.js +2 -2
  81. package/dist/make-client-session.js.map +1 -1
  82. package/dist/materializer-helper.js +6 -6
  83. package/dist/materializer-helper.js.map +1 -1
  84. package/dist/otel.d.ts +1 -1
  85. package/dist/otel.d.ts.map +1 -1
  86. package/dist/otel.js +2 -2
  87. package/dist/otel.js.map +1 -1
  88. package/dist/rematerialize-from-eventlog.d.ts +1 -1
  89. package/dist/rematerialize-from-eventlog.d.ts.map +1 -1
  90. package/dist/rematerialize-from-eventlog.js +11 -9
  91. package/dist/rematerialize-from-eventlog.js.map +1 -1
  92. package/dist/schema/EventDef/define.d.ts +16 -2
  93. package/dist/schema/EventDef/define.d.ts.map +1 -1
  94. package/dist/schema/EventDef/define.js +5 -4
  95. package/dist/schema/EventDef/define.js.map +1 -1
  96. package/dist/schema/EventDef/deprecated.d.ts +99 -0
  97. package/dist/schema/EventDef/deprecated.d.ts.map +1 -0
  98. package/dist/schema/EventDef/deprecated.js +144 -0
  99. package/dist/schema/EventDef/deprecated.js.map +1 -0
  100. package/dist/schema/EventDef/deprecated.test.d.ts +2 -0
  101. package/dist/schema/EventDef/deprecated.test.d.ts.map +1 -0
  102. package/dist/schema/EventDef/deprecated.test.js +95 -0
  103. package/dist/schema/EventDef/deprecated.test.js.map +1 -0
  104. package/dist/schema/EventDef/event-def.d.ts +4 -0
  105. package/dist/schema/EventDef/event-def.d.ts.map +1 -1
  106. package/dist/schema/EventDef/mod.d.ts +1 -0
  107. package/dist/schema/EventDef/mod.d.ts.map +1 -1
  108. package/dist/schema/EventDef/mod.js +1 -0
  109. package/dist/schema/EventDef/mod.js.map +1 -1
  110. package/dist/schema/EventSequenceNumber/client.d.ts.map +1 -1
  111. package/dist/schema/EventSequenceNumber/client.js +11 -11
  112. package/dist/schema/EventSequenceNumber/client.js.map +1 -1
  113. package/dist/schema/EventSequenceNumber.test.js +1 -1
  114. package/dist/schema/EventSequenceNumber.test.js.map +1 -1
  115. package/dist/schema/LiveStoreEvent/client.d.ts +6 -6
  116. package/dist/schema/LiveStoreEvent/client.d.ts.map +1 -1
  117. package/dist/schema/LiveStoreEvent/client.js +6 -3
  118. package/dist/schema/LiveStoreEvent/client.js.map +1 -1
  119. package/dist/schema/LiveStoreEvent/client.test.d.ts +2 -0
  120. package/dist/schema/LiveStoreEvent/client.test.d.ts.map +1 -0
  121. package/dist/schema/LiveStoreEvent/client.test.js +83 -0
  122. package/dist/schema/LiveStoreEvent/client.test.js.map +1 -0
  123. package/dist/schema/schema.d.ts.map +1 -1
  124. package/dist/schema/schema.js +7 -4
  125. package/dist/schema/schema.js.map +1 -1
  126. package/dist/schema/state/sqlite/client-document-def.d.ts +1 -0
  127. package/dist/schema/state/sqlite/client-document-def.d.ts.map +1 -1
  128. package/dist/schema/state/sqlite/client-document-def.js +34 -13
  129. package/dist/schema/state/sqlite/client-document-def.js.map +1 -1
  130. package/dist/schema/state/sqlite/client-document-def.test.js +121 -2
  131. package/dist/schema/state/sqlite/client-document-def.test.js.map +1 -1
  132. package/dist/schema/state/sqlite/column-annotations.d.ts.map +1 -1
  133. package/dist/schema/state/sqlite/column-annotations.js +1 -1
  134. package/dist/schema/state/sqlite/column-annotations.js.map +1 -1
  135. package/dist/schema/state/sqlite/column-annotations.test.js +1 -1
  136. package/dist/schema/state/sqlite/column-annotations.test.js.map +1 -1
  137. package/dist/schema/state/sqlite/column-def.d.ts.map +1 -1
  138. package/dist/schema/state/sqlite/column-def.js +36 -34
  139. package/dist/schema/state/sqlite/column-def.js.map +1 -1
  140. package/dist/schema/state/sqlite/column-def.test.js +7 -6
  141. package/dist/schema/state/sqlite/column-def.test.js.map +1 -1
  142. package/dist/schema/state/sqlite/column-spec.d.ts.map +1 -1
  143. package/dist/schema/state/sqlite/column-spec.js +8 -8
  144. package/dist/schema/state/sqlite/column-spec.js.map +1 -1
  145. package/dist/schema/state/sqlite/column-spec.test.js +1 -1
  146. package/dist/schema/state/sqlite/column-spec.test.js.map +1 -1
  147. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js +2 -2
  148. package/dist/schema/state/sqlite/db-schema/ast/sqlite.js.map +1 -1
  149. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts +2 -2
  150. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.d.ts.map +1 -1
  151. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js +11 -2
  152. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.js.map +1 -1
  153. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js +1 -1
  154. package/dist/schema/state/sqlite/db-schema/dsl/field-defs.test.js.map +1 -1
  155. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts +1 -1
  156. package/dist/schema/state/sqlite/db-schema/dsl/mod.d.ts.map +1 -1
  157. package/dist/schema/state/sqlite/db-schema/dsl/mod.js +1 -1
  158. package/dist/schema/state/sqlite/db-schema/dsl/mod.js.map +1 -1
  159. package/dist/schema/state/sqlite/mod.d.ts.map +1 -1
  160. package/dist/schema/state/sqlite/mod.js +3 -5
  161. package/dist/schema/state/sqlite/mod.js.map +1 -1
  162. package/dist/schema/state/sqlite/query-builder/api.d.ts +37 -13
  163. package/dist/schema/state/sqlite/query-builder/api.d.ts.map +1 -1
  164. package/dist/schema/state/sqlite/query-builder/astToSql.d.ts.map +1 -1
  165. package/dist/schema/state/sqlite/query-builder/astToSql.js +77 -7
  166. package/dist/schema/state/sqlite/query-builder/astToSql.js.map +1 -1
  167. package/dist/schema/state/sqlite/query-builder/impl.d.ts +1 -1
  168. package/dist/schema/state/sqlite/query-builder/impl.d.ts.map +1 -1
  169. package/dist/schema/state/sqlite/query-builder/impl.js +28 -14
  170. package/dist/schema/state/sqlite/query-builder/impl.js.map +1 -1
  171. package/dist/schema/state/sqlite/query-builder/impl.test.js +112 -3
  172. package/dist/schema/state/sqlite/query-builder/impl.test.js.map +1 -1
  173. package/dist/schema/state/sqlite/schema-helpers.js +2 -2
  174. package/dist/schema/state/sqlite/schema-helpers.js.map +1 -1
  175. package/dist/schema/state/sqlite/table-def.d.ts +5 -3
  176. package/dist/schema/state/sqlite/table-def.d.ts.map +1 -1
  177. package/dist/schema/state/sqlite/table-def.js +1 -1
  178. package/dist/schema/state/sqlite/table-def.js.map +1 -1
  179. package/dist/schema/state/sqlite/table-def.test.js +57 -4
  180. package/dist/schema/state/sqlite/table-def.test.js.map +1 -1
  181. package/dist/schema/unknown-events.d.ts +1 -1
  182. package/dist/schema/unknown-events.d.ts.map +1 -1
  183. package/dist/schema/unknown-events.js +1 -1
  184. package/dist/schema/unknown-events.js.map +1 -1
  185. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js +1 -1
  186. package/dist/schema-management/__tests__/migrations-autoincrement-quoting.test.js.map +1 -1
  187. package/dist/schema-management/common.js +2 -2
  188. package/dist/schema-management/common.js.map +1 -1
  189. package/dist/schema-management/migrations.js +1 -1
  190. package/dist/schema-management/migrations.js.map +1 -1
  191. package/dist/sql-queries/sql-queries.js +8 -6
  192. package/dist/sql-queries/sql-queries.js.map +1 -1
  193. package/dist/sql-queries/sql-query-builder.d.ts.map +1 -1
  194. package/dist/sql-queries/sql-query-builder.js.map +1 -1
  195. package/dist/sqlite-db-helper.js +3 -3
  196. package/dist/sqlite-db-helper.js.map +1 -1
  197. package/dist/sqlite-types.d.ts +2 -2
  198. package/dist/sqlite-types.d.ts.map +1 -1
  199. package/dist/sqlite-types.js.map +1 -1
  200. package/dist/sync/ClientSessionSyncProcessor.d.ts +8 -9
  201. package/dist/sync/ClientSessionSyncProcessor.d.ts.map +1 -1
  202. package/dist/sync/ClientSessionSyncProcessor.js +93 -107
  203. package/dist/sync/ClientSessionSyncProcessor.js.map +1 -1
  204. package/dist/sync/errors.d.ts +0 -38
  205. package/dist/sync/errors.d.ts.map +1 -1
  206. package/dist/sync/errors.js +3 -20
  207. package/dist/sync/errors.js.map +1 -1
  208. package/dist/sync/mock-sync-backend.d.ts +5 -3
  209. package/dist/sync/mock-sync-backend.d.ts.map +1 -1
  210. package/dist/sync/mock-sync-backend.js +70 -68
  211. package/dist/sync/mock-sync-backend.js.map +1 -1
  212. package/dist/sync/next/compact-events.js +6 -6
  213. package/dist/sync/next/compact-events.js.map +1 -1
  214. package/dist/sync/next/facts.d.ts.map +1 -1
  215. package/dist/sync/next/facts.js +6 -6
  216. package/dist/sync/next/facts.js.map +1 -1
  217. package/dist/sync/next/history-dag-common.d.ts.map +1 -1
  218. package/dist/sync/next/history-dag-common.js +6 -6
  219. package/dist/sync/next/history-dag-common.js.map +1 -1
  220. package/dist/sync/next/history-dag.js +3 -3
  221. package/dist/sync/next/history-dag.js.map +1 -1
  222. package/dist/sync/next/rebase-events.js +1 -1
  223. package/dist/sync/next/rebase-events.js.map +1 -1
  224. package/dist/sync/next/test/compact-events.calculator.test.js +2 -2
  225. package/dist/sync/next/test/compact-events.calculator.test.js.map +1 -1
  226. package/dist/sync/next/test/compact-events.test.d.ts.map +1 -1
  227. package/dist/sync/next/test/compact-events.test.js +2 -2
  228. package/dist/sync/next/test/compact-events.test.js.map +1 -1
  229. package/dist/sync/next/test/event-fixtures.d.ts.map +1 -1
  230. package/dist/sync/next/test/event-fixtures.js +2 -2
  231. package/dist/sync/next/test/event-fixtures.js.map +1 -1
  232. package/dist/sync/sync-backend-kv.d.ts.map +1 -1
  233. package/dist/sync/sync-backend-kv.js.map +1 -1
  234. package/dist/sync/sync-backend.d.ts +3 -3
  235. package/dist/sync/sync-backend.d.ts.map +1 -1
  236. package/dist/sync/sync-backend.js +1 -1
  237. package/dist/sync/sync-backend.js.map +1 -1
  238. package/dist/sync/sync.d.ts +20 -0
  239. package/dist/sync/sync.d.ts.map +1 -1
  240. package/dist/sync/syncstate.d.ts +4 -17
  241. package/dist/sync/syncstate.d.ts.map +1 -1
  242. package/dist/sync/syncstate.js +51 -74
  243. package/dist/sync/syncstate.js.map +1 -1
  244. package/dist/sync/syncstate.test.js +112 -96
  245. package/dist/sync/syncstate.test.js.map +1 -1
  246. package/dist/sync/transport-chunking.js +3 -3
  247. package/dist/sync/transport-chunking.js.map +1 -1
  248. package/dist/sync/validate-push-payload.d.ts +2 -2
  249. package/dist/sync/validate-push-payload.d.ts.map +1 -1
  250. package/dist/sync/validate-push-payload.js +4 -6
  251. package/dist/sync/validate-push-payload.js.map +1 -1
  252. package/dist/util.js +2 -2
  253. package/dist/util.js.map +1 -1
  254. package/dist/version.d.ts +7 -1
  255. package/dist/version.d.ts.map +1 -1
  256. package/dist/version.js +8 -4
  257. package/dist/version.js.map +1 -1
  258. package/package.json +66 -12
  259. package/src/ClientSessionLeaderThreadProxy.ts +16 -9
  260. package/src/WorkerTransportError.ts +12 -0
  261. package/src/adapter-types.ts +39 -3
  262. package/src/bounded-collections.ts +6 -5
  263. package/src/debug-info.ts +4 -4
  264. package/src/devtools/devtools-messages-client-session.ts +12 -0
  265. package/src/devtools/devtools-messages-common.ts +8 -4
  266. package/src/devtools/devtools-messages-leader.ts +12 -0
  267. package/src/devtools/mod.ts +1 -1
  268. package/src/errors.ts +18 -17
  269. package/src/index.ts +2 -0
  270. package/src/leader-thread/LeaderSyncProcessor.ts +417 -347
  271. package/src/leader-thread/RejectedPushError.ts +106 -0
  272. package/src/leader-thread/connection.ts +1 -1
  273. package/src/leader-thread/eventlog.ts +16 -14
  274. package/src/leader-thread/leader-worker-devtools.ts +107 -66
  275. package/src/leader-thread/make-leader-thread-layer.test.ts +1 -1
  276. package/src/leader-thread/make-leader-thread-layer.ts +41 -31
  277. package/src/leader-thread/materialize-event.ts +8 -4
  278. package/src/leader-thread/recreate-db.ts +1 -1
  279. package/src/leader-thread/shutdown-channel.ts +2 -6
  280. package/src/leader-thread/stream-events.ts +10 -5
  281. package/src/leader-thread/types.ts +7 -6
  282. package/src/logging.ts +4 -4
  283. package/src/make-client-session.ts +2 -2
  284. package/src/materializer-helper.ts +9 -9
  285. package/src/otel.ts +3 -2
  286. package/src/rematerialize-from-eventlog.ts +60 -60
  287. package/src/schema/EventDef/define.ts +22 -6
  288. package/src/schema/EventDef/deprecated.test.ts +129 -0
  289. package/src/schema/EventDef/deprecated.ts +175 -0
  290. package/src/schema/EventDef/event-def.ts +5 -0
  291. package/src/schema/EventDef/mod.ts +1 -0
  292. package/src/schema/EventSequenceNumber/client.ts +11 -11
  293. package/src/schema/EventSequenceNumber.test.ts +2 -1
  294. package/src/schema/LiveStoreEvent/client.test.ts +97 -0
  295. package/src/schema/LiveStoreEvent/client.ts +6 -3
  296. package/src/schema/schema.ts +9 -4
  297. package/src/schema/state/sqlite/client-document-def.test.ts +142 -3
  298. package/src/schema/state/sqlite/client-document-def.ts +37 -14
  299. package/src/schema/state/sqlite/column-annotations.test.ts +2 -1
  300. package/src/schema/state/sqlite/column-annotations.ts +2 -1
  301. package/src/schema/state/sqlite/column-def.test.ts +8 -6
  302. package/src/schema/state/sqlite/column-def.ts +41 -36
  303. package/src/schema/state/sqlite/column-spec.test.ts +3 -1
  304. package/src/schema/state/sqlite/column-spec.ts +9 -8
  305. package/src/schema/state/sqlite/db-schema/ast/sqlite.ts +2 -2
  306. package/src/schema/state/sqlite/db-schema/dsl/field-defs.test.ts +2 -1
  307. package/src/schema/state/sqlite/db-schema/dsl/field-defs.ts +13 -4
  308. package/src/schema/state/sqlite/db-schema/dsl/mod.ts +3 -3
  309. package/src/schema/state/sqlite/mod.ts +4 -5
  310. package/src/schema/state/sqlite/query-builder/api.ts +37 -8
  311. package/src/schema/state/sqlite/query-builder/astToSql.ts +87 -7
  312. package/src/schema/state/sqlite/query-builder/impl.test.ts +145 -3
  313. package/src/schema/state/sqlite/query-builder/impl.ts +26 -12
  314. package/src/schema/state/sqlite/schema-helpers.ts +2 -2
  315. package/src/schema/state/sqlite/table-def.test.ts +67 -4
  316. package/src/schema/state/sqlite/table-def.ts +8 -15
  317. package/src/schema/unknown-events.ts +2 -2
  318. package/src/schema-management/__tests__/migrations-autoincrement-quoting.test.ts +3 -1
  319. package/src/schema-management/common.ts +2 -2
  320. package/src/schema-management/migrations.ts +1 -1
  321. package/src/sql-queries/sql-queries.ts +10 -6
  322. package/src/sql-queries/sql-query-builder.ts +1 -0
  323. package/src/sqlite-db-helper.ts +3 -3
  324. package/src/sqlite-types.ts +3 -2
  325. package/src/sync/ClientSessionSyncProcessor.ts +142 -133
  326. package/src/sync/errors.ts +10 -22
  327. package/src/sync/mock-sync-backend.ts +139 -97
  328. package/src/sync/next/compact-events.ts +5 -5
  329. package/src/sync/next/facts.ts +7 -6
  330. package/src/sync/next/history-dag-common.ts +9 -6
  331. package/src/sync/next/history-dag.ts +3 -3
  332. package/src/sync/next/rebase-events.ts +1 -1
  333. package/src/sync/next/test/compact-events.calculator.test.ts +3 -2
  334. package/src/sync/next/test/compact-events.test.ts +4 -3
  335. package/src/sync/next/test/event-fixtures.ts +2 -2
  336. package/src/sync/sync-backend-kv.ts +1 -0
  337. package/src/sync/sync-backend.ts +5 -4
  338. package/src/sync/sync.ts +21 -0
  339. package/src/sync/syncstate.test.ts +513 -435
  340. package/src/sync/syncstate.ts +80 -86
  341. package/src/sync/transport-chunking.ts +3 -3
  342. package/src/sync/validate-push-payload.ts +4 -6
  343. package/src/util.ts +2 -2
  344. package/src/version.ts +8 -4
@@ -95,10 +95,12 @@ export const clientDocument = <
95
95
  Object.defineProperty(setEventDef, 'schema', {
96
96
  value: Schema.Struct({
97
97
  id: Schema.String,
98
- value: options.partialSet ? Schema.partial(valueSchema) : valueSchema,
98
+ value: options.partialSet === true ? Schema.partial(valueSchema) : valueSchema,
99
99
  }).annotations({ title: `${name}Set:Args` }),
100
100
  })
101
- Object.defineProperty(setEventDef, 'options', { value: { derived: true, clientOnly: true, facts: undefined } })
101
+ Object.defineProperty(setEventDef, 'options', {
102
+ value: { derived: true, clientOnly: true, facts: undefined, deprecated: undefined },
103
+ })
102
104
 
103
105
  const clientDocumentTableDefTrait: ClientDocumentTableDef.Trait<
104
106
  TName,
@@ -106,20 +108,26 @@ export const clientDocument = <
106
108
  TEncoded,
107
109
  ClientDocumentTableOptions<TType>
108
110
  > = {
111
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- dynamic table def composition; type safety ensured by ClientDocumentTableDef.Trait
109
112
  get: makeGetQueryBuilder(() => clientDocumentTableDef) as any,
113
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- dynamic table def composition; type safety ensured by SetEventDefLike signature
110
114
  set: setEventDef as any,
115
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- phantom type field for generic inference only
111
116
  Value: 'only-for-type-inference' as any,
112
117
  default: options.default,
113
118
  valueSchema,
114
119
  [ClientDocumentTableDefSymbol]: {
115
120
  derived: {
121
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- dynamic event def composition; type checked at usage sites
116
122
  setEventDef: derivedSetEventDef as any,
123
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- dynamic materializer composition; type checked at usage sites
117
124
  setMaterializer: derivedSetMaterializer as any,
118
125
  },
119
126
  options,
120
127
  },
121
128
  }
122
129
 
130
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- composing tableDef + clientDocumentTableDefTrait into final type; validated by satisfies above
123
131
  const clientDocumentTableDef = {
124
132
  ...tableDef,
125
133
  ...clientDocumentTableDefTrait,
@@ -139,11 +147,14 @@ export const mergeDefaultValues = <T>(defaultValues: T, explicitDefaultValues: T
139
147
  }
140
148
 
141
149
  // Get all unique keys from both objects
150
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- Object.keys requires indexable type; T is constrained to object by preceding typeof checks
142
151
  const allKeys = new Set([...Object.keys(defaultValues as any), ...Object.keys(explicitDefaultValues as any)])
143
152
 
144
153
  return Array.from(allKeys).reduce((acc, key) => {
154
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- dynamic key access on generic object; keys validated from Object.keys above
145
155
  acc[key] = (explicitDefaultValues as any)[key] ?? (defaultValues as any)[key]
146
156
  return acc
157
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- reduce accumulator type; result type is T
147
158
  }, {} as any)
148
159
  }
149
160
 
@@ -175,7 +186,10 @@ export const createOptimisticEventSchema = ({
175
186
  defaultValue: any
176
187
  partialSet: boolean
177
188
  }) => {
178
- const targetSchema = partialSet ? Schema.partial(valueSchema) : valueSchema
189
+ const targetSchema = partialSet === true ? Schema.partial(valueSchema) : valueSchema
190
+ // The transform decode must yield values in the target schema's ENCODED shape.
191
+ // This keeps JSON columns consistent when Encoded != Type (e.g. Option).
192
+ const encodeTarget = Schema.encodeSync(targetSchema)
179
193
 
180
194
  return Schema.transform(
181
195
  Schema.Unknown, // Accept any historical event structure
@@ -184,17 +198,21 @@ export const createOptimisticEventSchema = ({
184
198
  decode: (eventValue) => {
185
199
  // Try direct decode first (for current schema events)
186
200
  try {
187
- return Schema.decodeUnknownSync(targetSchema)(eventValue)
201
+ const decoded = Schema.decodeUnknownSync(targetSchema)(eventValue)
202
+ // Re-encode so downstream parseJson/column decoding sees encoded values.
203
+ return encodeTarget(decoded)
188
204
  } catch {
189
205
  // Optimistic decoding for historical events
190
206
 
191
207
  // Handle null/undefined/non-object cases
192
208
  if (typeof eventValue !== 'object' || eventValue === null) {
193
- console.warn(`Client document: Non-object event value, using ${partialSet ? 'empty partial' : 'defaults'}`)
194
- return partialSet ? {} : defaultValue
209
+ console.warn(
210
+ `Client document: Non-object event value, using ${partialSet === true ? 'empty partial' : 'defaults'}`,
211
+ )
212
+ return encodeTarget(partialSet === true ? {} : defaultValue)
195
213
  }
196
214
 
197
- if (partialSet) {
215
+ if (partialSet === true) {
198
216
  // For partial sets: only preserve fields that exist in new schema
199
217
  const partialResult: Record<string, unknown> = {}
200
218
  let hasValidFields = false
@@ -207,16 +225,17 @@ export const createOptimisticEventSchema = ({
207
225
  // Drop fields that don't exist in new schema
208
226
  }
209
227
 
210
- if (hasValidFields) {
228
+ if (hasValidFields === true) {
211
229
  try {
212
- return Schema.decodeUnknownSync(targetSchema)(partialResult)
230
+ const decoded = Schema.decodeUnknownSync(targetSchema)(partialResult)
231
+ return encodeTarget(decoded)
213
232
  } catch {
214
233
  // Even filtered fields don't match schema
215
234
  console.warn('Client document: Partial fields incompatible, returning empty partial')
216
- return {}
235
+ return encodeTarget({})
217
236
  }
218
237
  }
219
- return {}
238
+ return encodeTarget({})
220
239
  } else {
221
240
  // Full set: merge old data with new defaults
222
241
  const merged: Record<string, unknown> = { ...defaultValue }
@@ -231,12 +250,13 @@ export const createOptimisticEventSchema = ({
231
250
 
232
251
  // Try to decode the merged value
233
252
  try {
234
- return Schema.decodeUnknownSync(valueSchema)(merged)
253
+ const decoded = Schema.decodeUnknownSync(valueSchema)(merged)
254
+ return encodeTarget(decoded)
235
255
  } catch {
236
256
  // Merged value still doesn't match (e.g., type changes)
237
257
  // Fall back to pure defaults
238
258
  console.warn('Client document: Could not preserve event data, using defaults')
239
- return defaultValue
259
+ return encodeTarget(defaultValue)
240
260
  }
241
261
  }
242
262
  }
@@ -357,11 +377,14 @@ const makeGetQueryBuilder = <TTableDef extends ClientDocumentTableDef<any, any,
357
377
  return {
358
378
  [QueryBuilderTypeId]: QueryBuilderTypeId,
359
379
  [QueryBuilderAstSymbol]: ast,
380
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- phantom type field for generic inference only
360
381
  ResultType: 'only-for-type-inference' as any,
361
382
  asSql: () => ({ query, bindValues: [id] }),
362
383
  toString: () => query.toString(),
384
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- spreading empty object to satisfy QueryBuilder interface requirements
363
385
  ...({} as any), // Needed for type cast
364
386
  }
387
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- makeGetQueryBuilder return type uses complex conditional generics
365
388
  }) as any
366
389
  }
367
390
 
@@ -544,7 +567,7 @@ export namespace ClientDocumentTableDef {
544
567
  readonly name: `${TName}Set`
545
568
  readonly args: { id: string; value: TType }
546
569
  }
547
- readonly options: { derived: true; clientOnly: true; facts: undefined }
570
+ readonly options: { derived: true; clientOnly: true; facts: undefined; deprecated: undefined }
548
571
  }
549
572
 
550
573
  export type SetEventDef<TName extends string, TType, TOptions extends ClientDocumentTableOptions<TType>> = EventDef<
@@ -1,6 +1,7 @@
1
- import { Schema, SchemaAST } from '@livestore/utils/effect'
2
1
  import { describe, expect, test } from 'vitest'
3
2
 
3
+ import { Schema, SchemaAST } from '@livestore/utils/effect'
4
+
4
5
  import { withColumnType, withPrimaryKey } from './column-annotations.ts'
5
6
 
6
7
  describe.concurrent('annotations', () => {
@@ -1,5 +1,6 @@
1
1
  import type { Schema } from '@livestore/utils/effect'
2
2
  import { dual, Option, SchemaAST } from '@livestore/utils/effect'
3
+
3
4
  import type { SqliteDsl } from './db-schema/mod.ts'
4
5
 
5
6
  export const PrimaryKeyId = Symbol.for('livestore/state/sqlite/annotations/primary-key')
@@ -79,7 +80,7 @@ const validateSchemaColumnTypeCompatibility = (
79
80
  const applyAnnotations = <T extends Schema.Schema.All>(schema: T, overrides: Record<PropertyKey, unknown>): T => {
80
81
  const identifier = SchemaAST.getIdentifierAnnotation(schema.ast)
81
82
  const shouldPreserveIdentifier = Option.isSome(identifier) && !(SchemaAST.IdentifierAnnotationId in overrides)
82
- const annotations: Record<PropertyKey, unknown> = shouldPreserveIdentifier
83
+ const annotations: Record<PropertyKey, unknown> = shouldPreserveIdentifier === true
83
84
  ? { ...overrides, [SchemaAST.IdentifierAnnotationId]: identifier.value }
84
85
  : overrides
85
86
 
@@ -1,6 +1,8 @@
1
- import { Schema } from '@livestore/utils/effect'
2
1
  import { assert, describe, expect, it } from 'vitest'
3
2
 
3
+ import { Schema } from '@livestore/utils/effect'
4
+ import { objectToString } from '@livestore/utils'
5
+
4
6
  import * as State from '../mod.ts'
5
7
  import { withAutoIncrement, withColumnType, withDefault, withPrimaryKey, withUnique } from './column-annotations.ts'
6
8
 
@@ -299,7 +301,7 @@ describe('getColumnDefForSchema', () => {
299
301
  it('should handle Uint8Array as blob column', () => {
300
302
  const columnDef = State.SQLite.getColumnDefForSchema(Schema.Uint8Array)
301
303
  expect(columnDef.columnType).toBe('blob')
302
- expect(columnDef.schema.toString()).toBe('Uint8ArrayFromSelf')
304
+ expect(objectToString(columnDef.schema)).toBe('Uint8ArrayFromSelf')
303
305
  })
304
306
  })
305
307
 
@@ -356,8 +358,8 @@ describe('getColumnDefForSchema', () => {
356
358
 
357
359
  expect(table.sqliteDef.columns.active.nullable).toBe(true)
358
360
  expect(table.sqliteDef.columns.active.columnType).toBe('integer')
359
- expect(table.sqliteDef.columns.active.schema.toString()).toBe('(number <-> boolean) | null')
360
- expect((table.rowSchema as any).fields.active.toString()).toBe('(number <-> boolean) | null')
361
+ expect(objectToString(table.sqliteDef.columns.active.schema)).toBe('(number <-> boolean) | null')
362
+ expect(String((table.rowSchema as any).fields.active)).toBe('(number <-> boolean) | null')
361
363
  })
362
364
 
363
365
  it('should handle optional complex types with JSON encoding', () => {
@@ -406,8 +408,8 @@ describe('getColumnDefForSchema', () => {
406
408
  const table = State.SQLite.table({ name: 'timers', schema })
407
409
 
408
410
  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
+ expect(objectToString(table.sqliteDef.columns.status.schema)).toBe('"idle" | "running" | "stopped"')
412
+ expect(String((table.rowSchema as any).fields.status)).toBe('"idle" | "running" | "stopped"')
411
413
  })
412
414
 
413
415
  it('should handle Schema.NullOr with complex types', () => {
@@ -20,19 +20,20 @@ export const getColumnDefForSchema = (
20
20
 
21
21
  // Extract annotations
22
22
  const getAnnotation = <T>(annotationId: symbol): Option.Option<T> =>
23
- propertySignature
23
+ propertySignature !== undefined
24
24
  ? hasPropertyAnnotation<T>(propertySignature, annotationId)
25
25
  : SchemaAST.getAnnotation<T>(annotationId)(ast)
26
26
 
27
27
  const columnType = SchemaAST.getAnnotation<SqliteDsl.FieldColumnType>(ColumnType)(ast)
28
28
 
29
29
  // Check if schema has null (e.g., Schema.NullOr) or undefined or if it's forced nullable (optional field)
30
- const isNullable = forceNullable || hasNull(ast) || hasUndefined(ast)
30
+ const isNullable = forceNullable === true || hasNull(ast) === true || hasUndefined(ast) === true
31
31
 
32
32
  // Get base column definition with nullable flag
33
- const baseColumn = Option.isSome(columnType)
34
- ? getColumnForType(columnType.value, isNullable)
35
- : getColumnForSchema(schema, isNullable)
33
+ const baseColumn =
34
+ Option.isSome(columnType) === true
35
+ ? getColumnForType(columnType.value, isNullable)
36
+ : getColumnForSchema(schema, isNullable)
36
37
 
37
38
  // Apply annotations
38
39
  const primaryKey = getAnnotation<boolean>(PrimaryKeyId).pipe(Option.getOrElse(() => false))
@@ -41,9 +42,9 @@ export const getColumnDefForSchema = (
41
42
 
42
43
  return {
43
44
  ...baseColumn,
44
- ...(primaryKey && { primaryKey: true }),
45
- ...(autoIncrement && { autoIncrement: true }),
46
- ...(Option.isSome(defaultValue) && { default: Option.some(defaultValue.value) }),
45
+ ...(primaryKey === true ? { primaryKey: true } : {}),
46
+ ...(autoIncrement === true ? { autoIncrement: true } : {}),
47
+ ...(Option.isSome(defaultValue) === true ? { default: Option.some(defaultValue.value) } : {}),
47
48
  }
48
49
  }
49
50
 
@@ -51,9 +52,9 @@ const hasPropertyAnnotation = <T>(
51
52
  propertySignature: SchemaAST.PropertySignature,
52
53
  annotationId: symbol,
53
54
  ): Option.Option<T> => {
54
- if ('annotations' in propertySignature && propertySignature.annotations) {
55
+ if ('annotations' in propertySignature && propertySignature.annotations !== undefined) {
55
56
  const annotation = SchemaAST.getAnnotation<T>(annotationId)(propertySignature as any)
56
- if (Option.isSome(annotation)) return annotation
57
+ if (Option.isSome(annotation) === true) return annotation
57
58
  }
58
59
  return SchemaAST.getAnnotation<T>(annotationId)(propertySignature.type)
59
60
  }
@@ -74,15 +75,15 @@ export const schemaFieldsToColumns = (
74
75
  const fieldSchema = Schema.make(prop.type)
75
76
 
76
77
  // Warn about lossy conversion for fields with both null and undefined
77
- if (prop.isOptional) {
78
+ if (prop.isOptional === true) {
78
79
  const { hasNull, hasUndefined } = checkNullUndefined(fieldSchema.ast)
79
- if (hasNull && hasUndefined) {
80
+ if (hasNull === true && hasUndefined === true) {
80
81
  console.warn(`Field '${prop.name}' has both null and undefined - treating | undefined as | null`)
81
82
  }
82
83
  }
83
84
 
84
85
  // Get column definition - pass nullable flag for optional fields
85
- const columnDef = getColumnDefForSchema(fieldSchema, prop, prop.isOptional)
86
+ const columnDef = getColumnDefForSchema(fieldSchema, prop, prop.isOptional === true)
86
87
 
87
88
  // Check for primary key and unique annotations
88
89
  const hasPrimaryKey = hasPropertyAnnotation<boolean>(prop, PrimaryKeyId).pipe(Option.getOrElse(() => false))
@@ -91,16 +92,16 @@ export const schemaFieldsToColumns = (
91
92
  // Build final column
92
93
  columns[prop.name] = {
93
94
  ...columnDef,
94
- ...(hasPrimaryKey && { primaryKey: true }),
95
+ ...(hasPrimaryKey === true ? { primaryKey: true } : {}),
95
96
  }
96
97
 
97
98
  // Validate primary key + nullable
98
99
  const column = columns[prop.name]
99
- if (column?.primaryKey && column.nullable) {
100
+ if (column?.primaryKey === true && column.nullable === true) {
100
101
  throw new Error('Primary key columns cannot be nullable')
101
102
  }
102
103
 
103
- if (hasUnique) uniqueColumns.push(prop.name)
104
+ if (hasUnique === true) uniqueColumns.push(prop.name)
104
105
  }
105
106
 
106
107
  return { columns, uniqueColumns }
@@ -111,9 +112,9 @@ const checkNullUndefined = (ast: SchemaAST.AST): { hasNull: boolean; hasUndefine
111
112
  let hasUndefined = false
112
113
 
113
114
  const visit = (type: SchemaAST.AST): void => {
114
- if (SchemaAST.isUndefinedKeyword(type)) hasUndefined = true
115
- else if (SchemaAST.isLiteral(type) && type.literal === null) hasNull = true
116
- else if (SchemaAST.isUnion(type)) type.types.forEach(visit)
115
+ if (SchemaAST.isUndefinedKeyword(type) === true) hasUndefined = true
116
+ else if (SchemaAST.isLiteral(type) === true && type.literal === null) hasNull = true
117
+ else if (SchemaAST.isUnion(type) === true) type.types.forEach(visit)
117
118
  }
118
119
 
119
120
  visit(ast)
@@ -121,16 +122,16 @@ const checkNullUndefined = (ast: SchemaAST.AST): { hasNull: boolean; hasUndefine
121
122
  }
122
123
 
123
124
  const hasNull = (ast: SchemaAST.AST): boolean => {
124
- if (SchemaAST.isLiteral(ast) && ast.literal === null) return true
125
- if (SchemaAST.isUnion(ast)) {
125
+ if (SchemaAST.isLiteral(ast) === true && ast.literal === null) return true
126
+ if (SchemaAST.isUnion(ast) === true) {
126
127
  return ast.types.some((type) => hasNull(type))
127
128
  }
128
129
  return false
129
130
  }
130
131
 
131
132
  const hasUndefined = (ast: SchemaAST.AST): boolean => {
132
- if (SchemaAST.isUndefinedKeyword(ast)) return true
133
- if (SchemaAST.isUnion(ast)) {
133
+ if (SchemaAST.isUndefinedKeyword(ast) === true) return true
134
+ if (SchemaAST.isUnion(ast) === true) {
134
135
  return ast.types.some((type) => hasUndefined(type))
135
136
  }
136
137
  return false
@@ -158,7 +159,7 @@ const getColumnForSchema = (schema: Schema.Schema.AnyNoContext, nullable = false
158
159
  const coreSchema = stripNullable(ast) === ast ? schema : Schema.make(coreAst)
159
160
 
160
161
  // Special case: Boolean is transformed to integer in SQLite
161
- if (SchemaAST.isBooleanKeyword(coreAst)) {
162
+ if (SchemaAST.isBooleanKeyword(coreAst) === true) {
162
163
  return SqliteDsl.boolean({ nullable })
163
164
  }
164
165
 
@@ -166,11 +167,11 @@ const getColumnForSchema = (schema: Schema.Schema.AnyNoContext, nullable = false
166
167
  const encodedAst = Schema.encodedSchema(coreSchema).ast
167
168
 
168
169
  // Check if the encoded type matches SQLite native types
169
- if (SchemaAST.isStringKeyword(encodedAst)) {
170
+ if (SchemaAST.isStringKeyword(encodedAst) === true) {
170
171
  return SqliteDsl.text({ schema: coreSchema, nullable })
171
172
  }
172
173
 
173
- if (SchemaAST.isNumberKeyword(encodedAst)) {
174
+ if (SchemaAST.isNumberKeyword(encodedAst) === true) {
174
175
  // Special cases for integer columns
175
176
  const id = SchemaAST.getIdentifierAnnotation(coreAst).pipe(Option.getOrElse(() => ''))
176
177
  if (id === 'Int' || id === 'DateFromNumber') {
@@ -179,23 +180,23 @@ const getColumnForSchema = (schema: Schema.Schema.AnyNoContext, nullable = false
179
180
  return SqliteDsl.real({ schema: coreSchema, nullable })
180
181
  }
181
182
 
182
- if (isUint8ArraySchema(coreAst) || isUint8ArraySchema(encodedAst)) {
183
+ if (isUint8ArraySchema(coreAst) === true || isUint8ArraySchema(encodedAst) === true) {
183
184
  return SqliteDsl.blob({ schema: Schema.Uint8ArrayFromSelf as Schema.Schema<Uint8Array<ArrayBuffer>>, nullable })
184
185
  }
185
186
 
186
187
  const literalColumn = getLiteralColumnDefinition(encodedAst, coreSchema, nullable, coreAst)
187
- if (literalColumn) return literalColumn
188
+ if (literalColumn !== null) return literalColumn
188
189
 
189
190
  // Fallback to checking the original AST in case the encoded schema differs
190
191
  const coreLiteralColumn = getLiteralColumnDefinition(coreAst, coreSchema, nullable, coreAst)
191
- if (coreLiteralColumn) return coreLiteralColumn
192
+ if (coreLiteralColumn !== null) return coreLiteralColumn
192
193
 
193
194
  // Everything else needs JSON encoding
194
195
  return SqliteDsl.json({ schema: coreSchema, nullable })
195
196
  }
196
197
 
197
198
  const stripNullable = (ast: SchemaAST.AST): SchemaAST.AST => {
198
- if (!SchemaAST.isUnion(ast)) return ast
199
+ if (SchemaAST.isUnion(ast) === false) return ast
199
200
 
200
201
  // Filter out null/undefined members while preserving any annotations on the union
201
202
  const coreTypes = ast.types.filter(
@@ -220,7 +221,7 @@ const getLiteralColumnDefinition = (
220
221
  sourceAst: SchemaAST.AST,
221
222
  ): SqliteDsl.ColumnDefinition.Any | null => {
222
223
  const literalValues = extractLiteralValues(ast)
223
- if (!literalValues) return null
224
+ if (literalValues == null) return null
224
225
 
225
226
  const literalType = getLiteralValueType(literalValues)
226
227
  switch (literalType) {
@@ -235,7 +236,7 @@ const getLiteralColumnDefinition = (
235
236
  const useIntegerColumn =
236
237
  literalValues.length > 1 && literalValues.every((value) => typeof value === 'number' && Number.isInteger(value))
237
238
 
238
- return useIntegerColumn ? SqliteDsl.integer({ schema, nullable }) : SqliteDsl.real({ schema, nullable })
239
+ return useIntegerColumn === true ? SqliteDsl.integer({ schema, nullable }) : SqliteDsl.real({ schema, nullable })
239
240
  }
240
241
  case 'boolean':
241
242
  return SqliteDsl.boolean({ nullable })
@@ -247,9 +248,13 @@ const getLiteralColumnDefinition = (
247
248
  }
248
249
 
249
250
  const extractLiteralValues = (ast: SchemaAST.AST): ReadonlyArray<SchemaAST.LiteralValue> | null => {
250
- if (SchemaAST.isLiteral(ast)) return [ast.literal]
251
+ if (SchemaAST.isLiteral(ast) === true) return [ast.literal]
251
252
 
252
- if (SchemaAST.isUnion(ast) && ast.types.length > 0 && ast.types.every((type) => SchemaAST.isLiteral(type))) {
253
+ if (
254
+ SchemaAST.isUnion(ast) === true &&
255
+ ast.types.length > 0 &&
256
+ ast.types.every((type) => SchemaAST.isLiteral(type)) === true
257
+ ) {
253
258
  return ast.types.map((type) => (type as SchemaAST.Literal).literal)
254
259
  }
255
260
 
@@ -270,11 +275,11 @@ const getLiteralValueType = (
270
275
 
271
276
  const isUint8ArraySchema = (ast: SchemaAST.AST): boolean => {
272
277
  const identifier = SchemaAST.getIdentifierAnnotation(ast)
273
- if (Option.isSome(identifier) && identifier.value.includes('Uint8Array')) {
278
+ if (Option.isSome(identifier) === true && identifier.value.includes('Uint8Array') === true) {
274
279
  return true
275
280
  }
276
281
 
277
- if (SchemaAST.isTupleType(ast)) {
282
+ if (SchemaAST.isTupleType(ast) === true) {
278
283
  return ast.elements.length === 0 && ast.rest.length === 1 && SchemaAST.isNumberKeyword(ast.rest[0]!.type)
279
284
  }
280
285
 
@@ -1,5 +1,7 @@
1
- import { Option, Schema } from '@livestore/utils/effect'
2
1
  import { describe, expect, it } from 'vitest'
2
+
3
+ import { Option, Schema } from '@livestore/utils/effect'
4
+
3
5
  import { makeColumnSpec } from './column-spec.ts'
4
6
  import { SqliteAst } from './db-schema/mod.ts'
5
7
 
@@ -1,4 +1,5 @@
1
1
  import { Schema } from '@livestore/utils/effect'
2
+
2
3
  import { type SqliteAst, SqliteDsl } from './db-schema/mod.ts'
3
4
 
4
5
  /**
@@ -12,13 +13,13 @@ import { type SqliteAst, SqliteDsl } from './db-schema/mod.ts'
12
13
  export const makeColumnSpec = (tableAst: SqliteAst.Table) => {
13
14
  const pkColumns = tableAst.columns.filter((_) => _.primaryKey)
14
15
  const hasSinglePk = pkColumns.length === 1
15
- const pkColumn = hasSinglePk ? pkColumns[0] : undefined
16
+ const pkColumn = hasSinglePk === true ? pkColumns[0] : undefined
16
17
 
17
18
  // Build column definitions, handling the special SQLite rule that AUTOINCREMENT
18
19
  // is only valid on a single column declared as INTEGER PRIMARY KEY (column-level).
19
20
  const columnDefStrs = tableAst.columns.map((column) =>
20
21
  toSqliteColumnSpec(column, {
21
- inlinePrimaryKey: hasSinglePk && column === pkColumn && column.primaryKey === true,
22
+ inlinePrimaryKey: hasSinglePk && column === pkColumn && column.primaryKey,
22
23
  }),
23
24
  )
24
25
 
@@ -36,24 +37,24 @@ const toSqliteColumnSpec = (column: SqliteAst.Column, opts: { inlinePrimaryKey:
36
37
  const columnTypeStr = column.type._tag
37
38
  // When PRIMARY KEY is declared inline, NOT NULL is implied and should not be emitted,
38
39
  // and AUTOINCREMENT must immediately follow PRIMARY KEY within the same constraint.
39
- const nullableStr = opts.inlinePrimaryKey ? '' : column.nullable === false ? 'not null' : ''
40
+ const nullableStr = opts.inlinePrimaryKey === true ? '' : column.nullable === false ? 'not null' : ''
40
41
 
41
42
  // Only include AUTOINCREMENT when it's valid: single-column INTEGER PRIMARY KEY
42
- const includeAutoIncrement = opts.inlinePrimaryKey && column.type._tag === 'integer' && column.autoIncrement === true
43
+ const includeAutoIncrement = opts.inlinePrimaryKey === true && column.type._tag === 'integer' && column.autoIncrement === true
43
44
 
44
- const pkStr = opts.inlinePrimaryKey ? 'primary key' : ''
45
- const autoIncrementStr = includeAutoIncrement ? 'autoincrement' : ''
45
+ const pkStr = opts.inlinePrimaryKey === true ? 'primary key' : ''
46
+ const autoIncrementStr = includeAutoIncrement === true ? 'autoincrement' : ''
46
47
 
47
48
  const defaultValueStr = (() => {
48
49
  if (column.default._tag === 'None') return ''
49
50
 
50
51
  const defaultValue = column.default.value
51
- if (SqliteDsl.isDefaultThunk(defaultValue)) return ''
52
+ if (SqliteDsl.isDefaultThunk(defaultValue) === true) return ''
52
53
 
53
54
  const resolvedDefault = SqliteDsl.resolveColumnDefault(defaultValue)
54
55
 
55
56
  if (resolvedDefault === null) return 'default null'
56
- if (SqliteDsl.isSqlDefaultValue(resolvedDefault)) return `default ${resolvedDefault.sql}`
57
+ if (SqliteDsl.isSqlDefaultValue(resolvedDefault) === true) return `default ${resolvedDefault.sql}`
57
58
 
58
59
  const encodeValue = Schema.encodeSync(column.schema)
59
60
  const encodedDefaultValue = encodeValue(resolvedDefault)
@@ -124,7 +124,7 @@ const trimInfoForHasing = (obj: Table | Column | Index | ForeignKey | DbSchema):
124
124
 
125
125
  // NEW: Include schema hash for JSON columns
126
126
  // This ensures that changes to the JSON schema are detected
127
- if (isJsonColumn(obj) && obj.schema) {
127
+ if (isJsonColumn(obj) === true && obj.schema !== undefined) {
128
128
  // Use Effect's Schema.hash for consistent hashing
129
129
  baseInfo.jsonSchemaHash = Schema.hash(obj.schema)
130
130
  }
@@ -155,7 +155,7 @@ const trimInfoForHasing = (obj: Table | Column | Index | ForeignKey | DbSchema):
155
155
  }
156
156
  }
157
157
  default: {
158
- throw new Error(`Unreachable: ${obj}`)
158
+ throw new Error(`Unreachable: ${String(obj)}`)
159
159
  }
160
160
  }
161
161
  }
@@ -1,6 +1,7 @@
1
- import { Schema } from '@livestore/utils/effect'
2
1
  import { describe, expect, test } from 'vitest'
3
2
 
3
+ import { Schema } from '@livestore/utils/effect'
4
+
4
5
  import * as F from './field-defs.ts'
5
6
 
6
7
  describe.concurrent('FieldDefs', () => {
@@ -6,6 +6,7 @@ export type SqlDefaultValue = {
6
6
  }
7
7
 
8
8
  export const isSqlDefaultValue = (value: unknown): value is SqlDefaultValue => {
9
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- type guard property access after structural check
9
10
  return typeof value === 'object' && value !== null && 'sql' in value && typeof (value as any).sql === 'string'
10
11
  }
11
12
 
@@ -16,14 +17,14 @@ export const isDefaultThunk = (value: unknown): value is ColumnDefaultThunk<unkn
16
17
  export type ColumnDefaultValue<T> = T | null | ColumnDefaultThunk<T | null> | SqlDefaultValue
17
18
 
18
19
  export const resolveColumnDefault = <T>(value: ColumnDefaultValue<T>): T | null | SqlDefaultValue =>
19
- isDefaultThunk(value) ? (value as ColumnDefaultThunk<T | null>)() : value
20
+ isDefaultThunk(value) === true ? value() : value
20
21
 
21
- export type ColumnDefinition<TEncoded, TDecoded> = {
22
+ export type ColumnDefinition<TEncoded, TDecoded, TNullable extends boolean = boolean> = {
22
23
  readonly columnType: FieldColumnType
23
24
  readonly schema: Schema.Schema<TDecoded, TEncoded>
24
25
  readonly default: Option.Option<ColumnDefaultValue<TDecoded>>
25
26
  /** @default false */
26
- readonly nullable: boolean
27
+ readonly nullable: TNullable
27
28
  /** @default false */
28
29
  readonly primaryKey: boolean
29
30
  /** @default false */
@@ -40,6 +41,7 @@ export const isColumnDefinition = (value: unknown): value is ColumnDefinition.An
40
41
  typeof value === 'object' &&
41
42
  value !== null &&
42
43
  'columnType' in value &&
44
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- type guard narrowing; columnType checked to be in valid set
43
45
  validColumnTypes.includes(value.columnType as any)
44
46
  )
45
47
  }
@@ -105,6 +107,7 @@ const makeColDef =
105
107
  const schema = nullable === true ? Schema.NullOr(schemaWithoutNull) : schemaWithoutNull
106
108
  const default_ = def?.default === undefined || def.default === NoDefault ? Option.none() : Option.some(def.default)
107
109
 
110
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- column factory return type uses complex conditional generics; consumer type safety enforced by ColDefFn signature
108
111
  return {
109
112
  columnType,
110
113
  schema,
@@ -200,10 +203,12 @@ type MakeSpecializedColDefFn = {
200
203
 
201
204
  const makeSpecializedColDef: MakeSpecializedColDefFn = (columnType, opts) => (def?: ColumnDefinitionInput) => {
202
205
  const nullable = def?.nullable ?? false
206
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- schema type variance; custom schema compatibility checked at call site
203
207
  const schemaWithoutNull = opts._tag === 'baseSchemaFn' ? opts.baseSchemaFn(def?.schema as any) : opts.baseSchema
204
208
  const schema = nullable === true ? Schema.NullOr(schemaWithoutNull) : schemaWithoutNull
205
209
  const default_ = def?.default === undefined || def.default === NoDefault ? Option.none() : Option.some(def.default)
206
210
 
211
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- specialized column factory return type uses complex conditional generics; consumer type safety enforced by SpecializedColDefFn signature
207
212
  return {
208
213
  columnType,
209
214
  schema,
@@ -236,7 +241,7 @@ export const boolean: SpecializedColDefFn<'integer', false, boolean> = makeSpeci
236
241
  _tag: 'baseSchema',
237
242
  baseSchema: Schema.transform(Schema.Number, Schema.Boolean, {
238
243
  decode: (_) => _ === 1,
239
- encode: (_) => (_ ? 1 : 0),
244
+ encode: (_) => (_ === true ? 1 : 0),
240
245
  }),
241
246
  })
242
247
 
@@ -259,15 +264,19 @@ export const defaultSchemaForColumnType = <TColumnType extends FieldColumnType>(
259
264
 
260
265
  switch (columnType) {
261
266
  case 'text': {
267
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
262
268
  return Schema.String as any as Schema.Schema<T>
263
269
  }
264
270
  case 'integer': {
271
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
265
272
  return Schema.Number as any as Schema.Schema<T>
266
273
  }
267
274
  case 'real': {
275
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
268
276
  return Schema.Number as any as Schema.Schema<T>
269
277
  }
270
278
  case 'blob': {
279
+ // oxlint-disable-next-line typescript-eslint(no-unsafe-type-assertion) -- switch-based type narrowing for column type to schema mapping; each case is correct for its branch
271
280
  return Schema.Uint8ArrayFromSelf as any as Schema.Schema<T>
272
281
  }
273
282
  default: {
@@ -31,7 +31,7 @@ export type DbSchemaFromInputSchema<TSchemaInput extends DbSchemaInput> =
31
31
  export const makeDbSchema = <TDbSchemaInput extends DbSchemaInput>(
32
32
  schema: TDbSchemaInput,
33
33
  ): DbSchemaFromInputSchema<TDbSchemaInput> => {
34
- return Array.isArray(schema) ? Object.fromEntries(schema.map((_) => [_.name, _])) : (schema as any)
34
+ return Array.isArray(schema) === true ? Object.fromEntries(schema.map((_) => [_.name, _])) : (schema as any)
35
35
  }
36
36
 
37
37
  export const table = <TTableName extends string, TColumns extends Columns, TIndexes extends Index[]>(
@@ -76,6 +76,7 @@ export const insertStructSchemaForTable = <TTableDefinition extends TableDefinit
76
76
  Object.fromEntries(
77
77
  tableDef.ast.columns.map((column) => [
78
78
  column.name,
79
+
79
80
  column.nullable === true || column.default._tag === 'Some' ? Schema.optional(column.schema) : column.schema,
80
81
  ]),
81
82
  ),
@@ -195,8 +196,7 @@ export namespace FromColumns {
195
196
  }
196
197
 
197
198
  export type NullableColumnNames<TColumns extends Columns> = keyof {
198
- // TODO double check why there is a `true` in the type
199
- [K in keyof TColumns as TColumns[K] extends ColumnDefinition<any, true> ? K : never]: {}
199
+ [K in keyof TColumns as TColumns[K]['nullable'] extends true ? K : never]: {}
200
200
  }
201
201
 
202
202
  export type RequiredInsertColumns<TColumns extends Columns> = {