@treenity/core 1.0.48 → 3.0.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 (807) hide show
  1. package/README.md +72 -12
  2. package/dist/chain.d.ts +19 -0
  3. package/dist/chain.d.ts.map +1 -0
  4. package/dist/chain.js +59 -0
  5. package/dist/chain.js.map +1 -0
  6. package/dist/client/handle.d.ts +13 -0
  7. package/dist/client/handle.d.ts.map +1 -0
  8. package/dist/client/handle.js +46 -0
  9. package/dist/client/handle.js.map +1 -0
  10. package/dist/client/index.d.ts +21 -0
  11. package/dist/client/index.d.ts.map +1 -0
  12. package/dist/client/index.js +5 -0
  13. package/dist/client/index.js.map +1 -0
  14. package/dist/client/trpc.d.ts +13 -0
  15. package/dist/client/trpc.d.ts.map +1 -0
  16. package/dist/client/trpc.js +79 -0
  17. package/dist/client/trpc.js.map +1 -0
  18. package/dist/client.d.ts +2 -0
  19. package/dist/client.d.ts.map +1 -0
  20. package/dist/client.js +2 -0
  21. package/dist/client.js.map +1 -0
  22. package/dist/comp/handle.d.ts +14 -0
  23. package/dist/comp/handle.d.ts.map +1 -0
  24. package/dist/comp/handle.js +21 -0
  25. package/dist/comp/handle.js.map +1 -0
  26. package/dist/comp/index.d.ts +41 -0
  27. package/dist/comp/index.d.ts.map +1 -0
  28. package/dist/comp/index.js +127 -0
  29. package/dist/comp/index.js.map +1 -0
  30. package/dist/comp/needs.d.ts +26 -0
  31. package/dist/comp/needs.d.ts.map +1 -0
  32. package/dist/comp/needs.js +101 -0
  33. package/dist/comp/needs.js.map +1 -0
  34. package/dist/comp/validate.d.ts +13 -0
  35. package/dist/comp/validate.d.ts.map +1 -0
  36. package/dist/comp/validate.js +117 -0
  37. package/dist/comp/validate.js.map +1 -0
  38. package/dist/comp.d.ts +2 -0
  39. package/dist/comp.d.ts.map +1 -0
  40. package/dist/comp.js +2 -0
  41. package/dist/comp.js.map +1 -0
  42. package/dist/contexts/schema/index.d.ts +7 -0
  43. package/dist/contexts/schema/index.d.ts.map +1 -0
  44. package/dist/contexts/schema/index.js +2 -0
  45. package/dist/contexts/schema/index.js.map +1 -0
  46. package/dist/contexts/schema.d.ts +2 -0
  47. package/dist/contexts/schema.d.ts.map +1 -0
  48. package/dist/contexts/schema.js +2 -0
  49. package/dist/contexts/schema.js.map +1 -0
  50. package/dist/contexts/service/index.d.ts +31 -0
  51. package/dist/contexts/service/index.d.ts.map +1 -0
  52. package/dist/contexts/service/index.js +16 -0
  53. package/dist/contexts/service/index.js.map +1 -0
  54. package/dist/contexts/service.d.ts +1 -14
  55. package/dist/contexts/service.d.ts.map +1 -1
  56. package/dist/contexts/service.js +2 -0
  57. package/dist/contexts/service.js.map +1 -0
  58. package/dist/contexts/telegram/index.d.ts +19 -0
  59. package/dist/contexts/telegram/index.d.ts.map +1 -0
  60. package/dist/contexts/telegram/index.js +89 -0
  61. package/dist/contexts/telegram/index.js.map +1 -0
  62. package/dist/contexts/text/index.d.ts +7 -0
  63. package/dist/contexts/text/index.d.ts.map +1 -0
  64. package/dist/contexts/text/index.js +9 -0
  65. package/dist/contexts/text/index.js.map +1 -0
  66. package/dist/contexts/text.d.ts +2 -0
  67. package/dist/contexts/text.d.ts.map +1 -0
  68. package/dist/contexts/text.js +2 -0
  69. package/dist/contexts/text.js.map +1 -0
  70. package/dist/core/component.d.ts +43 -0
  71. package/dist/core/component.d.ts.map +1 -0
  72. package/dist/core/component.js +101 -0
  73. package/dist/core/component.js.map +1 -0
  74. package/dist/core/context.d.ts +5 -0
  75. package/dist/core/context.d.ts.map +1 -0
  76. package/dist/core/context.js +3 -0
  77. package/dist/core/context.js.map +1 -0
  78. package/dist/core/index.d.ts +5 -0
  79. package/dist/core/index.d.ts.map +1 -0
  80. package/dist/core/index.js +8 -0
  81. package/dist/core/index.js.map +1 -0
  82. package/dist/core/path.d.ts +7 -0
  83. package/dist/core/path.d.ts.map +1 -0
  84. package/dist/core/path.js +41 -0
  85. package/dist/core/path.js.map +1 -0
  86. package/dist/core/registry.d.ts +17 -0
  87. package/dist/core/registry.d.ts.map +1 -0
  88. package/dist/core/registry.js +100 -0
  89. package/dist/core/registry.js.map +1 -0
  90. package/dist/core.d.ts +2 -0
  91. package/dist/core.d.ts.map +1 -0
  92. package/dist/core.js +2 -0
  93. package/dist/core.js.map +1 -0
  94. package/dist/index.d.ts +1 -12
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +2 -0
  97. package/dist/index.js.map +1 -0
  98. package/dist/log.d.ts +38 -0
  99. package/dist/log.d.ts.map +1 -0
  100. package/dist/log.js +150 -0
  101. package/dist/log.js.map +1 -0
  102. package/dist/mod/discover.d.ts +4 -0
  103. package/dist/mod/discover.d.ts.map +1 -0
  104. package/dist/mod/discover.js +103 -0
  105. package/dist/mod/discover.js.map +1 -0
  106. package/dist/mod/examples/ticker/seed.d.ts +3 -0
  107. package/dist/mod/examples/ticker/seed.d.ts.map +1 -0
  108. package/dist/mod/examples/ticker/seed.js +16 -0
  109. package/dist/mod/examples/ticker/seed.js.map +1 -0
  110. package/dist/mod/examples/ticker/service.d.ts +2 -0
  111. package/dist/mod/examples/ticker/service.d.ts.map +1 -0
  112. package/dist/mod/examples/ticker/service.js +17 -0
  113. package/dist/mod/examples/ticker/service.js.map +1 -0
  114. package/dist/mod/examples/ticker/types.d.ts +16 -0
  115. package/dist/mod/examples/ticker/types.d.ts.map +1 -0
  116. package/dist/mod/examples/ticker/types.js +20 -0
  117. package/dist/mod/examples/ticker/types.js.map +1 -0
  118. package/dist/mod/examples/ticker/view.d.ts +2 -0
  119. package/dist/mod/examples/ticker/view.d.ts.map +1 -0
  120. package/dist/mod/examples/ticker/view.js +10 -0
  121. package/dist/mod/examples/ticker/view.js.map +1 -0
  122. package/dist/mod/index.d.ts +11 -0
  123. package/dist/mod/index.d.ts.map +1 -0
  124. package/dist/mod/index.js +8 -0
  125. package/dist/mod/index.js.map +1 -0
  126. package/dist/mod/loader.d.ts +19 -0
  127. package/dist/mod/loader.d.ts.map +1 -0
  128. package/dist/mod/loader.js +180 -0
  129. package/dist/mod/loader.js.map +1 -0
  130. package/dist/mod/optimistic.d.ts +34 -0
  131. package/dist/mod/optimistic.d.ts.map +1 -0
  132. package/dist/mod/optimistic.js +176 -0
  133. package/dist/mod/optimistic.js.map +1 -0
  134. package/dist/mod/prefab.d.ts +18 -0
  135. package/dist/mod/prefab.d.ts.map +1 -0
  136. package/dist/mod/prefab.js +42 -0
  137. package/dist/mod/prefab.js.map +1 -0
  138. package/dist/mod/tracking.d.ts +8 -0
  139. package/dist/mod/tracking.d.ts.map +1 -0
  140. package/dist/mod/tracking.js +44 -0
  141. package/dist/mod/tracking.js.map +1 -0
  142. package/dist/mod/types.d.ts +31 -0
  143. package/dist/mod/types.d.ts.map +1 -0
  144. package/dist/mod/types.js +5 -0
  145. package/dist/mod/types.js.map +1 -0
  146. package/dist/mod.d.ts +2 -0
  147. package/dist/mod.d.ts.map +1 -0
  148. package/dist/mod.js +2 -0
  149. package/dist/mod.js.map +1 -0
  150. package/dist/mods/autostart/server.d.ts +2 -0
  151. package/dist/mods/autostart/server.d.ts.map +1 -0
  152. package/dist/mods/autostart/server.js +2 -0
  153. package/dist/mods/autostart/server.js.map +1 -0
  154. package/dist/mods/autostart/service.d.ts +14 -0
  155. package/dist/mods/autostart/service.d.ts.map +1 -0
  156. package/dist/mods/autostart/service.js +88 -0
  157. package/dist/mods/autostart/service.js.map +1 -0
  158. package/dist/mods/clients.d.ts +2 -0
  159. package/dist/mods/clients.d.ts.map +1 -0
  160. package/dist/mods/clients.js +3 -0
  161. package/dist/mods/clients.js.map +1 -0
  162. package/dist/mods/llm/index.d.ts +13 -0
  163. package/dist/mods/llm/index.d.ts.map +1 -0
  164. package/dist/mods/llm/index.js +43 -0
  165. package/dist/mods/llm/index.js.map +1 -0
  166. package/dist/mods/llm/server.d.ts +2 -0
  167. package/dist/mods/llm/server.d.ts.map +1 -0
  168. package/dist/mods/llm/server.js +2 -0
  169. package/dist/mods/llm/server.js.map +1 -0
  170. package/dist/mods/mcp/server.d.ts +2 -0
  171. package/dist/mods/mcp/server.js +2 -0
  172. package/dist/mods/mcp/service.d.ts +1 -0
  173. package/dist/mods/mcp/service.js +16 -0
  174. package/dist/mods/mcp/types.d.ts +4 -0
  175. package/dist/mods/mcp/types.js +6 -0
  176. package/dist/mods/servers.d.ts +4 -0
  177. package/dist/mods/servers.d.ts.map +1 -0
  178. package/dist/mods/servers.js +5 -0
  179. package/dist/mods/servers.js.map +1 -0
  180. package/dist/mods/treenity/agent-port.d.ts +2 -0
  181. package/dist/mods/treenity/agent-port.d.ts.map +1 -0
  182. package/dist/mods/treenity/agent-port.js +76 -0
  183. package/dist/mods/treenity/agent-port.js.map +1 -0
  184. package/dist/mods/treenity/builtins.d.ts +2 -0
  185. package/dist/mods/treenity/builtins.d.ts.map +1 -0
  186. package/dist/mods/treenity/builtins.js +18 -0
  187. package/dist/mods/treenity/builtins.js.map +1 -0
  188. package/dist/mods/treenity/groups.d.ts +2 -0
  189. package/dist/mods/treenity/groups.d.ts.map +1 -0
  190. package/dist/mods/treenity/groups.js +18 -0
  191. package/dist/mods/treenity/groups.js.map +1 -0
  192. package/dist/mods/treenity/logs.d.ts +18 -0
  193. package/dist/mods/treenity/logs.d.ts.map +1 -0
  194. package/dist/mods/treenity/logs.js +17 -0
  195. package/dist/mods/treenity/logs.js.map +1 -0
  196. package/dist/mods/treenity/mod-type.d.ts +2 -0
  197. package/dist/mods/treenity/mod-type.d.ts.map +1 -0
  198. package/dist/mods/treenity/mod-type.js +9 -0
  199. package/dist/mods/treenity/mod-type.js.map +1 -0
  200. package/dist/mods/treenity/seed.d.ts +2 -0
  201. package/dist/mods/treenity/seed.d.ts.map +1 -0
  202. package/dist/mods/treenity/seed.js +55 -0
  203. package/dist/mods/treenity/seed.js.map +1 -0
  204. package/dist/mods/treenity/server.d.ts +7 -0
  205. package/dist/mods/treenity/server.d.ts.map +1 -0
  206. package/dist/mods/treenity/server.js +7 -0
  207. package/dist/mods/treenity/server.js.map +1 -0
  208. package/dist/mods/treenity/system.d.ts +36 -0
  209. package/dist/mods/treenity/system.d.ts.map +1 -0
  210. package/dist/mods/treenity/system.js +61 -0
  211. package/dist/mods/treenity/system.js.map +1 -0
  212. package/dist/mods/uix/client.d.ts +3 -0
  213. package/dist/mods/uix/client.d.ts.map +1 -0
  214. package/dist/mods/uix/client.js +96 -0
  215. package/dist/mods/uix/client.js.map +1 -0
  216. package/dist/mods/uix/compile.d.ts +7 -0
  217. package/dist/mods/uix/compile.d.ts.map +1 -0
  218. package/dist/mods/uix/compile.js +96 -0
  219. package/dist/mods/uix/compile.js.map +1 -0
  220. package/dist/mods/uix/jsx-parser.d.ts +2 -0
  221. package/dist/mods/uix/jsx-parser.d.ts.map +1 -0
  222. package/dist/mods/uix/jsx-parser.js +565 -0
  223. package/dist/mods/uix/jsx-parser.js.map +1 -0
  224. package/dist/mods/uix/verify.d.ts +7 -0
  225. package/dist/mods/uix/verify.d.ts.map +1 -0
  226. package/dist/mods/uix/verify.js +59 -0
  227. package/dist/mods/uix/verify.js.map +1 -0
  228. package/dist/schema/_test-fixture.d.ts +11 -0
  229. package/dist/schema/_test-fixture.d.ts.map +1 -0
  230. package/dist/schema/_test-fixture.js +8 -0
  231. package/dist/schema/_test-fixture.js.map +1 -0
  232. package/dist/schema/catalog.d.ts +23 -0
  233. package/dist/schema/catalog.d.ts.map +1 -0
  234. package/dist/schema/catalog.js +82 -0
  235. package/dist/schema/catalog.js.map +1 -0
  236. package/dist/schema/extract-schemas.d.ts +5 -0
  237. package/dist/schema/extract-schemas.d.ts.map +1 -0
  238. package/dist/schema/extract-schemas.js +444 -0
  239. package/dist/schema/extract-schemas.js.map +1 -0
  240. package/dist/schema/load.d.ts +2 -0
  241. package/dist/schema/load.d.ts.map +1 -0
  242. package/dist/schema/load.js +23 -0
  243. package/dist/schema/load.js.map +1 -0
  244. package/dist/schema/test-fixture.types.d.ts +2 -0
  245. package/dist/schema/test-fixture.types.d.ts.map +1 -0
  246. package/dist/schema/test-fixture.types.js +19 -0
  247. package/dist/schema/test-fixture.types.js.map +1 -0
  248. package/dist/schema/types.d.ts +38 -0
  249. package/dist/schema/types.d.ts.map +1 -0
  250. package/dist/schema/types.js +3 -0
  251. package/dist/schema/types.js.map +1 -0
  252. package/dist/server/actions.d.ts +35 -0
  253. package/dist/server/actions.d.ts.map +1 -0
  254. package/dist/server/actions.js +170 -0
  255. package/dist/server/actions.js.map +1 -0
  256. package/dist/server/agent.d.ts +6 -0
  257. package/dist/server/agent.d.ts.map +1 -0
  258. package/dist/server/agent.js +15 -0
  259. package/dist/server/agent.js.map +1 -0
  260. package/dist/server/auth.d.ts +39 -0
  261. package/dist/server/auth.d.ts.map +1 -0
  262. package/dist/server/auth.js +336 -0
  263. package/dist/server/auth.js.map +1 -0
  264. package/dist/server/client.d.ts +190 -0
  265. package/dist/server/client.d.ts.map +1 -0
  266. package/dist/server/client.js +22 -0
  267. package/dist/server/client.js.map +1 -0
  268. package/dist/server/cookies.d.ts +5 -0
  269. package/dist/server/cookies.d.ts.map +1 -0
  270. package/dist/server/cookies.js +24 -0
  271. package/dist/server/cookies.js.map +1 -0
  272. package/dist/server/doc-index.d.ts +38 -0
  273. package/dist/server/doc-index.d.ts.map +1 -0
  274. package/dist/server/doc-index.js +245 -0
  275. package/dist/server/doc-index.js.map +1 -0
  276. package/dist/server/errors.d.ts +7 -0
  277. package/dist/server/errors.d.ts.map +1 -0
  278. package/dist/server/errors.js +11 -0
  279. package/dist/server/errors.js.map +1 -0
  280. package/dist/server/factory.d.ts +29 -0
  281. package/dist/server/factory.d.ts.map +1 -0
  282. package/dist/server/factory.js +89 -0
  283. package/dist/server/factory.js.map +1 -0
  284. package/dist/server/main.d.ts +2 -0
  285. package/dist/server/main.d.ts.map +1 -0
  286. package/dist/server/main.js +19 -0
  287. package/dist/server/main.js.map +1 -0
  288. package/dist/server/mcp.d.ts +4 -0
  289. package/dist/server/mcp.js +279 -0
  290. package/dist/server/migrate.d.ts +3 -0
  291. package/dist/server/migrate.d.ts.map +1 -0
  292. package/dist/server/migrate.js +56 -0
  293. package/dist/server/migrate.js.map +1 -0
  294. package/dist/server/mod-catalog.d.ts +14 -0
  295. package/dist/server/mod-catalog.d.ts.map +1 -0
  296. package/dist/server/mod-catalog.js +40 -0
  297. package/dist/server/mod-catalog.js.map +1 -0
  298. package/dist/server/mods-mount.d.ts +3 -0
  299. package/dist/server/mods-mount.d.ts.map +1 -0
  300. package/dist/server/mods-mount.js +168 -0
  301. package/dist/server/mods-mount.js.map +1 -0
  302. package/dist/server/mount-adapters.d.ts +9 -0
  303. package/dist/server/mount-adapters.d.ts.map +1 -0
  304. package/dist/server/mount-adapters.js +80 -0
  305. package/dist/server/mount-adapters.js.map +1 -0
  306. package/dist/server/mount.d.ts +3 -0
  307. package/dist/server/mount.d.ts.map +1 -0
  308. package/dist/server/mount.js +195 -0
  309. package/dist/server/mount.js.map +1 -0
  310. package/dist/server/prefab.d.ts +18 -0
  311. package/dist/server/prefab.d.ts.map +1 -0
  312. package/dist/server/prefab.js +72 -0
  313. package/dist/server/prefab.js.map +1 -0
  314. package/dist/server/refs.d.ts +3 -0
  315. package/dist/server/refs.d.ts.map +1 -0
  316. package/dist/server/refs.js +59 -0
  317. package/dist/server/refs.js.map +1 -0
  318. package/dist/server/seed/index.d.ts +6 -0
  319. package/dist/server/seed/index.d.ts.map +1 -0
  320. package/dist/server/seed/index.js +16 -0
  321. package/dist/server/seed/index.js.map +1 -0
  322. package/dist/server/server.d.ts +28 -0
  323. package/dist/server/server.d.ts.map +1 -0
  324. package/dist/server/server.js +127 -0
  325. package/dist/server/server.js.map +1 -0
  326. package/dist/server/sub.d.ts +34 -0
  327. package/dist/server/sub.d.ts.map +1 -0
  328. package/dist/server/sub.js +174 -0
  329. package/dist/server/sub.js.map +1 -0
  330. package/dist/server/trpc.d.ts +199 -0
  331. package/dist/server/trpc.d.ts.map +1 -0
  332. package/dist/server/trpc.js +323 -0
  333. package/dist/server/trpc.js.map +1 -0
  334. package/dist/server/types-mount.d.ts +3 -0
  335. package/dist/server/types-mount.d.ts.map +1 -0
  336. package/dist/server/types-mount.js +144 -0
  337. package/dist/server/types-mount.js.map +1 -0
  338. package/dist/server/validate.d.ts +3 -0
  339. package/dist/server/validate.d.ts.map +1 -0
  340. package/dist/server/validate.js +20 -0
  341. package/dist/server/validate.js.map +1 -0
  342. package/dist/server/volatile.d.ts +11 -0
  343. package/dist/server/volatile.d.ts.map +1 -0
  344. package/dist/server/volatile.js +26 -0
  345. package/dist/server/volatile.js.map +1 -0
  346. package/dist/server/watch.d.ts +23 -0
  347. package/dist/server/watch.d.ts.map +1 -0
  348. package/dist/server/watch.js +178 -0
  349. package/dist/server/watch.js.map +1 -0
  350. package/dist/tree/cache.d.ts +3 -0
  351. package/dist/tree/cache.d.ts.map +1 -0
  352. package/dist/tree/cache.js +48 -0
  353. package/dist/tree/cache.js.map +1 -0
  354. package/dist/tree/fs.d.ts +3 -0
  355. package/dist/tree/fs.d.ts.map +1 -0
  356. package/dist/tree/fs.js +276 -0
  357. package/dist/tree/fs.js.map +1 -0
  358. package/dist/tree/index.d.ts +38 -0
  359. package/dist/tree/index.d.ts.map +1 -0
  360. package/dist/tree/index.js +183 -0
  361. package/dist/tree/index.js.map +1 -0
  362. package/dist/tree/inflight.d.ts +2 -0
  363. package/dist/tree/inflight.d.ts.map +1 -0
  364. package/dist/tree/inflight.js +15 -0
  365. package/dist/tree/inflight.js.map +1 -0
  366. package/dist/tree/json-codec.d.ts +2 -0
  367. package/dist/tree/json-codec.d.ts.map +1 -0
  368. package/dist/tree/json-codec.js +13 -0
  369. package/dist/tree/json-codec.js.map +1 -0
  370. package/dist/tree/mimefs.d.ts +13 -0
  371. package/dist/tree/mimefs.d.ts.map +1 -0
  372. package/dist/tree/mimefs.js +124 -0
  373. package/dist/tree/mimefs.js.map +1 -0
  374. package/dist/tree/mongo.d.ts +5 -0
  375. package/dist/tree/mongo.d.ts.map +1 -0
  376. package/dist/tree/mongo.js +110 -0
  377. package/dist/tree/mongo.js.map +1 -0
  378. package/dist/tree/patch.d.ts +30 -0
  379. package/dist/tree/patch.d.ts.map +1 -0
  380. package/dist/tree/patch.js +112 -0
  381. package/dist/tree/patch.js.map +1 -0
  382. package/dist/tree/query.d.ts +12 -0
  383. package/dist/tree/query.d.ts.map +1 -0
  384. package/dist/tree/query.js +61 -0
  385. package/dist/tree/query.js.map +1 -0
  386. package/dist/tree/repath.d.ts +3 -0
  387. package/dist/tree/repath.d.ts.map +1 -0
  388. package/dist/tree/repath.js +38 -0
  389. package/dist/tree/repath.js.map +1 -0
  390. package/dist/tree-chain.d.ts +19 -0
  391. package/dist/tree-chain.d.ts.map +1 -0
  392. package/dist/tree-chain.js +111 -0
  393. package/dist/tree-chain.js.map +1 -0
  394. package/dist/tree.d.ts +2 -0
  395. package/dist/tree.d.ts.map +1 -0
  396. package/dist/tree.js +2 -0
  397. package/dist/tree.js.map +1 -0
  398. package/dist/uri.d.ts +11 -0
  399. package/dist/uri.d.ts.map +1 -0
  400. package/dist/uri.js +84 -0
  401. package/dist/uri.js.map +1 -0
  402. package/package.json +78 -37
  403. package/src/chain.test.ts +190 -0
  404. package/src/chain.ts +84 -0
  405. package/src/client/client.test.ts +192 -0
  406. package/src/client/handle.ts +53 -0
  407. package/src/client/index.ts +18 -0
  408. package/src/client/trpc.ts +92 -0
  409. package/src/client.ts +1 -0
  410. package/src/comp/CLAUDE.md +14 -0
  411. package/src/comp/handle.ts +36 -0
  412. package/src/comp/index.test.ts +165 -0
  413. package/src/comp/index.ts +186 -0
  414. package/src/comp/needs.test.ts +499 -0
  415. package/src/comp/needs.ts +113 -0
  416. package/src/comp/validate.test.ts +304 -0
  417. package/src/comp/validate.ts +125 -0
  418. package/src/comp.ts +1 -0
  419. package/src/contexts/schema/index.ts +7 -0
  420. package/src/contexts/schema.ts +1 -0
  421. package/src/contexts/service/index.test.ts +323 -0
  422. package/src/contexts/service/index.ts +43 -0
  423. package/src/contexts/service.ts +1 -0
  424. package/src/contexts/telegram/index.ts +115 -0
  425. package/src/contexts/text/index.test.ts +31 -0
  426. package/src/contexts/text/index.ts +18 -0
  427. package/src/contexts/text.ts +1 -0
  428. package/src/core/component.ts +153 -0
  429. package/src/core/context.ts +14 -0
  430. package/src/core/index.test.ts +224 -0
  431. package/src/core/index.ts +9 -0
  432. package/src/core/path.ts +38 -0
  433. package/src/core/registry.ts +112 -0
  434. package/src/core.ts +1 -0
  435. package/src/index.ts +1 -0
  436. package/src/log.test.ts +70 -0
  437. package/src/log.ts +199 -0
  438. package/src/mod/discover.test.ts +133 -0
  439. package/src/mod/discover.ts +100 -0
  440. package/src/mod/docs/00-index.md +19 -0
  441. package/src/mod/docs/01-primitives.md +38 -0
  442. package/src/mod/docs/02-core-api.md +68 -0
  443. package/src/mod/docs/03-registry.md +30 -0
  444. package/src/mod/docs/04-store.md +62 -0
  445. package/src/mod/docs/05-comp.md +111 -0
  446. package/src/mod/docs/06-actions.md +193 -0
  447. package/src/mod/docs/07-realtime.md +108 -0
  448. package/src/mod/docs/08-services.md +35 -0
  449. package/src/mod/docs/09-mounts.md +43 -0
  450. package/src/mod/docs/10-acl.md +60 -0
  451. package/src/mod/docs/11-server.md +62 -0
  452. package/src/mod/docs/12-conventions.md +108 -0
  453. package/src/mod/docs/13-example.md +142 -0
  454. package/src/mod/docs/14-mod-format.md +377 -0
  455. package/src/mod/docs/15-documenting-types.md +156 -0
  456. package/src/mod/examples/ticker/seed.ts +19 -0
  457. package/src/mod/examples/ticker/service.ts +19 -0
  458. package/src/mod/examples/ticker/ticker.test.ts +18 -0
  459. package/src/mod/examples/ticker/types.ts +22 -0
  460. package/src/mod/examples/ticker/view.tsx +19 -0
  461. package/src/mod/index.ts +12 -0
  462. package/src/mod/loader.test.ts +220 -0
  463. package/src/mod/loader.ts +207 -0
  464. package/src/mod/optimistic.test.ts +446 -0
  465. package/src/mod/optimistic.ts +210 -0
  466. package/src/mod/prefab.ts +62 -0
  467. package/src/mod/tracking.test.ts +59 -0
  468. package/src/mod/tracking.ts +51 -0
  469. package/src/mod/types.ts +40 -0
  470. package/src/mod.ts +1 -0
  471. package/src/mods/autostart/CLAUDE.md +6 -0
  472. package/src/mods/autostart/autostart.test.ts +85 -0
  473. package/src/mods/autostart/server.ts +1 -0
  474. package/src/mods/autostart/service.ts +98 -0
  475. package/src/mods/clients.ts +2 -0
  476. package/src/mods/llm/CLAUDE.md +6 -0
  477. package/src/mods/llm/index.ts +57 -0
  478. package/src/mods/llm/llm.test.ts +109 -0
  479. package/src/mods/llm/server.ts +1 -0
  480. package/src/mods/servers.ts +4 -0
  481. package/src/mods/treenity/agent-port.ts +93 -0
  482. package/src/mods/treenity/builtins.ts +21 -0
  483. package/src/mods/treenity/groups.ts +19 -0
  484. package/src/mods/treenity/logs.ts +26 -0
  485. package/src/mods/treenity/mod-type.ts +10 -0
  486. package/src/mods/treenity/seed.ts +58 -0
  487. package/src/mods/treenity/server.ts +6 -0
  488. package/src/mods/treenity/system.ts +70 -0
  489. package/src/mods/uix/CLAUDE.md +7 -0
  490. package/src/mods/uix/client.ts +117 -0
  491. package/src/mods/uix/compile.test.ts +228 -0
  492. package/src/mods/uix/compile.ts +112 -0
  493. package/src/mods/uix/jsx-parser.test.ts +554 -0
  494. package/src/mods/uix/jsx-parser.ts +489 -0
  495. package/src/mods/uix/lazy-load.test.ts +261 -0
  496. package/src/mods/uix/uix-repomix.md +3509 -0
  497. package/src/mods/uix/verify.ts +68 -0
  498. package/src/schema/CLAUDE.md +13 -0
  499. package/src/schema/_test-fixture.ts +12 -0
  500. package/src/schema/catalog.ts +101 -0
  501. package/src/schema/extract-schemas.test.ts +84 -0
  502. package/src/schema/extract-schemas.ts +462 -0
  503. package/src/schema/generated/ai.agent.json +133 -0
  504. package/src/schema/generated/ai.approval.json +105 -0
  505. package/src/schema/generated/ai.approvals.json +24 -0
  506. package/src/schema/generated/ai.assignment.json +28 -0
  507. package/src/schema/generated/ai.plan.json +84 -0
  508. package/src/schema/generated/ai.policy.json +105 -0
  509. package/src/schema/generated/ai.pool.json +37 -0
  510. package/src/schema/generated/ai.thread.json +64 -0
  511. package/src/schema/generated/autostart.json +44 -0
  512. package/src/schema/generated/board.column.json +25 -0
  513. package/src/schema/generated/board.kanban.json +7 -0
  514. package/src/schema/generated/board.task.json +147 -0
  515. package/src/schema/generated/brahman.action.back.json +12 -0
  516. package/src/schema/generated/brahman.action.broadcast.json +31 -0
  517. package/src/schema/generated/brahman.action.call.json +57 -0
  518. package/src/schema/generated/brahman.action.emittext.json +23 -0
  519. package/src/schema/generated/brahman.action.eval.json +23 -0
  520. package/src/schema/generated/brahman.action.file.json +28 -0
  521. package/src/schema/generated/brahman.action.forward.json +29 -0
  522. package/src/schema/generated/brahman.action.getvalue.json +28 -0
  523. package/src/schema/generated/brahman.action.ifelse.json +42 -0
  524. package/src/schema/generated/brahman.action.keywordselect.json +46 -0
  525. package/src/schema/generated/brahman.action.message.json +127 -0
  526. package/src/schema/generated/brahman.action.onerror.json +29 -0
  527. package/src/schema/generated/brahman.action.page.json +22 -0
  528. package/src/schema/generated/brahman.action.params.json +36 -0
  529. package/src/schema/generated/brahman.action.question.json +43 -0
  530. package/src/schema/generated/brahman.action.remove.json +12 -0
  531. package/src/schema/generated/brahman.action.resethistory.json +12 -0
  532. package/src/schema/generated/brahman.action.resetsession.json +12 -0
  533. package/src/schema/generated/brahman.action.selectlang.json +20 -0
  534. package/src/schema/generated/brahman.action.setvalue.json +27 -0
  535. package/src/schema/generated/brahman.action.tag.json +27 -0
  536. package/src/schema/generated/brahman.bot.json +68 -0
  537. package/src/schema/generated/brahman.page.json +25 -0
  538. package/src/schema/generated/brahman.session.json +29 -0
  539. package/src/schema/generated/brahman.user.json +58 -0
  540. package/src/schema/generated/cafe.contact.json +56 -0
  541. package/src/schema/generated/cafe.mail.json +29 -0
  542. package/src/schema/generated/canary.item.json +40 -0
  543. package/src/schema/generated/claude-search.json +20 -0
  544. package/src/schema/generated/craft.product.json +47 -0
  545. package/src/schema/generated/craft.shop.json +94 -0
  546. package/src/schema/generated/craft.subscription.json +27 -0
  547. package/src/schema/generated/default.json +15 -0
  548. package/src/schema/generated/doc.page.json +23 -0
  549. package/src/schema/generated/examples.demo.generator.json +16 -0
  550. package/src/schema/generated/examples.demo.sensor.json +35 -0
  551. package/src/schema/generated/examples.demo.sensor.reading.json +25 -0
  552. package/src/schema/generated/flow.node.action.json +61 -0
  553. package/src/schema/generated/flow.node.code.json +43 -0
  554. package/src/schema/generated/flow.node.condition.json +37 -0
  555. package/src/schema/generated/flow.node.end.json +35 -0
  556. package/src/schema/generated/flow.node.http.json +65 -0
  557. package/src/schema/generated/flow.node.llm.json +67 -0
  558. package/src/schema/generated/flow.node.loop.json +49 -0
  559. package/src/schema/generated/flow.node.start.json +39 -0
  560. package/src/schema/generated/flow.scenario.json +118 -0
  561. package/src/schema/generated/groups.json +20 -0
  562. package/src/schema/generated/grove.attempt.json +199 -0
  563. package/src/schema/generated/grove.path.json +93 -0
  564. package/src/schema/generated/grove.review.json +27 -0
  565. package/src/schema/generated/grove.task.json +164 -0
  566. package/src/schema/generated/intel.scenario.json +58 -0
  567. package/src/schema/generated/intel.signal.json +113 -0
  568. package/src/schema/generated/intel.world.json +15 -0
  569. package/src/schema/generated/landing.block.json +201 -0
  570. package/src/schema/generated/landing.page.json +84 -0
  571. package/src/schema/generated/launcher.json +91 -0
  572. package/src/schema/generated/mcp.server.json +15 -0
  573. package/src/schema/generated/metatron.config.json +119 -0
  574. package/src/schema/generated/metatron.permission.json +36 -0
  575. package/src/schema/generated/metatron.skill.json +36 -0
  576. package/src/schema/generated/metatron.task.json +114 -0
  577. package/src/schema/generated/metatron.template.json +26 -0
  578. package/src/schema/generated/metatron.workspace.json +60 -0
  579. package/src/schema/generated/mindmap.map.json +22 -0
  580. package/src/schema/generated/order.status.json +21 -0
  581. package/src/schema/generated/polyhope.backtest.json +161 -0
  582. package/src/schema/generated/polyhope.feed.json +33 -0
  583. package/src/schema/generated/polyhope.run.json +94 -0
  584. package/src/schema/generated/polyhope.strategy.json +152 -0
  585. package/src/schema/generated/polymax.activity.json +65 -0
  586. package/src/schema/generated/polymax.aggr-feed.json +28 -0
  587. package/src/schema/generated/polymax.aggr.json +20 -0
  588. package/src/schema/generated/polymax.alert.json +56 -0
  589. package/src/schema/generated/polymax.bot-config.json +14 -0
  590. package/src/schema/generated/polymax.bot-status.json +35 -0
  591. package/src/schema/generated/polymax.classification.json +55 -0
  592. package/src/schema/generated/polymax.deposits.json +45 -0
  593. package/src/schema/generated/polymax.holding.json +55 -0
  594. package/src/schema/generated/polymax.identity.json +71 -0
  595. package/src/schema/generated/polymax.lb-entry.json +75 -0
  596. package/src/schema/generated/polymax.leaderboard.json +37 -0
  597. package/src/schema/generated/polymax.market-ref.json +25 -0
  598. package/src/schema/generated/polymax.performance.json +65 -0
  599. package/src/schema/generated/polymax.profile.json +16 -0
  600. package/src/schema/generated/polymax.scan-result.json +50 -0
  601. package/src/schema/generated/polymax.status.json +40 -0
  602. package/src/schema/generated/polymax.tags.json +53 -0
  603. package/src/schema/generated/polymax.trader.json +16 -0
  604. package/src/schema/generated/polymax.wallet-market.json +50 -0
  605. package/src/schema/generated/polymax.wallet-pnl.json +35 -0
  606. package/src/schema/generated/pult.concept.json +53 -0
  607. package/src/schema/generated/pult.config.json +227 -0
  608. package/src/schema/generated/pult.connector.json +72 -0
  609. package/src/schema/generated/pult.market.json +113 -0
  610. package/src/schema/generated/pult.order.json +113 -0
  611. package/src/schema/generated/pult.rete.json +68 -0
  612. package/src/schema/generated/pult.sensor.json +74 -0
  613. package/src/schema/generated/pult.signal.json +54 -0
  614. package/src/schema/generated/pult.synapse.json +93 -0
  615. package/src/schema/generated/pult.trade.json +93 -0
  616. package/src/schema/generated/resim.config.json +34 -0
  617. package/src/schema/generated/resim.function.json +62 -0
  618. package/src/schema/generated/resim.goal.json +22 -0
  619. package/src/schema/generated/resim.resource.json +40 -0
  620. package/src/schema/generated/resim.state.json +48 -0
  621. package/src/schema/generated/resim.world.json +40 -0
  622. package/src/schema/generated/saveme.action.save.json +29 -0
  623. package/src/schema/generated/saveme.message.json +36 -0
  624. package/src/schema/generated/saveme.router.json +31 -0
  625. package/src/schema/generated/sim.agent.json +24 -0
  626. package/src/schema/generated/sim.ai.json +24 -0
  627. package/src/schema/generated/sim.config.json +38 -0
  628. package/src/schema/generated/sim.descriptive.json +26 -0
  629. package/src/schema/generated/sim.events.json +47 -0
  630. package/src/schema/generated/sim.item.json +20 -0
  631. package/src/schema/generated/sim.memory.json +17 -0
  632. package/src/schema/generated/sim.nearby.json +17 -0
  633. package/src/schema/generated/sim.position.json +25 -0
  634. package/src/schema/generated/sim.round.json +64 -0
  635. package/src/schema/generated/sim.world.json +32 -0
  636. package/src/schema/generated/t.agent.port.json +74 -0
  637. package/src/schema/generated/t.coolify.json +50 -0
  638. package/src/schema/generated/t.event.json +46 -0
  639. package/src/schema/generated/t.llm.json +20 -0
  640. package/src/schema/generated/t.logs.json +155 -0
  641. package/src/schema/generated/t.mod.json +27 -0
  642. package/src/schema/generated/t.note.json +31 -0
  643. package/src/schema/generated/t.person.json +36 -0
  644. package/src/schema/generated/t.tenant.json +57 -0
  645. package/src/schema/generated/t.tenant.status.json +42 -0
  646. package/src/schema/generated/t3d.animator.json +46 -0
  647. package/src/schema/generated/t3d.audio.json +58 -0
  648. package/src/schema/generated/t3d.camera.json +50 -0
  649. package/src/schema/generated/t3d.collider.json +84 -0
  650. package/src/schema/generated/t3d.light.json +90 -0
  651. package/src/schema/generated/t3d.line.json +47 -0
  652. package/src/schema/generated/t3d.lod.json +28 -0
  653. package/src/schema/generated/t3d.material.json +131 -0
  654. package/src/schema/generated/t3d.mesh.json +65 -0
  655. package/src/schema/generated/t3d.object.json +64 -0
  656. package/src/schema/generated/t3d.particles.json +109 -0
  657. package/src/schema/generated/t3d.rigidbody.json +81 -0
  658. package/src/schema/generated/t3d.scene.json +7 -0
  659. package/src/schema/generated/t3d.script.json +23 -0
  660. package/src/schema/generated/t3d.text.json +86 -0
  661. package/src/schema/generated/t3d.trail.json +45 -0
  662. package/src/schema/generated/tagger.config.json +115 -0
  663. package/src/schema/generated/tagger.result.json +57 -0
  664. package/src/schema/generated/tagger.tree.json +36 -0
  665. package/src/schema/generated/task.json +96 -0
  666. package/src/schema/generated/test.fixture.json +43 -0
  667. package/src/schema/generated/ticker.config.json +43 -0
  668. package/src/schema/generated/ticker.price.json +20 -0
  669. package/src/schema/generated/todo.item.json +25 -0
  670. package/src/schema/generated/todo.list.json +33 -0
  671. package/src/schema/generated/treenity.system.json +259 -0
  672. package/src/schema/generated/ui.table.json +46 -0
  673. package/src/schema/generated/whisper.audio.json +25 -0
  674. package/src/schema/generated/whisper.checklist.json +17 -0
  675. package/src/schema/generated/whisper.config.json +30 -0
  676. package/src/schema/generated/whisper.inbox.json +24 -0
  677. package/src/schema/generated/whisper.meta.json +35 -0
  678. package/src/schema/generated/whisper.text.json +16 -0
  679. package/src/schema/load.ts +24 -0
  680. package/src/schema/schema.test.ts +86 -0
  681. package/src/schema/test-fixture.types.ts +21 -0
  682. package/src/schema/types.ts +34 -0
  683. package/src/server/CLAUDE.md +26 -0
  684. package/src/server/actions.test.ts +272 -0
  685. package/src/server/actions.ts +274 -0
  686. package/src/server/agent-sub.test.ts +90 -0
  687. package/src/server/agent.test.ts +305 -0
  688. package/src/server/agent.ts +17 -0
  689. package/src/server/api.test.ts +463 -0
  690. package/src/server/auth.test.ts +441 -0
  691. package/src/server/auth.ts +387 -0
  692. package/src/server/client.ts +24 -0
  693. package/src/server/conditions.test.ts +128 -0
  694. package/src/server/cookies.ts +25 -0
  695. package/src/server/coverage.test.ts +827 -0
  696. package/src/server/doc-index.ts +287 -0
  697. package/src/server/e2e.test.ts +967 -0
  698. package/src/server/errors.ts +11 -0
  699. package/src/server/factory.ts +121 -0
  700. package/src/server/main.ts +24 -0
  701. package/src/server/migrate.test.ts +123 -0
  702. package/src/server/migrate.ts +62 -0
  703. package/src/server/mod-catalog.ts +59 -0
  704. package/src/server/mods-mount.ts +177 -0
  705. package/src/server/mount-adapters.ts +87 -0
  706. package/src/server/mount.parametrized.test.ts +52 -0
  707. package/src/server/mount.query.test.ts +127 -0
  708. package/src/server/mount.test.ts +565 -0
  709. package/src/server/mount.ts +208 -0
  710. package/src/server/prefab.test.ts +415 -0
  711. package/src/server/prefab.ts +105 -0
  712. package/src/server/refs.test.ts +82 -0
  713. package/src/server/refs.ts +64 -0
  714. package/src/server/seed/index.ts +24 -0
  715. package/src/server/server.ts +164 -0
  716. package/src/server/stress.test.ts +844 -0
  717. package/src/server/sub.test.ts +55 -0
  718. package/src/server/sub.ts +224 -0
  719. package/src/server/trpc.ts +375 -0
  720. package/src/server/types-mount.ts +142 -0
  721. package/src/server/validate.test.ts +91 -0
  722. package/src/server/validate.ts +22 -0
  723. package/src/server/volatile.test.ts +140 -0
  724. package/src/server/volatile.ts +32 -0
  725. package/src/server/watch.test.ts +594 -0
  726. package/src/server/watch.ts +202 -0
  727. package/src/server/workflow.test.ts +82 -0
  728. package/src/tree/CLAUDE.md +13 -0
  729. package/src/tree/cache.test.ts +213 -0
  730. package/src/tree/cache.ts +51 -0
  731. package/src/tree/fs.test.ts +247 -0
  732. package/src/tree/fs.ts +257 -0
  733. package/src/tree/index.test.ts +190 -0
  734. package/src/tree/index.ts +217 -0
  735. package/src/tree/inflight.ts +15 -0
  736. package/src/tree/json-codec.ts +16 -0
  737. package/src/tree/mimefs.test.ts +289 -0
  738. package/src/tree/mimefs.ts +142 -0
  739. package/src/tree/mongo.ts +125 -0
  740. package/src/tree/patch.test.ts +192 -0
  741. package/src/tree/patch.ts +133 -0
  742. package/src/tree/query.test.ts +110 -0
  743. package/src/tree/query.ts +70 -0
  744. package/src/tree/repath.test.ts +86 -0
  745. package/src/tree/repath.ts +53 -0
  746. package/src/tree-chain.test.ts +716 -0
  747. package/src/tree-chain.ts +150 -0
  748. package/src/tree.ts +1 -0
  749. package/src/uri.test.ts +113 -0
  750. package/src/uri.ts +84 -0
  751. package/CHANGELOG.md +0 -314
  752. package/dist/context.d.ts +0 -41
  753. package/dist/context.d.ts.map +0 -1
  754. package/dist/context.mjs +0 -81
  755. package/dist/context.mjs.map +0 -1
  756. package/dist/contexts/node-engine.d.ts +0 -12
  757. package/dist/contexts/node-engine.d.ts.map +0 -1
  758. package/dist/contexts/node-engine.mjs +0 -7
  759. package/dist/contexts/node-engine.mjs.map +0 -1
  760. package/dist/contexts/noflo/types.d.ts +0 -20
  761. package/dist/contexts/noflo/types.d.ts.map +0 -1
  762. package/dist/contexts/object.d.ts +0 -11
  763. package/dist/contexts/object.d.ts.map +0 -1
  764. package/dist/contexts/object.mjs +0 -15
  765. package/dist/contexts/object.mjs.map +0 -1
  766. package/dist/contexts/proto.d.ts +0 -11
  767. package/dist/contexts/proto.d.ts.map +0 -1
  768. package/dist/contexts/proto.mjs +0 -7
  769. package/dist/contexts/proto.mjs.map +0 -1
  770. package/dist/contexts/react-context.d.ts +0 -21
  771. package/dist/contexts/react-context.d.ts.map +0 -1
  772. package/dist/contexts/react-context.mjs +0 -24
  773. package/dist/contexts/react-context.mjs.map +0 -1
  774. package/dist/contexts/service.mjs +0 -7
  775. package/dist/contexts/service.mjs.map +0 -1
  776. package/dist/get-type-cache.d.ts +0 -2
  777. package/dist/get-type-cache.d.ts.map +0 -1
  778. package/dist/get-type-cache.mjs +0 -7
  779. package/dist/get-type-cache.mjs.map +0 -1
  780. package/dist/index.mjs +0 -10
  781. package/dist/index.mjs.map +0 -1
  782. package/dist/link/link.d.ts +0 -25
  783. package/dist/link/link.d.ts.map +0 -1
  784. package/dist/link/link.mjs +0 -72
  785. package/dist/link/link.mjs.map +0 -1
  786. package/dist/link/link.test.d.ts +0 -2
  787. package/dist/link/link.test.d.ts.map +0 -1
  788. package/dist/loading.d.ts +0 -9
  789. package/dist/loading.d.ts.map +0 -1
  790. package/dist/meta-type.d.ts +0 -58
  791. package/dist/meta-type.d.ts.map +0 -1
  792. package/dist/meta-type.mjs +0 -104
  793. package/dist/meta-type.mjs.map +0 -1
  794. package/dist/meta.d.ts +0 -20
  795. package/dist/meta.d.ts.map +0 -1
  796. package/dist/meta.mjs +0 -16
  797. package/dist/meta.mjs.map +0 -1
  798. package/dist/node/index.d.ts +0 -2
  799. package/dist/node/index.d.ts.map +0 -1
  800. package/dist/node/types.d.ts +0 -37
  801. package/dist/node/types.d.ts.map +0 -1
  802. package/dist/test/context.test.d.ts +0 -2
  803. package/dist/test/context.test.d.ts.map +0 -1
  804. package/dist/types.d.ts +0 -14
  805. package/dist/types.d.ts.map +0 -1
  806. package/dist/types.mjs +0 -16
  807. package/dist/types.mjs.map +0 -1
@@ -0,0 +1,827 @@
1
+ // Coverage gap tests — exercises uncovered code paths across the codebase.
2
+ // Excludes Mongo (requires connection). Focuses on:
3
+ // - mount-adapters (memory, query, overlay, types, fs validation)
4
+ // - sift queries via memory store getChildren
5
+ // - sub.ts remove CDC path
6
+ // - actions.ts (executeAction, setComponent, applyTemplate)
7
+ // - fs store OCC
8
+ // - validate.ts edge cases
9
+ // - volatile extractPaths
10
+
11
+ import { registerType } from '#comp';
12
+ import { createNode, isComponent, type NodeData, register, resolve } from '#core';
13
+ import { clearRegistry } from '#core/index.test';
14
+ import { createMemoryTree, createOverlayTree, type Tree } from '#tree';
15
+ import { createFsTree } from '#tree/fs';
16
+ import { createQueryTree, mapNodeForSift, mapSiftQuery, matchesFilter } from '#tree/query';
17
+ import assert from 'node:assert/strict';
18
+ import { mkdtemp, rm } from 'node:fs/promises';
19
+ import { tmpdir } from 'node:os';
20
+ import { join } from 'node:path';
21
+ import { afterEach, beforeEach, describe, it } from 'node:test';
22
+ import { applyTemplate, executeAction, executeStream, setComponent } from './actions';
23
+ import { OpError } from './errors';
24
+ import { withMounts } from './mount';
25
+ import { getActiveQueryCount, unwatchAllQueries, unwatchQuery, watchQuery, withSubscriptions } from './sub';
26
+ import { createTypesStore } from './types-mount';
27
+ import { withValidation } from './validate';
28
+ import { extractPaths, isVolatile, withVolatile } from './volatile';
29
+
30
+ // ── Helpers ──
31
+
32
+ function fullPipeline(rootStore?: Tree) {
33
+ const bootstrap = rootStore ?? createMemoryTree();
34
+ const mountable = withMounts(bootstrap);
35
+ const volatile = withVolatile(mountable);
36
+ const validated = withValidation(volatile);
37
+ const events: any[] = [];
38
+ const store = withSubscriptions(validated, (e) => events.push(e));
39
+ return { bootstrap, store, events };
40
+ }
41
+
42
+ // ── mount-adapters (non-Mongo) ──
43
+
44
+ describe('Mount adapters', () => {
45
+ beforeEach(() => {
46
+ clearRegistry();
47
+
48
+ // Register mount adapters manually (same as mount-adapters.ts but without Mongo import side effects)
49
+ register('t.mount.memory', 'mount', () => createMemoryTree());
50
+ register('t.mount.types', 'mount', (_node: any, deps: Tree) => createTypesStore(deps));
51
+ register('t.mount.query', 'mount', (config: any, parentStore: Tree, _ctx: any, globalStore?: Tree) => {
52
+ const n = config as NodeData;
53
+ const qv = n['query'];
54
+ const query = isComponent(qv) ? qv as unknown as { source: string; match: Record<string, unknown> } : undefined;
55
+ if (!query?.source || !query?.match) throw new Error("t.mount.query requires 'query' component with source and match");
56
+ return createQueryTree({ source: query.source, match: query.match }, globalStore || parentStore);
57
+ });
58
+ register('t.mount.overlay', 'mount', async (config: any, parentStore: Tree, ctx: any, globalStore?: Tree) => {
59
+ const n = config as NodeData;
60
+ const mount = n['mount'] as any;
61
+ if (!mount?.layers?.length) throw new Error('t.mount.overlay: layers required');
62
+ const stores: Tree[] = [];
63
+ for (const name of mount.layers) {
64
+ const comp = n[name] as any;
65
+ if (!comp) throw new Error(`t.mount.overlay: component "${name}" not found`);
66
+ const adapter = resolve(comp.$type, 'mount');
67
+ if (!adapter) throw new Error(`No mount adapter for "${comp.$type}"`);
68
+ stores.push(await adapter(comp, stores[0] ?? ({} as Tree), ctx, globalStore));
69
+ }
70
+ let result = stores[0];
71
+ for (let i = 1; i < stores.length; i++) result = createOverlayTree(stores[i], result);
72
+ return result;
73
+ });
74
+ });
75
+
76
+ it('t.mount.memory creates independent store', async () => {
77
+ const root = createMemoryTree();
78
+ await root.set(createNode('/mnt', 'folder', {}, {
79
+ mount: { $type: 't.mount.memory' },
80
+ }));
81
+ const ms = withMounts(root);
82
+
83
+ await ms.set(createNode('/mnt/a', 'item'));
84
+ assert.ok(await ms.get('/mnt/a'));
85
+ // Not visible in root store (mounted into separate memory)
86
+ assert.equal(await root.get('/mnt/a'), undefined);
87
+ });
88
+
89
+ it('t.mount.query requires query component', async () => {
90
+ const root = createMemoryTree();
91
+ await root.set(createNode('/bad', 'folder', {}, {
92
+ mount: { $type: 't.mount.query' },
93
+ // missing 'query' component
94
+ }));
95
+ const ms = withMounts(root);
96
+
97
+ await assert.rejects(() => ms.getChildren('/bad'));
98
+ });
99
+
100
+ it('t.mount.overlay merges two memory stores', async () => {
101
+ const root = createMemoryTree();
102
+ await root.set(createNode('/ovl', 'folder', {}, {
103
+ mount: { $type: 't.mount.overlay', layers: ['base', 'upper'] },
104
+ base: { $type: 't.mount.memory' },
105
+ upper: { $type: 't.mount.memory' },
106
+ }));
107
+ const ms = withMounts(root);
108
+
109
+ await ms.set(createNode('/ovl/x', 'item'));
110
+ assert.ok(await ms.get('/ovl/x'));
111
+ });
112
+
113
+ it('t.mount.overlay throws without layers', async () => {
114
+ const root = createMemoryTree();
115
+ await root.set(createNode('/bad', 'folder', {}, {
116
+ mount: { $type: 't.mount.overlay' },
117
+ }));
118
+ const ms = withMounts(root);
119
+
120
+ await assert.rejects(() => ms.getChildren('/bad'));
121
+ });
122
+
123
+ it('t.mount.overlay throws on missing component', async () => {
124
+ const root = createMemoryTree();
125
+ await root.set(createNode('/bad2', 'folder', {}, {
126
+ mount: { $type: 't.mount.overlay', layers: ['base', 'ghost'] },
127
+ base: { $type: 't.mount.memory' },
128
+ // 'ghost' component missing
129
+ }));
130
+ const ms = withMounts(root);
131
+
132
+ await assert.rejects(() => ms.getChildren('/bad2'));
133
+ });
134
+
135
+ it('t.mount.overlay throws on unknown adapter type', async () => {
136
+ const root = createMemoryTree();
137
+ await root.set(createNode('/bad3', 'folder', {}, {
138
+ mount: { $type: 't.mount.overlay', layers: ['base'] },
139
+ base: { $type: 'unknown.adapter' },
140
+ }));
141
+ const ms = withMounts(root);
142
+
143
+ await assert.rejects(() => ms.getChildren('/bad3'));
144
+ });
145
+ });
146
+
147
+ // ── Sift queries via memory store ──
148
+
149
+ describe('Sift queries via memory store', () => {
150
+ let store: Tree;
151
+
152
+ beforeEach(async () => {
153
+ store = createMemoryTree();
154
+ // Seed diverse data
155
+ for (let i = 0; i < 20; i++) {
156
+ await store.set({
157
+ $path: `/items/${i}`,
158
+ $type: i % 3 === 0 ? 'order' : 'task',
159
+ status: { $type: 'status', value: i % 2 === 0 ? 'active' : 'done' },
160
+ priority: i % 5,
161
+ tags: i < 10 ? ['urgent'] : ['low'],
162
+ } as any);
163
+ }
164
+ });
165
+
166
+ it('$eq (implicit)', async () => {
167
+ const result = await store.getChildren('/items', { query: { priority: 0 } });
168
+ assert.ok(result.items.length > 0);
169
+ for (const n of result.items) assert.equal((n as any).priority, 0);
170
+ });
171
+
172
+ it('$gt / $lt', async () => {
173
+ const result = await store.getChildren('/items', { query: { priority: { $gt: 3 } } });
174
+ assert.ok(result.items.length > 0);
175
+ for (const n of result.items) assert.ok((n as any).priority > 3);
176
+ });
177
+
178
+ it('$in', async () => {
179
+ const result = await store.getChildren('/items', { query: { priority: { $in: [0, 4] } } });
180
+ for (const n of result.items) assert.ok([0, 4].includes((n as any).priority));
181
+ });
182
+
183
+ it('$and (composite)', async () => {
184
+ const result = await store.getChildren('/items', {
185
+ query: { $and: [{ priority: { $gte: 2 } }, { 'status.value': 'active' }] },
186
+ });
187
+ for (const n of result.items) {
188
+ assert.ok((n as any).priority >= 2);
189
+ assert.equal((n as any).status.value, 'active');
190
+ }
191
+ });
192
+
193
+ it('$or', async () => {
194
+ const result = await store.getChildren('/items', {
195
+ query: { $or: [{ priority: 0 }, { priority: 4 }] },
196
+ });
197
+ for (const n of result.items) assert.ok([0, 4].includes((n as any).priority));
198
+ });
199
+
200
+ it('$not / $ne', async () => {
201
+ const result = await store.getChildren('/items', { query: { priority: { $ne: 0 } } });
202
+ for (const n of result.items) assert.notEqual((n as any).priority, 0);
203
+ });
204
+
205
+ it('$type mapping — _type instead of $type', async () => {
206
+ const result = await store.getChildren('/items', { query: { _type: 'order' } });
207
+ assert.ok(result.items.length > 0);
208
+ for (const n of result.items) assert.equal(n.$type, 'order');
209
+ });
210
+
211
+ it('dot-path nested queries', async () => {
212
+ const result = await store.getChildren('/items', { query: { 'status.value': 'done' } });
213
+ assert.ok(result.items.length > 0);
214
+ for (const n of result.items) assert.equal((n as any).status.value, 'done');
215
+ });
216
+
217
+ it('$elemMatch on arrays', async () => {
218
+ const result = await store.getChildren('/items', { query: { tags: { $in: ['urgent'] } } });
219
+ assert.equal(result.items.length, 10);
220
+ for (const n of result.items) assert.ok((n as any).tags.includes('urgent'));
221
+ });
222
+
223
+ it('$exists', async () => {
224
+ await store.set({ $path: '/items/special', $type: 'special', rare: true } as any);
225
+ const result = await store.getChildren('/items', { query: { rare: { $exists: true } } });
226
+ assert.equal(result.items.length, 1);
227
+ assert.equal(result.items[0].$path, '/items/special');
228
+ });
229
+
230
+ it('empty query returns all', async () => {
231
+ const result = await store.getChildren('/items', { query: {} });
232
+ assert.equal(result.items.length, 20);
233
+ });
234
+
235
+ it('query + pagination', async () => {
236
+ const page = await store.getChildren('/items', {
237
+ query: { 'status.value': 'active' },
238
+ limit: 3,
239
+ offset: 0,
240
+ });
241
+ assert.equal(page.items.length, 3);
242
+ assert.ok(page.total >= 3);
243
+ });
244
+
245
+ it('query on non-existent path returns empty', async () => {
246
+ const result = await store.getChildren('/nonexistent', { query: { x: 1 } });
247
+ assert.equal(result.items.length, 0);
248
+ });
249
+ });
250
+
251
+ // ── mapSiftQuery / mapNodeForSift edge cases ──
252
+
253
+ describe('query.ts mapping helpers', () => {
254
+ it('mapSiftQuery renames all $ fields', () => {
255
+ const mapped = mapSiftQuery({ $type: 'x', $path: '/a', $acl: [], $owner: 'u', $rev: 1 }) as Record<string, unknown>;
256
+ assert.equal(mapped._type, 'x');
257
+ assert.equal(mapped._path, '/a');
258
+ assert.deepEqual(mapped._acl, []);
259
+ assert.equal(mapped._owner, 'u');
260
+ assert.equal(mapped._rev, 1);
261
+ });
262
+
263
+ it('mapSiftQuery handles nested arrays and objects', () => {
264
+ const mapped = mapSiftQuery({ $and: [{ $type: 'a' }, { $path: '/b' }] });
265
+ assert.deepEqual(mapped, { $and: [{ _type: 'a' }, { _path: '/b' }] });
266
+ });
267
+
268
+ it('mapSiftQuery passes primitives through', () => {
269
+ assert.equal(mapSiftQuery('hello'), 'hello');
270
+ assert.equal(mapSiftQuery(42), 42);
271
+ assert.equal(mapSiftQuery(null), null);
272
+ assert.equal(mapSiftQuery(true), true);
273
+ });
274
+
275
+ it('mapNodeForSift converts $ prefixed keys', () => {
276
+ const mapped = mapNodeForSift({ $path: '/x', $type: 'y', name: 'z' } as NodeData);
277
+ assert.equal(mapped._path, '/x');
278
+ assert.equal(mapped._type, 'y');
279
+ assert.equal(mapped.name, 'z');
280
+ assert.equal(mapped.$path, undefined);
281
+ });
282
+ });
283
+
284
+ // ── sub.ts: remove CDC path ──
285
+
286
+ describe('sub.ts: remove + CDC', () => {
287
+ beforeEach(() => {
288
+ clearRegistry();
289
+
290
+ });
291
+
292
+ it('remove emits rmVps when node was in query', async () => {
293
+ const mem = createMemoryTree();
294
+ const events: any[] = [];
295
+ const store = withSubscriptions(mem, (e) => events.push(e));
296
+
297
+ // Register a query watch
298
+ watchQuery('/active', '/items', { 'status.value': 'active' }, 'user1');
299
+
300
+ // Create a matching node
301
+ await store.set({ $path: '/items/a', $type: 'item', status: { $type: 'status', value: 'active' } } as NodeData);
302
+
303
+ events.length = 0;
304
+
305
+ // Remove it — should emit rmVps
306
+ await store.remove('/items/a');
307
+ assert.equal(events.length, 1);
308
+ assert.equal(events[0].type, 'remove');
309
+ assert.deepEqual(events[0].rmVps, ['/active']);
310
+
311
+ unwatchAllQueries('user1');
312
+ });
313
+
314
+ it('remove of non-matching node has empty rmVps', async () => {
315
+ const mem = createMemoryTree();
316
+ const events: any[] = [];
317
+ const store = withSubscriptions(mem, (e) => events.push(e));
318
+
319
+ watchQuery('/active', '/items', { 'status.value': 'active' }, 'user1');
320
+
321
+ await store.set({ $path: '/items/b', $type: 'item', status: { $type: 'status', value: 'done' } } as NodeData);
322
+ events.length = 0;
323
+
324
+ await store.remove('/items/b');
325
+ assert.equal(events.length, 1);
326
+ assert.equal(events[0].type, 'remove');
327
+ assert.equal(events[0].rmVps, undefined);
328
+
329
+ unwatchAllQueries('user1');
330
+ });
331
+
332
+ it('remove of non-existent node emits nothing', async () => {
333
+ const mem = createMemoryTree();
334
+ const events: any[] = [];
335
+ const store = withSubscriptions(mem, (e) => events.push(e));
336
+
337
+ await store.remove('/ghost');
338
+ assert.equal(events.length, 0);
339
+ });
340
+
341
+ it('unwatchQuery removes single user', () => {
342
+ watchQuery('/vp1', '/src', { x: 1 }, 'userA');
343
+ watchQuery('/vp1', '/src', { x: 1 }, 'userB');
344
+ assert.equal(getActiveQueryCount(), 1);
345
+
346
+ unwatchQuery('/vp1', 'userA');
347
+ assert.equal(getActiveQueryCount(), 1, 'entry should remain (userB watching)');
348
+
349
+ unwatchQuery('/vp1', 'userB');
350
+ assert.equal(getActiveQueryCount(), 0, 'entry fully cleaned');
351
+
352
+ // Idempotent
353
+ unwatchQuery('/vp1', 'userB');
354
+ assert.equal(getActiveQueryCount(), 0);
355
+ });
356
+
357
+ it('unwatchAllQueries cleans up all entries for user', () => {
358
+ watchQuery('/a', '/s', { x: 1 }, 'u1');
359
+ watchQuery('/b', '/s', { y: 2 }, 'u1');
360
+ watchQuery('/a', '/s', { x: 1 }, 'u2');
361
+ assert.equal(getActiveQueryCount(), 2);
362
+
363
+ unwatchAllQueries('u1');
364
+ assert.equal(getActiveQueryCount(), 1, '/a should remain (u2 watching)');
365
+
366
+ unwatchAllQueries('u2');
367
+ assert.equal(getActiveQueryCount(), 0);
368
+ });
369
+ });
370
+
371
+ // ── actions.ts: executeAction, setComponent, applyTemplate ──
372
+
373
+ describe('actions.ts operations', () => {
374
+ beforeEach(() => {
375
+ clearRegistry();
376
+
377
+ });
378
+
379
+ it('executeAction generates Immer patches', async () => {
380
+ class Counter {
381
+ count = 0;
382
+ increment() { this.count++; }
383
+ }
384
+ registerType('counter', Counter);
385
+
386
+ const store = createMemoryTree();
387
+ await store.set(createNode('/c', 'item', {}, {
388
+ counter: { $type: 'counter', count: 0 },
389
+ }));
390
+
391
+ await executeAction(store, '/c', 'counter', undefined, 'increment');
392
+
393
+ const node = await store.get('/c');
394
+ assert.equal((node!['counter'] as any).count, 1);
395
+ // $rev incremented
396
+ assert.equal(node!.$rev, 2); // once from initial set, once from executeAction
397
+ });
398
+
399
+ it('executeAction without component name uses node type', async () => {
400
+ register('mytype', 'action:doStuff', (actx: any) => {
401
+ actx.node.result = 42;
402
+ return 'ok';
403
+ });
404
+
405
+ const store = createMemoryTree();
406
+ await store.set(createNode('/n', 'mytype'));
407
+
408
+ const result = await executeAction(store, '/n', undefined, undefined, 'doStuff');
409
+ assert.equal(result, 'ok');
410
+ });
411
+
412
+ it('executeAction throws NOT_FOUND for missing node', async () => {
413
+ const store = createMemoryTree();
414
+ await assert.rejects(
415
+ () => executeAction(store, '/missing', undefined, undefined, 'x'),
416
+ (e: any) => { assert.equal(e.code, 'NOT_FOUND'); return true; },
417
+ );
418
+ });
419
+
420
+ it('executeAction throws NOT_FOUND for missing component', async () => {
421
+ const store = createMemoryTree();
422
+ await store.set(createNode('/n', 'item'));
423
+ await assert.rejects(
424
+ () => executeAction(store, '/n', 'ghost', undefined, 'x'),
425
+ (e: any) => { assert.equal(e.code, 'NOT_FOUND'); return true; },
426
+ );
427
+ });
428
+
429
+ it('executeAction throws BAD_REQUEST for missing action', async () => {
430
+ class Dummy { x = 1; }
431
+ registerType('dummy', Dummy);
432
+
433
+ const store = createMemoryTree();
434
+ await store.set(createNode('/n', 'item', {}, {
435
+ dummy: { $type: 'dummy', x: 1 },
436
+ }));
437
+
438
+ await assert.rejects(
439
+ () => executeAction(store, '/n', 'dummy', undefined, 'nonexistent'),
440
+ (e: any) => { assert.equal(e.code, 'BAD_REQUEST'); return true; },
441
+ );
442
+ });
443
+
444
+ it('pure action (no patches) does not persist', async () => {
445
+ register('reader', 'action:read', (_actx: any, data: any) => {
446
+ return { echo: data };
447
+ });
448
+
449
+ const store = createMemoryTree();
450
+ await store.set(createNode('/r', 'reader'));
451
+
452
+ const result = await executeAction(store, '/r', undefined, undefined, 'read', { msg: 'hello' });
453
+ assert.deepEqual(result, { echo: { msg: 'hello' } });
454
+ // $rev stays at 1 — no store.set() called
455
+ const node = await store.get('/r');
456
+ assert.equal(node!.$rev, 1);
457
+ });
458
+
459
+ it('executeAction throws NOT_FOUND for missing node (no type)', async () => {
460
+ const store = createMemoryTree();
461
+ await assert.rejects(
462
+ () => executeAction(store, '/missing', undefined, undefined, 'x'),
463
+ (e: any) => { assert.equal(e.code, 'NOT_FOUND'); return true; },
464
+ );
465
+ });
466
+
467
+ it('executeStream: yields values from async generator action', async () => {
468
+ class Emitter {
469
+ async *emit(data: { n: number }) {
470
+ for (let i = 0; i < data.n; i++) yield i;
471
+ }
472
+ }
473
+ registerType('emitter', Emitter);
474
+
475
+ const store = createMemoryTree();
476
+ await store.set(createNode('/e', 'item', {}, {
477
+ emitter: { $type: 'emitter' },
478
+ }));
479
+
480
+ const collected: unknown[] = [];
481
+ for await (const item of executeStream(store, '/e', 'emitter', undefined, 'emit', { n: 3 })) {
482
+ collected.push(item);
483
+ }
484
+ assert.deepEqual(collected, [0, 1, 2]);
485
+ });
486
+
487
+ it('executeStream: BAD_REQUEST for non-generator action', async () => {
488
+ class Plain { run() { return 42; } }
489
+ registerType('plain', Plain);
490
+
491
+ const store = createMemoryTree();
492
+ await store.set(createNode('/p', 'item', {}, { plain: { $type: 'plain' } }));
493
+
494
+ await assert.rejects(
495
+ async () => {
496
+ for await (const _ of executeStream(store, '/p', 'plain', undefined, 'run')) { /* */ }
497
+ },
498
+ (e: any) => { assert.equal(e.code, 'BAD_REQUEST'); return true; },
499
+ );
500
+ });
501
+
502
+ it('setComponent updates single component', async () => {
503
+ const store = createMemoryTree();
504
+ await store.set(createNode('/s', 'item', {}, {
505
+ meta: { $type: 'meta', title: 'old' },
506
+ }));
507
+
508
+ await setComponent(store, '/s', 'meta', { $type: 'meta', title: 'new' });
509
+
510
+ const node = await store.get('/s');
511
+ assert.equal((node as any).meta.title, 'new');
512
+ });
513
+
514
+ it('setComponent throws NOT_FOUND for missing node', async () => {
515
+ const store = createMemoryTree();
516
+ await assert.rejects(
517
+ () => setComponent(store, '/missing', 'x', {}),
518
+ (e: any) => { assert.equal(e.code, 'NOT_FOUND'); return true; },
519
+ );
520
+ });
521
+
522
+ it('setComponent throws CONFLICT on stale rev', async () => {
523
+ const store = createMemoryTree();
524
+ await store.set(createNode('/s', 'item'));
525
+ await assert.rejects(
526
+ () => setComponent(store, '/s', 'x', {}, 999),
527
+ (e: any) => { assert.equal(e.code, 'CONFLICT'); return true; },
528
+ );
529
+ });
530
+
531
+ it('applyTemplate copies children to target', async () => {
532
+ const store = createMemoryTree();
533
+ await store.set(createNode('/templates/blog', 'template'));
534
+ await store.set(createNode('/templates/blog/header', 'block', { text: 'Hello' }));
535
+ await store.set(createNode('/templates/blog/body', 'block', { text: 'Content' }));
536
+
537
+ // Existing children at target get removed
538
+ await store.set(createNode('/pages/p1', 'page'));
539
+ await store.set(createNode('/pages/p1/old', 'block'));
540
+
541
+ const result = await applyTemplate(store, '/templates/blog', '/pages/p1');
542
+ assert.equal(result.blocks, 2);
543
+ assert.equal(result.applied, '/templates/blog');
544
+
545
+ // Old child gone
546
+ assert.equal(await store.get('/pages/p1/old'), undefined);
547
+
548
+ // New children present
549
+ const header = await store.get('/pages/p1/header');
550
+ assert.ok(header);
551
+ assert.equal((header as any).text, 'Hello');
552
+ });
553
+
554
+ it('applyTemplate throws NOT_FOUND for missing template', async () => {
555
+ const store = createMemoryTree();
556
+ await assert.rejects(
557
+ () => applyTemplate(store, '/missing', '/target'),
558
+ (e: any) => { assert.equal(e.code, 'NOT_FOUND'); return true; },
559
+ );
560
+ });
561
+ });
562
+
563
+ // ── fs store: OCC + remove edge cases ──
564
+
565
+ describe('FsStore OCC', () => {
566
+ let dir: string;
567
+
568
+ afterEach(async () => {
569
+ if (dir) await rm(dir, { recursive: true, force: true });
570
+ });
571
+
572
+ it('OCC rejects stale rev', async () => {
573
+ dir = await mkdtemp(join(tmpdir(), 'treenity-fs-occ-'));
574
+ const store = await createFsTree(dir);
575
+
576
+ await store.set(createNode('/n', 'item')); // rev becomes 1
577
+ const node = await store.get('/n');
578
+
579
+ // Simulate stale read
580
+ await store.set({ ...node!, $rev: node!.$rev }); // rev becomes 2
581
+
582
+ // Now try with stale rev=1
583
+ await assert.rejects(() => store.set({ ...node!, $rev: 1 }));
584
+ });
585
+
586
+ it('OCC throws when node does not exist but rev provided', async () => {
587
+ dir = await mkdtemp(join(tmpdir(), 'treenity-fs-occ2-'));
588
+ const store = await createFsTree(dir);
589
+
590
+ await assert.rejects(
591
+ () => store.set({ ...createNode('/ghost', 'item'), $rev: 1 }),
592
+ );
593
+ });
594
+ });
595
+
596
+ // ── validate.ts edge cases ──
597
+
598
+ describe('Validation edge cases', () => {
599
+ beforeEach(() => {
600
+ clearRegistry();
601
+
602
+ });
603
+
604
+ it('rejects boolean where string expected', async () => {
605
+ register('typed', 'schema', () => ({
606
+ properties: { name: { type: 'string' } },
607
+ }));
608
+
609
+ const store = withValidation(createMemoryTree());
610
+
611
+ await assert.rejects(
612
+ () => store.set({ $path: '/v', $type: 'x', comp: { $type: 'typed', name: 123 } } as any),
613
+ );
614
+ });
615
+
616
+ it('rejects string where number expected', async () => {
617
+ register('numtype', 'schema', () => ({
618
+ properties: { count: { type: 'number' } },
619
+ }));
620
+
621
+ const store = withValidation(createMemoryTree());
622
+
623
+ await assert.rejects(
624
+ () => store.set({ $path: '/v', $type: 'x', comp: { $type: 'numtype', count: 'not a number' } } as any),
625
+ );
626
+ });
627
+
628
+ it('rejects number where boolean expected', async () => {
629
+ register('booltype', 'schema', () => ({
630
+ properties: { flag: { type: 'boolean' } },
631
+ }));
632
+
633
+ const store = withValidation(createMemoryTree());
634
+
635
+ await assert.rejects(
636
+ () => store.set({ $path: '/v', $type: 'x', comp: { $type: 'booltype', flag: 42 } } as any),
637
+ );
638
+ });
639
+
640
+ it('allows null/undefined values (optional by default)', async () => {
641
+ register('opttype', 'schema', () => ({
642
+ properties: { name: { type: 'string' } },
643
+ }));
644
+
645
+ const store = withValidation(createMemoryTree());
646
+ // null and undefined should pass — optional by default
647
+ await store.set({ $path: '/v', $type: 'x', comp: { $type: 'opttype', name: null } } as any);
648
+ await store.set({ $path: '/v2', $type: 'x', comp: { $type: 'opttype' } } as any);
649
+ });
650
+
651
+ it('skips components without schema', async () => {
652
+ const store = withValidation(createMemoryTree());
653
+ await store.set({ $path: '/v', $type: 'x', comp: { $type: 'untyped', anything: 'goes' } } as any);
654
+ const node = await store.get('/v');
655
+ assert.ok(node, 'node should be stored');
656
+ assert.equal((node as any).comp.anything, 'goes');
657
+ });
658
+
659
+ it('skips schemas without properties', async () => {
660
+ register('emptyschema', 'schema', () => ({}));
661
+
662
+ const store = withValidation(createMemoryTree());
663
+ await store.set({ $path: '/v', $type: 'x', comp: { $type: 'emptyschema', x: 1 } } as any);
664
+ const node = await store.get('/v');
665
+ assert.ok(node, 'node should be stored');
666
+ assert.equal((node as any).comp.x, 1);
667
+ });
668
+ });
669
+
670
+ // ── volatile.ts: extractPaths ──
671
+
672
+ describe('extractPaths', () => {
673
+ it('extracts from { items: [...] }', () => {
674
+ const paths = extractPaths({ items: [{ $path: '/a' }, { $path: '/b' }] });
675
+ assert.deepEqual(paths, ['/a', '/b']);
676
+ });
677
+
678
+ it('extracts from single node', () => {
679
+ const paths = extractPaths({ $path: '/single' });
680
+ assert.deepEqual(paths, ['/single']);
681
+ });
682
+
683
+ it('returns empty for null/undefined', () => {
684
+ assert.deepEqual(extractPaths(null), []);
685
+ assert.deepEqual(extractPaths(undefined), []);
686
+ assert.deepEqual(extractPaths('string'), []);
687
+ assert.deepEqual(extractPaths(42), []);
688
+ });
689
+
690
+ it('filters items without $path', () => {
691
+ const paths = extractPaths({ items: [{ $path: '/a' }, { name: 'no path' }, { $path: '/b' }] });
692
+ assert.deepEqual(paths, ['/a', '/b']);
693
+ });
694
+
695
+ it('returns empty for object without $path or items', () => {
696
+ assert.deepEqual(extractPaths({ foo: 'bar' }), []);
697
+ });
698
+ });
699
+
700
+ // ── volatile.ts: isVolatile ──
701
+
702
+ describe('isVolatile', () => {
703
+ beforeEach(() => {
704
+ clearRegistry();
705
+
706
+ });
707
+
708
+ it('returns true for $volatile flag', () => {
709
+ assert.equal(isVolatile({ $path: '/a', $type: 'x', $volatile: true } as any), true);
710
+ });
711
+
712
+ it('returns false without $volatile and no handler', () => {
713
+ assert.equal(isVolatile({ $path: '/a', $type: 'x' } as any), false);
714
+ });
715
+
716
+ it('returns true when type has volatile handler', () => {
717
+ register('ephemeral', 'volatile', () => true);
718
+ assert.equal(isVolatile({ $path: '/a', $type: 'ephemeral' } as any), true);
719
+ });
720
+
721
+ it('$volatile false overrides type handler', () => {
722
+ register('ephemeral2', 'volatile', () => true);
723
+ assert.equal(isVolatile({ $path: '/a', $type: 'ephemeral2', $volatile: false } as any), false);
724
+ });
725
+ });
726
+
727
+ // ── OpError ──
728
+
729
+ describe('OpError', () => {
730
+ it('has correct name and code', () => {
731
+ const err = new OpError('NOT_FOUND', 'thing not found');
732
+ assert.equal(err.name, 'OpError');
733
+ assert.equal(err.code, 'NOT_FOUND');
734
+ assert.equal(err.message, 'thing not found');
735
+ assert.ok(err instanceof Error);
736
+ });
737
+ });
738
+
739
+ // ── TypesStore edge cases ──
740
+
741
+ describe('TypesStore', () => {
742
+ beforeEach(() => {
743
+ clearRegistry();
744
+
745
+ });
746
+
747
+ it('get returns undefined for unregistered type', async () => {
748
+ const backing = createMemoryTree();
749
+ const ts = createTypesStore(backing);
750
+ const result = await ts.get('/sys/types/nonexistent');
751
+ assert.equal(result, undefined);
752
+ });
753
+
754
+ it('remove throws on registry type', async () => {
755
+ register('vendor.widget', 'schema', () => ({ properties: {} }));
756
+ const backing = createMemoryTree();
757
+ const ts = createTypesStore(backing);
758
+
759
+ await assert.rejects(() => ts.remove('/sys/types/vendor/widget'));
760
+ });
761
+
762
+ it('remove works on dynamic (stored) type', async () => {
763
+ const backing = createMemoryTree();
764
+ await backing.set(createNode('/sys/types/custom/thing', 'type'));
765
+
766
+ const ts = createTypesStore(backing);
767
+ const result = await ts.remove('/sys/types/custom/thing');
768
+ assert.equal(result, true);
769
+ });
770
+
771
+ it('set goes to backing store', async () => {
772
+ const backing = createMemoryTree();
773
+ const ts = createTypesStore(backing);
774
+ await ts.set(createNode('/sys/types/dynamic/type', 'type'));
775
+
776
+ const node = await backing.get('/sys/types/dynamic/type');
777
+ assert.ok(node);
778
+ });
779
+ });
780
+
781
+ // ── QueryStore: merged query from parent ──
782
+
783
+ describe('QueryStore advanced', () => {
784
+ it('merges external query with config match via $and', async () => {
785
+ const parent = createMemoryTree();
786
+ await parent.set({ $path: '/items/1', $type: 'item', status: { $type: 's', value: 'active' }, priority: 1 } as any);
787
+ await parent.set({ $path: '/items/2', $type: 'item', status: { $type: 's', value: 'active' }, priority: 5 } as any);
788
+ await parent.set({ $path: '/items/3', $type: 'item', status: { $type: 's', value: 'done' }, priority: 1 } as any);
789
+
790
+ const qs = createQueryTree({ source: '/items', match: { 'status.value': 'active' } }, parent);
791
+ // Pass additional query — should merge with $and
792
+ const result = await qs.getChildren('/view', { query: { priority: { $gt: 3 } } });
793
+ assert.equal(result.items.length, 1);
794
+ assert.equal(result.items[0].$path, '/items/2');
795
+ });
796
+
797
+ it('returns queryMount metadata', async () => {
798
+ const parent = createMemoryTree();
799
+ await parent.set({ $path: '/items/1', $type: 'item', status: { $type: 's', value: 'active' } } as any);
800
+
801
+ const qs = createQueryTree({ source: '/items', match: { 'status.value': 'active' } }, parent);
802
+ const result = await qs.getChildren('/view');
803
+ assert.deepEqual(result.queryMount, { source: '/items', match: { 'status.value': 'active' } });
804
+ });
805
+ });
806
+
807
+ // ── matchesFilter edge cases ──
808
+
809
+ describe('matchesFilter advanced', () => {
810
+ it('$regex matching', () => {
811
+ const node = { $path: '/a', $type: 'x', name: 'hello-world' } as NodeData;
812
+ assert.equal(matchesFilter(node, { name: { $regex: 'hello' } }), true);
813
+ assert.equal(matchesFilter(node, { name: { $regex: '^nope' } }), false);
814
+ });
815
+
816
+ it('$path in match maps correctly', () => {
817
+ const node = { $path: '/items/42', $type: 'item' } as NodeData;
818
+ assert.equal(matchesFilter(node, { $path: '/items/42' }), true);
819
+ assert.equal(matchesFilter(node, { $path: '/items/99' }), false);
820
+ });
821
+
822
+ it('$acl / $owner in match', () => {
823
+ const node = { $path: '/a', $type: 'x', $owner: 'alice', $acl: [{ g: 'admin', p: 7 }] } as any;
824
+ assert.equal(matchesFilter(node, { $owner: 'alice' }), true);
825
+ assert.equal(matchesFilter(node, { $owner: 'bob' }), false);
826
+ });
827
+ });