@lix-js/sdk 0.5.0-preview.0 → 0.5.0-preview.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1378) hide show
  1. package/dist/account/create-account.d.ts +5 -5
  2. package/dist/account/create-account.d.ts.map +1 -1
  3. package/dist/account/create-account.js +2 -2
  4. package/dist/account/create-account.js.map +1 -1
  5. package/dist/account/index.d.ts +1 -1
  6. package/dist/account/index.d.ts.map +1 -1
  7. package/dist/account/schema.d.ts +23 -7
  8. package/dist/account/schema.d.ts.map +1 -1
  9. package/dist/account/schema.js +84 -27
  10. package/dist/account/schema.js.map +1 -1
  11. package/dist/account/schema.test.js +87 -83
  12. package/dist/account/schema.test.js.map +1 -1
  13. package/dist/account/switch-account.d.ts +2 -2
  14. package/dist/account/switch-account.d.ts.map +1 -1
  15. package/dist/account/switch-account.js +3 -4
  16. package/dist/account/switch-account.js.map +1 -1
  17. package/dist/account/switch-account.test.js +4 -4
  18. package/dist/account/switch-account.test.js.map +1 -1
  19. package/dist/change/apply-changes.d.ts +13 -0
  20. package/dist/change/apply-changes.d.ts.map +1 -1
  21. package/dist/change/apply-changes.js +14 -4
  22. package/dist/change/apply-changes.js.map +1 -1
  23. package/dist/change/apply-changes.test.js +91 -1
  24. package/dist/change/apply-changes.test.js.map +1 -1
  25. package/dist/change/create-change-v2.d.ts +11 -0
  26. package/dist/change/create-change-v2.d.ts.map +1 -0
  27. package/dist/change/create-change-v2.js +31 -0
  28. package/dist/change/create-change-v2.js.map +1 -0
  29. package/dist/change/create-change-v2.test.d.ts +2 -0
  30. package/dist/change/create-change-v2.test.d.ts.map +1 -0
  31. package/dist/change/create-change-v2.test.js +39 -0
  32. package/dist/change/create-change-v2.test.js.map +1 -0
  33. package/dist/change/create-change.d.ts +2 -2
  34. package/dist/change/create-change.d.ts.map +1 -1
  35. package/dist/change/create-change.js +3 -1
  36. package/dist/change/create-change.js.map +1 -1
  37. package/dist/change/create-change.test.js +4 -6
  38. package/dist/change/create-change.test.js.map +1 -1
  39. package/dist/change/index.d.ts +1 -1
  40. package/dist/change/index.d.ts.map +1 -1
  41. package/dist/change/index.js.map +1 -1
  42. package/dist/change/schema.d.ts +40 -2
  43. package/dist/change/schema.d.ts.map +1 -1
  44. package/dist/change/schema.js +50 -9
  45. package/dist/change/schema.js.map +1 -1
  46. package/dist/change/schema.test.js +33 -0
  47. package/dist/change/schema.test.js.map +1 -1
  48. package/dist/change-author/index.d.ts +1 -1
  49. package/dist/change-author/index.d.ts.map +1 -1
  50. package/dist/change-author/index.js +1 -1
  51. package/dist/change-author/index.js.map +1 -1
  52. package/dist/change-author/schema.d.ts +12 -9
  53. package/dist/change-author/schema.d.ts.map +1 -1
  54. package/dist/change-author/schema.js +16 -10
  55. package/dist/change-author/schema.js.map +1 -1
  56. package/dist/change-author/schema.test.js +283 -229
  57. package/dist/change-author/schema.test.js.map +1 -1
  58. package/dist/change-proposal/create-change-proposal.d.ts +3 -3
  59. package/dist/change-proposal/create-change-proposal.d.ts.map +1 -1
  60. package/dist/change-proposal/database-schema.js +1 -1
  61. package/dist/change-set/apply-change-set.d.ts +2 -2
  62. package/dist/change-set/apply-change-set.d.ts.map +1 -1
  63. package/dist/change-set/apply-change-set.js +40 -51
  64. package/dist/change-set/apply-change-set.js.map +1 -1
  65. package/dist/change-set/apply-change-set.test.js +6 -3
  66. package/dist/change-set/apply-change-set.test.js.map +1 -1
  67. package/dist/change-set/before-after-of-file.d.ts +31 -0
  68. package/dist/change-set/before-after-of-file.d.ts.map +1 -0
  69. package/dist/change-set/before-after-of-file.js +191 -0
  70. package/dist/change-set/before-after-of-file.js.map +1 -0
  71. package/dist/change-set/before-after-of-file.test.d.ts +2 -0
  72. package/dist/change-set/before-after-of-file.test.d.ts.map +1 -0
  73. package/dist/change-set/before-after-of-file.test.js +221 -0
  74. package/dist/change-set/before-after-of-file.test.js.map +1 -0
  75. package/dist/change-set/change-set-element-in-symmetric-difference.d.ts +2 -1
  76. package/dist/change-set/change-set-element-in-symmetric-difference.d.ts.map +1 -1
  77. package/dist/change-set/change-set-element-in-symmetric-difference.js.map +1 -1
  78. package/dist/change-set/change-set-element-in-symmetric-difference.test.js +204 -34
  79. package/dist/change-set/change-set-element-in-symmetric-difference.test.js.map +1 -1
  80. package/dist/change-set/checkout-change-set.d.ts +15 -0
  81. package/dist/change-set/checkout-change-set.d.ts.map +1 -0
  82. package/dist/change-set/checkout-change-set.js +64 -0
  83. package/dist/change-set/checkout-change-set.js.map +1 -0
  84. package/dist/change-set/checkout-change-set.test.d.ts +2 -0
  85. package/dist/change-set/checkout-change-set.test.d.ts.map +1 -0
  86. package/dist/change-set/checkout-change-set.test.js +127 -0
  87. package/dist/change-set/checkout-change-set.test.js.map +1 -0
  88. package/dist/change-set/create-change-set.d.ts +7 -9
  89. package/dist/change-set/create-change-set.d.ts.map +1 -1
  90. package/dist/change-set/create-change-set.js +3 -25
  91. package/dist/change-set/create-change-set.js.map +1 -1
  92. package/dist/change-set/create-change-set.test.js +0 -31
  93. package/dist/change-set/create-change-set.test.js.map +1 -1
  94. package/dist/change-set/create-checkpoint.d.ts.map +1 -1
  95. package/dist/change-set/create-checkpoint.js +11 -2
  96. package/dist/change-set/create-checkpoint.js.map +1 -1
  97. package/dist/change-set/create-checkpoint.test.js +53 -0
  98. package/dist/change-set/create-checkpoint.test.js.map +1 -1
  99. package/dist/change-set/create-merge-change-set.d.ts +4 -4
  100. package/dist/change-set/create-merge-change-set.d.ts.map +1 -1
  101. package/dist/change-set/create-transition-change-set.d.ts +4 -4
  102. package/dist/change-set/create-transition-change-set.d.ts.map +1 -1
  103. package/dist/change-set/create-undo-change-set.d.ts +5 -5
  104. package/dist/change-set/create-undo-change-set.d.ts.map +1 -1
  105. package/dist/change-set/create-undo-change-set.js +4 -3
  106. package/dist/change-set/create-undo-change-set.js.map +1 -1
  107. package/dist/change-set/database-schema.d.ts +39 -0
  108. package/dist/change-set/database-schema.d.ts.map +1 -0
  109. package/dist/change-set/database-schema.js +86 -0
  110. package/dist/change-set/database-schema.js.map +1 -0
  111. package/dist/change-set/database-schema.test.d.ts +2 -0
  112. package/dist/change-set/database-schema.test.d.ts.map +1 -0
  113. package/dist/change-set/database-schema.test.js +547 -0
  114. package/dist/change-set/database-schema.test.js.map +1 -0
  115. package/dist/change-set/diff-for-file.d.ts +29 -0
  116. package/dist/change-set/diff-for-file.d.ts.map +1 -0
  117. package/dist/change-set/diff-for-file.js +19 -0
  118. package/dist/change-set/diff-for-file.js.map +1 -0
  119. package/dist/change-set/get-before-after-of-file.d.ts +31 -0
  120. package/dist/change-set/get-before-after-of-file.d.ts.map +1 -0
  121. package/dist/change-set/get-before-after-of-file.js +189 -0
  122. package/dist/change-set/get-before-after-of-file.js.map +1 -0
  123. package/dist/change-set/get-before-after-of-file.test.d.ts +2 -0
  124. package/dist/change-set/get-before-after-of-file.test.d.ts.map +1 -0
  125. package/dist/change-set/get-before-after-of-file.test.js +220 -0
  126. package/dist/change-set/get-before-after-of-file.test.js.map +1 -0
  127. package/dist/change-set/index.d.ts +1 -5
  128. package/dist/change-set/index.d.ts.map +1 -1
  129. package/dist/change-set/index.js +1 -5
  130. package/dist/change-set/index.js.map +1 -1
  131. package/dist/change-set/merge-change-sets.d.ts +23 -0
  132. package/dist/change-set/merge-change-sets.d.ts.map +1 -0
  133. package/dist/change-set/merge-change-sets.js +69 -0
  134. package/dist/change-set/merge-change-sets.js.map +1 -0
  135. package/dist/change-set/merge-change-sets.test.d.ts +2 -0
  136. package/dist/change-set/merge-change-sets.test.d.ts.map +1 -0
  137. package/dist/change-set/merge-change-sets.test.js +184 -0
  138. package/dist/change-set/merge-change-sets.test.js.map +1 -0
  139. package/dist/change-set/restore-change-set.d.ts +14 -0
  140. package/dist/change-set/restore-change-set.d.ts.map +1 -0
  141. package/dist/change-set/restore-change-set.js +98 -0
  142. package/dist/change-set/restore-change-set.js.map +1 -0
  143. package/dist/change-set/restore-change-set.test.d.ts +2 -0
  144. package/dist/change-set/restore-change-set.test.d.ts.map +1 -0
  145. package/dist/change-set/restore-change-set.test.js +238 -0
  146. package/dist/change-set/restore-change-set.test.js.map +1 -0
  147. package/dist/change-set/schema.d.ts +28 -72
  148. package/dist/change-set/schema.d.ts.map +1 -1
  149. package/dist/change-set/schema.js +37 -84
  150. package/dist/change-set/schema.js.map +1 -1
  151. package/dist/change-set/schema.test.js +0 -247
  152. package/dist/change-set/schema.test.js.map +1 -1
  153. package/dist/change-set-edge/database-schema.d.ts +11 -0
  154. package/dist/change-set-edge/database-schema.d.ts.map +1 -0
  155. package/dist/change-set-edge/database-schema.js +29 -0
  156. package/dist/change-set-edge/database-schema.js.map +1 -0
  157. package/dist/change-set-edge/database-schema.test.d.ts +2 -0
  158. package/dist/change-set-edge/database-schema.test.d.ts.map +1 -0
  159. package/dist/change-set-edge/database-schema.test.js +166 -0
  160. package/dist/change-set-edge/database-schema.test.js.map +1 -0
  161. package/dist/change-set-edge/index.d.ts +2 -0
  162. package/dist/change-set-edge/index.d.ts.map +1 -0
  163. package/dist/change-set-edge/index.js +2 -0
  164. package/dist/change-set-edge/index.js.map +1 -0
  165. package/dist/change-set-v2/apply-change-set.d.ts +10 -0
  166. package/dist/change-set-v2/apply-change-set.d.ts.map +1 -0
  167. package/dist/change-set-v2/apply-change-set.js +147 -0
  168. package/dist/change-set-v2/apply-change-set.js.map +1 -0
  169. package/dist/change-set-v2/apply-change-set.test.d.ts +2 -0
  170. package/dist/change-set-v2/apply-change-set.test.d.ts.map +1 -0
  171. package/dist/change-set-v2/apply-change-set.test.js +270 -0
  172. package/dist/change-set-v2/apply-change-set.test.js.map +1 -0
  173. package/dist/change-set-v2/create-change-set.d.ts +10 -0
  174. package/dist/change-set-v2/create-change-set.d.ts.map +1 -0
  175. package/dist/change-set-v2/create-change-set.js +57 -0
  176. package/dist/change-set-v2/create-change-set.js.map +1 -0
  177. package/dist/change-set-v2/create-change-set.test.d.ts +2 -0
  178. package/dist/change-set-v2/create-change-set.test.d.ts.map +1 -0
  179. package/dist/change-set-v2/create-change-set.test.js +59 -0
  180. package/dist/change-set-v2/create-change-set.test.js.map +1 -0
  181. package/dist/change-set-v2/create-checkpoint.d.ts +7 -0
  182. package/dist/change-set-v2/create-checkpoint.d.ts.map +1 -0
  183. package/dist/change-set-v2/create-checkpoint.js +79 -0
  184. package/dist/change-set-v2/create-checkpoint.js.map +1 -0
  185. package/dist/change-set-v2/create-checkpoint.test.d.ts +2 -0
  186. package/dist/change-set-v2/create-checkpoint.test.d.ts.map +1 -0
  187. package/dist/change-set-v2/create-checkpoint.test.js +289 -0
  188. package/dist/change-set-v2/create-checkpoint.test.js.map +1 -0
  189. package/dist/change-set-v2/create-merge-change-set.d.ts +23 -0
  190. package/dist/change-set-v2/create-merge-change-set.d.ts.map +1 -0
  191. package/dist/change-set-v2/create-merge-change-set.js +68 -0
  192. package/dist/change-set-v2/create-merge-change-set.js.map +1 -0
  193. package/dist/change-set-v2/create-merge-change-set.test.d.ts +2 -0
  194. package/dist/change-set-v2/create-merge-change-set.test.d.ts.map +1 -0
  195. package/dist/change-set-v2/create-merge-change-set.test.js +223 -0
  196. package/dist/change-set-v2/create-merge-change-set.test.js.map +1 -0
  197. package/dist/change-set-v2/index.d.ts +5 -0
  198. package/dist/change-set-v2/index.d.ts.map +1 -0
  199. package/dist/change-set-v2/index.js +5 -0
  200. package/dist/change-set-v2/index.js.map +1 -0
  201. package/dist/change-set-v2/schema.d.ts +50 -0
  202. package/dist/change-set-v2/schema.d.ts.map +1 -0
  203. package/dist/change-set-v2/schema.js +347 -0
  204. package/dist/change-set-v2/schema.js.map +1 -0
  205. package/dist/change-set-v2/schema.test.d.ts +2 -0
  206. package/dist/change-set-v2/schema.test.d.ts.map +1 -0
  207. package/dist/change-set-v2/schema.test.js +713 -0
  208. package/dist/change-set-v2/schema.test.js.map +1 -0
  209. package/dist/commit/apply-commit.d.ts +32 -0
  210. package/dist/commit/apply-commit.d.ts.map +1 -0
  211. package/dist/commit/apply-commit.js +63 -0
  212. package/dist/commit/apply-commit.js.map +1 -0
  213. package/dist/commit/apply-commit.test.d.ts +2 -0
  214. package/dist/commit/apply-commit.test.d.ts.map +1 -0
  215. package/dist/commit/apply-commit.test.js +367 -0
  216. package/dist/commit/apply-commit.test.js.map +1 -0
  217. package/dist/commit/create-checkpoint.d.ts +19 -0
  218. package/dist/commit/create-checkpoint.d.ts.map +1 -0
  219. package/dist/commit/create-checkpoint.js +118 -0
  220. package/dist/commit/create-checkpoint.js.map +1 -0
  221. package/dist/commit/create-checkpoint.test.d.ts +2 -0
  222. package/dist/commit/create-checkpoint.test.d.ts.map +1 -0
  223. package/dist/commit/create-checkpoint.test.js +472 -0
  224. package/dist/commit/create-checkpoint.test.js.map +1 -0
  225. package/dist/commit/create-commit.d.ts +38 -0
  226. package/dist/commit/create-commit.d.ts.map +1 -0
  227. package/dist/commit/create-commit.js +68 -0
  228. package/dist/commit/create-commit.js.map +1 -0
  229. package/dist/commit/create-merge-commit.d.ts +24 -0
  230. package/dist/commit/create-merge-commit.d.ts.map +1 -0
  231. package/dist/commit/create-merge-commit.js +103 -0
  232. package/dist/commit/create-merge-commit.js.map +1 -0
  233. package/dist/commit/create-merge-commit.test.d.ts +2 -0
  234. package/dist/commit/create-merge-commit.test.d.ts.map +1 -0
  235. package/dist/commit/create-merge-commit.test.js +242 -0
  236. package/dist/commit/create-merge-commit.test.js.map +1 -0
  237. package/dist/commit/create-transition-commit.d.ts +18 -0
  238. package/dist/commit/create-transition-commit.d.ts.map +1 -0
  239. package/dist/commit/create-transition-commit.js +136 -0
  240. package/dist/commit/create-transition-commit.js.map +1 -0
  241. package/dist/commit/create-transition-commit.test.d.ts +2 -0
  242. package/dist/commit/create-transition-commit.test.d.ts.map +1 -0
  243. package/dist/commit/create-transition-commit.test.js +221 -0
  244. package/dist/commit/create-transition-commit.test.js.map +1 -0
  245. package/dist/commit/create-undo-commit.d.ts +27 -0
  246. package/dist/commit/create-undo-commit.d.ts.map +1 -0
  247. package/dist/commit/create-undo-commit.js +143 -0
  248. package/dist/commit/create-undo-commit.js.map +1 -0
  249. package/dist/commit/create-undo-commit.test.d.ts +2 -0
  250. package/dist/commit/create-undo-commit.test.d.ts.map +1 -0
  251. package/dist/commit/create-undo-commit.test.js +298 -0
  252. package/dist/commit/create-undo-commit.test.js.map +1 -0
  253. package/dist/commit/index.d.ts +6 -0
  254. package/dist/commit/index.d.ts.map +1 -0
  255. package/dist/commit/index.js +6 -0
  256. package/dist/commit/index.js.map +1 -0
  257. package/dist/commit/schema.d.ts +73 -0
  258. package/dist/commit/schema.d.ts.map +1 -0
  259. package/dist/commit/schema.js +90 -0
  260. package/dist/commit/schema.js.map +1 -0
  261. package/dist/commit/schema.test.d.ts +2 -0
  262. package/dist/commit/schema.test.d.ts.map +1 -0
  263. package/dist/commit/schema.test.js +216 -0
  264. package/dist/commit/schema.test.js.map +1 -0
  265. package/dist/database/apply-schema.d.ts +3 -0
  266. package/dist/database/apply-schema.d.ts.map +1 -1
  267. package/dist/database/apply-schema.js +91 -258
  268. package/dist/database/apply-schema.js.map +1 -1
  269. package/dist/database/index.d.ts +0 -2
  270. package/dist/database/index.d.ts.map +1 -1
  271. package/dist/database/index.js +0 -2
  272. package/dist/database/index.js.map +1 -1
  273. package/dist/database/init-db.d.ts.map +1 -1
  274. package/dist/database/init-db.js +83 -44
  275. package/dist/database/init-db.js.map +1 -1
  276. package/dist/database/init-db.test.js +2 -480
  277. package/dist/database/init-db.test.js.map +1 -1
  278. package/dist/database/kysely-plugin/json-column-plugin.d.ts +5 -1
  279. package/dist/database/kysely-plugin/json-column-plugin.d.ts.map +1 -1
  280. package/dist/database/kysely-plugin/json-column-plugin.js +52 -10
  281. package/dist/database/kysely-plugin/json-column-plugin.js.map +1 -1
  282. package/dist/database/kysely-plugin/json-column-plugin.test.d.ts +2 -0
  283. package/dist/database/kysely-plugin/json-column-plugin.test.d.ts.map +1 -0
  284. package/dist/database/kysely-plugin/json-column-plugin.test.js +329 -0
  285. package/dist/database/kysely-plugin/json-column-plugin.test.js.map +1 -0
  286. package/dist/database/mutation-log/database-schema.d.ts.map +1 -1
  287. package/dist/database/mutation-log/database-schema.js +0 -4
  288. package/dist/database/mutation-log/database-schema.js.map +1 -1
  289. package/dist/database/nano-id.d.ts +4 -1
  290. package/dist/database/nano-id.d.ts.map +1 -1
  291. package/dist/database/nano-id.js +4 -1
  292. package/dist/database/nano-id.js.map +1 -1
  293. package/dist/database/nano-id.test.js +3 -3
  294. package/dist/database/nano-id.test.js.map +1 -1
  295. package/dist/database/schema.d.ts +21 -14
  296. package/dist/database/schema.d.ts.map +1 -1
  297. package/dist/database/schema.js +9 -5
  298. package/dist/database/schema.js.map +1 -1
  299. package/dist/deterministic/generate-human-id.d.ts +20 -0
  300. package/dist/deterministic/generate-human-id.d.ts.map +1 -0
  301. package/dist/deterministic/generate-human-id.js +86 -0
  302. package/dist/deterministic/generate-human-id.js.map +1 -0
  303. package/dist/deterministic/generate-human-id.test.d.ts +2 -0
  304. package/dist/deterministic/generate-human-id.test.d.ts.map +1 -0
  305. package/dist/deterministic/generate-human-id.test.js +123 -0
  306. package/dist/deterministic/generate-human-id.test.js.map +1 -0
  307. package/dist/deterministic/index.d.ts +8 -0
  308. package/dist/deterministic/index.d.ts.map +1 -0
  309. package/dist/deterministic/index.js +8 -0
  310. package/dist/deterministic/index.js.map +1 -0
  311. package/dist/deterministic/is-deterministic-mode.d.ts +14 -0
  312. package/dist/deterministic/is-deterministic-mode.d.ts.map +1 -0
  313. package/dist/deterministic/is-deterministic-mode.js +25 -0
  314. package/dist/deterministic/is-deterministic-mode.js.map +1 -0
  315. package/dist/deterministic/is-deterministic-mode.test.d.ts +2 -0
  316. package/dist/deterministic/is-deterministic-mode.test.d.ts.map +1 -0
  317. package/dist/deterministic/is-deterministic-mode.test.js +103 -0
  318. package/dist/deterministic/is-deterministic-mode.test.js.map +1 -0
  319. package/dist/deterministic/nano-id.d.ts +61 -0
  320. package/dist/deterministic/nano-id.d.ts.map +1 -0
  321. package/dist/deterministic/nano-id.js +161 -0
  322. package/dist/deterministic/nano-id.js.map +1 -0
  323. package/dist/deterministic/nano-id.test.d.ts +2 -0
  324. package/dist/deterministic/nano-id.test.d.ts.map +1 -0
  325. package/dist/deterministic/nano-id.test.js +163 -0
  326. package/dist/deterministic/nano-id.test.js.map +1 -0
  327. package/dist/deterministic/options.d.ts +53 -0
  328. package/dist/deterministic/options.d.ts.map +1 -0
  329. package/dist/deterministic/options.js +52 -0
  330. package/dist/deterministic/options.js.map +1 -0
  331. package/dist/deterministic/options.test.d.ts +2 -0
  332. package/dist/deterministic/options.test.d.ts.map +1 -0
  333. package/dist/deterministic/options.test.js +111 -0
  334. package/dist/deterministic/options.test.js.map +1 -0
  335. package/dist/deterministic/random.d.ts +68 -0
  336. package/dist/deterministic/random.d.ts.map +1 -0
  337. package/dist/deterministic/random.js +225 -0
  338. package/dist/deterministic/random.js.map +1 -0
  339. package/dist/deterministic/random.test.d.ts +2 -0
  340. package/dist/deterministic/random.test.d.ts.map +1 -0
  341. package/dist/deterministic/random.test.js +244 -0
  342. package/dist/deterministic/random.test.js.map +1 -0
  343. package/dist/deterministic/sequence.d.ts +56 -0
  344. package/dist/deterministic/sequence.d.ts.map +1 -0
  345. package/dist/deterministic/sequence.js +107 -0
  346. package/dist/deterministic/sequence.js.map +1 -0
  347. package/dist/deterministic/sequence.test.d.ts +2 -0
  348. package/dist/deterministic/sequence.test.d.ts.map +1 -0
  349. package/dist/deterministic/sequence.test.js +71 -0
  350. package/dist/deterministic/sequence.test.js.map +1 -0
  351. package/dist/deterministic/timestamp.d.ts +47 -0
  352. package/dist/deterministic/timestamp.d.ts.map +1 -0
  353. package/dist/deterministic/timestamp.js +74 -0
  354. package/dist/deterministic/timestamp.js.map +1 -0
  355. package/dist/deterministic/timestamp.test.d.ts +2 -0
  356. package/dist/deterministic/timestamp.test.d.ts.map +1 -0
  357. package/dist/deterministic/timestamp.test.js +145 -0
  358. package/dist/deterministic/timestamp.test.js.map +1 -0
  359. package/dist/deterministic/uuid-v7.d.ts +49 -0
  360. package/dist/deterministic/uuid-v7.d.ts.map +1 -0
  361. package/dist/deterministic/uuid-v7.js +75 -0
  362. package/dist/deterministic/uuid-v7.js.map +1 -0
  363. package/dist/deterministic/uuid-v7.test.d.ts +2 -0
  364. package/dist/deterministic/uuid-v7.test.d.ts.map +1 -0
  365. package/dist/deterministic/uuid-v7.test.js +114 -0
  366. package/dist/deterministic/uuid-v7.test.js.map +1 -0
  367. package/dist/discussion/create-discussion.d.ts +2 -1
  368. package/dist/discussion/create-discussion.d.ts.map +1 -1
  369. package/dist/discussion/create-discussion.js.map +1 -1
  370. package/dist/discussion/create-discussion.test.js +13 -2
  371. package/dist/discussion/create-discussion.test.js.map +1 -1
  372. package/dist/entity/eb-entity.d.ts +76 -0
  373. package/dist/entity/eb-entity.d.ts.map +1 -0
  374. package/dist/entity/eb-entity.js +156 -0
  375. package/dist/entity/eb-entity.js.map +1 -0
  376. package/dist/entity/eb-entity.test.d.ts +2 -0
  377. package/dist/entity/eb-entity.test.d.ts.map +1 -0
  378. package/dist/entity/eb-entity.test.js +573 -0
  379. package/dist/entity/eb-entity.test.js.map +1 -0
  380. package/dist/entity/index.d.ts +7 -0
  381. package/dist/entity/index.d.ts.map +1 -0
  382. package/dist/entity/index.js +4 -0
  383. package/dist/entity/index.js.map +1 -0
  384. package/dist/entity/label/create-entity-label.d.ts +61 -0
  385. package/dist/entity/label/create-entity-label.d.ts.map +1 -0
  386. package/dist/entity/label/create-entity-label.js +92 -0
  387. package/dist/entity/label/create-entity-label.js.map +1 -0
  388. package/dist/entity/label/create-entity-label.test.d.ts +2 -0
  389. package/dist/entity/label/create-entity-label.test.d.ts.map +1 -0
  390. package/dist/entity/label/create-entity-label.test.js +261 -0
  391. package/dist/entity/label/create-entity-label.test.js.map +1 -0
  392. package/dist/entity/label/schema.d.ts +40 -0
  393. package/dist/entity/label/schema.d.ts.map +1 -0
  394. package/dist/entity/label/schema.js +42 -0
  395. package/dist/entity/label/schema.js.map +1 -0
  396. package/dist/entity/label/schema.test.d.ts +2 -0
  397. package/dist/entity/label/schema.test.d.ts.map +1 -0
  398. package/dist/entity/label/schema.test.js +596 -0
  399. package/dist/entity/label/schema.test.js.map +1 -0
  400. package/dist/entity/schema.d.ts +13 -0
  401. package/dist/entity/schema.d.ts.map +1 -0
  402. package/dist/entity/schema.js +5 -0
  403. package/dist/entity/schema.js.map +1 -0
  404. package/dist/entity/thread/create-entity-thread.d.ts +75 -0
  405. package/dist/entity/thread/create-entity-thread.d.ts.map +1 -0
  406. package/dist/entity/thread/create-entity-thread.js +109 -0
  407. package/dist/entity/thread/create-entity-thread.js.map +1 -0
  408. package/dist/entity/thread/create-entity-thread.test.d.ts +2 -0
  409. package/dist/entity/thread/create-entity-thread.test.d.ts.map +1 -0
  410. package/dist/entity/thread/create-entity-thread.test.js +240 -0
  411. package/dist/entity/thread/create-entity-thread.test.js.map +1 -0
  412. package/dist/entity/thread/query-threads.test.d.ts +2 -0
  413. package/dist/entity/thread/query-threads.test.d.ts.map +1 -0
  414. package/dist/entity/thread/query-threads.test.js +330 -0
  415. package/dist/entity/thread/query-threads.test.js.map +1 -0
  416. package/dist/entity/thread/schema.d.ts +40 -0
  417. package/dist/entity/thread/schema.d.ts.map +1 -0
  418. package/dist/entity/thread/schema.js +42 -0
  419. package/dist/entity/thread/schema.js.map +1 -0
  420. package/dist/entity/thread/schema.test.d.ts +2 -0
  421. package/dist/entity/thread/schema.test.d.ts.map +1 -0
  422. package/dist/entity/thread/schema.test.js +144 -0
  423. package/dist/entity/thread/schema.test.js.map +1 -0
  424. package/dist/entity-views/entity-state-all.d.ts +52 -0
  425. package/dist/entity-views/entity-state-all.d.ts.map +1 -1
  426. package/dist/entity-views/entity-state-all.js +19 -11
  427. package/dist/entity-views/entity-state-all.js.map +1 -1
  428. package/dist/entity-views/entity-state-all.test.js +173 -0
  429. package/dist/entity-views/entity-state-all.test.js.map +1 -1
  430. package/dist/entity-views/entity-state-history.d.ts +55 -15
  431. package/dist/entity-views/entity-state-history.d.ts.map +1 -1
  432. package/dist/entity-views/entity-state-history.js +7 -4
  433. package/dist/entity-views/entity-state-history.js.map +1 -1
  434. package/dist/entity-views/entity-state-history.test.js +70 -15
  435. package/dist/entity-views/entity-state-history.test.js.map +1 -1
  436. package/dist/entity-views/entity-state.d.ts +52 -0
  437. package/dist/entity-views/entity-state.d.ts.map +1 -1
  438. package/dist/entity-views/entity-state.js +18 -10
  439. package/dist/entity-views/entity-state.js.map +1 -1
  440. package/dist/entity-views/entity-state.test.js +120 -1
  441. package/dist/entity-views/entity-state.test.js.map +1 -1
  442. package/dist/entity-views/entity-view-builder.test.js +6 -6
  443. package/dist/entity-views/entity-view-builder.test.js.map +1 -1
  444. package/dist/entity-views/types.d.ts +2 -2
  445. package/dist/file/database-schema.d.ts +25 -0
  446. package/dist/file/database-schema.d.ts.map +1 -0
  447. package/dist/file/database-schema.js +26 -0
  448. package/dist/file/database-schema.js.map +1 -0
  449. package/dist/file/database-schema.test.d.ts +2 -0
  450. package/dist/file/database-schema.test.d.ts.map +1 -0
  451. package/dist/file/database-schema.test.js +60 -0
  452. package/dist/file/database-schema.test.js.map +1 -0
  453. package/dist/file/file-handlers.d.ts.map +1 -1
  454. package/dist/file/file-handlers.js +36 -0
  455. package/dist/file/file-handlers.js.map +1 -1
  456. package/dist/file/file-handlers.test.js +4 -4
  457. package/dist/file/file-handlers.test.js.map +1 -1
  458. package/dist/file/materialize-file-data-at-changeset.d.ts +1 -1
  459. package/dist/file/materialize-file-data-at-changeset.d.ts.map +1 -1
  460. package/dist/file/materialize-file-data-at-changeset.js +55 -29
  461. package/dist/file/materialize-file-data-at-changeset.js.map +1 -1
  462. package/dist/file/materialize-file-data-at-commit.d.ts +9 -0
  463. package/dist/file/materialize-file-data-at-commit.d.ts.map +1 -0
  464. package/dist/file/materialize-file-data-at-commit.js +119 -0
  465. package/dist/file/materialize-file-data-at-commit.js.map +1 -0
  466. package/dist/file/schema.d.ts +68 -5
  467. package/dist/file/schema.d.ts.map +1 -1
  468. package/dist/file/schema.js +118 -50
  469. package/dist/file/schema.js.map +1 -1
  470. package/dist/file/schema.test.js +543 -35
  471. package/dist/file/schema.test.js.map +1 -1
  472. package/dist/file-queue/database-schema.d.ts +17 -0
  473. package/dist/file-queue/database-schema.d.ts.map +1 -0
  474. package/dist/file-queue/database-schema.js +53 -0
  475. package/dist/file-queue/database-schema.js.map +1 -0
  476. package/dist/file-queue/file-handlers.d.ts +1 -1
  477. package/dist/file-queue/file-handlers.d.ts.map +1 -1
  478. package/dist/file-queue/file-handlers.js +60 -29
  479. package/dist/file-queue/file-handlers.js.map +1 -1
  480. package/dist/file-queue/file-queue-process.d.ts.map +1 -1
  481. package/dist/file-queue/file-queue-process.js +26 -17
  482. package/dist/file-queue/file-queue-process.js.map +1 -1
  483. package/dist/file-queue/file-queue-process.test.js +133 -43
  484. package/dist/file-queue/file-queue-process.test.js.map +1 -1
  485. package/dist/file-queue/with-skip-file-queue.d.ts +18 -0
  486. package/dist/file-queue/with-skip-file-queue.d.ts.map +1 -1
  487. package/dist/file-queue/with-skip-file-queue.js +56 -10
  488. package/dist/file-queue/with-skip-file-queue.js.map +1 -1
  489. package/dist/file-queue/with-skip-file-queue.test.js +28 -12
  490. package/dist/file-queue/with-skip-file-queue.test.js.map +1 -1
  491. package/dist/hooks/create-hooks.d.ts +4 -26
  492. package/dist/hooks/create-hooks.d.ts.map +1 -1
  493. package/dist/hooks/create-hooks.js +3 -7
  494. package/dist/hooks/create-hooks.js.map +1 -1
  495. package/dist/index.d.ts +3 -0
  496. package/dist/index.d.ts.map +1 -1
  497. package/dist/index.js +3 -0
  498. package/dist/index.js.map +1 -1
  499. package/dist/key-value/database-schema.d.ts +3 -2
  500. package/dist/key-value/database-schema.d.ts.map +1 -1
  501. package/dist/key-value/database-schema.js +3 -3
  502. package/dist/key-value/database-schema.test.js +13 -4
  503. package/dist/key-value/database-schema.test.js.map +1 -1
  504. package/dist/key-value/index.d.ts +1 -1
  505. package/dist/key-value/index.d.ts.map +1 -1
  506. package/dist/key-value/index.js.map +1 -1
  507. package/dist/key-value/schema.d.ts +63 -3
  508. package/dist/key-value/schema.d.ts.map +1 -1
  509. package/dist/key-value/schema.js +8 -2
  510. package/dist/key-value/schema.js.map +1 -1
  511. package/dist/key-value/schema.test.js +91 -2
  512. package/dist/key-value/schema.test.js.map +1 -1
  513. package/dist/key-value-v2/schema.d.ts +27 -0
  514. package/dist/key-value-v2/schema.d.ts.map +1 -0
  515. package/dist/key-value-v2/schema.js +73 -0
  516. package/dist/key-value-v2/schema.js.map +1 -0
  517. package/dist/key-value-v2/schema.test.d.ts +2 -0
  518. package/dist/key-value-v2/schema.test.d.ts.map +1 -0
  519. package/dist/key-value-v2/schema.test.js +144 -0
  520. package/dist/key-value-v2/schema.test.js.map +1 -0
  521. package/dist/label/create-label.d.ts +5 -5
  522. package/dist/label/create-label.d.ts.map +1 -1
  523. package/dist/label/create-label.js +2 -2
  524. package/dist/label/create-label.js.map +1 -1
  525. package/dist/label/index.d.ts +1 -1
  526. package/dist/label/index.d.ts.map +1 -1
  527. package/dist/label/index.js.map +1 -1
  528. package/dist/label/schema.d.ts +3 -3
  529. package/dist/label/schema.d.ts.map +1 -1
  530. package/dist/label/schema.js +4 -6
  531. package/dist/label/schema.js.map +1 -1
  532. package/dist/lix/close-lix.d.ts +1 -10
  533. package/dist/lix/close-lix.d.ts.map +1 -1
  534. package/dist/lix/close-lix.js +1 -10
  535. package/dist/lix/close-lix.js.map +1 -1
  536. package/dist/lix/merge.test.js +4 -1
  537. package/dist/lix/merge.test.js.map +1 -1
  538. package/dist/lix/new-lix.d.ts +4 -2
  539. package/dist/lix/new-lix.d.ts.map +1 -1
  540. package/dist/lix/new-lix.js +244 -60
  541. package/dist/lix/new-lix.js.map +1 -1
  542. package/dist/lix/new-lix.test.js +175 -1
  543. package/dist/lix/new-lix.test.js.map +1 -1
  544. package/dist/lix/open-lix-in-memory.d.ts +1 -9
  545. package/dist/lix/open-lix-in-memory.d.ts.map +1 -1
  546. package/dist/lix/open-lix-in-memory.js +7 -15
  547. package/dist/lix/open-lix-in-memory.js.map +1 -1
  548. package/dist/lix/open-lix-in-memory.test.js +2 -1
  549. package/dist/lix/open-lix-in-memory.test.js.map +1 -1
  550. package/dist/lix/open-lix.d.ts +12 -13
  551. package/dist/lix/open-lix.d.ts.map +1 -1
  552. package/dist/lix/open-lix.js +147 -55
  553. package/dist/lix/open-lix.js.map +1 -1
  554. package/dist/lix/open-lix.test.js +242 -3
  555. package/dist/lix/open-lix.test.js.map +1 -1
  556. package/dist/lix/storage/in-memory.d.ts +7 -6
  557. package/dist/lix/storage/in-memory.d.ts.map +1 -1
  558. package/dist/lix/storage/in-memory.js +10 -17
  559. package/dist/lix/storage/in-memory.js.map +1 -1
  560. package/dist/lix/storage/in-memory.test.js +7 -68
  561. package/dist/lix/storage/in-memory.test.js.map +1 -1
  562. package/dist/lix/storage/lix-storage-adapter.d.ts +35 -5
  563. package/dist/lix/storage/lix-storage-adapter.d.ts.map +1 -1
  564. package/dist/lix/storage/opfs.d.ts +39 -10
  565. package/dist/lix/storage/opfs.d.ts.map +1 -1
  566. package/dist/lix/storage/opfs.js +148 -37
  567. package/dist/lix/storage/opfs.js.map +1 -1
  568. package/dist/lix/storage/opfs.test.js +203 -24
  569. package/dist/lix/storage/opfs.test.js.map +1 -1
  570. package/dist/lix/to-blob.d.ts +2 -9
  571. package/dist/lix/to-blob.d.ts.map +1 -1
  572. package/dist/lix/to-blob.js +2 -9
  573. package/dist/lix/to-blob.js.map +1 -1
  574. package/dist/log/create-lix-own-log.d.ts +9 -1
  575. package/dist/log/create-lix-own-log.d.ts.map +1 -1
  576. package/dist/log/create-lix-own-log.js +14 -25
  577. package/dist/log/create-lix-own-log.js.map +1 -1
  578. package/dist/log/create-lix-own-log.test.js +9 -5
  579. package/dist/log/create-lix-own-log.test.js.map +1 -1
  580. package/dist/log/create-log.d.ts +2 -2
  581. package/dist/log/create-log.d.ts.map +1 -1
  582. package/dist/log/create-log.js +2 -2
  583. package/dist/log/create-log.js.map +1 -1
  584. package/dist/log/database-schema.d.ts +33 -0
  585. package/dist/log/database-schema.d.ts.map +1 -0
  586. package/dist/log/database-schema.js +14 -0
  587. package/dist/log/database-schema.js.map +1 -0
  588. package/dist/log/database-schema.test.d.ts +2 -0
  589. package/dist/log/database-schema.test.d.ts.map +1 -0
  590. package/dist/log/database-schema.test.js +22 -0
  591. package/dist/log/database-schema.test.js.map +1 -0
  592. package/dist/log/index.d.ts +1 -1
  593. package/dist/log/index.d.ts.map +1 -1
  594. package/dist/log/index.js.map +1 -1
  595. package/dist/log/schema.d.ts +3 -3
  596. package/dist/log/schema.d.ts.map +1 -1
  597. package/dist/log/schema.js +4 -5
  598. package/dist/log/schema.js.map +1 -1
  599. package/dist/observe/create-observe.d.ts.map +1 -1
  600. package/dist/observe/create-observe.js +32 -3
  601. package/dist/observe/create-observe.js.map +1 -1
  602. package/dist/observe/create-observe.test.js +298 -44
  603. package/dist/observe/create-observe.test.js.map +1 -1
  604. package/dist/observe/determine-schema-keys.d.ts +6 -0
  605. package/dist/observe/determine-schema-keys.d.ts.map +1 -0
  606. package/dist/observe/determine-schema-keys.js +145 -0
  607. package/dist/observe/determine-schema-keys.js.map +1 -0
  608. package/dist/observe/determine-schema-keys.test.d.ts +2 -0
  609. package/dist/observe/determine-schema-keys.test.d.ts.map +1 -0
  610. package/dist/observe/determine-schema-keys.test.js +266 -0
  611. package/dist/observe/determine-schema-keys.test.js.map +1 -0
  612. package/dist/own-change-control/apply-own-change.d.ts +5 -1
  613. package/dist/own-change-control/apply-own-change.d.ts.map +1 -1
  614. package/dist/own-change-control/apply-own-change.js +26 -12
  615. package/dist/own-change-control/apply-own-change.js.map +1 -1
  616. package/dist/own-change-control/apply-own-change.test.js +86 -48
  617. package/dist/own-change-control/apply-own-change.test.js.map +1 -1
  618. package/dist/own-change-control/change-controlled-tables.d.ts +5 -7
  619. package/dist/own-change-control/change-controlled-tables.d.ts.map +1 -1
  620. package/dist/own-change-control/change-controlled-tables.js +27 -21
  621. package/dist/own-change-control/change-controlled-tables.js.map +1 -1
  622. package/dist/own-change-control/change-controlled-tables.test.js +35 -5
  623. package/dist/own-change-control/change-controlled-tables.test.js.map +1 -1
  624. package/dist/own-change-control/database-triggers.d.ts +2 -1
  625. package/dist/own-change-control/database-triggers.d.ts.map +1 -1
  626. package/dist/own-change-control/database-triggers.js +209 -67
  627. package/dist/own-change-control/database-triggers.js.map +1 -1
  628. package/dist/own-change-control/database-triggers.test.js +139 -8
  629. package/dist/own-change-control/database-triggers.test.js.map +1 -1
  630. package/dist/own-change-control/with-skip-own-change-control.d.ts.map +1 -1
  631. package/dist/own-change-control/with-skip-own-change-control.js +28 -6
  632. package/dist/own-change-control/with-skip-own-change-control.js.map +1 -1
  633. package/dist/own-change-control/with-skip-own-change-control.test.js +38 -1
  634. package/dist/own-change-control/with-skip-own-change-control.test.js.map +1 -1
  635. package/dist/plugin/lix-plugin.d.ts +3 -3
  636. package/dist/plugin/lix-plugin.d.ts.map +1 -1
  637. package/dist/plugin/load-plugin.d.ts.map +1 -1
  638. package/dist/plugin/load-plugin.js.map +1 -1
  639. package/dist/prototype/database-schema.d.ts +43 -0
  640. package/dist/prototype/database-schema.d.ts.map +1 -0
  641. package/dist/prototype/database-schema.js +72 -0
  642. package/dist/prototype/database-schema.js.map +1 -0
  643. package/dist/prototype/file-handlers.d.ts +24 -0
  644. package/dist/prototype/file-handlers.d.ts.map +1 -0
  645. package/dist/prototype/file-handlers.js +129 -0
  646. package/dist/prototype/file-handlers.js.map +1 -0
  647. package/dist/prototype/file-schema.d.ts +47 -0
  648. package/dist/prototype/file-schema.d.ts.map +1 -0
  649. package/dist/prototype/file-schema.js +135 -0
  650. package/dist/prototype/file-schema.js.map +1 -0
  651. package/dist/prototype/file-schema.test.d.ts +2 -0
  652. package/dist/prototype/file-schema.test.d.ts.map +1 -0
  653. package/dist/prototype/file-schema.test.js +146 -0
  654. package/dist/prototype/file-schema.test.js.map +1 -0
  655. package/dist/prototype/get-and-materialize-row.d.ts +5 -0
  656. package/dist/prototype/get-and-materialize-row.d.ts.map +1 -0
  657. package/dist/prototype/get-and-materialize-row.js +99 -0
  658. package/dist/prototype/get-and-materialize-row.js.map +1 -0
  659. package/dist/prototype/json-plugin.d.ts +49 -0
  660. package/dist/prototype/json-plugin.d.ts.map +1 -0
  661. package/dist/prototype/json-plugin.js +104 -0
  662. package/dist/prototype/json-plugin.js.map +1 -0
  663. package/dist/prototype/validate-file-path.d.ts +16 -0
  664. package/dist/prototype/validate-file-path.d.ts.map +1 -0
  665. package/dist/prototype/validate-file-path.js +44 -0
  666. package/dist/prototype/validate-file-path.js.map +1 -0
  667. package/dist/prototype/validate-file-path.test.d.ts +2 -0
  668. package/dist/prototype/validate-file-path.test.d.ts.map +1 -0
  669. package/dist/prototype/validate-file-path.test.js +36 -0
  670. package/dist/prototype/validate-file-path.test.js.map +1 -0
  671. package/dist/prototype/version-schema.d.ts +34 -0
  672. package/dist/prototype/version-schema.d.ts.map +1 -0
  673. package/dist/prototype/version-schema.js +86 -0
  674. package/dist/prototype/version-schema.js.map +1 -0
  675. package/dist/prototype/version-schema.test.d.ts +2 -0
  676. package/dist/prototype/version-schema.test.d.ts.map +1 -0
  677. package/dist/prototype/version-schema.test.js +114 -0
  678. package/dist/prototype/version-schema.test.js.map +1 -0
  679. package/dist/query-filter/change-conflict-in-version.d.ts +2 -0
  680. package/dist/query-filter/change-conflict-in-version.d.ts.map +1 -1
  681. package/dist/query-filter/change-conflict-in-version.js +2 -0
  682. package/dist/query-filter/change-conflict-in-version.js.map +1 -1
  683. package/dist/query-filter/change-in-version.d.ts +2 -0
  684. package/dist/query-filter/change-in-version.d.ts.map +1 -1
  685. package/dist/query-filter/change-in-version.js +2 -0
  686. package/dist/query-filter/change-in-version.js.map +1 -1
  687. package/dist/query-filter/change-is-leaf-in-version.d.ts +1 -0
  688. package/dist/query-filter/change-is-leaf-in-version.d.ts.map +1 -1
  689. package/dist/query-filter/change-is-leaf-in-version.js +1 -0
  690. package/dist/query-filter/change-is-leaf-in-version.js.map +1 -1
  691. package/dist/query-filter/change-is-leaf-of.d.ts +2 -0
  692. package/dist/query-filter/change-is-leaf-of.d.ts.map +1 -1
  693. package/dist/query-filter/change-is-leaf-of.js +2 -0
  694. package/dist/query-filter/change-is-leaf-of.js.map +1 -1
  695. package/dist/query-filter/change-is-leaf-v2.d.ts +69 -0
  696. package/dist/query-filter/change-is-leaf-v2.d.ts.map +1 -0
  697. package/dist/query-filter/change-is-leaf-v2.js +116 -0
  698. package/dist/query-filter/change-is-leaf-v2.js.map +1 -0
  699. package/dist/query-filter/change-is-leaf-v2.test.d.ts +2 -0
  700. package/dist/query-filter/change-is-leaf-v2.test.d.ts.map +1 -0
  701. package/dist/query-filter/change-is-leaf-v2.test.js +237 -0
  702. package/dist/query-filter/change-is-leaf-v2.test.js.map +1 -0
  703. package/dist/query-filter/change-is-leaf.d.ts +2 -0
  704. package/dist/query-filter/change-is-leaf.d.ts.map +1 -1
  705. package/dist/query-filter/change-is-leaf.js +2 -0
  706. package/dist/query-filter/change-is-leaf.js.map +1 -1
  707. package/dist/query-filter/change-is-lowest-common-ancestor-of.d.ts +2 -0
  708. package/dist/query-filter/change-is-lowest-common-ancestor-of.d.ts.map +1 -1
  709. package/dist/query-filter/change-is-lowest-common-ancestor-of.js +4 -0
  710. package/dist/query-filter/change-is-lowest-common-ancestor-of.js.map +1 -1
  711. package/dist/query-filter/change-is-lowest-common-ancestor-of.test.js +5 -3
  712. package/dist/query-filter/change-is-lowest-common-ancestor-of.test.js.map +1 -1
  713. package/dist/query-filter/change-set-element-in-ancestry-of.d.ts +10 -10
  714. package/dist/query-filter/change-set-element-in-ancestry-of.d.ts.map +1 -1
  715. package/dist/query-filter/change-set-element-in-ancestry-of.js +22 -17
  716. package/dist/query-filter/change-set-element-in-ancestry-of.js.map +1 -1
  717. package/dist/query-filter/change-set-element-in-ancestry-of.test.js +99 -26
  718. package/dist/query-filter/change-set-element-in-ancestry-of.test.js.map +1 -1
  719. package/dist/query-filter/change-set-element-in-symmetric-difference-of.d.ts +21 -0
  720. package/dist/query-filter/change-set-element-in-symmetric-difference-of.d.ts.map +1 -0
  721. package/dist/query-filter/change-set-element-in-symmetric-difference-of.js +37 -0
  722. package/dist/query-filter/change-set-element-in-symmetric-difference-of.js.map +1 -0
  723. package/dist/query-filter/change-set-element-in-symmetric-difference-of.test.d.ts +2 -0
  724. package/dist/query-filter/change-set-element-in-symmetric-difference-of.test.d.ts.map +1 -0
  725. package/dist/query-filter/change-set-element-in-symmetric-difference-of.test.js +276 -0
  726. package/dist/query-filter/change-set-element-in-symmetric-difference-of.test.js.map +1 -0
  727. package/dist/query-filter/change-set-element-in-symmetric-difference.d.ts +2 -2
  728. package/dist/query-filter/change-set-element-in-symmetric-difference.d.ts.map +1 -1
  729. package/dist/query-filter/change-set-element-in-symmetric-difference.js.map +1 -1
  730. package/dist/query-filter/change-set-element-in-symmetric-difference.test.js.map +1 -1
  731. package/dist/query-filter/change-set-element-is-leaf-of.d.ts +11 -11
  732. package/dist/query-filter/change-set-element-is-leaf-of.d.ts.map +1 -1
  733. package/dist/query-filter/change-set-element-is-leaf-of.js +58 -36
  734. package/dist/query-filter/change-set-element-is-leaf-of.js.map +1 -1
  735. package/dist/query-filter/change-set-element-is-leaf-of.test.js +83 -24
  736. package/dist/query-filter/change-set-element-is-leaf-of.test.js.map +1 -1
  737. package/dist/query-filter/change-set-is-ancestor-of.d.ts +2 -2
  738. package/dist/query-filter/change-set-is-ancestor-of.d.ts.map +1 -1
  739. package/dist/query-filter/change-set-is-ancestor-of.js.map +1 -1
  740. package/dist/query-filter/change-set-is-descendant-of.d.ts +2 -2
  741. package/dist/query-filter/change-set-is-descendant-of.d.ts.map +1 -1
  742. package/dist/query-filter/change-set-is-descendant-of.js.map +1 -1
  743. package/dist/query-filter/commit-is-ancestor-of.d.ts +51 -0
  744. package/dist/query-filter/commit-is-ancestor-of.d.ts.map +1 -0
  745. package/dist/query-filter/commit-is-ancestor-of.js +63 -0
  746. package/dist/query-filter/commit-is-ancestor-of.js.map +1 -0
  747. package/dist/query-filter/commit-is-ancestor-of.test.d.ts +2 -0
  748. package/dist/query-filter/commit-is-ancestor-of.test.d.ts.map +1 -0
  749. package/dist/query-filter/commit-is-ancestor-of.test.js +292 -0
  750. package/dist/query-filter/commit-is-ancestor-of.test.js.map +1 -0
  751. package/dist/query-filter/commit-is-descendant-of.d.ts +44 -0
  752. package/dist/query-filter/commit-is-descendant-of.d.ts.map +1 -0
  753. package/dist/query-filter/commit-is-descendant-of.js +56 -0
  754. package/dist/query-filter/commit-is-descendant-of.js.map +1 -0
  755. package/dist/query-filter/commit-is-descendant-of.test.d.ts +2 -0
  756. package/dist/query-filter/commit-is-descendant-of.test.d.ts.map +1 -0
  757. package/dist/query-filter/commit-is-descendant-of.test.js +325 -0
  758. package/dist/query-filter/commit-is-descendant-of.test.js.map +1 -0
  759. package/dist/query-filter/index.d.ts +2 -4
  760. package/dist/query-filter/index.d.ts.map +1 -1
  761. package/dist/query-filter/index.js +2 -4
  762. package/dist/query-filter/index.js.map +1 -1
  763. package/dist/query-filter/version-change-in-difference.d.ts +2 -0
  764. package/dist/query-filter/version-change-in-difference.d.ts.map +1 -1
  765. package/dist/query-filter/version-change-in-difference.js +2 -0
  766. package/dist/query-filter/version-change-in-difference.js.map +1 -1
  767. package/dist/query-filter/version-change-in-symmetric-difference.d.ts +2 -0
  768. package/dist/query-filter/version-change-in-symmetric-difference.d.ts.map +1 -1
  769. package/dist/query-filter/version-change-in-symmetric-difference.js +2 -0
  770. package/dist/query-filter/version-change-in-symmetric-difference.js.map +1 -1
  771. package/dist/schema-definition/definition.d.ts +73 -30
  772. package/dist/schema-definition/definition.d.ts.map +1 -1
  773. package/dist/schema-definition/definition.js +38 -14
  774. package/dist/schema-definition/definition.js.map +1 -1
  775. package/dist/schema-definition/definition.test.js +70 -25
  776. package/dist/schema-definition/definition.test.js.map +1 -1
  777. package/dist/schema-definition/validate-lix-schema.d.ts.map +1 -1
  778. package/dist/schema-definition/validate-lix-schema.js.map +1 -1
  779. package/dist/schema-definition/validate-lix-schema.test.js +1 -1
  780. package/dist/schema-definition/validate-lix-schema.test.js.map +1 -1
  781. package/dist/server-protocol-handler/environment/create-in-memory-environment.test.js +2 -2
  782. package/dist/server-protocol-handler/environment/create-in-memory-environment.test.js.map +1 -1
  783. package/dist/server-protocol-handler/routes/push-v1.test.js +1 -1
  784. package/dist/server-protocol-handler/routes/push-v1.test.js.map +1 -1
  785. package/dist/services/env-variables/index.js +1 -1
  786. package/dist/services/env-variables/index.js.map +1 -1
  787. package/dist/snapshot/create-snapshot.d.ts +2 -2
  788. package/dist/snapshot/create-snapshot.d.ts.map +1 -1
  789. package/dist/snapshot/create-snapshot.test.js +3 -3
  790. package/dist/snapshot/create-snapshot.test.js.map +1 -1
  791. package/dist/snapshot/database-schema.d.ts +19 -0
  792. package/dist/snapshot/database-schema.d.ts.map +1 -0
  793. package/dist/snapshot/database-schema.js +33 -0
  794. package/dist/snapshot/database-schema.js.map +1 -0
  795. package/dist/snapshot/database-schema.test.d.ts +2 -0
  796. package/dist/snapshot/database-schema.test.d.ts.map +1 -0
  797. package/dist/snapshot/database-schema.test.js +58 -0
  798. package/dist/snapshot/database-schema.test.js.map +1 -0
  799. package/dist/snapshot/schema.d.ts.map +1 -1
  800. package/dist/snapshot/schema.js +10 -2
  801. package/dist/snapshot/schema.js.map +1 -1
  802. package/dist/snapshot/schema.test.js +86 -0
  803. package/dist/snapshot/schema.test.js.map +1 -1
  804. package/dist/state/cache/clear-state-cache.d.ts +8 -0
  805. package/dist/state/cache/clear-state-cache.d.ts.map +1 -0
  806. package/dist/state/cache/clear-state-cache.js +14 -0
  807. package/dist/state/cache/clear-state-cache.js.map +1 -0
  808. package/dist/state/cache/clear-state-cache.test.d.ts +2 -0
  809. package/dist/state/cache/clear-state-cache.test.d.ts.map +1 -0
  810. package/dist/state/cache/clear-state-cache.test.js +34 -0
  811. package/dist/state/cache/clear-state-cache.test.js.map +1 -0
  812. package/dist/state/cache/is-stale-state-cache.d.ts +5 -0
  813. package/dist/state/cache/is-stale-state-cache.d.ts.map +1 -0
  814. package/dist/state/cache/is-stale-state-cache.js +22 -0
  815. package/dist/state/cache/is-stale-state-cache.js.map +1 -0
  816. package/dist/state/cache/is-stale-state-cache.test.d.ts +2 -0
  817. package/dist/state/cache/is-stale-state-cache.test.d.ts.map +1 -0
  818. package/dist/state/cache/is-stale-state-cache.test.js +27 -0
  819. package/dist/state/cache/is-stale-state-cache.test.js.map +1 -0
  820. package/dist/state/cache/mark-state-cache-as-stale.d.ts +10 -0
  821. package/dist/state/cache/mark-state-cache-as-stale.d.ts.map +1 -0
  822. package/dist/state/cache/mark-state-cache-as-stale.js +42 -0
  823. package/dist/state/cache/mark-state-cache-as-stale.js.map +1 -0
  824. package/dist/state/cache/populate-state-cache.d.ts +9 -0
  825. package/dist/state/cache/populate-state-cache.d.ts.map +1 -0
  826. package/dist/state/cache/populate-state-cache.js +106 -0
  827. package/dist/state/cache/populate-state-cache.js.map +1 -0
  828. package/dist/state/cache/populate-state-cache.test.d.ts +2 -0
  829. package/dist/state/cache/populate-state-cache.test.d.ts.map +1 -0
  830. package/dist/state/cache/populate-state-cache.test.js +204 -0
  831. package/dist/state/cache/populate-state-cache.test.js.map +1 -0
  832. package/dist/state/cache/schema.d.ts +20 -0
  833. package/dist/state/cache/schema.d.ts.map +1 -0
  834. package/dist/state/cache/schema.js +21 -0
  835. package/dist/state/cache/schema.js.map +1 -0
  836. package/dist/state/cache/update-state-cache.d.ts +21 -0
  837. package/dist/state/cache/update-state-cache.d.ts.map +1 -0
  838. package/dist/state/cache/update-state-cache.js +294 -0
  839. package/dist/state/cache/update-state-cache.js.map +1 -0
  840. package/dist/state/cache/update-state-cache.test.d.ts +2 -0
  841. package/dist/state/cache/update-state-cache.test.d.ts.map +1 -0
  842. package/dist/state/cache/update-state-cache.test.js +440 -0
  843. package/dist/state/cache/update-state-cache.test.js.map +1 -0
  844. package/dist/state/commit.d.ts +18 -0
  845. package/dist/state/commit.d.ts.map +1 -0
  846. package/dist/state/commit.js +457 -0
  847. package/dist/state/commit.js.map +1 -0
  848. package/dist/state/commit.test.d.ts +2 -0
  849. package/dist/state/commit.test.d.ts.map +1 -0
  850. package/dist/state/commit.test.js +1173 -0
  851. package/dist/state/commit.test.js.map +1 -0
  852. package/dist/state/get-version-record-by-id-or-throw.d.ts +2 -2
  853. package/dist/state/get-version-record-by-id-or-throw.d.ts.map +1 -1
  854. package/dist/state/get-version-record-by-id-or-throw.js.map +1 -1
  855. package/dist/state/handle-state-mutation.d.ts +0 -12
  856. package/dist/state/handle-state-mutation.d.ts.map +1 -1
  857. package/dist/state/handle-state-mutation.js +11 -206
  858. package/dist/state/handle-state-mutation.js.map +1 -1
  859. package/dist/state/handle-state-mutation.test.js +213 -159
  860. package/dist/state/handle-state-mutation.test.js.map +1 -1
  861. package/dist/state/insert-transaction-state.d.ts +71 -0
  862. package/dist/state/insert-transaction-state.d.ts.map +1 -0
  863. package/dist/state/insert-transaction-state.js +272 -0
  864. package/dist/state/insert-transaction-state.js.map +1 -0
  865. package/dist/state/insert-transaction-state.test.d.ts +2 -0
  866. package/dist/state/insert-transaction-state.test.d.ts.map +1 -0
  867. package/dist/state/insert-transaction-state.test.js +789 -0
  868. package/dist/state/insert-transaction-state.test.js.map +1 -0
  869. package/dist/state/materialize-state.d.ts +3 -0
  870. package/dist/state/materialize-state.d.ts.map +1 -0
  871. package/dist/state/materialize-state.js +230 -0
  872. package/dist/state/materialize-state.js.map +1 -0
  873. package/dist/state/materialize-state.test.d.ts +2 -0
  874. package/dist/state/materialize-state.test.d.ts.map +1 -0
  875. package/dist/state/materialize-state.test.js +1934 -0
  876. package/dist/state/materialize-state.test.js.map +1 -0
  877. package/dist/state/primary-key.d.ts +39 -0
  878. package/dist/state/primary-key.d.ts.map +1 -0
  879. package/dist/state/primary-key.js +62 -0
  880. package/dist/state/primary-key.js.map +1 -0
  881. package/dist/state/primary-key.test.d.ts +2 -0
  882. package/dist/state/primary-key.test.d.ts.map +1 -0
  883. package/dist/state/primary-key.test.js +114 -0
  884. package/dist/state/primary-key.test.js.map +1 -0
  885. package/dist/state/resolved-state-view.d.ts +33 -0
  886. package/dist/state/resolved-state-view.d.ts.map +1 -0
  887. package/dist/state/resolved-state-view.js +182 -0
  888. package/dist/state/resolved-state-view.js.map +1 -0
  889. package/dist/state/resolved-state-view.test.d.ts +2 -0
  890. package/dist/state/resolved-state-view.test.d.ts.map +1 -0
  891. package/dist/state/resolved-state-view.test.js +433 -0
  892. package/dist/state/resolved-state-view.test.js.map +1 -0
  893. package/dist/state/schema.d.ts +6 -19
  894. package/dist/state/schema.d.ts.map +1 -1
  895. package/dist/state/schema.js +533 -796
  896. package/dist/state/schema.js.map +1 -1
  897. package/dist/state/schema.test.js +1684 -1013
  898. package/dist/state/schema.test.js.map +1 -1
  899. package/dist/state/untracked/schema.d.ts +25 -0
  900. package/dist/state/untracked/schema.d.ts.map +1 -0
  901. package/dist/state/untracked/schema.js +38 -0
  902. package/dist/state/untracked/schema.js.map +1 -0
  903. package/dist/state/untracked/schema.test.d.ts +2 -0
  904. package/dist/state/untracked/schema.test.d.ts.map +1 -0
  905. package/dist/state/untracked/schema.test.js +275 -0
  906. package/dist/state/untracked/schema.test.js.map +1 -0
  907. package/dist/state/untracked/update-untracked-state.d.ts +36 -0
  908. package/dist/state/untracked/update-untracked-state.d.ts.map +1 -0
  909. package/dist/state/untracked/update-untracked-state.js +113 -0
  910. package/dist/state/untracked/update-untracked-state.js.map +1 -0
  911. package/dist/state/untracked/update-untracked-state.test.d.ts +2 -0
  912. package/dist/state/untracked/update-untracked-state.test.d.ts.map +1 -0
  913. package/dist/state/untracked/update-untracked-state.test.js +417 -0
  914. package/dist/state/untracked/update-untracked-state.test.js.map +1 -0
  915. package/dist/state/validate-snapshot-content.d.ts +9 -0
  916. package/dist/state/validate-snapshot-content.d.ts.map +1 -0
  917. package/dist/state/validate-snapshot-content.js +42 -0
  918. package/dist/state/validate-snapshot-content.js.map +1 -0
  919. package/dist/state/validate-snapshot-content.test.d.ts +2 -0
  920. package/dist/state/validate-snapshot-content.test.d.ts.map +1 -0
  921. package/dist/state/validate-snapshot-content.test.js +67 -0
  922. package/dist/state/validate-snapshot-content.test.js.map +1 -0
  923. package/dist/state/validate-state-mutation.d.ts +2 -2
  924. package/dist/state/validate-state-mutation.d.ts.map +1 -1
  925. package/dist/state/validate-state-mutation.js +211 -51
  926. package/dist/state/validate-state-mutation.js.map +1 -1
  927. package/dist/state/validate-state-mutation.test.js +910 -75
  928. package/dist/state/validate-state-mutation.test.js.map +1 -1
  929. package/dist/state-history/schema.d.ts +29 -19
  930. package/dist/state-history/schema.d.ts.map +1 -1
  931. package/dist/state-history/schema.js +49 -37
  932. package/dist/state-history/schema.js.map +1 -1
  933. package/dist/state-history/schema.test.js +221 -67
  934. package/dist/state-history/schema.test.js.map +1 -1
  935. package/dist/stored-schema/index.d.ts +1 -1
  936. package/dist/stored-schema/index.d.ts.map +1 -1
  937. package/dist/stored-schema/index.js +1 -1
  938. package/dist/stored-schema/index.js.map +1 -1
  939. package/dist/stored-schema/schema.d.ts +1 -1
  940. package/dist/stored-schema/schema.d.ts.map +1 -1
  941. package/dist/stored-schema/schema.test.js.map +1 -1
  942. package/dist/sync/push-to-server.test.js.map +1 -1
  943. package/dist/test-utilities/simulation-test/cache-miss-simulation.d.ts +8 -0
  944. package/dist/test-utilities/simulation-test/cache-miss-simulation.d.ts.map +1 -0
  945. package/dist/test-utilities/simulation-test/cache-miss-simulation.js +79 -0
  946. package/dist/test-utilities/simulation-test/cache-miss-simulation.js.map +1 -0
  947. package/dist/test-utilities/simulation-test/cache-miss-simulation.test.d.ts +2 -0
  948. package/dist/test-utilities/simulation-test/cache-miss-simulation.test.d.ts.map +1 -0
  949. package/dist/test-utilities/simulation-test/cache-miss-simulation.test.js +127 -0
  950. package/dist/test-utilities/simulation-test/cache-miss-simulation.test.js.map +1 -0
  951. package/dist/test-utilities/simulation-test/chaotic-timestamp-simulation.d.ts +2 -0
  952. package/dist/test-utilities/simulation-test/chaotic-timestamp-simulation.d.ts.map +1 -0
  953. package/dist/test-utilities/simulation-test/chaotic-timestamp-simulation.js +2 -0
  954. package/dist/test-utilities/simulation-test/chaotic-timestamp-simulation.js.map +1 -0
  955. package/dist/test-utilities/simulation-test/out-of-order-sequence-simulation.d.ts +10 -0
  956. package/dist/test-utilities/simulation-test/out-of-order-sequence-simulation.d.ts.map +1 -0
  957. package/dist/test-utilities/simulation-test/out-of-order-sequence-simulation.js +52 -0
  958. package/dist/test-utilities/simulation-test/out-of-order-sequence-simulation.js.map +1 -0
  959. package/dist/test-utilities/simulation-test/out-of-order-sequence-simulation.test.d.ts +2 -0
  960. package/dist/test-utilities/simulation-test/out-of-order-sequence-simulation.test.d.ts.map +1 -0
  961. package/dist/test-utilities/simulation-test/out-of-order-sequence-simulation.test.js +71 -0
  962. package/dist/test-utilities/simulation-test/out-of-order-sequence-simulation.test.js.map +1 -0
  963. package/dist/test-utilities/simulation-test/simulation-test.d.ts +82 -0
  964. package/dist/test-utilities/simulation-test/simulation-test.d.ts.map +1 -0
  965. package/dist/test-utilities/simulation-test/simulation-test.js +85 -0
  966. package/dist/test-utilities/simulation-test/simulation-test.js.map +1 -0
  967. package/dist/test-utilities/simulation-test/simulation-test.test.d.ts +2 -0
  968. package/dist/test-utilities/simulation-test/simulation-test.test.d.ts.map +1 -0
  969. package/dist/test-utilities/simulation-test/simulation-test.test.js +310 -0
  970. package/dist/test-utilities/simulation-test/simulation-test.test.js.map +1 -0
  971. package/dist/thread/comment-utils.d.ts +2 -0
  972. package/dist/thread/comment-utils.d.ts.map +1 -0
  973. package/dist/thread/comment-utils.js +2 -0
  974. package/dist/thread/comment-utils.js.map +1 -0
  975. package/dist/thread/comment.d.ts +24 -0
  976. package/dist/thread/comment.d.ts.map +1 -0
  977. package/dist/thread/comment.js +43 -0
  978. package/dist/thread/comment.js.map +1 -0
  979. package/dist/thread/create-thread-comment.d.ts +2 -2
  980. package/dist/thread/create-thread-comment.d.ts.map +1 -1
  981. package/dist/thread/create-thread-comment.js +20 -3
  982. package/dist/thread/create-thread-comment.js.map +1 -1
  983. package/dist/thread/create-thread-comment.test.js +49 -3
  984. package/dist/thread/create-thread-comment.test.js.map +1 -1
  985. package/dist/thread/create-thread.d.ts +18 -4
  986. package/dist/thread/create-thread.d.ts.map +1 -1
  987. package/dist/thread/create-thread.js +24 -3
  988. package/dist/thread/create-thread.js.map +1 -1
  989. package/dist/thread/create-thread.test.js +149 -0
  990. package/dist/thread/create-thread.test.js.map +1 -1
  991. package/dist/thread/database-schema.d.ts +20 -0
  992. package/dist/thread/database-schema.d.ts.map +1 -0
  993. package/dist/thread/database-schema.js +57 -0
  994. package/dist/thread/database-schema.js.map +1 -0
  995. package/dist/thread/database-schema.test.d.ts +2 -0
  996. package/dist/thread/database-schema.test.d.ts.map +1 -0
  997. package/dist/thread/database-schema.test.js +59 -0
  998. package/dist/thread/database-schema.test.js.map +1 -0
  999. package/dist/thread/index.d.ts +2 -1
  1000. package/dist/thread/index.d.ts.map +1 -1
  1001. package/dist/thread/schema.d.ts +13 -10
  1002. package/dist/thread/schema.d.ts.map +1 -1
  1003. package/dist/thread/schema.js +20 -14
  1004. package/dist/thread/schema.js.map +1 -1
  1005. package/dist/thread/schema.test.js +65 -0
  1006. package/dist/thread/schema.test.js.map +1 -1
  1007. package/dist/version/create-version.d.ts +14 -9
  1008. package/dist/version/create-version.d.ts.map +1 -1
  1009. package/dist/version/create-version.js +40 -12
  1010. package/dist/version/create-version.js.map +1 -1
  1011. package/dist/version/create-version.test.js +80 -25
  1012. package/dist/version/create-version.test.js.map +1 -1
  1013. package/dist/version/database-schema.d.ts +21 -0
  1014. package/dist/version/database-schema.d.ts.map +1 -0
  1015. package/dist/version/database-schema.js +169 -0
  1016. package/dist/version/database-schema.js.map +1 -0
  1017. package/dist/version/database-schema.test.d.ts +2 -0
  1018. package/dist/version/database-schema.test.d.ts.map +1 -0
  1019. package/dist/version/database-schema.test.js +625 -0
  1020. package/dist/version/database-schema.test.js.map +1 -0
  1021. package/dist/version/index.d.ts +1 -1
  1022. package/dist/version/index.d.ts.map +1 -1
  1023. package/dist/version/merge-version.d.ts +3 -0
  1024. package/dist/version/merge-version.d.ts.map +1 -1
  1025. package/dist/version/merge-version.js +3 -0
  1026. package/dist/version/merge-version.js.map +1 -1
  1027. package/dist/version/merge-version.test.js +10 -5
  1028. package/dist/version/merge-version.test.js.map +1 -1
  1029. package/dist/version/schema.d.ts +28 -23
  1030. package/dist/version/schema.d.ts.map +1 -1
  1031. package/dist/version/schema.js +42 -30
  1032. package/dist/version/schema.js.map +1 -1
  1033. package/dist/version/schema.test.js +311 -88
  1034. package/dist/version/schema.test.js.map +1 -1
  1035. package/dist/version/select-active-version.d.ts +7 -0
  1036. package/dist/version/select-active-version.d.ts.map +1 -0
  1037. package/dist/version/select-active-version.js +7 -0
  1038. package/dist/version/select-active-version.js.map +1 -0
  1039. package/dist/version/switch-version.d.ts +3 -3
  1040. package/dist/version/switch-version.d.ts.map +1 -1
  1041. package/dist/version/switch-version.js +1 -1
  1042. package/dist/version/switch-version.test.js +1 -1
  1043. package/dist/version/switch-version.test.js.map +1 -1
  1044. package/dist/version/update-changes-in-version.d.ts +2 -0
  1045. package/dist/version/update-changes-in-version.d.ts.map +1 -1
  1046. package/dist/version/update-changes-in-version.js +2 -0
  1047. package/dist/version/update-changes-in-version.js.map +1 -1
  1048. package/dist/version-v2/create-version.d.ts +18 -0
  1049. package/dist/version-v2/create-version.d.ts.map +1 -0
  1050. package/dist/version-v2/create-version.js +35 -0
  1051. package/dist/version-v2/create-version.js.map +1 -0
  1052. package/dist/version-v2/create-version.test.d.ts +2 -0
  1053. package/dist/version-v2/create-version.test.d.ts.map +1 -0
  1054. package/dist/version-v2/create-version.test.js +88 -0
  1055. package/dist/version-v2/create-version.test.js.map +1 -0
  1056. package/dist/version-v2/database-schema.d.ts +21 -0
  1057. package/dist/version-v2/database-schema.d.ts.map +1 -0
  1058. package/dist/version-v2/database-schema.js +169 -0
  1059. package/dist/version-v2/database-schema.js.map +1 -0
  1060. package/dist/version-v2/database-schema.test.d.ts +2 -0
  1061. package/dist/version-v2/database-schema.test.d.ts.map +1 -0
  1062. package/dist/version-v2/database-schema.test.js +625 -0
  1063. package/dist/version-v2/database-schema.test.js.map +1 -0
  1064. package/dist/version-v2/index.d.ts +2 -0
  1065. package/dist/version-v2/index.d.ts.map +1 -0
  1066. package/dist/version-v2/index.js +2 -0
  1067. package/dist/version-v2/index.js.map +1 -0
  1068. package/dist/version-v2/swich-version.d.ts +27 -0
  1069. package/dist/version-v2/swich-version.d.ts.map +1 -0
  1070. package/dist/version-v2/swich-version.js +46 -0
  1071. package/dist/version-v2/swich-version.js.map +1 -0
  1072. package/dist/version-v2/switch-version.d.ts +27 -0
  1073. package/dist/version-v2/switch-version.d.ts.map +1 -0
  1074. package/dist/version-v2/switch-version.js +91 -0
  1075. package/dist/version-v2/switch-version.js.map +1 -0
  1076. package/dist/version-v2/switch-version.test.d.ts +2 -0
  1077. package/dist/version-v2/switch-version.test.d.ts.map +1 -0
  1078. package/dist/version-v2/switch-version.test.js +110 -0
  1079. package/dist/version-v2/switch-version.test.js.map +1 -0
  1080. package/dist/version-v2/with-skip-update-working-change-set.d.ts +3 -0
  1081. package/dist/version-v2/with-skip-update-working-change-set.d.ts.map +1 -0
  1082. package/dist/version-v2/with-skip-update-working-change-set.js +50 -0
  1083. package/dist/version-v2/with-skip-update-working-change-set.js.map +1 -0
  1084. package/dist/version-v2/with-skip-update-working-change-set.test.d.ts +2 -0
  1085. package/dist/version-v2/with-skip-update-working-change-set.test.d.ts.map +1 -0
  1086. package/dist/version-v2/with-skip-update-working-change-set.test.js +49 -0
  1087. package/dist/version-v2/with-skip-update-working-change-set.test.js.map +1 -0
  1088. package/package.json +3 -3
  1089. package/src/account/create-account.ts +7 -7
  1090. package/src/account/index.ts +2 -2
  1091. package/src/account/schema.test.ts +99 -99
  1092. package/src/account/schema.ts +91 -35
  1093. package/src/account/switch-account.test.ts +4 -4
  1094. package/src/account/switch-account.ts +6 -6
  1095. package/src/change/index.ts +4 -1
  1096. package/src/change/schema.test.ts +38 -0
  1097. package/src/change/schema.ts +91 -11
  1098. package/src/change-author/index.ts +4 -1
  1099. package/src/change-author/schema.test.ts +306 -242
  1100. package/src/change-author/schema.ts +18 -12
  1101. package/src/change-proposal/create-change-proposal.ts +3 -3
  1102. package/src/change-proposal/database-schema.ts +1 -1
  1103. package/src/change-set/apply-change-set.test.ts +10 -7
  1104. package/src/change-set/apply-change-set.ts +44 -56
  1105. package/src/change-set/create-change-set.test.ts +0 -39
  1106. package/src/change-set/create-change-set.ts +9 -33
  1107. package/src/change-set/index.ts +3 -11
  1108. package/src/change-set/schema.test.ts +0 -310
  1109. package/src/change-set/schema.ts +43 -100
  1110. package/src/commit/apply-commit.test.ts +426 -0
  1111. package/src/commit/apply-commit.ts +74 -0
  1112. package/src/{change-set → commit}/create-checkpoint.test.ts +244 -26
  1113. package/src/commit/create-checkpoint.ts +140 -0
  1114. package/src/commit/create-commit.ts +80 -0
  1115. package/src/{change-set/create-merge-change-set.test.ts → commit/create-merge-commit.test.ts} +50 -19
  1116. package/src/{change-set/create-merge-change-set.ts → commit/create-merge-commit.ts} +55 -16
  1117. package/src/{change-set/create-transition-change-set.test.ts → commit/create-transition-commit.test.ts} +43 -32
  1118. package/src/{change-set/create-transition-change-set.ts → commit/create-transition-commit.ts} +60 -22
  1119. package/src/{change-set/create-undo-change-set.test.ts → commit/create-undo-commit.test.ts} +52 -23
  1120. package/src/{change-set/create-undo-change-set.ts → commit/create-undo-commit.ts} +59 -26
  1121. package/src/commit/index.ts +11 -0
  1122. package/src/commit/schema.test.ts +257 -0
  1123. package/src/commit/schema.ts +104 -0
  1124. package/src/database/index.ts +0 -2
  1125. package/src/database/init-db.ts +113 -45
  1126. package/src/database/kysely-plugin/json-column-plugin.test.ts +404 -0
  1127. package/src/database/kysely-plugin/json-column-plugin.ts +80 -15
  1128. package/src/database/nano-id.test.ts +3 -3
  1129. package/src/database/nano-id.ts +4 -1
  1130. package/src/database/schema.ts +26 -24
  1131. package/src/deterministic/generate-human-id.test.ts +154 -0
  1132. package/src/deterministic/generate-human-id.ts +94 -0
  1133. package/src/deterministic/index.ts +7 -0
  1134. package/src/deterministic/is-deterministic-mode.test.ts +133 -0
  1135. package/src/deterministic/is-deterministic-mode.ts +32 -0
  1136. package/src/deterministic/nano-id.test.ts +200 -0
  1137. package/src/deterministic/nano-id.ts +188 -0
  1138. package/src/deterministic/options.test.ts +157 -0
  1139. package/src/deterministic/options.ts +62 -0
  1140. package/src/deterministic/random.test.ts +293 -0
  1141. package/src/deterministic/random.ts +261 -0
  1142. package/src/deterministic/sequence.test.ts +93 -0
  1143. package/src/deterministic/sequence.ts +132 -0
  1144. package/src/deterministic/timestamp.test.ts +170 -0
  1145. package/src/deterministic/timestamp.ts +83 -0
  1146. package/src/deterministic/uuid-v7.test.ts +144 -0
  1147. package/src/deterministic/uuid-v7.ts +82 -0
  1148. package/src/entity/eb-entity.test.ts +687 -0
  1149. package/src/entity/eb-entity.ts +203 -0
  1150. package/src/entity/index.ts +12 -0
  1151. package/src/entity/label/create-entity-label.test.ts +316 -0
  1152. package/src/entity/label/create-entity-label.ts +113 -0
  1153. package/src/entity/label/schema.test.ts +692 -0
  1154. package/src/entity/label/schema.ts +55 -0
  1155. package/src/entity/schema.ts +22 -0
  1156. package/src/entity/thread/create-entity-thread.test.ts +282 -0
  1157. package/src/entity/thread/create-entity-thread.ts +134 -0
  1158. package/src/entity/thread/query-threads.test.ts +394 -0
  1159. package/src/entity/thread/schema.test.ts +170 -0
  1160. package/src/entity/thread/schema.ts +55 -0
  1161. package/src/entity-views/README.md +214 -0
  1162. package/src/entity-views/entity-state-all.test.ts +202 -0
  1163. package/src/entity-views/entity-state-all.ts +80 -11
  1164. package/src/entity-views/entity-state-history.test.ts +78 -16
  1165. package/src/entity-views/entity-state-history.ts +68 -19
  1166. package/src/entity-views/entity-state.test.ts +141 -1
  1167. package/src/entity-views/entity-state.ts +79 -10
  1168. package/src/entity-views/entity-view-builder.test.ts +6 -6
  1169. package/src/entity-views/types.ts +2 -2
  1170. package/src/file/file-handlers.test.ts +4 -4
  1171. package/src/file/file-handlers.ts +40 -0
  1172. package/src/file/materialize-file-data-at-commit.ts +157 -0
  1173. package/src/file/schema.test.ts +693 -37
  1174. package/src/file/schema.ts +183 -56
  1175. package/src/hooks/create-hooks.ts +7 -40
  1176. package/src/index.ts +3 -0
  1177. package/src/key-value/index.ts +1 -1
  1178. package/src/key-value/schema.test.ts +103 -2
  1179. package/src/key-value/schema.ts +66 -5
  1180. package/src/label/create-label.ts +7 -7
  1181. package/src/label/index.ts +1 -1
  1182. package/src/label/schema.ts +7 -10
  1183. package/src/lix/new-lix.test.ts +202 -2
  1184. package/src/lix/new-lix.ts +305 -81
  1185. package/src/lix/open-lix.test.ts +308 -5
  1186. package/src/lix/open-lix.ts +169 -68
  1187. package/src/lix/storage/in-memory.test.ts +9 -83
  1188. package/src/lix/storage/in-memory.ts +13 -18
  1189. package/src/lix/storage/lix-storage-adapter.ts +41 -5
  1190. package/src/lix/storage/opfs.test.ts +254 -31
  1191. package/src/lix/storage/opfs.ts +178 -40
  1192. package/src/log/create-lix-own-log.test.ts +11 -7
  1193. package/src/log/create-lix-own-log.ts +21 -32
  1194. package/src/log/create-log.ts +4 -4
  1195. package/src/log/index.ts +1 -1
  1196. package/src/log/schema.ts +6 -10
  1197. package/src/observe/create-observe.test.ts +395 -60
  1198. package/src/observe/create-observe.ts +41 -3
  1199. package/src/observe/determine-schema-keys.test.ts +371 -0
  1200. package/src/observe/determine-schema-keys.ts +165 -0
  1201. package/src/plugin/lix-plugin.ts +3 -3
  1202. package/src/query-filter/change-set-element-in-ancestry-of.test.ts +112 -26
  1203. package/src/query-filter/change-set-element-in-ancestry-of.ts +25 -20
  1204. package/src/query-filter/change-set-element-in-symmetric-difference.test.ts +6 -6
  1205. package/src/query-filter/change-set-element-in-symmetric-difference.ts +3 -3
  1206. package/src/query-filter/change-set-element-is-leaf-of.test.ts +83 -24
  1207. package/src/query-filter/change-set-element-is-leaf-of.ts +61 -39
  1208. package/src/query-filter/commit-is-ancestor-of.test.ts +333 -0
  1209. package/src/query-filter/commit-is-ancestor-of.ts +77 -0
  1210. package/src/query-filter/commit-is-descendant-of.test.ts +365 -0
  1211. package/src/query-filter/commit-is-descendant-of.ts +70 -0
  1212. package/src/query-filter/index.ts +2 -4
  1213. package/src/schema-definition/definition.test.ts +73 -25
  1214. package/src/schema-definition/definition.ts +87 -30
  1215. package/src/schema-definition/index.ts +1 -1
  1216. package/src/schema-definition/validate-lix-schema.test.ts +14 -5
  1217. package/src/schema-definition/validate-lix-schema.ts +9 -13
  1218. package/src/server-protocol-handler/environment/create-in-memory-environment.test.ts +2 -2
  1219. package/src/server-protocol-handler/routes/push-v1.test.ts +1 -1
  1220. package/src/snapshot/schema.test.ts +113 -0
  1221. package/src/snapshot/schema.ts +10 -2
  1222. package/src/state/README.md +95 -0
  1223. package/src/state/cache/clear-state-cache.test.ts +43 -0
  1224. package/src/state/cache/clear-state-cache.ts +16 -0
  1225. package/src/state/cache/is-stale-state-cache.test.ts +35 -0
  1226. package/src/state/cache/is-stale-state-cache.ts +29 -0
  1227. package/src/state/cache/mark-state-cache-as-stale.ts +53 -0
  1228. package/src/state/cache/populate-state-cache.test.ts +259 -0
  1229. package/src/state/cache/populate-state-cache.ts +124 -0
  1230. package/src/state/cache/schema.ts +41 -0
  1231. package/src/state/cache/update-state-cache.test.ts +510 -0
  1232. package/src/state/cache/update-state-cache.ts +317 -0
  1233. package/src/state/commit.test.ts +1402 -0
  1234. package/src/state/commit.ts +587 -0
  1235. package/src/state/insert-transaction-state.test.ts +928 -0
  1236. package/src/state/insert-transaction-state.ts +306 -0
  1237. package/src/state/materialize-state.test.ts +2358 -0
  1238. package/src/state/materialize-state.ts +235 -0
  1239. package/src/state/primary-key.test.ts +158 -0
  1240. package/src/state/primary-key.ts +80 -0
  1241. package/src/state/resolved-state-view.test.ts +521 -0
  1242. package/src/state/resolved-state-view.ts +202 -0
  1243. package/src/state/schema.test.ts +3116 -2272
  1244. package/src/state/schema.ts +614 -910
  1245. package/src/state/untracked/schema.test.ts +301 -0
  1246. package/src/state/untracked/schema.ts +55 -0
  1247. package/src/state/untracked/update-untracked-state.test.ts +466 -0
  1248. package/src/state/untracked/update-untracked-state.ts +133 -0
  1249. package/src/state/validate-state-mutation.test.ts +1032 -77
  1250. package/src/state/validate-state-mutation.ts +270 -68
  1251. package/src/state-history/schema.test.ts +246 -71
  1252. package/src/state-history/schema.ts +78 -55
  1253. package/src/stored-schema/index.ts +4 -1
  1254. package/src/stored-schema/schema.test.ts +7 -7
  1255. package/src/stored-schema/schema.ts +1 -1
  1256. package/src/sync/push-to-server.test.ts +6 -6
  1257. package/src/test-utilities/simulation-test/cache-miss-simulation.test.ts +162 -0
  1258. package/src/test-utilities/simulation-test/cache-miss-simulation.ts +99 -0
  1259. package/src/test-utilities/simulation-test/chaotic-timestamp-simulation.ts +0 -0
  1260. package/src/test-utilities/simulation-test/out-of-order-sequence-simulation.test.ts +88 -0
  1261. package/src/test-utilities/simulation-test/out-of-order-sequence-simulation.ts +69 -0
  1262. package/src/test-utilities/simulation-test/simulation-test.test.ts +400 -0
  1263. package/src/test-utilities/simulation-test/simulation-test.ts +176 -0
  1264. package/src/thread/create-thread-comment.test.ts +62 -3
  1265. package/src/thread/create-thread-comment.ts +34 -6
  1266. package/src/thread/create-thread.test.ts +180 -0
  1267. package/src/thread/create-thread.ts +32 -7
  1268. package/src/thread/index.ts +3 -2
  1269. package/src/thread/schema.test.ts +81 -0
  1270. package/src/thread/schema.ts +24 -19
  1271. package/src/version/create-version.test.ts +92 -26
  1272. package/src/version/create-version.ts +49 -19
  1273. package/src/version/index.ts +2 -2
  1274. package/src/version/schema.test.ts +328 -92
  1275. package/src/version/schema.ts +47 -33
  1276. package/src/version/select-active-version.ts +18 -0
  1277. package/src/version/switch-version.test.ts +1 -1
  1278. package/src/version/switch-version.ts +3 -3
  1279. package/dist/entity-views/entity-state_history.d.ts +0 -67
  1280. package/dist/entity-views/entity-state_history.d.ts.map +0 -1
  1281. package/dist/entity-views/entity-state_history.js +0 -58
  1282. package/dist/entity-views/entity-state_history.js.map +0 -1
  1283. package/dist/entity-views/generic-types.d.ts +0 -128
  1284. package/dist/entity-views/generic-types.d.ts.map +0 -1
  1285. package/dist/entity-views/generic-types.js +0 -2
  1286. package/dist/entity-views/generic-types.js.map +0 -1
  1287. package/dist/entity-views/generic-types.test.d.ts +0 -2
  1288. package/dist/entity-views/generic-types.test.d.ts.map +0 -1
  1289. package/dist/entity-views/generic-types.test.js +0 -99
  1290. package/dist/entity-views/generic-types.test.js.map +0 -1
  1291. package/dist/lix/to-blob.test.d.ts +0 -2
  1292. package/dist/lix/to-blob.test.d.ts.map +0 -1
  1293. package/dist/lix/to-blob.test.js +0 -18
  1294. package/dist/lix/to-blob.test.js.map +0 -1
  1295. package/dist/repository/comparison-example.js +0 -173
  1296. package/dist/repository/comparison-example.js.map +0 -1
  1297. package/dist/repository/entity-repository.d.ts +0 -53
  1298. package/dist/repository/entity-repository.d.ts.map +0 -1
  1299. package/dist/repository/entity-repository.js +0 -187
  1300. package/dist/repository/entity-repository.js.map +0 -1
  1301. package/dist/repository/entity-repository.test.d.ts +0 -2
  1302. package/dist/repository/entity-repository.test.d.ts.map +0 -1
  1303. package/dist/repository/entity-repository.test.js +0 -94
  1304. package/dist/repository/entity-repository.test.js.map +0 -1
  1305. package/dist/repository/example.d.ts +0 -6
  1306. package/dist/repository/example.d.ts.map +0 -1
  1307. package/dist/repository/example.js +0 -87
  1308. package/dist/repository/example.js.map +0 -1
  1309. package/dist/repository/file-repository.d.ts +0 -39
  1310. package/dist/repository/file-repository.d.ts.map +0 -1
  1311. package/dist/repository/file-repository.js +0 -93
  1312. package/dist/repository/file-repository.js.map +0 -1
  1313. package/dist/repository/file-repository.test.d.ts +0 -2
  1314. package/dist/repository/file-repository.test.d.ts.map +0 -1
  1315. package/dist/repository/file-repository.test.js +0 -165
  1316. package/dist/repository/file-repository.test.js.map +0 -1
  1317. package/dist/repository/index.d.ts +0 -6
  1318. package/dist/repository/index.d.ts.map +0 -1
  1319. package/dist/repository/index.js +0 -6
  1320. package/dist/repository/index.js.map +0 -1
  1321. package/dist/repository/integration.test.d.ts +0 -2
  1322. package/dist/repository/integration.test.d.ts.map +0 -1
  1323. package/dist/repository/integration.test.js +0 -136
  1324. package/dist/repository/integration.test.js.map +0 -1
  1325. package/dist/repository/key-value-repository.d.ts +0 -30
  1326. package/dist/repository/key-value-repository.d.ts.map +0 -1
  1327. package/dist/repository/key-value-repository.js +0 -60
  1328. package/dist/repository/key-value-repository.js.map +0 -1
  1329. package/dist/repository/key-value-repository.test.d.ts +0 -2
  1330. package/dist/repository/key-value-repository.test.d.ts.map +0 -1
  1331. package/dist/repository/key-value-repository.test.js +0 -122
  1332. package/dist/repository/key-value-repository.test.js.map +0 -1
  1333. package/dist/repository/markdown-plugin-example.js +0 -118
  1334. package/dist/repository/markdown-plugin-example.js.map +0 -1
  1335. package/dist/repository/query-builder.d.ts +0 -69
  1336. package/dist/repository/query-builder.d.ts.map +0 -1
  1337. package/dist/repository/query-builder.js +0 -155
  1338. package/dist/repository/query-builder.js.map +0 -1
  1339. package/dist/repository/query-builder.test.d.ts +0 -2
  1340. package/dist/repository/query-builder.test.d.ts.map +0 -1
  1341. package/dist/repository/query-builder.test.js +0 -244
  1342. package/dist/repository/query-builder.test.js.map +0 -1
  1343. package/dist/repository/repository-manager.d.ts +0 -27
  1344. package/dist/repository/repository-manager.d.ts.map +0 -1
  1345. package/dist/repository/repository-manager.js +0 -19
  1346. package/dist/repository/repository-manager.js.map +0 -1
  1347. package/dist/repository/repository-manager.test.d.ts +0 -2
  1348. package/dist/repository/repository-manager.test.d.ts.map +0 -1
  1349. package/dist/repository/repository-manager.test.js +0 -65
  1350. package/dist/repository/repository-manager.test.js.map +0 -1
  1351. package/dist/repository/test-helpers.js +0 -402
  1352. package/dist/repository/test-helpers.js.map +0 -1
  1353. package/dist/schema-definition/lix-generated.test.d.ts +0 -2
  1354. package/dist/schema-definition/lix-generated.test.d.ts.map +0 -1
  1355. package/dist/schema-definition/lix-generated.test.js +0 -127
  1356. package/dist/schema-definition/lix-generated.test.js.map +0 -1
  1357. package/dist/state/entity-view-builder.d.ts +0 -145
  1358. package/dist/state/entity-view-builder.d.ts.map +0 -1
  1359. package/dist/state/entity-view-builder.js +0 -280
  1360. package/dist/state/entity-view-builder.js.map +0 -1
  1361. package/dist/state/entity-view-builder.test.d.ts +0 -2
  1362. package/dist/state/entity-view-builder.test.d.ts.map +0 -1
  1363. package/dist/state/entity-view-builder.test.js +0 -523
  1364. package/dist/state/entity-view-builder.test.js.map +0 -1
  1365. package/src/change-set/create-checkpoint.ts +0 -101
  1366. package/src/file/materialize-file-data-at-changeset.ts +0 -123
  1367. package/src/query-filter/change-has-label.test.ts +0 -79
  1368. package/src/query-filter/change-has-label.ts +0 -45
  1369. package/src/query-filter/change-set-has-label.test.ts +0 -42
  1370. package/src/query-filter/change-set-has-label.ts +0 -50
  1371. package/src/query-filter/change-set-is-ancestor-of.test.ts +0 -178
  1372. package/src/query-filter/change-set-is-ancestor-of.ts +0 -77
  1373. package/src/query-filter/change-set-is-descendant-of.test.ts +0 -169
  1374. package/src/query-filter/change-set-is-descendant-of.ts +0 -70
  1375. package/src/state/create-changeset-for-transaction.ts +0 -321
  1376. package/src/state/get-version-record-by-id-or-throw.ts +0 -51
  1377. package/src/state/handle-state-mutation.test.ts +0 -761
  1378. package/src/state/handle-state-mutation.ts +0 -418
@@ -1,8 +1,10 @@
1
- import { test, expect, describe } from "vitest";
1
+ import { test, expect } from "vitest";
2
2
  import { openLix } from "../lix/open-lix.js";
3
3
  import { Kysely, sql } from "kysely";
4
4
  import { createVersion } from "../version/create-version.js";
5
- test("select, insert, update, delete entity", async () => {
5
+ import { simulationTest, normalSimulation, } from "../test-utilities/simulation-test/simulation-test.js";
6
+ test("dstest discovery", () => { });
7
+ simulationTest("select, insert, update, delete entity", async ({ openSimulatedLix }) => {
6
8
  const mockSchema = {
7
9
  "x-lix-key": "mock_schema",
8
10
  "x-lix-version": "1.0",
@@ -14,7 +16,15 @@ test("select, insert, update, delete entity", async () => {
14
16
  },
15
17
  },
16
18
  };
17
- const lix = await openLix({});
19
+ const lix = await openSimulatedLix({
20
+ keyValues: [
21
+ {
22
+ key: "lix_deterministic_mode",
23
+ value: { enabled: true, bootstrap: true },
24
+ lixcol_version_id: "global",
25
+ },
26
+ ],
27
+ });
18
28
  await lix.db
19
29
  .insertInto("stored_schema")
20
30
  .values({ value: mockSchema })
@@ -89,8 +99,16 @@ test("select, insert, update, delete entity", async () => {
89
99
  .execute();
90
100
  expect(viewAfterDelete).toHaveLength(0);
91
101
  });
92
- test("validates the schema on insert", async () => {
93
- const lix = await openLix({});
102
+ simulationTest("validates the schema on insert", async ({ openSimulatedLix }) => {
103
+ const lix = await openSimulatedLix({
104
+ keyValues: [
105
+ {
106
+ key: "lix_deterministic_mode",
107
+ value: { enabled: true, bootstrap: true },
108
+ lixcol_version_id: "global",
109
+ },
110
+ ],
111
+ });
94
112
  const mockSchema = {
95
113
  "x-lix-key": "mock_schema",
96
114
  "x-lix-version": "1.0",
@@ -121,8 +139,8 @@ test("validates the schema on insert", async () => {
121
139
  })
122
140
  .execute()).rejects.toThrow(/value must be number/);
123
141
  });
124
- test("validates the schema on update", async () => {
125
- const lix = await openLix({});
142
+ simulationTest("validates the schema on update", async ({ openSimulatedLix }) => {
143
+ const lix = await openSimulatedLix({});
126
144
  const mockSchema = {
127
145
  "x-lix-key": "mock_schema",
128
146
  "x-lix-version": "1.0",
@@ -180,8 +198,16 @@ test("validates the schema on update", async () => {
180
198
  },
181
199
  ]);
182
200
  });
183
- test("state is separated by version", async () => {
184
- const lix = await openLix({});
201
+ simulationTest("state is separated by version", async ({ openSimulatedLix }) => {
202
+ const lix = await openSimulatedLix({
203
+ keyValues: [
204
+ {
205
+ key: "lix_deterministic_mode",
206
+ value: { enabled: true, bootstrap: true },
207
+ lixcol_version_id: "global",
208
+ },
209
+ ],
210
+ });
185
211
  await createVersion({ lix, id: "version_a" });
186
212
  await createVersion({ lix, id: "version_b" });
187
213
  await lix.db
@@ -246,7 +272,9 @@ test("state is separated by version", async () => {
246
272
  expect(stateAfterInserts[1]?.updated_at).toBeDefined();
247
273
  await lix.db
248
274
  .updateTable("state_all")
249
- .set({ snapshot_content: { value: "hello world from version b UPDATED" } })
275
+ .set({
276
+ snapshot_content: { value: "hello world from version b UPDATED" },
277
+ })
250
278
  .where("entity_id", "=", "e0")
251
279
  .where("schema_key", "=", "mock_schema")
252
280
  .where("version_id", "=", "version_b")
@@ -303,8 +331,16 @@ test("state is separated by version", async () => {
303
331
  },
304
332
  ]);
305
333
  });
306
- test("created_at and updated_at timestamps are computed correctly", async () => {
307
- const lix = await openLix({});
334
+ simulationTest("created_at and updated_at timestamps are computed correctly", async ({ openSimulatedLix }) => {
335
+ const lix = await openSimulatedLix({
336
+ keyValues: [
337
+ {
338
+ key: "lix_deterministic_mode",
339
+ value: { enabled: true, bootstrap: true },
340
+ lixcol_version_id: "global",
341
+ },
342
+ ],
343
+ });
308
344
  const mockSchema = {
309
345
  "x-lix-key": "mock_schema",
310
346
  "x-lix-version": "1.0",
@@ -344,8 +380,6 @@ test("created_at and updated_at timestamps are computed correctly", async () =>
344
380
  expect(stateAfterInsert[0]?.created_at).toBeDefined();
345
381
  expect(stateAfterInsert[0]?.updated_at).toBeDefined();
346
382
  expect(stateAfterInsert[0]?.created_at).toBe(stateAfterInsert[0]?.updated_at);
347
- // Wait a bit to ensure different timestamps
348
- await new Promise((resolve) => setTimeout(resolve, 1));
349
383
  // Update the entity
350
384
  await lix.db
351
385
  .updateTable("state_all")
@@ -369,10 +403,17 @@ test("created_at and updated_at timestamps are computed correctly", async () =>
369
403
  expect(stateAfterUpdate[0]?.created_at).toBe(stateAfterInsert[0]?.created_at);
370
404
  // updated_at should be different (newer)
371
405
  expect(stateAfterUpdate[0]?.updated_at).not.toBe(stateAfterInsert[0]?.updated_at);
372
- expect(new Date(stateAfterUpdate[0].updated_at).getTime()).toBeGreaterThan(new Date(stateAfterInsert[0].updated_at).getTime());
373
406
  });
374
- test("created_at and updated_at are version specific", async () => {
375
- const lix = await openLix({});
407
+ simulationTest("created_at and updated_at are version specific", async ({ openSimulatedLix }) => {
408
+ const lix = await openSimulatedLix({
409
+ keyValues: [
410
+ {
411
+ key: "lix_deterministic_mode",
412
+ value: { enabled: true, bootstrap: true },
413
+ lixcol_version_id: "global",
414
+ },
415
+ ],
416
+ });
376
417
  await createVersion({ lix, id: "version_a" });
377
418
  await createVersion({ lix, id: "version_b" });
378
419
  const mockSchema = {
@@ -405,8 +446,6 @@ test("created_at and updated_at are version specific", async () => {
405
446
  },
406
447
  })
407
448
  .execute();
408
- // Wait a bit to ensure different timestamps
409
- await new Promise((resolve) => setTimeout(resolve, 1));
410
449
  // Insert same entity in version B
411
450
  await lix.db
412
451
  .insertInto("state_all")
@@ -443,8 +482,6 @@ test("created_at and updated_at are version specific", async () => {
443
482
  expect(stateVersionB[0]?.updated_at).toBeDefined();
444
483
  // the same entity has been inserted but with different changes
445
484
  expect(stateVersionA[0]?.created_at).not.toBe(stateVersionB[0]?.created_at);
446
- // Wait and update only version B
447
- await new Promise((resolve) => setTimeout(resolve, 1));
448
485
  await lix.db
449
486
  .updateTable("state_all")
450
487
  .set({
@@ -471,10 +508,17 @@ test("created_at and updated_at are version specific", async () => {
471
508
  expect(updatedStateVersionA[0]?.updated_at).toBe(stateVersionA[0]?.updated_at);
472
509
  // Version B should have updated timestamp
473
510
  expect(updatedStateVersionB[0]?.updated_at).not.toBe(stateVersionB[0]?.updated_at);
474
- expect(new Date(updatedStateVersionB[0].updated_at).getTime()).toBeGreaterThan(new Date(stateVersionB[0].updated_at).getTime());
475
511
  });
476
- test("state appears in both versions when they share the same change set", async () => {
477
- const lix = await openLix({});
512
+ simulationTest("state appears in both versions when they share the same commit", async ({ openSimulatedLix }) => {
513
+ const lix = await openSimulatedLix({
514
+ keyValues: [
515
+ {
516
+ key: "lix_deterministic_mode",
517
+ value: { enabled: true, bootstrap: true },
518
+ lixcol_version_id: "global",
519
+ },
520
+ ],
521
+ });
478
522
  const versionA = await createVersion({ lix, id: "version_a" });
479
523
  // Insert state into version A
480
524
  await lix.db
@@ -496,12 +540,14 @@ test("state appears in both versions when they share the same change set", async
496
540
  .where("id", "=", versionA.id)
497
541
  .selectAll()
498
542
  .executeTakeFirstOrThrow();
499
- // Create version B with the same change set as version A
500
- await createVersion({
543
+ const sharedCommitId = versionAAfterInsert.commit_id;
544
+ // Create version B from version A
545
+ const versionB = await createVersion({
501
546
  lix,
502
547
  id: "version_b",
503
- changeSet: { id: versionAAfterInsert.change_set_id },
548
+ commit_id: sharedCommitId,
504
549
  });
550
+ expect(versionB.commit_id).toBe(sharedCommitId);
505
551
  const stateInBothVersions = await lix.db
506
552
  .selectFrom("state_all")
507
553
  .where("schema_key", "=", "mock_schema")
@@ -515,17 +561,27 @@ test("state appears in both versions when they share the same change set", async
515
561
  schema_key: "mock_schema",
516
562
  snapshot_content: { value: "shared state" },
517
563
  version_id: "version_a",
564
+ commit_id: sharedCommitId,
518
565
  },
519
566
  {
520
567
  entity_id: "e0",
521
568
  schema_key: "mock_schema",
522
569
  snapshot_content: { value: "shared state" },
523
570
  version_id: "version_b",
571
+ commit_id: sharedCommitId,
524
572
  },
525
573
  ]);
526
574
  });
527
- test("state diverges when versions have common ancestor but different changes", async () => {
528
- const lix = await openLix({});
575
+ simulationTest("state diverges when versions have common ancestor but different changes", async ({ openSimulatedLix }) => {
576
+ const lix = await openSimulatedLix({
577
+ keyValues: [
578
+ {
579
+ key: "lix_deterministic_mode",
580
+ value: { enabled: true, bootstrap: true },
581
+ lixcol_version_id: "global",
582
+ },
583
+ ],
584
+ });
529
585
  // Create base version and add initial state
530
586
  const baseVersion = await createVersion({ lix, id: "base_version" });
531
587
  await lix.db
@@ -547,21 +603,21 @@ test("state diverges when versions have common ancestor but different changes",
547
603
  .where("id", "=", baseVersion.id)
548
604
  .selectAll()
549
605
  .executeTakeFirstOrThrow();
550
- // Create two versions from the same base changeset
606
+ // Create two versions from the same base version
551
607
  await createVersion({
552
608
  lix,
553
609
  id: "version_a",
554
- changeSet: { id: baseVersionAfterInsert.change_set_id },
610
+ commit_id: baseVersionAfterInsert.commit_id,
555
611
  });
556
612
  await createVersion({
557
613
  lix,
558
614
  id: "version_b",
559
- changeSet: { id: baseVersionAfterInsert.change_set_id },
615
+ commit_id: baseVersionAfterInsert.commit_id,
560
616
  });
561
617
  const versions = await lix.db
562
618
  .selectFrom("version")
563
619
  .where("id", "in", ["base_version", "version_a", "version_b"])
564
- .select(["id", "change_set_id"])
620
+ .select(["id", "commit_id"])
565
621
  .execute();
566
622
  expect(versions).toHaveLength(3);
567
623
  // Both versions should initially see the base state
@@ -595,6 +651,7 @@ test("state diverges when versions have common ancestor but different changes",
595
651
  .where("schema_key", "=", "mock_schema")
596
652
  .where("entity_id", "=", "e0")
597
653
  .selectAll()
654
+ .orderBy("version_id")
598
655
  .execute();
599
656
  // All three versions should have different states
600
657
  expect(divergedState).toMatchObject([
@@ -615,112 +672,16 @@ test("state diverges when versions have common ancestor but different changes",
615
672
  },
616
673
  ]);
617
674
  });
618
- // Write-through cache behavior tests
619
- test("write-through cache: insert operations populate cache immediately", async () => {
620
- const lix = await openLix({});
621
- const activeVersion = await lix.db
622
- .selectFrom("active_version")
623
- .innerJoin("version", "active_version.version_id", "version.id")
624
- .selectAll("version")
625
- .executeTakeFirstOrThrow();
626
- // Insert state data - should populate cache via write-through
627
- await lix.db
628
- .insertInto("state_all")
629
- .values({
630
- entity_id: "write-through-entity",
631
- schema_key: "write-through-schema",
632
- file_id: "write-through-file",
633
- plugin_key: "write-through-plugin",
634
- snapshot_content: { test: "write-through-data" },
635
- schema_version: "1.0",
636
- version_id: activeVersion.id,
637
- })
638
- .execute();
639
- // Cache should be populated immediately via write-through
640
- const cacheEntry = await lix.db
641
- .selectFrom("internal_state_cache")
642
- .where("entity_id", "=", "write-through-entity")
643
- .where("schema_key", "=", "write-through-schema")
644
- .where("file_id", "=", "write-through-file")
645
- .where("version_id", "=", activeVersion.id)
646
- .selectAll()
647
- .executeTakeFirst();
648
- expect(cacheEntry).toBeDefined();
649
- expect(cacheEntry?.entity_id).toBe("write-through-entity");
650
- expect(cacheEntry?.plugin_key).toBe("write-through-plugin");
651
- expect(cacheEntry?.snapshot_content).toEqual({
652
- test: "write-through-data",
653
- });
654
- // State view should return the same data (from cache)
655
- const stateResults = await lix.db
656
- .selectFrom("state_all")
657
- .where("entity_id", "=", "write-through-entity")
658
- .selectAll()
659
- .execute();
660
- expect(stateResults).toHaveLength(1);
661
- expect(stateResults[0]?.entity_id).toBe("write-through-entity");
662
- expect(stateResults[0]?.snapshot_content).toEqual({
663
- test: "write-through-data",
664
- });
665
- });
666
- test("write-through cache: update operations update cache immediately", async () => {
667
- const lix = await openLix({});
668
- const activeVersion = await lix.db
669
- .selectFrom("active_version")
670
- .innerJoin("version", "active_version.version_id", "version.id")
671
- .selectAll("version")
672
- .executeTakeFirstOrThrow();
673
- // Insert initial state
674
- await lix.db
675
- .insertInto("state_all")
676
- .values({
677
- entity_id: "update-cache-entity",
678
- schema_key: "update-cache-schema",
679
- file_id: "update-cache-file",
680
- plugin_key: "initial-plugin",
681
- snapshot_content: { initial: "value" },
682
- schema_version: "1.0",
683
- version_id: activeVersion.id,
684
- })
685
- .execute();
686
- // Update the state - should update cache via write-through
687
- await lix.db
688
- .updateTable("state_all")
689
- .set({
690
- snapshot_content: { updated: "value" },
691
- plugin_key: "updated-plugin",
692
- })
693
- .where("entity_id", "=", "update-cache-entity")
694
- .where("schema_key", "=", "update-cache-schema")
695
- .where("file_id", "=", "update-cache-file")
696
- .where("version_id", "=", activeVersion.id)
697
- .execute();
698
- // Cache should be immediately updated
699
- const cacheEntry = await lix.db
700
- .selectFrom("internal_state_cache")
701
- .where("entity_id", "=", "update-cache-entity")
702
- .where("schema_key", "=", "update-cache-schema")
703
- .where("file_id", "=", "update-cache-file")
704
- .where("version_id", "=", activeVersion.id)
705
- .selectAll()
706
- .executeTakeFirst();
707
- expect(cacheEntry).toBeDefined();
708
- expect(cacheEntry?.snapshot_content).toEqual({
709
- updated: "value",
675
+ simulationTest("delete operations remove entries from underlying data", async ({ openSimulatedLix }) => {
676
+ const lix = await openSimulatedLix({
677
+ keyValues: [
678
+ {
679
+ key: "lix_deterministic_mode",
680
+ value: { enabled: true, bootstrap: true },
681
+ lixcol_version_id: "global",
682
+ },
683
+ ],
710
684
  });
711
- expect(cacheEntry?.plugin_key).toBe("updated-plugin");
712
- // State view should return updated data
713
- const stateResults = await lix.db
714
- .selectFrom("state_all")
715
- .where("entity_id", "=", "update-cache-entity")
716
- .selectAll()
717
- .execute();
718
- expect(stateResults).toHaveLength(1);
719
- expect(stateResults[0]?.snapshot_content).toEqual({ updated: "value" });
720
- expect(stateResults[0]?.plugin_key).toBe("updated-plugin");
721
- });
722
- test("delete operations remove entries from underlying data", async () => {
723
- const lix = await openLix({});
724
685
  const activeVersion = await lix.db
725
686
  .selectFrom("active_version")
726
687
  .innerJoin("version", "active_version.version_id", "version.id")
@@ -762,8 +723,16 @@ test("delete operations remove entries from underlying data", async () => {
762
723
  .execute();
763
724
  expect(afterDelete).toHaveLength(0);
764
725
  });
765
- test("change.created_at and state timestamps are consistent", async () => {
766
- const lix = await openLix({});
726
+ simulationTest("change.created_at and state timestamps are consistent", async ({ openSimulatedLix }) => {
727
+ const lix = await openSimulatedLix({
728
+ keyValues: [
729
+ {
730
+ key: "lix_deterministic_mode",
731
+ value: { enabled: true, bootstrap: true },
732
+ lixcol_version_id: "global",
733
+ },
734
+ ],
735
+ });
767
736
  const mockSchema = {
768
737
  "x-lix-key": "mock_schema",
769
738
  "x-lix-version": "1.0",
@@ -809,9 +778,17 @@ test("change.created_at and state timestamps are consistent", async () => {
809
778
  // Verify all timestamps are identical
810
779
  expect(changeRecord.created_at).toBe(cacheRecord.created_at);
811
780
  expect(changeRecord.created_at).toBe(cacheRecord.updated_at);
812
- });
813
- test("state and state_all views expose change_id for blame and diff functionality", async () => {
814
- const lix = await openLix({});
781
+ }, { simulations: [normalSimulation] });
782
+ simulationTest("state and state_all views expose change_id for blame and diff functionality", async ({ expectDeterministic, openSimulatedLix }) => {
783
+ const lix = await openSimulatedLix({
784
+ keyValues: [
785
+ {
786
+ key: "lix_deterministic_mode",
787
+ value: { enabled: true, bootstrap: true },
788
+ lixcol_version_id: "global",
789
+ },
790
+ ],
791
+ });
815
792
  const mockSchema = {
816
793
  "x-lix-key": "mock_schema",
817
794
  "x-lix-version": "1.0",
@@ -847,7 +824,7 @@ test("state and state_all views expose change_id for blame and diff functionalit
847
824
  .where("schema_key", "=", "mock_schema")
848
825
  .selectAll()
849
826
  .execute();
850
- expect(stateAllResult).toHaveLength(1);
827
+ expectDeterministic(stateAllResult).toHaveLength(1);
851
828
  expect(stateAllResult[0]?.change_id).toBeDefined();
852
829
  expect(typeof stateAllResult[0]?.change_id).toBe("string");
853
830
  // Query state view (filtered by active version) to verify change_id is exposed
@@ -857,7 +834,7 @@ test("state and state_all views expose change_id for blame and diff functionalit
857
834
  .where("schema_key", "=", "mock_schema")
858
835
  .selectAll()
859
836
  .execute();
860
- expect(stateResult).toHaveLength(1);
837
+ expectDeterministic(stateResult).toHaveLength(1);
861
838
  expect(stateResult[0]?.change_id).toBeDefined();
862
839
  expect(typeof stateResult[0]?.change_id).toBe("string");
863
840
  // Verify that change_id matches between state and state_all views
@@ -874,7 +851,9 @@ test("state and state_all views expose change_id for blame and diff functionalit
874
851
  expect(stateAllResult[0]?.change_id).toBe(changeRecord.id);
875
852
  // Verify that the snapshot content in the change matches the state view
876
853
  expect(changeRecord.snapshot_content).toEqual({ value: "initial value" });
877
- expect(stateResult[0]?.snapshot_content).toEqual({ value: "initial value" });
854
+ expect(stateResult[0]?.snapshot_content).toEqual({
855
+ value: "initial value",
856
+ });
878
857
  // Update the entity to create a new change
879
858
  await lix.db
880
859
  .updateTable("state_all")
@@ -895,671 +874,1165 @@ test("state and state_all views expose change_id for blame and diff functionalit
895
874
  expect(updatedStateResult[0]?.change_id).toBeDefined();
896
875
  // The change_id should be different after the update (new change created)
897
876
  expect(updatedStateResult[0]?.change_id).not.toBe(stateResult[0]?.change_id);
898
- // Get the new change record
877
+ // Get the new change record by matching the change_id from the updated state
899
878
  const newChangeRecord = await lix.db
900
879
  .selectFrom("change")
901
- .where("entity_id", "=", "change-id-test-entity")
902
- .where("schema_key", "=", "mock_schema")
903
- .orderBy("created_at", "desc")
880
+ .where("change.id", "=", updatedStateResult[0].change_id)
904
881
  .select(["change.id", "snapshot_content"])
905
882
  .executeTakeFirstOrThrow();
906
883
  // Verify the new change_id matches the latest change
907
884
  expect(updatedStateResult[0]?.change_id).toBe(newChangeRecord.id);
908
885
  // Verify that the updated snapshot content in the change matches the state view
909
- expect(newChangeRecord.snapshot_content).toEqual({ value: "updated value" });
886
+ expect(newChangeRecord.snapshot_content).toEqual({
887
+ value: "updated value",
888
+ });
910
889
  expect(updatedStateResult[0]?.snapshot_content).toEqual({
911
890
  value: "updated value",
912
891
  });
913
892
  });
914
- // Important to note that only a full cache clear (like during schema changes) triggers
915
- // a cache miss and repopulation from the CTE at the moment!
916
- //
917
- // This is simpler, at the cost of state inconsistencies when changes are made
918
- // without populating or invalidating the cache.
919
- test.todo("state view should work and re-populate the cache after cache is fully (!) cleared", async () => {
920
- const lix = await openLix({});
921
- // Insert a key-value pair
922
- await lix.db
923
- .insertInto("key_value")
924
- .values({
925
- key: "test_cache_miss",
926
- value: "initial_value",
927
- })
928
- .execute();
929
- // Verify it's accessible through state view (should populate cache)
930
- const stateBeforeCacheClear = await lix.db
931
- .selectFrom("state_all")
932
- .where("schema_key", "=", "lix_key_value")
933
- .where("entity_id", "=", "test_cache_miss")
934
- .selectAll()
935
- .execute();
936
- expect(stateBeforeCacheClear).toHaveLength(1);
937
- expect(stateBeforeCacheClear[0]).toMatchObject({
938
- entity_id: "test_cache_miss",
939
- schema_key: "lix_key_value",
940
- snapshot_content: {
941
- key: "test_cache_miss",
942
- value: "initial_value",
943
- },
944
- });
945
- // Verify it's in the cache
946
- const cacheBeforeClear = await lix.db
947
- .selectFrom("internal_state_cache")
948
- .where("schema_key", "=", "lix_key_value")
949
- .where("entity_id", "=", "test_cache_miss")
950
- .selectAll()
951
- .execute();
952
- expect(cacheBeforeClear).toHaveLength(1);
953
- // Simulate cache invalidation (like what happens during stored_schema insertion)
954
- await lix.db
955
- .deleteFrom("internal_state_cache")
956
- .execute();
957
- // Verify cache is empty
958
- const cacheAfterClear = await lix.db
959
- .selectFrom("internal_state_cache")
960
- .selectAll()
961
- .execute();
962
- expect(cacheAfterClear).toHaveLength(0);
963
- // Try to access the same data through state view again
964
- // This should trigger cache miss logic and repopulate from CTE
965
- const stateAfterCacheClear = await lix.db
966
- .selectFrom("state_all")
967
- .where("schema_key", "=", "lix_key_value")
968
- .where("entity_id", "=", "test_cache_miss")
969
- .selectAll()
970
- .execute();
971
- // This should work - if cache miss logic is working correctly
972
- expect(stateAfterCacheClear).toHaveLength(1);
973
- expect(stateAfterCacheClear[0]).toMatchObject({
974
- entity_id: "test_cache_miss",
975
- schema_key: "lix_key_value",
976
- snapshot_content: {
977
- key: "test_cache_miss",
978
- value: "initial_value",
979
- },
893
+ simulationTest("state and state_all views expose commit_id for history queries", async ({ expectDeterministic, openSimulatedLix }) => {
894
+ const lix = await openSimulatedLix({
895
+ keyValues: [
896
+ {
897
+ key: "lix_deterministic_mode",
898
+ value: { enabled: true, bootstrap: true },
899
+ lixcol_version_id: "global",
900
+ },
901
+ ],
980
902
  });
981
- // Verify cache was repopulated
982
- const cacheAfterRefill = await lix.db
983
- .selectFrom("internal_state_cache")
984
- .where("schema_key", "=", "lix_key_value")
985
- .where("entity_id", "=", "test_cache_miss")
986
- .selectAll()
987
- .execute();
988
- expect(cacheAfterRefill).toHaveLength(1);
989
- });
990
- test("delete operations are validated for foreign key constraints", async () => {
991
- const lix = await openLix({});
992
- // Define parent schema (referenced entity)
993
- const parentSchema = {
994
- "x-lix-key": "parent_entity",
903
+ const mockSchema = {
904
+ "x-lix-key": "mock_schema",
995
905
  "x-lix-version": "1.0",
996
- "x-lix-primary-key": ["id"],
997
906
  type: "object",
998
- properties: {
999
- id: { type: "string" },
1000
- name: { type: "string" },
1001
- },
1002
- required: ["id", "name"],
1003
907
  additionalProperties: false,
1004
- };
1005
- // Define child schema with foreign key to parent
1006
- const childSchema = {
1007
- "x-lix-key": "child_entity",
1008
- "x-lix-version": "1.0",
1009
- "x-lix-primary-key": ["id"],
1010
- "x-lix-foreign-keys": {
1011
- parent_id: {
1012
- schemaKey: "parent_entity",
1013
- property: "id",
1014
- },
1015
- },
1016
- type: "object",
1017
908
  properties: {
1018
- id: { type: "string" },
1019
- parent_id: { type: "string" },
1020
- value: { type: "string" },
909
+ value: {
910
+ type: "string",
911
+ },
1021
912
  },
1022
- required: ["id", "parent_id", "value"],
1023
- additionalProperties: false,
1024
913
  };
1025
- // Register both schemas
1026
914
  await lix.db
1027
915
  .insertInto("stored_schema")
1028
- .values([{ value: parentSchema }, { value: childSchema }])
1029
- .execute();
1030
- // Insert parent entity
1031
- await lix.db
1032
- .insertInto("state_all")
1033
- .values({
1034
- entity_id: "parent-1",
1035
- schema_key: "parent_entity",
1036
- file_id: "test-file",
1037
- plugin_key: "test-plugin",
1038
- snapshot_content: {
1039
- id: "parent-1",
1040
- name: "Parent Entity",
1041
- },
1042
- schema_version: "1.0",
1043
- version_id: sql `(SELECT version_id FROM active_version)`,
1044
- })
916
+ .values({ value: mockSchema })
1045
917
  .execute();
1046
- // Insert child entity that references the parent
918
+ // Insert initial state using Kysely to ensure virtual table is triggered
1047
919
  await lix.db
1048
920
  .insertInto("state_all")
1049
921
  .values({
1050
- entity_id: "child-1",
1051
- schema_key: "child_entity",
1052
- file_id: "test-file",
1053
- plugin_key: "test-plugin",
1054
- snapshot_content: {
1055
- id: "child-1",
1056
- parent_id: "parent-1",
1057
- value: "Child Value",
1058
- },
922
+ entity_id: "change-set-id-test-entity",
923
+ schema_key: "mock_schema",
924
+ file_id: "change-set-id-test-file",
925
+ plugin_key: "change-set-id-test-plugin",
926
+ snapshot_content: { value: "initial value" },
1059
927
  schema_version: "1.0",
1060
928
  version_id: sql `(SELECT version_id FROM active_version)`,
1061
929
  })
1062
930
  .execute();
1063
- // Verify both entities exist
1064
- const parentBefore = await lix.db
931
+ const activeVersionAfterInsert = await lix.db
932
+ .selectFrom("active_version")
933
+ .innerJoin("version", "active_version.version_id", "version.id")
934
+ .selectAll("version")
935
+ .executeTakeFirstOrThrow();
936
+ // Query state_all view to verify change_set_id is exposed
937
+ const stateAllResult = await lix.db
1065
938
  .selectFrom("state_all")
1066
- .where("entity_id", "=", "parent-1")
1067
- .where("schema_key", "=", "parent_entity")
939
+ .where("entity_id", "=", "change-set-id-test-entity")
940
+ .where("schema_key", "=", "mock_schema")
1068
941
  .selectAll()
1069
942
  .execute();
1070
- const childBefore = await lix.db
1071
- .selectFrom("state_all")
1072
- .where("entity_id", "=", "child-1")
1073
- .where("schema_key", "=", "child_entity")
943
+ expectDeterministic(stateAllResult).toHaveLength(1);
944
+ expectDeterministic(stateAllResult[0]).toHaveProperty("commit_id");
945
+ expectDeterministic(stateAllResult[0]?.commit_id).toBe(activeVersionAfterInsert.commit_id);
946
+ // Query state view (filtered by active version) to verify commit_id is exposed
947
+ const stateResult = await lix.db
948
+ .selectFrom("state")
949
+ .where("entity_id", "=", "change-set-id-test-entity")
950
+ .where("schema_key", "=", "mock_schema")
1074
951
  .selectAll()
1075
952
  .execute();
1076
- expect(parentBefore).toHaveLength(1);
1077
- expect(childBefore).toHaveLength(1);
1078
- // Attempting to delete the parent entity should fail due to foreign key constraint
1079
- // because there's a child entity that references it
1080
- await expect(lix.db
1081
- .deleteFrom("state_all")
1082
- .where("entity_id", "=", "parent-1")
1083
- .where("schema_key", "=", "parent_entity")
1084
- .execute()).rejects.toThrow(/foreign key/i);
1085
- // Verify the parent still exists after failed deletion attempt
1086
- const parentAfter = await lix.db
1087
- .selectFrom("state_all")
1088
- .where("entity_id", "=", "parent-1")
1089
- .where("schema_key", "=", "parent_entity")
1090
- .selectAll()
953
+ expectDeterministic(stateResult).toHaveLength(1);
954
+ expectDeterministic(stateResult[0]?.commit_id).toBeDefined();
955
+ expectDeterministic(stateResult[0]?.commit_id).toBe(activeVersionAfterInsert.commit_id);
956
+ // Verify that commit_id matches between state and state_all views
957
+ expectDeterministic(stateResult[0]?.commit_id).toBe(stateAllResult[0]?.commit_id);
958
+ // Get the change_set_element records - there should be two:
959
+ // 1. One in the working change set
960
+ // 2. One in the version's current change set (after commit)
961
+ const changeSetElements = await lix.db
962
+ .selectFrom("change_set_element")
963
+ .where("entity_id", "=", "change-set-id-test-entity")
964
+ .where("schema_key", "=", "mock_schema")
965
+ .where("file_id", "=", "change-set-id-test-file")
966
+ .select(["change_set_id", "change_id"])
967
+ .orderBy("change_set_id")
1091
968
  .execute();
1092
- expect(parentAfter).toHaveLength(1);
1093
- });
1094
- describe.each([
1095
- { scenario: "cache hit", clearCache: false },
1096
- // { scenario: "cache miss", clearCache: true },
1097
- ])("($scenario) inheritance should work - child version should see entities from parent version", ({ clearCache }) => {
1098
- test("child version inherits entities from parent version", async () => {
1099
- const lix = await openLix({});
1100
- // Insert an entity into global version
1101
- await lix.db
1102
- .insertInto("state_all")
1103
- .values({
1104
- entity_id: "global-entity-1",
1105
- file_id: "test-file",
1106
- schema_key: "test_schema",
1107
- plugin_key: "test_plugin",
1108
- version_id: "global",
1109
- snapshot_content: {
1110
- id: "global-entity-1",
1111
- name: "Global Entity",
1112
- },
1113
- schema_version: "1.0",
1114
- })
1115
- .execute();
1116
- // Create a child version that inherits from global
1117
- const childVersion = await createVersion({
1118
- lix,
1119
- name: "child-version",
1120
- });
1121
- // Verify inheritance was set up correctly
1122
- expect(childVersion.inherits_from_version_id).toBe("global");
1123
- if (clearCache) {
1124
- // Clear the state cache to force re-materialization with inheritance (CTE path)
1125
- lix.sqlite.exec("DELETE FROM internal_state_cache");
1126
- }
1127
- // If clearCache is false, we test the cache hit path
1128
- // The child version should inherit the entity from global
1129
- const inheritedEntity = await lix.db
1130
- .selectFrom("state_all")
1131
- .where("entity_id", "=", "global-entity-1")
1132
- .where("version_id", "=", childVersion.id)
1133
- .selectAll()
1134
- .execute();
1135
- // This should pass - the entity should be visible in the child version via inheritance
1136
- expect(inheritedEntity).toHaveLength(1);
1137
- expect(inheritedEntity[0]?.entity_id).toBe("global-entity-1");
1138
- expect(inheritedEntity[0]?.version_id).toBe(childVersion.id); // Should return child version ID
1139
- expect(inheritedEntity[0]?.inherited_from_version_id).toBe("global"); // Should track inheritance source
1140
- expect(inheritedEntity[0]?.snapshot_content).toEqual({
969
+ expectDeterministic(changeSetElements).toHaveLength(2);
970
+ // Get the version to understand which change sets we're dealing with
971
+ const version = await lix.db
972
+ .selectFrom("version")
973
+ .where("id", "=", activeVersionAfterInsert.id)
974
+ .select(["id", "commit_id", "working_commit_id"])
975
+ .executeTakeFirstOrThrow();
976
+ // Get the change set ID from the version's commit
977
+ const versionCommit = await lix.db
978
+ .selectFrom("commit")
979
+ .where("id", "=", version.commit_id)
980
+ .selectAll()
981
+ .executeTakeFirstOrThrow();
982
+ // Get the change set ID from the working commit
983
+ const workingCommit = await lix.db
984
+ .selectFrom("commit")
985
+ .where("id", "=", version.working_commit_id)
986
+ .selectAll()
987
+ .executeTakeFirstOrThrow();
988
+ // Find which change_set_element is in the version's change set (not working)
989
+ const versionChangeSetElement = changeSetElements.find((el) => el.change_set_id === versionCommit.change_set_id);
990
+ const workingChangeSetElement = changeSetElements.find((el) => el.change_set_id === workingCommit.change_set_id);
991
+ expectDeterministic(versionChangeSetElement).toBeDefined();
992
+ expectDeterministic(workingChangeSetElement).toBeDefined();
993
+ // The state view should show the commit_id from the version,
994
+ // not related to the working change set (which is temporary and not part of the graph)
995
+ expectDeterministic(stateResult[0]?.commit_id).toBe(version.commit_id);
996
+ expectDeterministic(stateAllResult[0]?.commit_id).toBe(version.commit_id);
997
+ // Verify that the change_id also matches for consistency
998
+ expectDeterministic(stateResult[0]?.change_id).toBe(versionChangeSetElement.change_id);
999
+ expectDeterministic(stateAllResult[0]?.change_id).toBe(versionChangeSetElement.change_id);
1000
+ });
1001
+ // Write-through cache behavior tests
1002
+ simulationTest("write-through cache: insert operations populate cache immediately", async ({ openSimulatedLix }) => {
1003
+ const lix = await openSimulatedLix({
1004
+ keyValues: [
1005
+ {
1006
+ key: "lix_deterministic_mode",
1007
+ value: { enabled: true, bootstrap: true },
1008
+ lixcol_version_id: "global",
1009
+ },
1010
+ ],
1011
+ });
1012
+ const activeVersion = await lix.db
1013
+ .selectFrom("active_version")
1014
+ .innerJoin("version", "active_version.version_id", "version.id")
1015
+ .selectAll("version")
1016
+ .executeTakeFirstOrThrow();
1017
+ // Insert state data - should populate cache via write-through
1018
+ await lix.db
1019
+ .insertInto("state_all")
1020
+ .values({
1021
+ entity_id: "write-through-entity",
1022
+ schema_key: "write-through-schema",
1023
+ file_id: "write-through-file",
1024
+ plugin_key: "write-through-plugin",
1025
+ snapshot_content: { test: "write-through-data" },
1026
+ schema_version: "1.0",
1027
+ version_id: activeVersion.id,
1028
+ })
1029
+ .execute();
1030
+ // Cache should be populated immediately via write-through
1031
+ const cacheEntry = await lix.db
1032
+ .selectFrom("internal_state_cache")
1033
+ .where("entity_id", "=", "write-through-entity")
1034
+ .where("schema_key", "=", "write-through-schema")
1035
+ .where("file_id", "=", "write-through-file")
1036
+ .where("version_id", "=", activeVersion.id)
1037
+ .selectAll()
1038
+ .executeTakeFirst();
1039
+ expect(cacheEntry).toBeDefined();
1040
+ expect(cacheEntry?.entity_id).toBe("write-through-entity");
1041
+ expect(cacheEntry?.plugin_key).toBe("write-through-plugin");
1042
+ expect(cacheEntry?.snapshot_content).toEqual({
1043
+ test: "write-through-data",
1044
+ });
1045
+ // State view should return the same data (from cache)
1046
+ const stateResults = await lix.db
1047
+ .selectFrom("state_all")
1048
+ .where("entity_id", "=", "write-through-entity")
1049
+ .selectAll()
1050
+ .execute();
1051
+ expect(stateResults).toHaveLength(1);
1052
+ expect(stateResults[0]?.entity_id).toBe("write-through-entity");
1053
+ expect(stateResults[0]?.snapshot_content).toEqual({
1054
+ test: "write-through-data",
1055
+ });
1056
+ }, { simulations: [normalSimulation] });
1057
+ simulationTest("write-through cache: update operations update cache immediately", async ({ openSimulatedLix }) => {
1058
+ const lix = await openSimulatedLix({
1059
+ keyValues: [
1060
+ {
1061
+ key: "lix_deterministic_mode",
1062
+ value: { enabled: true, bootstrap: true },
1063
+ lixcol_version_id: "global",
1064
+ },
1065
+ ],
1066
+ });
1067
+ const activeVersion = await lix.db
1068
+ .selectFrom("active_version")
1069
+ .innerJoin("version", "active_version.version_id", "version.id")
1070
+ .selectAll("version")
1071
+ .executeTakeFirstOrThrow();
1072
+ // Insert initial state
1073
+ await lix.db
1074
+ .insertInto("state_all")
1075
+ .values({
1076
+ entity_id: "update-cache-entity",
1077
+ schema_key: "update-cache-schema",
1078
+ file_id: "update-cache-file",
1079
+ plugin_key: "initial-plugin",
1080
+ snapshot_content: { initial: "value" },
1081
+ schema_version: "1.0",
1082
+ version_id: activeVersion.id,
1083
+ })
1084
+ .execute();
1085
+ // Update the state - should update cache via write-through
1086
+ await lix.db
1087
+ .updateTable("state_all")
1088
+ .set({
1089
+ snapshot_content: { updated: "value" },
1090
+ plugin_key: "updated-plugin",
1091
+ })
1092
+ .where("entity_id", "=", "update-cache-entity")
1093
+ .where("schema_key", "=", "update-cache-schema")
1094
+ .where("file_id", "=", "update-cache-file")
1095
+ .where("version_id", "=", activeVersion.id)
1096
+ .execute();
1097
+ // Cache should be immediately updated
1098
+ const cacheEntry = await lix.db
1099
+ .selectFrom("internal_state_cache")
1100
+ .where("entity_id", "=", "update-cache-entity")
1101
+ .where("schema_key", "=", "update-cache-schema")
1102
+ .where("file_id", "=", "update-cache-file")
1103
+ .where("version_id", "=", activeVersion.id)
1104
+ .selectAll()
1105
+ .executeTakeFirst();
1106
+ expect(cacheEntry).toBeDefined();
1107
+ expect(cacheEntry?.snapshot_content).toEqual({
1108
+ updated: "value",
1109
+ });
1110
+ expect(cacheEntry?.plugin_key).toBe("updated-plugin");
1111
+ // State view should return updated data
1112
+ const stateResults = await lix.db
1113
+ .selectFrom("state_all")
1114
+ .where("entity_id", "=", "update-cache-entity")
1115
+ .selectAll()
1116
+ .execute();
1117
+ expect(stateResults).toHaveLength(1);
1118
+ expect(stateResults[0]?.snapshot_content).toEqual({ updated: "value" });
1119
+ expect(stateResults[0]?.plugin_key).toBe("updated-plugin");
1120
+ }, { simulations: [normalSimulation] });
1121
+ simulationTest("delete operations are validated for foreign key constraints", async ({ openSimulatedLix, expectDeterministic }) => {
1122
+ const lix = await openSimulatedLix({
1123
+ keyValues: [
1124
+ {
1125
+ key: "lix_deterministic_mode",
1126
+ value: { enabled: true, bootstrap: true },
1127
+ lixcol_version_id: "global",
1128
+ },
1129
+ ],
1130
+ });
1131
+ // Define parent schema (referenced entity)
1132
+ const parentSchema = {
1133
+ "x-lix-key": "parent_entity",
1134
+ "x-lix-version": "1.0",
1135
+ "x-lix-primary-key": ["id"],
1136
+ type: "object",
1137
+ properties: {
1138
+ id: { type: "string" },
1139
+ name: { type: "string" },
1140
+ },
1141
+ required: ["id", "name"],
1142
+ additionalProperties: false,
1143
+ };
1144
+ // Define child schema with foreign key to parent
1145
+ const childSchema = {
1146
+ "x-lix-key": "child_entity",
1147
+ "x-lix-version": "1.0",
1148
+ "x-lix-primary-key": ["id"],
1149
+ "x-lix-foreign-keys": [
1150
+ {
1151
+ properties: ["parent_id"],
1152
+ references: {
1153
+ schemaKey: "parent_entity",
1154
+ properties: ["id"],
1155
+ },
1156
+ },
1157
+ ],
1158
+ type: "object",
1159
+ properties: {
1160
+ id: { type: "string" },
1161
+ parent_id: { type: "string" },
1162
+ value: { type: "string" },
1163
+ },
1164
+ required: ["id", "parent_id", "value"],
1165
+ additionalProperties: false,
1166
+ };
1167
+ // Register both schemas
1168
+ await lix.db
1169
+ .insertInto("stored_schema")
1170
+ .values([{ value: parentSchema }, { value: childSchema }])
1171
+ .execute();
1172
+ // Insert parent entity
1173
+ await lix.db
1174
+ .insertInto("state_all")
1175
+ .values({
1176
+ entity_id: "parent-1",
1177
+ schema_key: "parent_entity",
1178
+ file_id: "test-file",
1179
+ plugin_key: "test-plugin",
1180
+ snapshot_content: {
1181
+ id: "parent-1",
1182
+ name: "Parent Entity",
1183
+ },
1184
+ schema_version: "1.0",
1185
+ version_id: sql `(SELECT version_id FROM active_version)`,
1186
+ })
1187
+ .execute();
1188
+ // Insert child entity that references the parent
1189
+ await lix.db
1190
+ .insertInto("state_all")
1191
+ .values({
1192
+ entity_id: "child-1",
1193
+ schema_key: "child_entity",
1194
+ file_id: "test-file",
1195
+ plugin_key: "test-plugin",
1196
+ snapshot_content: {
1197
+ id: "child-1",
1198
+ parent_id: "parent-1",
1199
+ value: "Child Value",
1200
+ },
1201
+ schema_version: "1.0",
1202
+ version_id: sql `(SELECT version_id FROM active_version)`,
1203
+ })
1204
+ .execute();
1205
+ // Verify both entities exist
1206
+ const parentBefore = await lix.db
1207
+ .selectFrom("state_all")
1208
+ .where("entity_id", "=", "parent-1")
1209
+ .where("schema_key", "=", "parent_entity")
1210
+ .selectAll()
1211
+ .execute();
1212
+ const childBefore = await lix.db
1213
+ .selectFrom("state_all")
1214
+ .where("entity_id", "=", "child-1")
1215
+ .where("schema_key", "=", "child_entity")
1216
+ .selectAll()
1217
+ .execute();
1218
+ expectDeterministic(parentBefore).toHaveLength(1);
1219
+ expectDeterministic(childBefore).toHaveLength(1);
1220
+ // Attempting to delete the parent entity should fail due to foreign key constraint
1221
+ // because there's a child entity that references it
1222
+ await expect(lix.db
1223
+ .deleteFrom("state_all")
1224
+ .where("entity_id", "=", "parent-1")
1225
+ .where("schema_key", "=", "parent_entity")
1226
+ .execute()).rejects.toThrow(/foreign key/i);
1227
+ // Verify the parent still exists after failed deletion attempt
1228
+ const parentAfter = await lix.db
1229
+ .selectFrom("state_all")
1230
+ .where("entity_id", "=", "parent-1")
1231
+ .where("schema_key", "=", "parent_entity")
1232
+ .selectAll()
1233
+ .execute();
1234
+ expectDeterministic(parentAfter).toHaveLength(1);
1235
+ });
1236
+ simulationTest("child version inherits entities from parent version", async ({ openSimulatedLix, expectDeterministic }) => {
1237
+ const lix = await openSimulatedLix({
1238
+ keyValues: [
1239
+ {
1240
+ key: "lix_deterministic_mode",
1241
+ value: { enabled: true, bootstrap: true },
1242
+ lixcol_version_id: "global",
1243
+ },
1244
+ ],
1245
+ });
1246
+ // Insert an entity into global version
1247
+ await lix.db
1248
+ .insertInto("state_all")
1249
+ .values({
1250
+ entity_id: "global-entity-1",
1251
+ file_id: "test-file",
1252
+ schema_key: "test_schema",
1253
+ plugin_key: "test_plugin",
1254
+ version_id: "global",
1255
+ snapshot_content: {
1141
1256
  id: "global-entity-1",
1142
1257
  name: "Global Entity",
1143
- });
1144
- });
1145
- // Flaky cache CTE
1146
- test.todo("inherited entities should reflect changes in parent", async () => {
1147
- const lix = await openLix({});
1148
- // Get the main version
1149
- const mainVersion = await lix.db
1150
- .selectFrom("version")
1151
- .where("name", "=", "main")
1152
- .selectAll()
1153
- .executeTakeFirstOrThrow();
1154
- const originalChangeSetId = mainVersion.change_set_id;
1155
- // Make a mutation to trigger version update in global context
1156
- await lix.db
1157
- .insertInto("key_value_all")
1158
- .values({
1159
- key: "cache_rebuild_test_key",
1160
- value: "cache_rebuild_test_value",
1161
- lixcol_version_id: mainVersion.id,
1162
- })
1163
- .execute();
1164
- // Check the global version after mutation
1165
- const globalVersionAfterMutation = await lix.db
1166
- .selectFrom("state_all")
1167
- .where("schema_key", "=", "lix_version")
1168
- .where("entity_id", "=", mainVersion.id)
1169
- .where("version_id", "=", "global")
1170
- .selectAll()
1171
- .executeTakeFirst();
1172
- console.log("🌍 Global version after mutation:", {
1173
- change_set_id: globalVersionAfterMutation?.snapshot_content
1174
- ?.change_set_id,
1175
- original: originalChangeSetId,
1176
- });
1177
- if (clearCache) {
1178
- // Clear the cache to force a rebuild from CTE
1179
- await lix.db
1180
- .deleteFrom("internal_state_cache")
1181
- .execute();
1182
- }
1183
- const state = await lix.db
1184
- .selectFrom("state_all")
1185
- .where("schema_key", "=", "lix_version")
1186
- .where("entity_id", "=", mainVersion.id)
1187
- .selectAll()
1188
- .execute();
1189
- console.log("🔍 State query result:", state.map((s) => ({
1190
- entity_id: s.entity_id,
1191
- version_id: s.version_id,
1192
- change_set_id: s.snapshot_content.change_set_id,
1193
- inherited_from_version_id: s.inherited_from_version_id,
1194
- })));
1195
- // testing for cached contents first to make a cache miss test fail faster
1196
- const cacheContents = await lix.db
1197
- .selectFrom("internal_state_cache")
1198
- .where("schema_key", "=", "lix_version")
1199
- .where("entity_id", "=", mainVersion.id)
1200
- .selectAll()
1201
- .execute();
1202
- // Both version entries should have the same updated change_set_id
1203
- const cachedInheritedMainVersion = cacheContents.find((entry) => entry.version_id === mainVersion.id);
1204
- const cachedMainVersionGlobal = cacheContents.find((entry) => entry.version_id === "global");
1205
- // we have copy on write deletion in place, so the cache should not contain the inherited version
1206
- expect(cachedInheritedMainVersion).toBeUndefined();
1207
- expect(cachedMainVersionGlobal).toBeDefined();
1208
- // Both version entries should have the same updated change_set_id
1209
- const inheritedMainVersion = state.find((entry) => entry.version_id === mainVersion.id);
1210
- const mainVersionGlobal = state.find((entry) => entry.version_id === "global");
1211
- expect(inheritedMainVersion).toBeDefined();
1212
- expect(mainVersionGlobal).toBeDefined();
1213
- // Both should have the same change_set_id
1214
- expect((inheritedMainVersion?.snapshot_content).change_set_id).toEqual((mainVersionGlobal?.snapshot_content).change_set_id);
1215
- // The change_set_id should be different from the original change_set_Id
1216
- expect((inheritedMainVersion?.snapshot_content).change_set_id).not.toEqual(originalChangeSetId);
1217
- expect((mainVersionGlobal?.snapshot_content).change_set_id).not.toEqual(originalChangeSetId);
1218
- expect((cachedMainVersionGlobal?.snapshot_content).change_set_id).toEqual(mainVersionGlobal?.snapshot_content.change_set_id);
1258
+ },
1259
+ schema_version: "1.0",
1260
+ })
1261
+ .execute();
1262
+ // Create a child version that inherits from global
1263
+ const childVersion = await createVersion({
1264
+ lix,
1265
+ name: "child-version",
1266
+ });
1267
+ // Verify inheritance was set up correctly
1268
+ expectDeterministic(childVersion.inherits_from_version_id).toBe("global");
1269
+ // The child version should inherit the entity from global
1270
+ const inheritedEntity = await lix.db
1271
+ .selectFrom("state_all")
1272
+ .where("entity_id", "=", "global-entity-1")
1273
+ .where("version_id", "=", childVersion.id)
1274
+ .selectAll()
1275
+ .execute();
1276
+ // This should pass - the entity should be visible in the child version via inheritance
1277
+ expectDeterministic(inheritedEntity).toHaveLength(1);
1278
+ expectDeterministic(inheritedEntity[0]?.entity_id).toBe("global-entity-1");
1279
+ expectDeterministic(inheritedEntity[0]?.version_id).toBe(childVersion.id); // Should return child version ID
1280
+ expectDeterministic(inheritedEntity[0]?.inherited_from_version_id).toBe("global"); // Should track inheritance source
1281
+ expectDeterministic(inheritedEntity[0]?.snapshot_content).toEqual({
1282
+ id: "global-entity-1",
1283
+ name: "Global Entity",
1219
1284
  });
1220
1285
  });
1221
- // TODO flaky test https://github.com/opral/lix-sdk/issues/308
1222
- describe.skip.each([
1223
- { scenario: "cache hit", clearCache: false },
1224
- { scenario: "cache miss", clearCache: true },
1225
- ])("($scenario) updating an inherited entity in child version should create a copy-on-write entity", () => {
1226
- test("child version inherits then overrides with own entity", async () => {
1227
- const lix = await openLix({});
1228
- // Insert an entity into global version
1229
- await lix.db
1230
- .insertInto("state_all")
1231
- .values({
1232
- entity_id: "shared-entity",
1233
- file_id: "test-file",
1234
- schema_key: "test_schema",
1235
- plugin_key: "test_plugin",
1236
- version_id: "global",
1237
- snapshot_content: {
1238
- id: "shared-entity",
1239
- name: "Original Global Value",
1240
- count: 1,
1286
+ simulationTest("child version inherits then overrides with own entity", async ({ openSimulatedLix, expectDeterministic }) => {
1287
+ const lix = await openSimulatedLix({
1288
+ keyValues: [
1289
+ {
1290
+ key: "lix_deterministic_mode",
1291
+ value: { enabled: true, bootstrap: true },
1292
+ lixcol_version_id: "global",
1241
1293
  },
1242
- schema_version: "1.0",
1243
- })
1244
- .execute();
1245
- // Create a child version that inherits from global
1246
- const childVersion = await createVersion({
1247
- lix,
1248
- name: "child-version",
1249
- });
1250
- // Note: For cache miss testing, we'll clear cache AFTER the update operation
1251
- // Verify the child initially sees the inherited entity
1252
- const inheritedEntity = await lix.db
1253
- .selectFrom("state_all")
1254
- .where("entity_id", "=", "shared-entity")
1255
- .where("version_id", "=", childVersion.id)
1256
- .selectAll()
1257
- .execute();
1258
- expect(inheritedEntity).toHaveLength(1);
1259
- expect(inheritedEntity[0]?.version_id).toBe(childVersion.id);
1260
- expect(inheritedEntity[0]?.inherited_from_version_id).toBe("global");
1261
- expect(inheritedEntity[0]?.snapshot_content).toEqual({
1262
- id: "shared-entity",
1263
- name: "Original Global Value",
1264
- count: 1,
1265
- });
1266
- // Now modify the entity in the child version (copy-on-write)
1267
- await lix.db
1268
- .updateTable("state_all")
1269
- .set({
1270
- snapshot_content: {
1271
- id: "shared-entity",
1272
- name: "Modified in Child Version",
1273
- count: 2,
1274
- },
1275
- })
1276
- .where("entity_id", "=", "shared-entity")
1277
- .where("version_id", "=", childVersion.id)
1278
- .execute();
1279
- // Clear cache after update to test cache miss scenario
1280
- // if (clearCache) {
1281
- // lix.sqlite.exec("DELETE FROM internal_state_cache");
1282
- // }
1283
- // Verify the child now has its own version of the entity
1284
- const childEntity = await lix.db
1285
- .selectFrom("state_all")
1286
- .where("entity_id", "=", "shared-entity")
1287
- .where("version_id", "=", childVersion.id)
1288
- .selectAll()
1289
- .execute();
1290
- expect(childEntity).toHaveLength(1);
1291
- expect(childEntity[0]?.version_id).toBe(childVersion.id);
1292
- expect(childEntity[0]?.inherited_from_version_id).toBe(null); // No longer inherited
1293
- expect(childEntity[0]?.snapshot_content).toEqual({
1294
- id: "shared-entity",
1295
- name: "Modified in Child Version",
1296
- count: 2,
1297
- });
1298
- // Verify the global version still has the original value
1299
- const globalEntity = await lix.db
1300
- .selectFrom("state_all")
1301
- .where("entity_id", "=", "shared-entity")
1302
- .where("version_id", "=", "global")
1303
- .selectAll()
1304
- .execute();
1305
- expect(globalEntity).toHaveLength(1);
1306
- expect(globalEntity[0]?.version_id).toBe("global");
1307
- expect(globalEntity[0]?.inherited_from_version_id).toBe(null);
1308
- expect(globalEntity[0]?.snapshot_content).toEqual({
1294
+ ],
1295
+ });
1296
+ // Insert an entity into global version
1297
+ await lix.db
1298
+ .insertInto("state_all")
1299
+ .values({
1300
+ entity_id: "shared-entity",
1301
+ file_id: "test-file",
1302
+ schema_key: "test_schema",
1303
+ plugin_key: "test_plugin",
1304
+ version_id: "global",
1305
+ snapshot_content: {
1309
1306
  id: "shared-entity",
1310
1307
  name: "Original Global Value",
1311
1308
  count: 1,
1312
- });
1313
- // Verify we now have 2 separate entities (one in global, one in child)
1314
- const allEntities = await lix.db
1315
- .selectFrom("state_all")
1316
- .where("entity_id", "=", "shared-entity")
1317
- .selectAll()
1318
- .execute();
1319
- expect(allEntities).toHaveLength(2);
1320
- // Sort by version_id for consistent ordering
1321
- allEntities.sort((a, b) => a.version_id.localeCompare(b.version_id));
1322
- // Child version entity (modified)
1323
- expect(allEntities[0]?.version_id).toBe(childVersion.id);
1324
- expect(allEntities[0]?.inherited_from_version_id).toBe(null);
1325
- expect(allEntities[0]?.snapshot_content).toEqual({
1326
- id: "shared-entity",
1327
- name: "Modified in Child Version",
1328
- count: 2,
1329
- });
1330
- // Global version entity (original)
1331
- expect(allEntities[1]?.version_id).toBe("global");
1332
- expect(allEntities[1]?.inherited_from_version_id).toBe(null);
1333
- expect(allEntities[1]?.snapshot_content).toEqual({
1334
- id: "shared-entity",
1335
- name: "Original Global Value",
1336
- count: 1,
1337
- });
1309
+ },
1310
+ schema_version: "1.0",
1311
+ })
1312
+ .execute();
1313
+ // Create a child version that inherits from global
1314
+ const childVersion = await createVersion({
1315
+ lix,
1316
+ id: "child-version",
1317
+ inherits_from_version_id: "global",
1318
+ });
1319
+ // Verify the child initially sees the inherited entity
1320
+ const inheritedEntity = await lix.db
1321
+ .selectFrom("state_all")
1322
+ .where("entity_id", "=", "shared-entity")
1323
+ .where("version_id", "=", childVersion.id)
1324
+ .selectAll()
1325
+ .execute();
1326
+ expectDeterministic(inheritedEntity).toHaveLength(1);
1327
+ expectDeterministic(inheritedEntity[0]?.version_id).toBe(childVersion.id);
1328
+ expectDeterministic(inheritedEntity[0]?.inherited_from_version_id).toBe("global");
1329
+ expectDeterministic(inheritedEntity[0]?.snapshot_content).toEqual({
1330
+ id: "shared-entity",
1331
+ name: "Original Global Value",
1332
+ count: 1,
1333
+ });
1334
+ // Now modify the entity in the child version (copy-on-write)
1335
+ await lix.db
1336
+ .updateTable("state_all")
1337
+ .set({
1338
+ snapshot_content: {
1339
+ id: "shared-entity",
1340
+ name: "Modified in Child Version",
1341
+ count: 2,
1342
+ },
1343
+ })
1344
+ .where("entity_id", "=", "shared-entity")
1345
+ .where("version_id", "=", childVersion.id)
1346
+ .execute();
1347
+ // Verify the child now has its own version of the entity
1348
+ const childEntity = await lix.db
1349
+ .selectFrom("state_all")
1350
+ .where("entity_id", "=", "shared-entity")
1351
+ .where("version_id", "=", childVersion.id)
1352
+ .selectAll()
1353
+ .execute();
1354
+ expectDeterministic(childEntity).toHaveLength(1);
1355
+ expectDeterministic(childEntity[0]?.version_id).toBe(childVersion.id);
1356
+ expectDeterministic(childEntity[0]?.inherited_from_version_id).toBe(null); // No longer inherited
1357
+ expectDeterministic(childEntity[0]?.snapshot_content).toEqual({
1358
+ id: "shared-entity",
1359
+ name: "Modified in Child Version",
1360
+ count: 2,
1361
+ });
1362
+ // Verify the global version still has the original value
1363
+ const globalEntity = await lix.db
1364
+ .selectFrom("state_all")
1365
+ .where("entity_id", "=", "shared-entity")
1366
+ .where("version_id", "=", "global")
1367
+ .selectAll()
1368
+ .execute();
1369
+ expectDeterministic(globalEntity).toHaveLength(1);
1370
+ expectDeterministic(globalEntity[0]?.version_id).toBe("global");
1371
+ expectDeterministic(globalEntity[0]?.inherited_from_version_id).toBe(null);
1372
+ expectDeterministic(globalEntity[0]?.snapshot_content).toEqual({
1373
+ id: "shared-entity",
1374
+ name: "Original Global Value",
1375
+ count: 1,
1376
+ });
1377
+ // Verify we now have 2 separate entities (one in global, one in child)
1378
+ const allEntities = await lix.db
1379
+ .selectFrom("state_all")
1380
+ .where("entity_id", "=", "shared-entity")
1381
+ .where("version_id", "in", ["global", childVersion.id])
1382
+ .orderBy("version_id", "asc")
1383
+ .selectAll()
1384
+ .execute();
1385
+ expectDeterministic(allEntities).toHaveLength(2);
1386
+ // Child version entity (modified)
1387
+ expectDeterministic(allEntities[0]?.version_id).toBe(childVersion.id);
1388
+ expectDeterministic(allEntities[0]?.inherited_from_version_id).toBe(null);
1389
+ expectDeterministic(allEntities[0]?.snapshot_content).toEqual({
1390
+ id: "shared-entity",
1391
+ name: "Modified in Child Version",
1392
+ count: 2,
1393
+ });
1394
+ // Global version entity (original)
1395
+ expectDeterministic(allEntities[1]?.version_id).toBe("global");
1396
+ expectDeterministic(allEntities[1]?.inherited_from_version_id).toBe(null);
1397
+ expectDeterministic(allEntities[1]?.snapshot_content).toEqual({
1398
+ id: "shared-entity",
1399
+ name: "Original Global Value",
1400
+ count: 1,
1401
+ });
1402
+ });
1403
+ simulationTest("child version deletes inherited entity via copy-on-write", async ({ openSimulatedLix, expectDeterministic }) => {
1404
+ const mockSchema = {
1405
+ "x-lix-key": "test_schema",
1406
+ "x-lix-version": "1.0",
1407
+ type: "object",
1408
+ additionalProperties: false,
1409
+ properties: {
1410
+ id: { type: "string" },
1411
+ name: { type: "string" },
1412
+ },
1413
+ };
1414
+ const lix = await openSimulatedLix({
1415
+ keyValues: [
1416
+ {
1417
+ key: "lix_deterministic_mode",
1418
+ value: { enabled: true, bootstrap: true },
1419
+ lixcol_version_id: "global",
1420
+ },
1421
+ ],
1338
1422
  });
1423
+ const activeVersion = await lix.db
1424
+ .selectFrom("active_version")
1425
+ .innerJoin("version", "active_version.version_id", "version.id")
1426
+ .selectAll("version")
1427
+ .executeTakeFirstOrThrow();
1428
+ // Insert schema
1429
+ await lix.db
1430
+ .insertInto("stored_schema")
1431
+ .values({ value: mockSchema })
1432
+ .execute();
1433
+ // Insert an entity into global version
1434
+ await lix.db
1435
+ .insertInto("state_all")
1436
+ .values({
1437
+ entity_id: "shared-entity",
1438
+ file_id: "test-file",
1439
+ schema_key: "test_schema",
1440
+ plugin_key: "test_plugin",
1441
+ version_id: "global",
1442
+ snapshot_content: {
1443
+ id: "shared-entity",
1444
+ name: "shared Entity",
1445
+ },
1446
+ schema_version: "1.0",
1447
+ })
1448
+ .execute();
1449
+ // Verify the child initially sees the inherited entity
1450
+ const inheritedEntity = await lix.db
1451
+ .selectFrom("state_all")
1452
+ .where("entity_id", "=", "shared-entity")
1453
+ .where("version_id", "=", activeVersion.id)
1454
+ .selectAll()
1455
+ .execute();
1456
+ expectDeterministic(inheritedEntity).toHaveLength(1);
1457
+ expectDeterministic(inheritedEntity[0]?.version_id).toBe(activeVersion.id);
1458
+ expectDeterministic(inheritedEntity[0]?.inherited_from_version_id).toBe("global");
1459
+ // Delete the inherited entity in child version (should create copy-on-write deletion)
1460
+ await lix.db
1461
+ .deleteFrom("state_all")
1462
+ .where("entity_id", "=", "shared-entity")
1463
+ .where("version_id", "=", activeVersion.id)
1464
+ .execute();
1465
+ // Verify the entity is deleted in child version
1466
+ const childEntityAfterDelete = await lix.db
1467
+ .selectFrom("state_all")
1468
+ .where("entity_id", "=", "shared-entity")
1469
+ .where("version_id", "=", activeVersion.id)
1470
+ .selectAll()
1471
+ .execute();
1472
+ // Entity should be deleted in child version (copy-on-write deletion)
1473
+ expectDeterministic(childEntityAfterDelete).toHaveLength(0);
1474
+ // Verify the entity still exists in global version (not affected by child deletion)
1475
+ const inheritedEntityAfterDelete = await lix.db
1476
+ .selectFrom("state_all")
1477
+ .where("entity_id", "=", "shared-entity")
1478
+ .where("version_id", "=", "global")
1479
+ .selectAll()
1480
+ .execute();
1481
+ expectDeterministic(inheritedEntityAfterDelete).toHaveLength(1);
1482
+ expectDeterministic(inheritedEntityAfterDelete[0]?.snapshot_content).toEqual({
1483
+ id: "shared-entity",
1484
+ name: "shared Entity",
1485
+ });
1486
+ // Verify we now only see the global entity through the state view (deletion marker is hidden)
1487
+ const allEntities = await lix.db
1488
+ .selectFrom("state_all")
1489
+ .where("entity_id", "=", "shared-entity")
1490
+ .selectAll()
1491
+ .execute();
1492
+ // Both cache hit and cache miss scenarios should behave identically:
1493
+ // copy-on-write deletion hides the entity from child but preserves it in parent
1494
+ expectDeterministic(allEntities).toHaveLength(1);
1495
+ expectDeterministic(allEntities[0]?.version_id).toBe("global");
1496
+ expectDeterministic(allEntities[0]?.inherited_from_version_id).toBe(null); // It's the original global entity
1339
1497
  });
1340
- describe.each([
1341
- { scenario: "cache hit", clearCache: false },
1342
- { scenario: "cache miss", clearCache: true },
1343
- ])("($scenario) deleting an inherited entity should create copy-on-write deletion", ({ clearCache }) => {
1344
- test.todo("child version deletes inherited entity via copy-on-write", async () => {
1345
- const mockSchema = {
1346
- "x-lix-key": "test_schema",
1347
- "x-lix-version": "1.0",
1348
- type: "object",
1349
- additionalProperties: false,
1350
- properties: {
1351
- id: { type: "string" },
1352
- name: { type: "string" },
1498
+ simulationTest("deleting without filtering for the version_id deletes the entity from all versions", async ({ openSimulatedLix, expectDeterministic }) => {
1499
+ const lix = await openSimulatedLix({
1500
+ keyValues: [
1501
+ {
1502
+ key: "lix_deterministic_mode",
1503
+ value: { enabled: true, bootstrap: true },
1504
+ lixcol_version_id: "global",
1353
1505
  },
1354
- };
1355
- const lix = await openLix({});
1356
- const activeVersion = await lix.db
1357
- .selectFrom("active_version")
1358
- .innerJoin("version", "active_version.version_id", "version.id")
1359
- .selectAll("version")
1360
- .executeTakeFirstOrThrow();
1361
- // Insert schema
1362
- await lix.db
1363
- .insertInto("stored_schema")
1364
- .values({ value: mockSchema })
1365
- .execute();
1366
- // Insert an entity into global version
1367
- await lix.db
1368
- .insertInto("state_all")
1369
- .values({
1506
+ ],
1507
+ });
1508
+ // Insert an entity into global version
1509
+ await lix.db
1510
+ .insertInto("state_all")
1511
+ .values({
1512
+ entity_id: "shared-entity",
1513
+ file_id: "test-file",
1514
+ schema_key: "test_schema",
1515
+ plugin_key: "test_plugin",
1516
+ version_id: "global",
1517
+ snapshot_content: {
1518
+ id: "shared-entity",
1519
+ name: "Global Entity",
1520
+ },
1521
+ schema_version: "1.0",
1522
+ })
1523
+ .execute();
1524
+ // Create a child version that inherits from global
1525
+ const childVersion = await createVersion({
1526
+ lix,
1527
+ name: "child-version",
1528
+ inherits_from_version_id: "global",
1529
+ });
1530
+ // Verify inheritance - both global and child should see the entity
1531
+ const beforeDelete = await lix.db
1532
+ .selectFrom("state_all")
1533
+ .where("entity_id", "=", "shared-entity")
1534
+ .where("version_id", "in", ["global", childVersion.id])
1535
+ .selectAll()
1536
+ .execute();
1537
+ expectDeterministic(beforeDelete).toHaveLength(2); // One in global, one inherited in child
1538
+ expectDeterministic(beforeDelete).toMatchObject([
1539
+ {
1370
1540
  entity_id: "shared-entity",
1371
- file_id: "test-file",
1372
- schema_key: "test_schema",
1373
- plugin_key: "test_plugin",
1374
1541
  version_id: "global",
1375
- snapshot_content: {
1376
- id: "shared-entity",
1377
- name: "shared Entity",
1542
+ inherited_from_version_id: null,
1543
+ snapshot_content: { id: "shared-entity", name: "Global Entity" },
1544
+ },
1545
+ {
1546
+ entity_id: "shared-entity",
1547
+ version_id: childVersion.id,
1548
+ inherited_from_version_id: "global",
1549
+ snapshot_content: { id: "shared-entity", name: "Global Entity" },
1550
+ },
1551
+ ]);
1552
+ await lix.db
1553
+ .deleteFrom("state_all")
1554
+ .where("entity_id", "=", "shared-entity")
1555
+ .where("schema_key", "=", "test_schema")
1556
+ .execute();
1557
+ const afterDelete = await lix.db
1558
+ .selectFrom("state_all")
1559
+ .where("entity_id", "=", "shared-entity")
1560
+ .selectAll()
1561
+ .execute();
1562
+ // Should be deleted from every version
1563
+ expectDeterministic(afterDelete).toHaveLength(0);
1564
+ });
1565
+ simulationTest("untracked mutations don't trigger change control", async ({ openSimulatedLix, expectDeterministic }) => {
1566
+ const lix = await openSimulatedLix({
1567
+ keyValues: [
1568
+ {
1569
+ key: "lix_deterministic_mode",
1570
+ value: { enabled: true, bootstrap: true },
1571
+ lixcol_version_id: "global",
1572
+ },
1573
+ ],
1574
+ });
1575
+ const mockSchema = {
1576
+ "x-lix-key": "mock_schema",
1577
+ "x-lix-version": "1.0",
1578
+ type: "object",
1579
+ additionalProperties: false,
1580
+ properties: {
1581
+ value: {
1582
+ type: "string",
1583
+ },
1584
+ },
1585
+ };
1586
+ await lix.db
1587
+ .insertInto("stored_schema")
1588
+ .values({ value: mockSchema })
1589
+ .execute();
1590
+ // Count changes before any untracked mutations
1591
+ const changesInitial = await lix.db
1592
+ .selectFrom("change")
1593
+ .selectAll()
1594
+ .execute();
1595
+ // 1. INSERT untracked state
1596
+ await lix.db
1597
+ .insertInto("state_all")
1598
+ .values({
1599
+ entity_id: "untracked-entity",
1600
+ file_id: "test-file",
1601
+ schema_key: "mock_schema",
1602
+ plugin_key: "test_plugin",
1603
+ schema_version: "1.0",
1604
+ version_id: sql `(SELECT version_id FROM active_version)`,
1605
+ snapshot_content: {
1606
+ value: "untracked value",
1607
+ },
1608
+ untracked: true,
1609
+ })
1610
+ .execute();
1611
+ // Count changes after untracked insert
1612
+ const changesAfterInsert = await lix.db
1613
+ .selectFrom("change")
1614
+ .selectAll()
1615
+ .execute();
1616
+ // Number of changes should be identical (no change control for untracked)
1617
+ expectDeterministic(changesAfterInsert.length).toBe(changesInitial.length);
1618
+ // Verify the untracked entity exists in state view
1619
+ const untrackedState = await lix.db
1620
+ .selectFrom("state_all")
1621
+ .where("entity_id", "=", "untracked-entity")
1622
+ .selectAll()
1623
+ .execute();
1624
+ expectDeterministic(untrackedState).toHaveLength(1);
1625
+ expectDeterministic(untrackedState[0]?.snapshot_content).toEqual({
1626
+ value: "untracked value",
1627
+ });
1628
+ expectDeterministic(untrackedState[0]?.untracked).toBe(1);
1629
+ // 2. UPDATE untracked state
1630
+ await lix.db
1631
+ .updateTable("state_all")
1632
+ .where("entity_id", "=", "untracked-entity")
1633
+ .set({
1634
+ snapshot_content: {
1635
+ value: "untracked value updated",
1636
+ },
1637
+ untracked: true,
1638
+ })
1639
+ .execute();
1640
+ // Count changes after untracked update
1641
+ const changesAfterUpdate = await lix.db
1642
+ .selectFrom("change")
1643
+ .selectAll()
1644
+ .execute();
1645
+ // Number of changes should still be identical (no change control for untracked)
1646
+ expectDeterministic(changesAfterUpdate.length).toBe(changesInitial.length);
1647
+ // Verify the untracked entity was updated
1648
+ const updatedState = await lix.db
1649
+ .selectFrom("state_all")
1650
+ .where("entity_id", "=", "untracked-entity")
1651
+ .selectAll()
1652
+ .execute();
1653
+ expectDeterministic(updatedState).toHaveLength(1);
1654
+ expectDeterministic(updatedState[0]?.snapshot_content).toEqual({
1655
+ value: "untracked value updated",
1656
+ });
1657
+ expectDeterministic(updatedState[0]?.untracked).toBe(1);
1658
+ // 3. DELETE untracked state
1659
+ await lix.db
1660
+ .deleteFrom("state_all")
1661
+ .where("entity_id", "=", "untracked-entity")
1662
+ .execute();
1663
+ // Count changes after untracked delete
1664
+ const changesAfterDelete = await lix.db
1665
+ .selectFrom("change")
1666
+ .selectAll()
1667
+ .execute();
1668
+ // Number of changes should still be identical (no change control for untracked)
1669
+ expectDeterministic(changesAfterDelete.length).toBe(changesInitial.length);
1670
+ // Verify the untracked entity was deleted
1671
+ const deletedState = await lix.db
1672
+ .selectFrom("state_all")
1673
+ .where("entity_id", "=", "untracked-entity")
1674
+ .selectAll()
1675
+ .execute();
1676
+ expectDeterministic(deletedState).toHaveLength(0);
1677
+ });
1678
+ simulationTest("tracked update to previously untracked entity deletes untracked state", async ({ openSimulatedLix, expectDeterministic }) => {
1679
+ const lix = await openSimulatedLix({
1680
+ keyValues: [
1681
+ {
1682
+ key: "lix_deterministic_mode",
1683
+ value: { enabled: true, bootstrap: true },
1684
+ lixcol_version_id: "global",
1685
+ },
1686
+ ],
1687
+ });
1688
+ const mockSchema = {
1689
+ "x-lix-key": "mock_schema",
1690
+ "x-lix-version": "1.0",
1691
+ type: "object",
1692
+ additionalProperties: false,
1693
+ properties: {
1694
+ value: {
1695
+ type: "string",
1696
+ },
1697
+ },
1698
+ };
1699
+ await lix.db
1700
+ .insertInto("stored_schema")
1701
+ .values({ value: mockSchema })
1702
+ .execute();
1703
+ // Insert untracked state
1704
+ await lix.db
1705
+ .insertInto("state_all")
1706
+ .values({
1707
+ entity_id: "override-entity",
1708
+ file_id: "test-file",
1709
+ schema_key: "mock_schema",
1710
+ plugin_key: "test_plugin",
1711
+ schema_version: "1.0",
1712
+ version_id: sql `(SELECT version_id FROM active_version)`,
1713
+ snapshot_content: {
1714
+ value: "untracked value",
1715
+ },
1716
+ untracked: true,
1717
+ })
1718
+ .execute();
1719
+ // Verify untracked state exists
1720
+ const untrackedState = await lix.db
1721
+ .selectFrom("state_all")
1722
+ .where("entity_id", "=", "override-entity")
1723
+ .selectAll()
1724
+ .execute();
1725
+ expectDeterministic(untrackedState).toHaveLength(1);
1726
+ expectDeterministic(untrackedState[0]?.snapshot_content).toEqual({
1727
+ value: "untracked value",
1728
+ });
1729
+ // Now update the untracked entity to make it tracked (should delete from untracked table)
1730
+ await lix.db
1731
+ .updateTable("state_all")
1732
+ .set({
1733
+ snapshot_content: {
1734
+ value: "tracked value",
1735
+ },
1736
+ untracked: false,
1737
+ })
1738
+ .where("entity_id", "=", "override-entity")
1739
+ .where("schema_key", "=", "mock_schema")
1740
+ .execute();
1741
+ // Verify tracked state has overridden untracked state
1742
+ const finalState = await lix.db
1743
+ .selectFrom("state_all")
1744
+ .where("entity_id", "=", "override-entity")
1745
+ .selectAll()
1746
+ .execute();
1747
+ expectDeterministic(finalState).toHaveLength(1);
1748
+ expectDeterministic(finalState[0]?.snapshot_content).toEqual({
1749
+ value: "tracked value",
1750
+ });
1751
+ // Verify a change was created for the tracked mutation
1752
+ const changes = await lix.db
1753
+ .selectFrom("change")
1754
+ .where("entity_id", "=", "override-entity")
1755
+ .where("schema_key", "=", "mock_schema")
1756
+ .selectAll()
1757
+ .execute();
1758
+ expectDeterministic(changes.length).toBeGreaterThan(0);
1759
+ });
1760
+ simulationTest("untracked state is persisted across lix sessions", async ({ openSimulatedLix, expectDeterministic }) => {
1761
+ const mockSchema = {
1762
+ "x-lix-key": "mock_schema",
1763
+ "x-lix-version": "1.0",
1764
+ type: "object",
1765
+ additionalProperties: false,
1766
+ properties: {
1767
+ value: {
1768
+ type: "string",
1769
+ },
1770
+ },
1771
+ };
1772
+ // First session - create and insert untracked state
1773
+ const lix1 = await openSimulatedLix({
1774
+ keyValues: [
1775
+ {
1776
+ key: "lix_deterministic_mode",
1777
+ value: { enabled: true, bootstrap: true },
1778
+ lixcol_version_id: "global",
1779
+ },
1780
+ ],
1781
+ });
1782
+ await lix1.db
1783
+ .insertInto("stored_schema")
1784
+ .values({ value: mockSchema })
1785
+ .execute();
1786
+ await lix1.db
1787
+ .insertInto("state_all")
1788
+ .values({
1789
+ entity_id: "persistent-entity",
1790
+ file_id: "test-file",
1791
+ schema_key: "mock_schema",
1792
+ plugin_key: "test_plugin",
1793
+ schema_version: "1.0",
1794
+ version_id: sql `(SELECT version_id FROM active_version)`,
1795
+ snapshot_content: {
1796
+ value: "persistent untracked value",
1797
+ },
1798
+ untracked: true,
1799
+ })
1800
+ .execute();
1801
+ // Second session - verify untracked state persists
1802
+ const lix2 = await openLix({ blob: await lix1.toBlob() });
1803
+ const persistedState = await lix2.db
1804
+ .selectFrom("state_all")
1805
+ .where("entity_id", "=", "persistent-entity")
1806
+ .selectAll()
1807
+ .execute();
1808
+ expectDeterministic(persistedState).toHaveLength(1);
1809
+ expectDeterministic(persistedState[0]?.snapshot_content).toEqual({
1810
+ value: "persistent untracked value",
1811
+ });
1812
+ await lix2.close();
1813
+ });
1814
+ simulationTest("untracked state has highest priority in UNION (untracked > tracked > inherited)", async ({ openSimulatedLix, expectDeterministic }) => {
1815
+ const lix = await openSimulatedLix({
1816
+ keyValues: [
1817
+ {
1818
+ key: "lix_deterministic_mode",
1819
+ value: { enabled: true, bootstrap: true },
1820
+ lixcol_version_id: "global",
1821
+ },
1822
+ ],
1823
+ });
1824
+ const mockSchema = {
1825
+ "x-lix-key": "mock_schema",
1826
+ "x-lix-version": "1.0",
1827
+ type: "object",
1828
+ additionalProperties: false,
1829
+ properties: {
1830
+ value: {
1831
+ type: "string",
1832
+ },
1833
+ },
1834
+ };
1835
+ await lix.db
1836
+ .insertInto("stored_schema")
1837
+ .values({ value: mockSchema })
1838
+ .execute();
1839
+ // Step 1: Insert tracked state with "init"
1840
+ await lix.db
1841
+ .insertInto("state_all")
1842
+ .values({
1843
+ entity_id: "entity0",
1844
+ file_id: "test-file",
1845
+ schema_key: "mock_schema",
1846
+ plugin_key: "test_plugin",
1847
+ schema_version: "1.0",
1848
+ version_id: sql `(SELECT version_id FROM active_version)`,
1849
+ snapshot_content: {
1850
+ value: "init",
1851
+ },
1852
+ untracked: false,
1853
+ })
1854
+ .execute();
1855
+ // Verify tracked state exists
1856
+ const afterInit = await lix.db
1857
+ .selectFrom("state_all")
1858
+ .where("entity_id", "=", "entity0")
1859
+ .selectAll()
1860
+ .execute();
1861
+ expectDeterministic(afterInit).toHaveLength(1);
1862
+ expectDeterministic(afterInit[0]?.snapshot_content).toEqual({
1863
+ value: "init",
1864
+ });
1865
+ // Step 2: Update to untracked state with "update" (should NOT delete tracked state)
1866
+ await lix.db
1867
+ .updateTable("state_all")
1868
+ .set({
1869
+ snapshot_content: {
1870
+ value: "update",
1871
+ },
1872
+ untracked: true,
1873
+ })
1874
+ .where("entity_id", "=", "entity0")
1875
+ .where("schema_key", "=", "mock_schema")
1876
+ .execute();
1877
+ // Step 3: Query should return untracked state "update" (highest priority)
1878
+ const afterUntrackedUpdate = await lix.db
1879
+ .selectFrom("state_all")
1880
+ .where("entity_id", "=", "entity0")
1881
+ .selectAll()
1882
+ .execute();
1883
+ expectDeterministic(afterUntrackedUpdate).toHaveLength(1);
1884
+ expectDeterministic(afterUntrackedUpdate[0]?.snapshot_content).toEqual({
1885
+ value: "update",
1886
+ });
1887
+ // Step 4: Update back to tracked state with "update2" (should delete untracked state)
1888
+ await lix.db
1889
+ .updateTable("state_all")
1890
+ .set({
1891
+ snapshot_content: {
1892
+ value: "update2",
1893
+ },
1894
+ untracked: false,
1895
+ })
1896
+ .where("entity_id", "=", "entity0")
1897
+ .where("schema_key", "=", "mock_schema")
1898
+ .execute();
1899
+ // Step 5: Query should return tracked state "update2"
1900
+ const afterTrackedUpdate = await lix.db
1901
+ .selectFrom("state_all")
1902
+ .where("entity_id", "=", "entity0")
1903
+ .selectAll()
1904
+ .execute();
1905
+ expectDeterministic(afterTrackedUpdate).toHaveLength(1);
1906
+ expectDeterministic(afterTrackedUpdate[0]?.snapshot_content).toEqual({
1907
+ value: "update2",
1908
+ });
1909
+ // Verify that a change was created for the final tracked mutation
1910
+ const changes = await lix.db
1911
+ .selectFrom("change")
1912
+ .where("entity_id", "=", "entity0")
1913
+ .where("schema_key", "=", "mock_schema")
1914
+ .selectAll()
1915
+ .execute();
1916
+ expectDeterministic(changes.length).toBeGreaterThan(0);
1917
+ });
1918
+ simulationTest("untracked state overrides inherited state (untracked > inherited)", async ({ openSimulatedLix, expectDeterministic }) => {
1919
+ const lix = await openSimulatedLix({
1920
+ keyValues: [
1921
+ {
1922
+ key: "lix_deterministic_mode",
1923
+ value: { enabled: true, bootstrap: true },
1924
+ lixcol_version_id: "global",
1378
1925
  },
1379
- schema_version: "1.0",
1380
- })
1381
- .execute();
1382
- if (clearCache) {
1383
- // Clear the state cache to force re-materialization with inheritance (CTE path)
1384
- lix.sqlite.exec("DELETE FROM internal_state_cache");
1385
- }
1386
- // If clearCache is false, we test the cache hit path
1387
- // Verify the child initially sees the inherited entity
1388
- const inheritedEntity = await lix.db
1389
- .selectFrom("state_all")
1390
- .where("entity_id", "=", "shared-entity")
1391
- .where("version_id", "=", activeVersion.id)
1392
- .selectAll()
1393
- .execute();
1394
- expect(inheritedEntity).toHaveLength(1);
1395
- expect(inheritedEntity[0]?.version_id).toBe(activeVersion.id);
1396
- expect(inheritedEntity[0]?.inherited_from_version_id).toBe("global");
1397
- // Delete the inherited entity in child version (should create copy-on-write deletion)
1398
- await lix.db
1399
- .deleteFrom("state_all")
1400
- .where("entity_id", "=", "shared-entity")
1401
- .where("version_id", "=", activeVersion.id)
1402
- .execute();
1403
- if (clearCache) {
1404
- // Clear cache after deletion to test CTE path for subsequent queries
1405
- lix.sqlite.exec("DELETE FROM internal_state_cache");
1406
- }
1407
- // Verify the entity is deleted in child version
1408
- const childEntityAfterDelete = await lix.db
1409
- .selectFrom("state_all")
1410
- .where("entity_id", "=", "shared-entity")
1411
- .where("version_id", "=", activeVersion.id)
1412
- .selectAll()
1413
- .execute();
1414
- // Entity should be deleted in child version (copy-on-write deletion)
1415
- expect(childEntityAfterDelete).toHaveLength(0);
1416
- // Verify the entity still exists in global version (not affected by child deletion)
1417
- const inheritedEntityAfterDelete = await lix.db
1418
- .selectFrom("state_all")
1419
- .where("entity_id", "=", "shared-entity")
1420
- .where("version_id", "=", "global")
1421
- .selectAll()
1422
- .execute();
1423
- expect(inheritedEntityAfterDelete).toHaveLength(1);
1424
- expect(inheritedEntityAfterDelete[0]?.snapshot_content).toEqual({
1425
- id: "shared-entity",
1426
- name: "shared Entity",
1427
- });
1428
- // Verify we now only see the global entity through the state view (deletion marker is hidden)
1429
- const allEntities = await lix.db
1430
- .selectFrom("state_all")
1431
- .where("entity_id", "=", "shared-entity")
1432
- .selectAll()
1433
- .execute();
1434
- // Debug: Log what entities we actually got in cache miss scenario
1435
- if (clearCache && allEntities.length !== 1) {
1436
- console.log(`Cache miss scenario returned ${allEntities.length} entities:`, allEntities.map((e) => ({
1437
- version_id: e.version_id,
1438
- inherited_from_version_id: e.inherited_from_version_id,
1439
- snapshot_content: e.snapshot_content,
1440
- })));
1441
- }
1442
- // Both cache hit and cache miss scenarios should behave identically:
1443
- // copy-on-write deletion hides the entity from child but preserves it in parent
1444
- expect(allEntities).toHaveLength(1);
1445
- expect(allEntities[0]?.version_id).toBe("global");
1446
- expect(allEntities[0]?.inherited_from_version_id).toBe(null); // It's the original global entity
1926
+ ],
1447
1927
  });
1448
- });
1449
- // TODO flaky test (ordering of deletions)
1450
- test.todo("deleting without filtering for the version_id deletes the entity from all versions", async () => {
1451
- const lix = await openLix({});
1452
- // Insert an entity into global version
1928
+ const mockSchema = {
1929
+ "x-lix-key": "mock_schema",
1930
+ "x-lix-version": "1.0",
1931
+ type: "object",
1932
+ additionalProperties: false,
1933
+ properties: {
1934
+ value: {
1935
+ type: "string",
1936
+ },
1937
+ },
1938
+ };
1939
+ await lix.db
1940
+ .insertInto("stored_schema")
1941
+ .values({ value: mockSchema })
1942
+ .execute();
1943
+ // Step 1: Insert entity in global version (will be inherited by child)
1453
1944
  await lix.db
1454
1945
  .insertInto("state_all")
1455
1946
  .values({
1456
- entity_id: "shared-entity",
1947
+ entity_id: "inherited-entity",
1457
1948
  file_id: "test-file",
1458
- schema_key: "test_schema",
1949
+ schema_key: "mock_schema",
1459
1950
  plugin_key: "test_plugin",
1951
+ schema_version: "1.0",
1460
1952
  version_id: "global",
1461
1953
  snapshot_content: {
1462
- id: "shared-entity",
1463
- name: "Global Entity",
1954
+ value: "inherited value",
1464
1955
  },
1465
- schema_version: "1.0",
1956
+ untracked: false,
1466
1957
  })
1467
1958
  .execute();
1468
- // Create a child version that inherits from global
1469
- const childVersion = await createVersion({
1470
- lix,
1471
- name: "child-version",
1472
- inherits_from_version_id: "global",
1473
- });
1474
- // Verify inheritance - both global and child should see the entity
1475
- const beforeDelete = await lix.db
1476
- .selectFrom("state_all")
1477
- .where("entity_id", "=", "shared-entity")
1478
- .where("version_id", "in", ["global", childVersion.id])
1479
- .selectAll()
1480
- .execute();
1481
- expect(beforeDelete).toHaveLength(2); // One in global, one inherited in child
1482
- expect(beforeDelete).toMatchObject([
1483
- {
1484
- entity_id: "shared-entity",
1485
- version_id: "global",
1486
- inherited_from_version_id: null,
1487
- snapshot_content: { id: "shared-entity", name: "Global Entity" },
1488
- },
1489
- {
1490
- entity_id: "shared-entity",
1491
- version_id: childVersion.id,
1492
- inherited_from_version_id: "global",
1493
- snapshot_content: { id: "shared-entity", name: "Global Entity" },
1494
- },
1495
- ]);
1496
- await lix.db
1497
- .deleteFrom("state_all")
1498
- .where("entity_id", "=", "shared-entity")
1499
- .where("schema_key", "=", "test_schema")
1500
- .execute();
1501
- const afterDelete = await lix.db
1959
+ // Step 2: Create a child version that inherits from global
1960
+ const childVersion = await createVersion({ lix, name: "child-version" });
1961
+ // Verify inheritance is set up correctly
1962
+ expectDeterministic(childVersion.inherits_from_version_id).toBe("global");
1963
+ // Step 3: Verify child initially sees inherited entity
1964
+ const inheritedState = await lix.db
1502
1965
  .selectFrom("state_all")
1503
- .where("entity_id", "=", "shared-entity")
1966
+ .where("entity_id", "=", "inherited-entity")
1967
+ .where("version_id", "=", childVersion.id)
1504
1968
  .selectAll()
1505
1969
  .execute();
1506
- // Should be deleted from every version
1507
- expect(afterDelete).toHaveLength(0);
1508
- });
1509
- // todo @martin-lysk the insert or ignore is not working as expected
1510
- // i am not fixing this now to avoid merge conflicts in the xUpdate function
1511
- test.todo("INSERT OR IGNORE into state virtual table should not throw validation errors for duplicates or update the row", async () => {
1512
- const lix = await openLix({});
1513
- // First, insert a record successfully
1970
+ expectDeterministic(inheritedState).toHaveLength(1);
1971
+ expectDeterministic(inheritedState[0]?.snapshot_content).toEqual({
1972
+ value: "inherited value",
1973
+ });
1974
+ expectDeterministic(inheritedState[0]?.inherited_from_version_id).toBe("global");
1975
+ // Step 4: Add untracked state for same entity in child version
1514
1976
  await lix.db
1515
1977
  .insertInto("state_all")
1516
1978
  .values({
1517
- entity_id: "test-duplicate-entity",
1518
- schema_key: "test_schema",
1519
- file_id: "test",
1979
+ entity_id: "inherited-entity",
1980
+ file_id: "test-file",
1981
+ schema_key: "mock_schema",
1520
1982
  plugin_key: "test_plugin",
1521
- snapshot_content: { id: "test-duplicate-entity", name: "Original" },
1522
1983
  schema_version: "1.0",
1523
- version_id: "global",
1984
+ version_id: childVersion.id,
1985
+ snapshot_content: {
1986
+ value: "untracked override",
1987
+ },
1988
+ untracked: true,
1524
1989
  })
1525
1990
  .execute();
1526
- // Verify the record exists
1527
- const originalRecord = await lix.db
1991
+ // Step 5: Query should return untracked state (higher priority than inherited)
1992
+ const finalState = await lix.db
1528
1993
  .selectFrom("state_all")
1529
- .where("entity_id", "=", "test-duplicate-entity")
1994
+ .where("entity_id", "=", "inherited-entity")
1995
+ .where("version_id", "=", childVersion.id)
1530
1996
  .selectAll()
1531
- .executeTakeFirst();
1532
- expect(originalRecord).toBeDefined();
1533
- expect(originalRecord?.snapshot_content).toMatchObject({
1534
- id: "test-duplicate-entity",
1535
- name: "Original",
1536
- });
1537
- // Now try to INSERT OR IGNORE the same entity - this should NOT throw an error
1538
- // but currently it does because validation runs before OR IGNORE logic
1539
- expect(() => {
1540
- lix.sqlite.exec(`
1541
- INSERT OR IGNORE INTO state (
1542
- entity_id, schema_key, file_id, plugin_key,
1543
- snapshot_content, schema_version, version_id
1544
- ) VALUES (
1545
- 'test-duplicate-entity', 'test_schema', 'test', 'test_plugin',
1546
- '{"id":"test-duplicate-entity","name":"Duplicate"}', '1.0', 'global'
1547
- )
1548
- `);
1549
- }).not.toThrow(); // This should not throw, but currently does
1550
- // Verify the original record is unchanged (OR IGNORE should have ignored the duplicate)
1551
- const afterIgnore = await lix.db
1997
+ .execute();
1998
+ expectDeterministic(finalState).toHaveLength(1);
1999
+ expectDeterministic(finalState[0]?.snapshot_content).toEqual({
2000
+ value: "untracked override",
2001
+ });
2002
+ expectDeterministic(finalState[0]?.inherited_from_version_id).toBe(null); // Should not be inherited anymore
2003
+ expectDeterministic(finalState[0]?.version_id).toBe(childVersion.id);
2004
+ // Step 6: Verify the inherited entity still exists in global version (unchanged)
2005
+ const globalState = await lix.db
1552
2006
  .selectFrom("state_all")
1553
- .where("entity_id", "=", "test-duplicate-entity")
2007
+ .where("entity_id", "=", "inherited-entity")
2008
+ .where("version_id", "=", "global")
1554
2009
  .selectAll()
1555
- .executeTakeFirst();
1556
- expect(afterIgnore?.snapshot_content).toMatchObject({
1557
- id: "test-duplicate-entity",
1558
- name: "Original", // Should still be original, not "Duplicate"
2010
+ .execute();
2011
+ expectDeterministic(globalState).toHaveLength(1);
2012
+ expectDeterministic(globalState[0]?.snapshot_content).toEqual({
2013
+ value: "inherited value",
1559
2014
  });
2015
+ expectDeterministic(globalState[0]?.inherited_from_version_id).toBe(null);
2016
+ // Step 7: No changes should be created for untracked mutations
2017
+ const changes = await lix.db
2018
+ .selectFrom("change")
2019
+ .where("entity_id", "=", "inherited-entity")
2020
+ .where("schema_key", "=", "mock_schema")
2021
+ .selectAll()
2022
+ .execute();
2023
+ // Should only have the original change from global version, not the untracked one
2024
+ expectDeterministic(changes).toHaveLength(1);
1560
2025
  });
1561
- test("should emit state_commit hook when database transaction commits", async () => {
1562
- const lix = await openLix({});
2026
+ simulationTest("untracked state inheritance", async ({ openSimulatedLix, expectDeterministic }) => {
2027
+ const lix = await openSimulatedLix({
2028
+ keyValues: [
2029
+ {
2030
+ key: "lix_deterministic_mode",
2031
+ value: { enabled: true, bootstrap: true },
2032
+ lixcol_version_id: "global",
2033
+ },
2034
+ ],
2035
+ });
1563
2036
  const mockSchema = {
1564
2037
  "x-lix-key": "mock_schema",
1565
2038
  "x-lix-version": "1.0",
@@ -1572,46 +2045,56 @@ test("should emit state_commit hook when database transaction commits", async ()
1572
2045
  },
1573
2046
  };
1574
2047
  await lix.db
1575
- .insertInto("stored_schema")
1576
- .values({ value: mockSchema })
2048
+ .insertInto("stored_schema_all")
2049
+ .values({ value: mockSchema, lixcol_version_id: "global" })
1577
2050
  .execute();
1578
- // Set up hook listener
1579
- let hookCallCount = 0;
1580
- lix.hooks.onStateCommit(() => {
1581
- hookCallCount++;
1582
- });
1583
- // Perform a database operation that should trigger the hook
2051
+ const activeVersion = await lix.db
2052
+ .selectFrom("active_version")
2053
+ .innerJoin("version", "active_version.version_id", "version.id")
2054
+ .selectAll("version")
2055
+ .executeTakeFirstOrThrow();
2056
+ // inserting into the global version
1584
2057
  await lix.db
1585
2058
  .insertInto("state_all")
1586
2059
  .values({
1587
- entity_id: "test-entity",
1588
2060
  file_id: "test-file",
1589
2061
  schema_key: "mock_schema",
1590
2062
  plugin_key: "test_plugin",
1591
2063
  schema_version: "1.0",
1592
- version_id: sql `(SELECT version_id FROM active_version)`,
1593
- snapshot_content: {
1594
- value: "test value",
1595
- },
1596
- })
1597
- .execute();
1598
- // Hook should have been called once
1599
- expect(hookCallCount).toBe(1);
1600
- // Perform another operation
1601
- await lix.db
1602
- .updateTable("state_all")
1603
- .set({
2064
+ entity_id: "test_key",
1604
2065
  snapshot_content: {
1605
- value: "updated value",
2066
+ value: "test_value",
1606
2067
  },
2068
+ version_id: "global",
2069
+ untracked: true,
1607
2070
  })
1608
- .where("entity_id", "=", "test-entity")
1609
2071
  .execute();
1610
- // Hook should have been called twice now
1611
- expect(hookCallCount).toBe(2);
2072
+ const globalState = await lix.db
2073
+ .selectFrom("state_all")
2074
+ .where("entity_id", "=", "test_key")
2075
+ .where("version_id", "=", "global")
2076
+ .select("snapshot_content")
2077
+ .executeTakeFirstOrThrow();
2078
+ expectDeterministic(globalState).toBeDefined();
2079
+ const versionState = await lix.db
2080
+ .selectFrom("state_all")
2081
+ .where("entity_id", "=", "test_key")
2082
+ .where("version_id", "=", activeVersion.id)
2083
+ .select("snapshot_content")
2084
+ .executeTakeFirstOrThrow();
2085
+ expectDeterministic(versionState).toBeDefined();
2086
+ expectDeterministic(versionState).toEqual(globalState);
1612
2087
  });
1613
- test("untracked mutations don't trigger change control", async () => {
1614
- const lix = await openLix({});
2088
+ simulationTest("tracked state in child overrides inherited untracked state", async ({ openSimulatedLix, expectDeterministic }) => {
2089
+ const lix = await openSimulatedLix({
2090
+ keyValues: [
2091
+ {
2092
+ key: "lix_deterministic_mode",
2093
+ value: { enabled: true, bootstrap: true },
2094
+ lixcol_version_id: "global",
2095
+ },
2096
+ ],
2097
+ });
1615
2098
  const mockSchema = {
1616
2099
  "x-lix-key": "mock_schema",
1617
2100
  "x-lix-version": "1.0",
@@ -1624,99 +2107,73 @@ test("untracked mutations don't trigger change control", async () => {
1624
2107
  },
1625
2108
  };
1626
2109
  await lix.db
1627
- .insertInto("stored_schema")
2110
+ .insertInto("stored_schema") // Use stored_schema, not stored_schema_all
1628
2111
  .values({ value: mockSchema })
1629
2112
  .execute();
1630
- // Count changes before any untracked mutations
1631
- const changesInitial = await lix.db
1632
- .selectFrom("change")
1633
- .selectAll()
1634
- .execute();
1635
- // 1. INSERT untracked state
2113
+ const childVersion = await createVersion({ lix, name: "child" });
2114
+ // 1. Insert untracked state in global version
1636
2115
  await lix.db
1637
2116
  .insertInto("state_all")
1638
2117
  .values({
1639
- entity_id: "untracked-entity",
1640
- file_id: "test-file",
2118
+ entity_id: "override_test",
2119
+ file_id: "f1",
1641
2120
  schema_key: "mock_schema",
1642
- plugin_key: "test_plugin",
2121
+ plugin_key: "p1",
1643
2122
  schema_version: "1.0",
1644
- version_id: sql `(SELECT version_id FROM active_version)`,
1645
- snapshot_content: {
1646
- value: "untracked value",
1647
- },
2123
+ snapshot_content: { value: "global untracked" },
2124
+ version_id: "global",
1648
2125
  untracked: true,
1649
2126
  })
1650
2127
  .execute();
1651
- // Count changes after untracked insert
1652
- const changesAfterInsert = await lix.db
1653
- .selectFrom("change")
1654
- .selectAll()
1655
- .execute();
1656
- // Number of changes should be identical (no change control for untracked)
1657
- expect(changesAfterInsert.length).toBe(changesInitial.length);
1658
- // Verify the untracked entity exists in state view
1659
- const untrackedState = await lix.db
2128
+ // 2. Verify child inherits untracked state
2129
+ const inheritedState = await lix.db
1660
2130
  .selectFrom("state_all")
1661
- .where("entity_id", "=", "untracked-entity")
2131
+ .where("entity_id", "=", "override_test")
2132
+ .where("version_id", "=", childVersion.id)
1662
2133
  .selectAll()
1663
2134
  .execute();
1664
- expect(untrackedState).toHaveLength(1);
1665
- expect(untrackedState[0]?.snapshot_content).toEqual({
1666
- value: "untracked value",
2135
+ expectDeterministic(inheritedState).toHaveLength(1);
2136
+ expectDeterministic(inheritedState[0]?.snapshot_content).toEqual({
2137
+ value: "global untracked",
1667
2138
  });
1668
- expect(untrackedState[0]?.untracked).toBe(1);
1669
- // 2. UPDATE untracked state
2139
+ expectDeterministic(inheritedState[0]?.untracked).toBe(1);
2140
+ // 3. Insert tracked state in child version for same entity
1670
2141
  await lix.db
1671
- .updateTable("state_all")
1672
- .where("entity_id", "=", "untracked-entity")
1673
- .set({
1674
- snapshot_content: {
1675
- value: "untracked value updated",
1676
- },
1677
- untracked: true,
2142
+ .insertInto("state_all")
2143
+ .values({
2144
+ entity_id: "override_test",
2145
+ file_id: "f1",
2146
+ schema_key: "mock_schema",
2147
+ plugin_key: "p1",
2148
+ schema_version: "1.0",
2149
+ snapshot_content: { value: "child tracked" },
2150
+ version_id: childVersion.id,
2151
+ untracked: false, // Important: this is tracked state
1678
2152
  })
1679
2153
  .execute();
1680
- // Count changes after untracked update
1681
- const changesAfterUpdate = await lix.db
1682
- .selectFrom("change")
1683
- .selectAll()
1684
- .execute();
1685
- // Number of changes should still be identical (no change control for untracked)
1686
- expect(changesAfterUpdate.length).toBe(changesInitial.length);
1687
- // Verify the untracked entity was updated
1688
- const updatedState = await lix.db
2154
+ // 4. Verify child now sees tracked state, not inherited untracked
2155
+ const finalState = await lix.db
1689
2156
  .selectFrom("state_all")
1690
- .where("entity_id", "=", "untracked-entity")
2157
+ .where("entity_id", "=", "override_test")
2158
+ .where("version_id", "=", childVersion.id)
1691
2159
  .selectAll()
1692
2160
  .execute();
1693
- expect(updatedState).toHaveLength(1);
1694
- expect(updatedState[0]?.snapshot_content).toEqual({
1695
- value: "untracked value updated",
2161
+ expectDeterministic(finalState).toHaveLength(1);
2162
+ expectDeterministic(finalState[0]?.snapshot_content).toEqual({
2163
+ value: "child tracked",
1696
2164
  });
1697
- expect(updatedState[0]?.untracked).toBe(1);
1698
- // 3. DELETE untracked state
1699
- await lix.db
1700
- .deleteFrom("state_all")
1701
- .where("entity_id", "=", "untracked-entity")
1702
- .execute();
1703
- // Count changes after untracked delete
1704
- const changesAfterDelete = await lix.db
1705
- .selectFrom("change")
1706
- .selectAll()
1707
- .execute();
1708
- // Number of changes should still be identical (no change control for untracked)
1709
- expect(changesAfterDelete.length).toBe(changesInitial.length);
1710
- // Verify the untracked entity was deleted
1711
- const deletedState = await lix.db
1712
- .selectFrom("state_all")
1713
- .where("entity_id", "=", "untracked-entity")
1714
- .selectAll()
1715
- .execute();
1716
- expect(deletedState).toHaveLength(0);
2165
+ expectDeterministic(finalState[0]?.untracked).toBe(0); // Should be tracked
1717
2166
  });
1718
- test("tracked update to previously untracked entity deletes untracked state", async () => {
1719
- const lix = await openLix({});
2167
+ simulationTest("untracked state in child overrides inherited untracked state", async ({ openSimulatedLix, expectDeterministic }) => {
2168
+ const lix = await openSimulatedLix({
2169
+ keyValues: [
2170
+ {
2171
+ key: "lix_deterministic_mode",
2172
+ value: { enabled: true, bootstrap: true },
2173
+ lixcol_version_id: "global",
2174
+ },
2175
+ ],
2176
+ });
1720
2177
  const mockSchema = {
1721
2178
  "x-lix-key": "mock_schema",
1722
2179
  "x-lix-version": "1.0",
@@ -1729,67 +2186,73 @@ test("tracked update to previously untracked entity deletes untracked state", as
1729
2186
  },
1730
2187
  };
1731
2188
  await lix.db
1732
- .insertInto("stored_schema")
2189
+ .insertInto("stored_schema") // Use stored_schema
1733
2190
  .values({ value: mockSchema })
1734
2191
  .execute();
1735
- // Insert untracked state
2192
+ const childVersion = await createVersion({ lix, name: "child" });
2193
+ // 1. Insert untracked state in global version
1736
2194
  await lix.db
1737
2195
  .insertInto("state_all")
1738
2196
  .values({
1739
- entity_id: "override-entity",
1740
- file_id: "test-file",
2197
+ entity_id: "untracked_override_test",
2198
+ file_id: "f1",
1741
2199
  schema_key: "mock_schema",
1742
- plugin_key: "test_plugin",
2200
+ plugin_key: "p1",
1743
2201
  schema_version: "1.0",
1744
- version_id: sql `(SELECT version_id FROM active_version)`,
1745
- snapshot_content: {
1746
- value: "untracked value",
1747
- },
2202
+ snapshot_content: { value: "global untracked" },
2203
+ version_id: "global",
1748
2204
  untracked: true,
1749
2205
  })
1750
2206
  .execute();
1751
- // Verify untracked state exists
1752
- const untrackedState = await lix.db
2207
+ // 2. Verify child inherits untracked state
2208
+ const inheritedState = await lix.db
1753
2209
  .selectFrom("state_all")
1754
- .where("entity_id", "=", "override-entity")
2210
+ .where("entity_id", "=", "untracked_override_test")
2211
+ .where("version_id", "=", childVersion.id)
1755
2212
  .selectAll()
1756
2213
  .execute();
1757
- expect(untrackedState).toHaveLength(1);
1758
- expect(untrackedState[0]?.snapshot_content).toEqual({
1759
- value: "untracked value",
2214
+ expectDeterministic(inheritedState).toHaveLength(1);
2215
+ expectDeterministic(inheritedState[0]?.snapshot_content).toEqual({
2216
+ value: "global untracked",
1760
2217
  });
1761
- // Now update the untracked entity to make it tracked (should delete from untracked table)
2218
+ expectDeterministic(inheritedState[0]?.untracked).toBe(1);
2219
+ // 3. Insert untracked state in child version for same entity
1762
2220
  await lix.db
1763
- .updateTable("state_all")
1764
- .set({
1765
- snapshot_content: {
1766
- value: "tracked value",
1767
- },
1768
- untracked: false,
2221
+ .insertInto("state_all")
2222
+ .values({
2223
+ entity_id: "untracked_override_test",
2224
+ file_id: "f1",
2225
+ schema_key: "mock_schema",
2226
+ plugin_key: "p1",
2227
+ schema_version: "1.0",
2228
+ snapshot_content: { value: "child untracked" },
2229
+ version_id: childVersion.id,
2230
+ untracked: true,
1769
2231
  })
1770
- .where("entity_id", "=", "override-entity")
1771
- .where("schema_key", "=", "mock_schema")
1772
2232
  .execute();
1773
- // Verify tracked state has overridden untracked state
2233
+ // 4. Verify child now sees its own untracked state
1774
2234
  const finalState = await lix.db
1775
- .selectFrom("state_all")
1776
- .where("entity_id", "=", "override-entity")
1777
- .selectAll()
1778
- .execute();
1779
- expect(finalState).toHaveLength(1);
1780
- expect(finalState[0]?.snapshot_content).toEqual({
1781
- value: "tracked value",
1782
- });
1783
- // Verify a change was created for the tracked mutation
1784
- const changes = await lix.db
1785
- .selectFrom("change")
1786
- .where("entity_id", "=", "override-entity")
1787
- .where("schema_key", "=", "mock_schema")
2235
+ .selectFrom("state_all")
2236
+ .where("entity_id", "=", "untracked_override_test")
2237
+ .where("version_id", "=", childVersion.id)
1788
2238
  .selectAll()
1789
2239
  .execute();
1790
- expect(changes.length).toBeGreaterThan(0);
2240
+ expectDeterministic(finalState).toHaveLength(1);
2241
+ expectDeterministic(finalState[0]?.snapshot_content).toEqual({
2242
+ value: "child untracked",
2243
+ });
2244
+ expectDeterministic(finalState[0]?.untracked).toBe(1);
1791
2245
  });
1792
- test("untracked state is persisted across lix sessions", async () => {
2246
+ simulationTest("untracked state has untracked change_id for both inherited and non-inherited entities", async ({ openSimulatedLix, expectDeterministic }) => {
2247
+ const lix = await openSimulatedLix({
2248
+ keyValues: [
2249
+ {
2250
+ key: "lix_deterministic_mode",
2251
+ value: { enabled: true, bootstrap: true },
2252
+ lixcol_version_id: "global",
2253
+ },
2254
+ ],
2255
+ });
1793
2256
  const mockSchema = {
1794
2257
  "x-lix-key": "mock_schema",
1795
2258
  "x-lix-version": "1.0",
@@ -1801,42 +2264,62 @@ test("untracked state is persisted across lix sessions", async () => {
1801
2264
  },
1802
2265
  },
1803
2266
  };
1804
- // First session - create and insert untracked state
1805
- const lix1 = await openLix({});
1806
- await lix1.db
2267
+ await lix.db
1807
2268
  .insertInto("stored_schema")
1808
2269
  .values({ value: mockSchema })
1809
2270
  .execute();
1810
- await lix1.db
2271
+ const childVersion = await createVersion({ lix, name: "child" });
2272
+ // 1. Insert untracked state in global version (will be inherited by child)
2273
+ await lix.db
1811
2274
  .insertInto("state_all")
1812
2275
  .values({
1813
- entity_id: "persistent-entity",
2276
+ entity_id: "inherited-entity",
1814
2277
  file_id: "test-file",
1815
2278
  schema_key: "mock_schema",
1816
2279
  plugin_key: "test_plugin",
1817
2280
  schema_version: "1.0",
1818
- version_id: sql `(SELECT version_id FROM active_version)`,
1819
- snapshot_content: {
1820
- value: "persistent untracked value",
1821
- },
2281
+ snapshot_content: { value: "global untracked" },
2282
+ version_id: "global",
1822
2283
  untracked: true,
1823
2284
  })
1824
2285
  .execute();
1825
- // Second session - verify untracked state persists
1826
- const lix2 = await openLix({ blob: await lix1.toBlob() });
1827
- const persistedState = await lix2.db
2286
+ // 2. Insert untracked state directly in child version (non-inherited)
2287
+ await lix.db
2288
+ .insertInto("state_all")
2289
+ .values({
2290
+ entity_id: "non-inherited-entity",
2291
+ file_id: "test-file",
2292
+ schema_key: "mock_schema",
2293
+ plugin_key: "test_plugin",
2294
+ schema_version: "1.0",
2295
+ snapshot_content: { value: "child untracked" },
2296
+ version_id: childVersion.id,
2297
+ untracked: true,
2298
+ })
2299
+ .execute();
2300
+ // 3. Query all untracked entities in child version
2301
+ const untrackedEntities = await lix.db
1828
2302
  .selectFrom("state_all")
1829
- .where("entity_id", "=", "persistent-entity")
2303
+ .where("version_id", "=", childVersion.id)
2304
+ .where("entity_id", "in", ["inherited-entity", "non-inherited-entity"])
2305
+ .where("untracked", "=", true)
1830
2306
  .selectAll()
1831
2307
  .execute();
1832
- expect(persistedState).toHaveLength(1);
1833
- expect(persistedState[0]?.snapshot_content).toEqual({
1834
- value: "persistent untracked value",
1835
- });
1836
- await lix2.close();
2308
+ expectDeterministic(untrackedEntities).toHaveLength(2);
2309
+ // 4. Check that both entities have untracked change_id
2310
+ for (const entity of untrackedEntities) {
2311
+ expectDeterministic(entity.change_id).toBe("untracked");
2312
+ }
2313
+ // 5. Verify specific entities
2314
+ const inheritedEntity = untrackedEntities.find((e) => e.entity_id === "inherited-entity");
2315
+ const nonInheritedEntity = untrackedEntities.find((e) => e.entity_id === "non-inherited-entity");
2316
+ expectDeterministic(inheritedEntity).toBeDefined();
2317
+ expectDeterministic(nonInheritedEntity).toBeDefined();
2318
+ // Both inherited and non-inherited untracked entities should have change_id = "untracked"
2319
+ expectDeterministic(inheritedEntity?.change_id).toBe("untracked");
2320
+ expectDeterministic(nonInheritedEntity?.change_id).toBe("untracked");
1837
2321
  });
1838
- test("untracked state has highest priority in UNION (untracked > tracked > inherited)", async () => {
1839
- const lix = await openLix({});
2322
+ simulationTest("state version_id defaults active version", async ({ openSimulatedLix, expectDeterministic }) => {
1840
2323
  const mockSchema = {
1841
2324
  "x-lix-key": "mock_schema",
1842
2325
  "x-lix-version": "1.0",
@@ -1848,183 +2331,371 @@ test("untracked state has highest priority in UNION (untracked > tracked > inher
1848
2331
  },
1849
2332
  },
1850
2333
  };
2334
+ const lix = await openSimulatedLix({
2335
+ keyValues: [
2336
+ {
2337
+ key: "lix_deterministic_mode",
2338
+ value: { enabled: true, bootstrap: true },
2339
+ lixcol_version_id: "global",
2340
+ },
2341
+ ],
2342
+ });
1851
2343
  await lix.db
1852
2344
  .insertInto("stored_schema")
1853
2345
  .values({ value: mockSchema })
1854
2346
  .execute();
1855
- // Step 1: Insert tracked state with "init"
2347
+ // Get the active version ID to verify it gets auto-filled
2348
+ const activeVersion = await lix.db
2349
+ .selectFrom("active_version")
2350
+ .select("version_id")
2351
+ .executeTakeFirstOrThrow();
2352
+ // Insert into state view without specifying version_id
2353
+ // This should auto-fill with the active version
1856
2354
  await lix.db
1857
- .insertInto("state_all")
2355
+ .insertInto("state")
1858
2356
  .values({
1859
2357
  entity_id: "entity0",
1860
- file_id: "test-file",
2358
+ file_id: "f0",
1861
2359
  schema_key: "mock_schema",
1862
- plugin_key: "test_plugin",
2360
+ plugin_key: "lix_own_entity",
1863
2361
  schema_version: "1.0",
1864
- version_id: sql `(SELECT version_id FROM active_version)`,
1865
- snapshot_content: {
1866
- value: "init",
1867
- },
1868
- untracked: false,
2362
+ snapshot_content: { value: "initial content" },
1869
2363
  })
1870
2364
  .execute();
1871
- // Verify tracked state exists
1872
- const afterInit = await lix.db
1873
- .selectFrom("state_all")
2365
+ // Verify the entity was inserted with the correct version_id
2366
+ const insertedEntity = await lix.db
2367
+ .selectFrom("state")
1874
2368
  .where("entity_id", "=", "entity0")
1875
2369
  .selectAll()
1876
2370
  .execute();
1877
- expect(afterInit).toHaveLength(1);
1878
- expect(afterInit[0]?.snapshot_content).toEqual({ value: "init" });
1879
- // Step 2: Update to untracked state with "update" (should NOT delete tracked state)
2371
+ expectDeterministic(insertedEntity).toHaveLength(1);
2372
+ expectDeterministic(insertedEntity[0]).toMatchObject({
2373
+ entity_id: "entity0",
2374
+ file_id: "f0",
2375
+ schema_key: "mock_schema",
2376
+ plugin_key: "lix_own_entity",
2377
+ schema_version: "1.0",
2378
+ snapshot_content: { value: "initial content" },
2379
+ });
2380
+ // Verify the version_id was auto-filled with the active version
2381
+ const entityInStateAll = await lix.db
2382
+ .selectFrom("state_all")
2383
+ .where("entity_id", "=", "entity0")
2384
+ .select("version_id")
2385
+ .executeTakeFirstOrThrow();
2386
+ expectDeterministic(entityInStateAll.version_id).toBe(activeVersion.version_id);
2387
+ // Test update operation
1880
2388
  await lix.db
1881
- .updateTable("state_all")
2389
+ .updateTable("state")
2390
+ .where("entity_id", "=", "entity0")
1882
2391
  .set({
1883
- snapshot_content: {
1884
- value: "update",
1885
- },
1886
- untracked: true,
2392
+ snapshot_content: { value: "updated content" },
1887
2393
  })
1888
- .where("entity_id", "=", "entity0")
1889
- .where("schema_key", "=", "mock_schema")
1890
2394
  .execute();
1891
- // Step 3: Query should return untracked state "update" (highest priority)
1892
- const afterUntrackedUpdate = await lix.db
1893
- .selectFrom("state_all")
2395
+ // Verify update worked
2396
+ const updatedEntity = await lix.db
2397
+ .selectFrom("state")
1894
2398
  .where("entity_id", "=", "entity0")
1895
2399
  .selectAll()
1896
2400
  .execute();
1897
- expect(afterUntrackedUpdate).toHaveLength(1);
1898
- expect(afterUntrackedUpdate[0]?.snapshot_content).toEqual({
1899
- value: "update",
2401
+ expectDeterministic(updatedEntity[0]?.snapshot_content).toEqual({
2402
+ value: "updated content",
1900
2403
  });
1901
- // Step 4: Update back to tracked state with "update2" (should delete untracked state)
2404
+ // Test delete operation
1902
2405
  await lix.db
1903
- .updateTable("state_all")
1904
- .set({
1905
- snapshot_content: {
1906
- value: "update2",
1907
- },
1908
- untracked: false,
1909
- })
2406
+ .deleteFrom("state")
1910
2407
  .where("entity_id", "=", "entity0")
1911
- .where("schema_key", "=", "mock_schema")
1912
2408
  .execute();
1913
- // Step 5: Query should return tracked state "update2"
1914
- const afterTrackedUpdate = await lix.db
1915
- .selectFrom("state_all")
2409
+ // Verify delete worked
2410
+ const deletedEntity = await lix.db
2411
+ .selectFrom("state")
1916
2412
  .where("entity_id", "=", "entity0")
1917
2413
  .selectAll()
1918
2414
  .execute();
1919
- expect(afterTrackedUpdate).toHaveLength(1);
1920
- expect(afterTrackedUpdate[0]?.snapshot_content).toEqual({ value: "update2" });
1921
- // Verify that a change was created for the final tracked mutation
1922
- const changes = await lix.db
1923
- .selectFrom("change")
1924
- .where("entity_id", "=", "entity0")
1925
- .where("schema_key", "=", "mock_schema")
2415
+ expectDeterministic(deletedEntity).toHaveLength(0);
2416
+ });
2417
+ // https://github.com/opral/lix-sdk/issues/344
2418
+ simulationTest("deleting key_value entities from state should not cause infinite loop", async ({ openSimulatedLix, expectDeterministic }) => {
2419
+ const lix = await openSimulatedLix({
2420
+ keyValues: [
2421
+ {
2422
+ key: "lix_deterministic_mode",
2423
+ value: { enabled: true, bootstrap: true },
2424
+ lixcol_version_id: "global",
2425
+ },
2426
+ ],
2427
+ });
2428
+ // 1. Insert key_value in global version (tracked)
2429
+ await lix.db
2430
+ .insertInto("key_value_all")
2431
+ .values({
2432
+ key: "test-key-global",
2433
+ value: "global-tracked-value",
2434
+ lixcol_version_id: "global",
2435
+ })
2436
+ .execute();
2437
+ // 2. Insert key_value in global version (untracked)
2438
+ await lix.db
2439
+ .insertInto("key_value_all")
2440
+ .values({
2441
+ key: "test-key-global-untracked",
2442
+ value: "global-untracked-value",
2443
+ lixcol_version_id: "global",
2444
+ lixcol_untracked: true,
2445
+ })
2446
+ .execute();
2447
+ // 3. Insert key_value in active version (tracked)
2448
+ await lix.db
2449
+ .insertInto("key_value")
2450
+ .values({
2451
+ key: "test-key-active",
2452
+ value: "active-tracked-value",
2453
+ })
2454
+ .execute();
2455
+ // 4. Insert key_value in active version (untracked)
2456
+ await lix.db
2457
+ .insertInto("key_value")
2458
+ .values({
2459
+ key: "test-key-active-untracked",
2460
+ value: "active-untracked-value",
2461
+ lixcol_untracked: true,
2462
+ })
2463
+ .execute();
2464
+ // Verify all entities exist before deletion (including inherited)
2465
+ const entitiesBeforeDelete = await lix.db
2466
+ .selectFrom("state")
2467
+ .where("schema_key", "=", "lix_key_value")
2468
+ .where("entity_id", "like", "test-key-%")
1926
2469
  .selectAll()
1927
2470
  .execute();
1928
- expect(changes.length).toBeGreaterThan(0);
2471
+ // state view shows active version entities + inherited from global
2472
+ expectDeterministic(entitiesBeforeDelete).toHaveLength(4);
2473
+ // Delete all key_value entities
2474
+ // this is the reproduction of the infinite loop issue
2475
+ await lix.db
2476
+ .deleteFrom("state")
2477
+ .where("schema_key", "=", "lix_key_value")
2478
+ .execute();
2479
+ // Verify all entities are deleted
2480
+ const keyValueAfterDelete = await lix.db
2481
+ .selectFrom("state")
2482
+ .where("schema_key", "=", "lix_key_value")
2483
+ .where("entity_id", "like", "test-key-%")
2484
+ .selectAll()
2485
+ .execute();
2486
+ expectDeterministic(keyValueAfterDelete).toHaveLength(0);
1929
2487
  });
1930
- test("untracked state overrides inherited state (untracked > inherited)", async () => {
1931
- const lix = await openLix({});
1932
- const mockSchema = {
1933
- "x-lix-key": "mock_schema",
1934
- "x-lix-version": "1.0",
1935
- type: "object",
1936
- additionalProperties: false,
1937
- properties: {
1938
- value: {
1939
- type: "string",
2488
+ // see https://github.com/opral/lix-sdk/issues/359
2489
+ simulationTest("commit_id in state should be from the real auto-commit, not the working commit", async ({ openSimulatedLix, expectDeterministic }) => {
2490
+ const lix = await openSimulatedLix({
2491
+ keyValues: [
2492
+ {
2493
+ key: "lix_deterministic_mode",
2494
+ value: { enabled: true, bootstrap: true },
2495
+ lixcol_version_id: "global",
1940
2496
  },
1941
- },
1942
- };
2497
+ ],
2498
+ });
2499
+ // Get the active version with its commit_id and working_commit_id
2500
+ const activeVersion = await lix.db
2501
+ .selectFrom("active_version")
2502
+ .innerJoin("version", "version.id", "active_version.version_id")
2503
+ .selectAll("version")
2504
+ .executeTakeFirstOrThrow();
2505
+ // Verify we have both commit_id and working_commit_id
2506
+ expectDeterministic(activeVersion.commit_id).toBeTruthy();
2507
+ expectDeterministic(activeVersion.working_commit_id).toBeTruthy();
2508
+ expectDeterministic(activeVersion.commit_id).not.toBe(activeVersion.working_commit_id);
2509
+ const commitsBeforeInsert = await lix.db
2510
+ .selectFrom("commit")
2511
+ .select("id")
2512
+ .execute();
2513
+ // Insert some state data
1943
2514
  await lix.db
1944
- .insertInto("stored_schema")
1945
- .values({ value: mockSchema })
2515
+ .insertInto("state")
2516
+ .values({
2517
+ entity_id: "test-entity-1",
2518
+ schema_key: "test_schema",
2519
+ file_id: "test-file",
2520
+ plugin_key: "test-plugin",
2521
+ schema_version: "1.0",
2522
+ snapshot_content: { value: "initial value" },
2523
+ })
1946
2524
  .execute();
1947
- // Step 1: Insert entity in global version (will be inherited by child)
2525
+ const commitsAfterInsert = await lix.db
2526
+ .selectFrom("commit")
2527
+ .select("id")
2528
+ .execute();
2529
+ // two commits for the global and active version
2530
+ expectDeterministic(commitsAfterInsert.length).toBe(commitsBeforeInsert.length + 2);
2531
+ const activeVersionAfterInsert = await lix.db
2532
+ .selectFrom("active_version")
2533
+ .innerJoin("version", "active_version.version_id", "version.id")
2534
+ .selectAll("version")
2535
+ .executeTakeFirstOrThrow();
2536
+ // Query the state to check the commit_id
2537
+ const stateAfterInsert = await lix.db
2538
+ .selectFrom("state")
2539
+ .where("entity_id", "=", "test-entity-1")
2540
+ .select(["entity_id", "commit_id"])
2541
+ .executeTakeFirstOrThrow();
2542
+ // The commit_id should NOT be the working_commit_id
2543
+ expectDeterministic(stateAfterInsert.commit_id).not.toBe(activeVersionAfterInsert.working_commit_id);
2544
+ // The commit_id should be the auto-commit ID (not the working commit)
2545
+ expectDeterministic(stateAfterInsert.commit_id).toBe(activeVersionAfterInsert.commit_id);
2546
+ // Update the state to trigger another auto-commit
1948
2547
  await lix.db
1949
- .insertInto("state_all")
2548
+ .updateTable("state")
2549
+ .where("entity_id", "=", "test-entity-1")
2550
+ .set({ snapshot_content: { value: "updated value" } })
2551
+ .execute();
2552
+ // Check the state again
2553
+ const stateAfterUpdate = await lix.db
2554
+ .selectFrom("state")
2555
+ .where("entity_id", "=", "test-entity-1")
2556
+ .select(["entity_id", "commit_id"])
2557
+ .executeTakeFirstOrThrow();
2558
+ const activeVersionAfterUpdate = await lix.db
2559
+ .selectFrom("active_version")
2560
+ .innerJoin("version", "active_version.version_id", "version.id")
2561
+ .selectAll("version")
2562
+ .executeTakeFirstOrThrow();
2563
+ // The commit_id should now be the new auto-commit ID
2564
+ expectDeterministic(stateAfterUpdate.commit_id).toBe(activeVersionAfterUpdate.commit_id);
2565
+ expectDeterministic(stateAfterUpdate.commit_id).not.toBe(activeVersion.working_commit_id);
2566
+ });
2567
+ simulationTest("delete ALL from state view should delete untracked entities", async ({ openSimulatedLix, expectDeterministic }) => {
2568
+ const lix = await openSimulatedLix({
2569
+ keyValues: [
2570
+ {
2571
+ key: "lix_deterministic_mode",
2572
+ value: { enabled: true, bootstrap: true },
2573
+ lixcol_version_id: "global",
2574
+ },
2575
+ ],
2576
+ });
2577
+ // Create a tracked entity in state
2578
+ await lix.db
2579
+ .insertInto("state")
1950
2580
  .values({
1951
- entity_id: "inherited-entity",
2581
+ entity_id: "tracked-entity",
2582
+ schema_key: "mock_test_schema",
1952
2583
  file_id: "test-file",
1953
- schema_key: "mock_schema",
1954
2584
  plugin_key: "test_plugin",
2585
+ snapshot_content: { value: "tracked" },
1955
2586
  schema_version: "1.0",
1956
- version_id: "global",
1957
- snapshot_content: {
1958
- value: "inherited value",
1959
- },
1960
- untracked: false,
1961
2587
  })
1962
2588
  .execute();
1963
- // Step 2: Create a child version that inherits from global
1964
- const childVersion = await createVersion({ lix, name: "child-version" });
1965
- // Verify inheritance is set up correctly
1966
- expect(childVersion.inherits_from_version_id).toBe("global");
1967
- // Step 3: Verify child initially sees inherited entity
1968
- const inheritedState = await lix.db
2589
+ // Create an untracked entity in state_all directly with the active version
2590
+ await lix.db
2591
+ .insertInto("state")
2592
+ .values({
2593
+ entity_id: "untracked-entity",
2594
+ schema_key: "mock_test_schema",
2595
+ file_id: "test-file",
2596
+ plugin_key: "test_plugin",
2597
+ snapshot_content: { value: "untracked" },
2598
+ schema_version: "1.0",
2599
+ untracked: true,
2600
+ })
2601
+ .execute();
2602
+ // Verify we have both entities in state view
2603
+ const beforeDelete = await lix.db
2604
+ .selectFrom("state")
2605
+ .where("schema_key", "=", "mock_test_schema")
2606
+ .selectAll()
2607
+ .execute();
2608
+ expectDeterministic(beforeDelete).toHaveLength(2);
2609
+ expectDeterministic(beforeDelete.some((e) => e.entity_id === "tracked-entity")).toBe(true);
2610
+ expectDeterministic(beforeDelete.some((e) => e.entity_id === "untracked-entity")).toBe(true);
2611
+ // Delete ALL from the state view (no WHERE clause)
2612
+ await lix.db
2613
+ .deleteFrom("state")
2614
+ .where("schema_key", "=", "mock_test_schema")
2615
+ .execute();
2616
+ // Check if ALL entries were deleted including untracked
2617
+ const afterDelete = await lix.db
2618
+ .selectFrom("state")
2619
+ .where("schema_key", "=", "mock_test_schema")
2620
+ .selectAll()
2621
+ .execute();
2622
+ // This should be 0 - all entries including untracked should be deleted
2623
+ expectDeterministic(afterDelete).toHaveLength(0);
2624
+ // Also check the underlying state_all table
2625
+ const stateAfterDelete = await lix.db
1969
2626
  .selectFrom("state_all")
1970
- .where("entity_id", "=", "inherited-entity")
1971
- .where("version_id", "=", childVersion.id)
2627
+ .where("schema_key", "=", "mock_test_schema")
1972
2628
  .selectAll()
1973
2629
  .execute();
1974
- expect(inheritedState).toHaveLength(1);
1975
- expect(inheritedState[0]?.snapshot_content).toEqual({
1976
- value: "inherited value",
2630
+ // All entities should be gone from state_all
2631
+ expectDeterministic(stateAfterDelete).toHaveLength(0);
2632
+ });
2633
+ simulationTest("delete from state view with WHERE should delete untracked entities", async ({ openSimulatedLix, expectDeterministic }) => {
2634
+ const lix = await openSimulatedLix({
2635
+ keyValues: [
2636
+ {
2637
+ key: "lix_deterministic_mode",
2638
+ value: { enabled: true, bootstrap: true },
2639
+ lixcol_version_id: "global",
2640
+ },
2641
+ ],
1977
2642
  });
1978
- expect(inheritedState[0]?.inherited_from_version_id).toBe("global");
1979
- // Step 4: Add untracked state for same entity in child version
2643
+ // Create a tracked entity in state
1980
2644
  await lix.db
1981
- .insertInto("state_all")
2645
+ .insertInto("state")
1982
2646
  .values({
1983
- entity_id: "inherited-entity",
2647
+ entity_id: "tracked-entity",
2648
+ schema_key: "mock_test_schema",
1984
2649
  file_id: "test-file",
1985
- schema_key: "mock_schema",
1986
2650
  plugin_key: "test_plugin",
2651
+ snapshot_content: { value: "tracked" },
2652
+ schema_version: "1.0",
2653
+ })
2654
+ .execute();
2655
+ // Create an untracked entity in state_all directly with the active version
2656
+ await lix.db
2657
+ .insertInto("state")
2658
+ .values({
2659
+ entity_id: "untracked-entity",
2660
+ schema_key: "mock_test_schema",
2661
+ file_id: "test-file",
2662
+ plugin_key: "test_plugin",
2663
+ snapshot_content: { value: "untracked" },
1987
2664
  schema_version: "1.0",
1988
- version_id: childVersion.id,
1989
- snapshot_content: {
1990
- value: "untracked override",
1991
- },
1992
2665
  untracked: true,
1993
2666
  })
1994
2667
  .execute();
1995
- // Step 5: Query should return untracked state (higher priority than inherited)
1996
- const finalState = await lix.db
1997
- .selectFrom("state_all")
1998
- .where("entity_id", "=", "inherited-entity")
1999
- .where("version_id", "=", childVersion.id)
2668
+ // Verify both entities exist in the state view
2669
+ const beforeDelete = await lix.db
2670
+ .selectFrom("state")
2671
+ .where("schema_key", "=", "mock_test_schema")
2000
2672
  .selectAll()
2001
2673
  .execute();
2002
- expect(finalState).toHaveLength(1);
2003
- expect(finalState[0]?.snapshot_content).toEqual({
2004
- value: "untracked override",
2005
- });
2006
- expect(finalState[0]?.inherited_from_version_id).toBe(null); // Should not be inherited anymore
2007
- expect(finalState[0]?.version_id).toBe(childVersion.id);
2008
- // Step 6: Verify the inherited entity still exists in global version (unchanged)
2009
- const globalState = await lix.db
2010
- .selectFrom("state_all")
2011
- .where("entity_id", "=", "inherited-entity")
2012
- .where("version_id", "=", "global")
2674
+ expectDeterministic(beforeDelete).toHaveLength(2);
2675
+ expectDeterministic(beforeDelete.some((e) => e.entity_id === "tracked-entity")).toBe(true);
2676
+ expectDeterministic(beforeDelete.some((e) => e.entity_id === "untracked-entity")).toBe(true);
2677
+ // Delete the untracked entity from the state view with WHERE clause
2678
+ await lix.db
2679
+ .deleteFrom("state")
2680
+ .where("entity_id", "=", "untracked-entity")
2681
+ .execute();
2682
+ // Check if the untracked entry was deleted
2683
+ const afterDelete = await lix.db
2684
+ .selectFrom("state")
2685
+ .where("schema_key", "=", "mock_test_schema")
2013
2686
  .selectAll()
2014
2687
  .execute();
2015
- expect(globalState).toHaveLength(1);
2016
- expect(globalState[0]?.snapshot_content).toEqual({
2017
- value: "inherited value",
2018
- });
2019
- expect(globalState[0]?.inherited_from_version_id).toBe(null);
2020
- // Step 7: No changes should be created for untracked mutations
2021
- const changes = await lix.db
2022
- .selectFrom("change")
2023
- .where("entity_id", "=", "inherited-entity")
2024
- .where("schema_key", "=", "mock_schema")
2688
+ // Should only have the tracked entity remaining
2689
+ expectDeterministic(afterDelete).toHaveLength(1);
2690
+ expectDeterministic(afterDelete[0]?.entity_id).toBe("tracked-entity");
2691
+ // Also check the underlying state_all table to confirm deletion
2692
+ const stateAfterDelete = await lix.db
2693
+ .selectFrom("state_all")
2694
+ .where("entity_id", "=", "untracked-entity")
2695
+ .where("schema_key", "=", "mock_test_schema")
2025
2696
  .selectAll()
2026
2697
  .execute();
2027
- // Should only have the original change from global version, not the untracked one
2028
- expect(changes).toHaveLength(1);
2698
+ // The untracked entry should be gone from state_all too
2699
+ expectDeterministic(stateAfterDelete).toHaveLength(0);
2029
2700
  });
2030
2701
  //# sourceMappingURL=schema.test.js.map