@treenity/core 1.0.47 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (696) hide show
  1. package/dist/chain.d.ts +20 -0
  2. package/dist/chain.d.ts.map +1 -0
  3. package/dist/chain.js +59 -0
  4. package/dist/chain.js.map +1 -0
  5. package/dist/client/handle.d.ts +13 -0
  6. package/dist/client/handle.d.ts.map +1 -0
  7. package/dist/client/handle.js +46 -0
  8. package/dist/client/handle.js.map +1 -0
  9. package/dist/client/index.d.ts +21 -0
  10. package/dist/client/index.d.ts.map +1 -0
  11. package/dist/client/index.js +5 -0
  12. package/dist/client/index.js.map +1 -0
  13. package/dist/client/trpc.d.ts +13 -0
  14. package/dist/client/trpc.d.ts.map +1 -0
  15. package/dist/client/trpc.js +78 -0
  16. package/dist/client/trpc.js.map +1 -0
  17. package/dist/client.d.ts +2 -0
  18. package/dist/client.d.ts.map +1 -0
  19. package/dist/client.js +2 -0
  20. package/dist/client.js.map +1 -0
  21. package/dist/comp/handle.d.ts +14 -0
  22. package/dist/comp/handle.d.ts.map +1 -0
  23. package/dist/comp/handle.js +21 -0
  24. package/dist/comp/handle.js.map +1 -0
  25. package/dist/comp/index.d.ts +42 -0
  26. package/dist/comp/index.d.ts.map +1 -0
  27. package/dist/comp/index.js +126 -0
  28. package/dist/comp/index.js.map +1 -0
  29. package/dist/comp/needs.d.ts +26 -0
  30. package/dist/comp/needs.d.ts.map +1 -0
  31. package/dist/comp/needs.js +101 -0
  32. package/dist/comp/needs.js.map +1 -0
  33. package/dist/comp/validate.d.ts +13 -0
  34. package/dist/comp/validate.d.ts.map +1 -0
  35. package/dist/comp/validate.js +117 -0
  36. package/dist/comp/validate.js.map +1 -0
  37. package/dist/comp.d.ts +2 -0
  38. package/dist/comp.d.ts.map +1 -0
  39. package/dist/comp.js +2 -0
  40. package/dist/comp.js.map +1 -0
  41. package/dist/contexts/schema/index.d.ts +7 -0
  42. package/dist/contexts/schema/index.d.ts.map +1 -0
  43. package/dist/contexts/schema/index.js +2 -0
  44. package/dist/contexts/schema/index.js.map +1 -0
  45. package/dist/contexts/schema.d.ts +2 -0
  46. package/dist/contexts/schema.d.ts.map +1 -0
  47. package/dist/contexts/schema.js +2 -0
  48. package/dist/contexts/schema.js.map +1 -0
  49. package/dist/contexts/service/index.d.ts +31 -0
  50. package/dist/contexts/service/index.d.ts.map +1 -0
  51. package/dist/contexts/service/index.js +16 -0
  52. package/dist/contexts/service/index.js.map +1 -0
  53. package/dist/contexts/service.d.ts +1 -14
  54. package/dist/contexts/service.d.ts.map +1 -1
  55. package/dist/contexts/service.js +2 -0
  56. package/dist/contexts/service.js.map +1 -0
  57. package/dist/contexts/telegram/index.d.ts +19 -0
  58. package/dist/contexts/telegram/index.d.ts.map +1 -0
  59. package/dist/contexts/telegram/index.js +89 -0
  60. package/dist/contexts/telegram/index.js.map +1 -0
  61. package/dist/contexts/text/index.d.ts +7 -0
  62. package/dist/contexts/text/index.d.ts.map +1 -0
  63. package/dist/contexts/text/index.js +9 -0
  64. package/dist/contexts/text/index.js.map +1 -0
  65. package/dist/contexts/text.d.ts +2 -0
  66. package/dist/contexts/text.d.ts.map +1 -0
  67. package/dist/contexts/text.js +2 -0
  68. package/dist/contexts/text.js.map +1 -0
  69. package/dist/core/component.d.ts +41 -0
  70. package/dist/core/component.d.ts.map +1 -0
  71. package/dist/core/component.js +105 -0
  72. package/dist/core/component.js.map +1 -0
  73. package/dist/core/context.d.ts +5 -0
  74. package/dist/core/context.d.ts.map +1 -0
  75. package/dist/core/context.js +3 -0
  76. package/dist/core/context.js.map +1 -0
  77. package/dist/core/index.d.ts +5 -0
  78. package/dist/core/index.d.ts.map +1 -0
  79. package/dist/core/index.js +8 -0
  80. package/dist/core/index.js.map +1 -0
  81. package/dist/core/path.d.ts +7 -0
  82. package/dist/core/path.d.ts.map +1 -0
  83. package/dist/core/path.js +37 -0
  84. package/dist/core/path.js.map +1 -0
  85. package/dist/core/registry.d.ts +16 -0
  86. package/dist/core/registry.d.ts.map +1 -0
  87. package/dist/core/registry.js +100 -0
  88. package/dist/core/registry.js.map +1 -0
  89. package/dist/core.d.ts +2 -0
  90. package/dist/core.d.ts.map +1 -0
  91. package/dist/core.js +2 -0
  92. package/dist/core.js.map +1 -0
  93. package/dist/log.d.ts +8 -0
  94. package/dist/log.d.ts.map +1 -0
  95. package/dist/log.js +31 -0
  96. package/dist/log.js.map +1 -0
  97. package/dist/mod/discover.d.ts +4 -0
  98. package/dist/mod/discover.d.ts.map +1 -0
  99. package/dist/mod/discover.js +103 -0
  100. package/dist/mod/discover.js.map +1 -0
  101. package/dist/mod/examples/ticker/seed.d.ts +3 -0
  102. package/dist/mod/examples/ticker/seed.d.ts.map +1 -0
  103. package/dist/mod/examples/ticker/seed.js +16 -0
  104. package/dist/mod/examples/ticker/seed.js.map +1 -0
  105. package/dist/mod/examples/ticker/service.d.ts +2 -0
  106. package/dist/mod/examples/ticker/service.d.ts.map +1 -0
  107. package/dist/mod/examples/ticker/service.js +18 -0
  108. package/dist/mod/examples/ticker/service.js.map +1 -0
  109. package/dist/mod/examples/ticker/types.d.ts +16 -0
  110. package/dist/mod/examples/ticker/types.d.ts.map +1 -0
  111. package/dist/mod/examples/ticker/types.js +20 -0
  112. package/dist/mod/examples/ticker/types.js.map +1 -0
  113. package/dist/mod/examples/ticker/view.d.ts +2 -0
  114. package/dist/mod/examples/ticker/view.d.ts.map +1 -0
  115. package/dist/mod/examples/ticker/view.js +10 -0
  116. package/dist/mod/examples/ticker/view.js.map +1 -0
  117. package/dist/mod/index.d.ts +11 -0
  118. package/dist/mod/index.d.ts.map +1 -0
  119. package/dist/mod/index.js +8 -0
  120. package/dist/mod/index.js.map +1 -0
  121. package/dist/mod/loader.d.ts +18 -0
  122. package/dist/mod/loader.d.ts.map +1 -0
  123. package/dist/mod/loader.js +154 -0
  124. package/dist/mod/loader.js.map +1 -0
  125. package/dist/mod/optimistic.d.ts +34 -0
  126. package/dist/mod/optimistic.d.ts.map +1 -0
  127. package/dist/mod/optimistic.js +176 -0
  128. package/dist/mod/optimistic.js.map +1 -0
  129. package/dist/mod/prefab.d.ts +18 -0
  130. package/dist/mod/prefab.d.ts.map +1 -0
  131. package/dist/mod/prefab.js +42 -0
  132. package/dist/mod/prefab.js.map +1 -0
  133. package/dist/mod/tracking.d.ts +8 -0
  134. package/dist/mod/tracking.d.ts.map +1 -0
  135. package/dist/mod/tracking.js +44 -0
  136. package/dist/mod/tracking.js.map +1 -0
  137. package/dist/mod/types.d.ts +31 -0
  138. package/dist/mod/types.d.ts.map +1 -0
  139. package/dist/mod/types.js +5 -0
  140. package/dist/mod/types.js.map +1 -0
  141. package/dist/mod.d.ts +2 -0
  142. package/dist/mod.d.ts.map +1 -0
  143. package/dist/mod.js +2 -0
  144. package/dist/mod.js.map +1 -0
  145. package/dist/mods/autostart/server.d.ts +2 -0
  146. package/dist/mods/autostart/server.d.ts.map +1 -0
  147. package/dist/mods/autostart/server.js +2 -0
  148. package/dist/mods/autostart/server.js.map +1 -0
  149. package/dist/mods/autostart/service.d.ts +14 -0
  150. package/dist/mods/autostart/service.d.ts.map +1 -0
  151. package/dist/mods/autostart/service.js +88 -0
  152. package/dist/mods/autostart/service.js.map +1 -0
  153. package/dist/mods/llm/index.d.ts +13 -0
  154. package/dist/mods/llm/index.d.ts.map +1 -0
  155. package/dist/mods/llm/index.js +43 -0
  156. package/dist/mods/llm/index.js.map +1 -0
  157. package/dist/mods/llm/server.d.ts +2 -0
  158. package/dist/mods/llm/server.d.ts.map +1 -0
  159. package/dist/mods/llm/server.js +2 -0
  160. package/dist/mods/llm/server.js.map +1 -0
  161. package/dist/mods/mcp/server.d.ts +3 -0
  162. package/dist/mods/mcp/server.d.ts.map +1 -0
  163. package/dist/mods/mcp/server.js +3 -0
  164. package/dist/mods/mcp/server.js.map +1 -0
  165. package/dist/mods/mcp/service.d.ts +2 -0
  166. package/dist/mods/mcp/service.d.ts.map +1 -0
  167. package/dist/mods/mcp/service.js +17 -0
  168. package/dist/mods/mcp/service.js.map +1 -0
  169. package/dist/mods/mcp/types.d.ts +5 -0
  170. package/dist/mods/mcp/types.d.ts.map +1 -0
  171. package/dist/mods/mcp/types.js +7 -0
  172. package/dist/mods/mcp/types.js.map +1 -0
  173. package/dist/mods/treenity/agent-port.d.ts +2 -0
  174. package/dist/mods/treenity/agent-port.d.ts.map +1 -0
  175. package/dist/mods/treenity/agent-port.js +76 -0
  176. package/dist/mods/treenity/agent-port.js.map +1 -0
  177. package/dist/mods/treenity/groups.d.ts +2 -0
  178. package/dist/mods/treenity/groups.d.ts.map +1 -0
  179. package/dist/mods/treenity/groups.js +18 -0
  180. package/dist/mods/treenity/groups.js.map +1 -0
  181. package/dist/mods/treenity/mod-type.d.ts +2 -0
  182. package/dist/mods/treenity/mod-type.d.ts.map +1 -0
  183. package/dist/mods/treenity/mod-type.js +9 -0
  184. package/dist/mods/treenity/mod-type.js.map +1 -0
  185. package/dist/mods/treenity/seed.d.ts +2 -0
  186. package/dist/mods/treenity/seed.d.ts.map +1 -0
  187. package/dist/mods/treenity/seed.js +53 -0
  188. package/dist/mods/treenity/seed.js.map +1 -0
  189. package/dist/mods/treenity/server.d.ts +5 -0
  190. package/dist/mods/treenity/server.d.ts.map +1 -0
  191. package/dist/mods/treenity/server.js +5 -0
  192. package/dist/mods/treenity/server.js.map +1 -0
  193. package/dist/mods/treenity/system.d.ts +36 -0
  194. package/dist/mods/treenity/system.d.ts.map +1 -0
  195. package/dist/mods/treenity/system.js +61 -0
  196. package/dist/mods/treenity/system.js.map +1 -0
  197. package/dist/mods/uix/client.d.ts +3 -0
  198. package/dist/mods/uix/client.d.ts.map +1 -0
  199. package/dist/mods/uix/client.js +96 -0
  200. package/dist/mods/uix/client.js.map +1 -0
  201. package/dist/mods/uix/compile.d.ts +7 -0
  202. package/dist/mods/uix/compile.d.ts.map +1 -0
  203. package/dist/mods/uix/compile.js +94 -0
  204. package/dist/mods/uix/compile.js.map +1 -0
  205. package/dist/mods/uix/jsx-parser.d.ts +2 -0
  206. package/dist/mods/uix/jsx-parser.d.ts.map +1 -0
  207. package/dist/mods/uix/jsx-parser.js +565 -0
  208. package/dist/mods/uix/jsx-parser.js.map +1 -0
  209. package/dist/mods/uix/verify.d.ts +7 -0
  210. package/dist/mods/uix/verify.d.ts.map +1 -0
  211. package/dist/mods/uix/verify.js +59 -0
  212. package/dist/mods/uix/verify.js.map +1 -0
  213. package/dist/schema/catalog.d.ts +23 -0
  214. package/dist/schema/catalog.d.ts.map +1 -0
  215. package/dist/schema/catalog.js +82 -0
  216. package/dist/schema/catalog.js.map +1 -0
  217. package/dist/schema/extract-schemas.d.ts +5 -0
  218. package/dist/schema/extract-schemas.d.ts.map +1 -0
  219. package/dist/schema/extract-schemas.js +444 -0
  220. package/dist/schema/extract-schemas.js.map +1 -0
  221. package/dist/schema/load.d.ts +2 -0
  222. package/dist/schema/load.d.ts.map +1 -0
  223. package/dist/schema/load.js +23 -0
  224. package/dist/schema/load.js.map +1 -0
  225. package/dist/schema/test-fixture.types.d.ts +2 -0
  226. package/dist/schema/test-fixture.types.d.ts.map +1 -0
  227. package/dist/schema/test-fixture.types.js +19 -0
  228. package/dist/schema/test-fixture.types.js.map +1 -0
  229. package/dist/schema/test-opaque.d.ts +3 -0
  230. package/dist/schema/test-opaque.d.ts.map +1 -0
  231. package/dist/schema/test-opaque.js +43 -0
  232. package/dist/schema/test-opaque.js.map +1 -0
  233. package/dist/schema/types.d.ts +37 -0
  234. package/dist/schema/types.d.ts.map +1 -0
  235. package/dist/schema/types.js +3 -0
  236. package/dist/schema/types.js.map +1 -0
  237. package/dist/server/actions.d.ts +35 -0
  238. package/dist/server/actions.d.ts.map +1 -0
  239. package/dist/server/actions.js +170 -0
  240. package/dist/server/actions.js.map +1 -0
  241. package/dist/server/agent.d.ts +6 -0
  242. package/dist/server/agent.d.ts.map +1 -0
  243. package/dist/server/agent.js +15 -0
  244. package/dist/server/agent.js.map +1 -0
  245. package/dist/server/auth.d.ts +39 -0
  246. package/dist/server/auth.d.ts.map +1 -0
  247. package/dist/server/auth.js +335 -0
  248. package/dist/server/auth.js.map +1 -0
  249. package/dist/server/client.d.ts +183 -0
  250. package/dist/server/client.d.ts.map +1 -0
  251. package/dist/server/client.js +22 -0
  252. package/dist/server/client.js.map +1 -0
  253. package/dist/server/cookies.d.ts +5 -0
  254. package/dist/server/cookies.d.ts.map +1 -0
  255. package/dist/server/cookies.js +24 -0
  256. package/dist/server/cookies.js.map +1 -0
  257. package/dist/server/doc-index.d.ts +38 -0
  258. package/dist/server/doc-index.d.ts.map +1 -0
  259. package/dist/server/doc-index.js +244 -0
  260. package/dist/server/doc-index.js.map +1 -0
  261. package/dist/server/errors.d.ts +7 -0
  262. package/dist/server/errors.d.ts.map +1 -0
  263. package/dist/server/errors.js +11 -0
  264. package/dist/server/errors.js.map +1 -0
  265. package/dist/server/factory.d.ts +23 -0
  266. package/dist/server/factory.d.ts.map +1 -0
  267. package/dist/server/factory.js +70 -0
  268. package/dist/server/factory.js.map +1 -0
  269. package/dist/server/main.d.ts +6 -0
  270. package/dist/server/main.d.ts.map +1 -0
  271. package/dist/server/main.js +45 -0
  272. package/dist/server/main.js.map +1 -0
  273. package/dist/server/mcp.d.ts +5 -0
  274. package/dist/server/mcp.d.ts.map +1 -0
  275. package/dist/server/mcp.js +280 -0
  276. package/dist/server/mcp.js.map +1 -0
  277. package/dist/server/migrate.d.ts +3 -0
  278. package/dist/server/migrate.d.ts.map +1 -0
  279. package/dist/server/migrate.js +56 -0
  280. package/dist/server/migrate.js.map +1 -0
  281. package/dist/server/mod-catalog.d.ts +14 -0
  282. package/dist/server/mod-catalog.d.ts.map +1 -0
  283. package/dist/server/mod-catalog.js +40 -0
  284. package/dist/server/mod-catalog.js.map +1 -0
  285. package/dist/server/mods-mount.d.ts +4 -0
  286. package/dist/server/mods-mount.d.ts.map +1 -0
  287. package/dist/server/mods-mount.js +169 -0
  288. package/dist/server/mods-mount.js.map +1 -0
  289. package/dist/server/mount-adapters.d.ts +9 -0
  290. package/dist/server/mount-adapters.d.ts.map +1 -0
  291. package/dist/server/mount-adapters.js +75 -0
  292. package/dist/server/mount-adapters.js.map +1 -0
  293. package/dist/server/mount.d.ts +3 -0
  294. package/dist/server/mount.d.ts.map +1 -0
  295. package/dist/server/mount.js +195 -0
  296. package/dist/server/mount.js.map +1 -0
  297. package/dist/server/prefab.d.ts +18 -0
  298. package/dist/server/prefab.d.ts.map +1 -0
  299. package/dist/server/prefab.js +70 -0
  300. package/dist/server/prefab.js.map +1 -0
  301. package/dist/server/seed/index.d.ts +6 -0
  302. package/dist/server/seed/index.d.ts.map +1 -0
  303. package/dist/server/seed/index.js +16 -0
  304. package/dist/server/seed/index.js.map +1 -0
  305. package/dist/server/server.d.ts +28 -0
  306. package/dist/server/server.d.ts.map +1 -0
  307. package/dist/server/server.js +117 -0
  308. package/dist/server/server.js.map +1 -0
  309. package/dist/server/sub.d.ts +34 -0
  310. package/dist/server/sub.d.ts.map +1 -0
  311. package/dist/server/sub.js +174 -0
  312. package/dist/server/sub.js.map +1 -0
  313. package/dist/server/trpc.d.ts +192 -0
  314. package/dist/server/trpc.d.ts.map +1 -0
  315. package/dist/server/trpc.js +319 -0
  316. package/dist/server/trpc.js.map +1 -0
  317. package/dist/server/types-mount.d.ts +3 -0
  318. package/dist/server/types-mount.d.ts.map +1 -0
  319. package/dist/server/types-mount.js +144 -0
  320. package/dist/server/types-mount.js.map +1 -0
  321. package/dist/server/validate.d.ts +3 -0
  322. package/dist/server/validate.d.ts.map +1 -0
  323. package/dist/server/validate.js +20 -0
  324. package/dist/server/validate.js.map +1 -0
  325. package/dist/server/volatile.d.ts +11 -0
  326. package/dist/server/volatile.d.ts.map +1 -0
  327. package/dist/server/volatile.js +26 -0
  328. package/dist/server/volatile.js.map +1 -0
  329. package/dist/server/watch.d.ts +23 -0
  330. package/dist/server/watch.d.ts.map +1 -0
  331. package/dist/server/watch.js +178 -0
  332. package/dist/server/watch.js.map +1 -0
  333. package/dist/tree/cache.d.ts +3 -0
  334. package/dist/tree/cache.d.ts.map +1 -0
  335. package/dist/tree/cache.js +48 -0
  336. package/dist/tree/cache.js.map +1 -0
  337. package/dist/tree/fs.d.ts +3 -0
  338. package/dist/tree/fs.d.ts.map +1 -0
  339. package/dist/tree/fs.js +274 -0
  340. package/dist/tree/fs.js.map +1 -0
  341. package/dist/tree/index.d.ts +38 -0
  342. package/dist/tree/index.d.ts.map +1 -0
  343. package/dist/tree/index.js +182 -0
  344. package/dist/tree/index.js.map +1 -0
  345. package/dist/tree/inflight.d.ts +2 -0
  346. package/dist/tree/inflight.d.ts.map +1 -0
  347. package/dist/tree/inflight.js +15 -0
  348. package/dist/tree/inflight.js.map +1 -0
  349. package/dist/tree/json-codec.d.ts +2 -0
  350. package/dist/tree/json-codec.d.ts.map +1 -0
  351. package/dist/tree/json-codec.js +13 -0
  352. package/dist/tree/json-codec.js.map +1 -0
  353. package/dist/tree/mimefs.d.ts +13 -0
  354. package/dist/tree/mimefs.d.ts.map +1 -0
  355. package/dist/tree/mimefs.js +124 -0
  356. package/dist/tree/mimefs.js.map +1 -0
  357. package/dist/tree/mongo.d.ts +5 -0
  358. package/dist/tree/mongo.d.ts.map +1 -0
  359. package/dist/tree/mongo.js +110 -0
  360. package/dist/tree/mongo.js.map +1 -0
  361. package/dist/tree/patch.d.ts +30 -0
  362. package/dist/tree/patch.d.ts.map +1 -0
  363. package/dist/tree/patch.js +112 -0
  364. package/dist/tree/patch.js.map +1 -0
  365. package/dist/tree/query.d.ts +12 -0
  366. package/dist/tree/query.d.ts.map +1 -0
  367. package/dist/tree/query.js +61 -0
  368. package/dist/tree/query.js.map +1 -0
  369. package/dist/tree/repath.d.ts +3 -0
  370. package/dist/tree/repath.d.ts.map +1 -0
  371. package/dist/tree/repath.js +38 -0
  372. package/dist/tree/repath.js.map +1 -0
  373. package/dist/tree-chain.d.ts +18 -0
  374. package/dist/tree-chain.d.ts.map +1 -0
  375. package/dist/tree-chain.js +109 -0
  376. package/dist/tree-chain.js.map +1 -0
  377. package/dist/tree.d.ts +2 -0
  378. package/dist/tree.d.ts.map +1 -0
  379. package/dist/tree.js +2 -0
  380. package/dist/tree.js.map +1 -0
  381. package/dist/uri.d.ts +11 -0
  382. package/dist/uri.d.ts.map +1 -0
  383. package/dist/uri.js +79 -0
  384. package/dist/uri.js.map +1 -0
  385. package/package.json +39 -40
  386. package/src/chain.test.ts +190 -0
  387. package/src/chain.ts +82 -0
  388. package/src/client/client.test.ts +192 -0
  389. package/src/client/handle.ts +53 -0
  390. package/src/client/index.ts +18 -0
  391. package/src/client/trpc.ts +91 -0
  392. package/src/client.ts +1 -0
  393. package/src/comp/CLAUDE.md +14 -0
  394. package/src/comp/handle.ts +36 -0
  395. package/src/comp/index.test.ts +129 -0
  396. package/src/comp/index.ts +175 -0
  397. package/src/comp/needs.test.ts +499 -0
  398. package/src/comp/needs.ts +113 -0
  399. package/src/comp/validate.test.ts +304 -0
  400. package/src/comp/validate.ts +125 -0
  401. package/src/comp.ts +1 -0
  402. package/src/contexts/schema/index.ts +7 -0
  403. package/src/contexts/schema.ts +1 -0
  404. package/src/contexts/service/index.test.ts +323 -0
  405. package/src/contexts/service/index.ts +43 -0
  406. package/src/contexts/service.ts +1 -0
  407. package/src/contexts/telegram/index.ts +115 -0
  408. package/src/contexts/text/index.test.ts +31 -0
  409. package/src/contexts/text/index.ts +18 -0
  410. package/src/contexts/text.ts +1 -0
  411. package/src/core/component.ts +151 -0
  412. package/src/core/context.ts +14 -0
  413. package/src/core/index.test.ts +203 -0
  414. package/src/core/index.ts +9 -0
  415. package/src/core/path.ts +35 -0
  416. package/src/core/registry.ts +115 -0
  417. package/src/core.ts +1 -0
  418. package/src/log.test.ts +70 -0
  419. package/src/log.ts +28 -0
  420. package/src/mod/discover.test.ts +133 -0
  421. package/src/mod/discover.ts +100 -0
  422. package/src/mod/docs/00-index.md +19 -0
  423. package/src/mod/docs/01-primitives.md +38 -0
  424. package/src/mod/docs/02-core-api.md +68 -0
  425. package/src/mod/docs/03-registry.md +30 -0
  426. package/src/mod/docs/04-store.md +62 -0
  427. package/src/mod/docs/05-comp.md +111 -0
  428. package/src/mod/docs/06-actions.md +193 -0
  429. package/src/mod/docs/07-realtime.md +100 -0
  430. package/src/mod/docs/08-services.md +33 -0
  431. package/src/mod/docs/09-mounts.md +43 -0
  432. package/src/mod/docs/10-acl.md +60 -0
  433. package/src/mod/docs/11-server.md +62 -0
  434. package/src/mod/docs/12-conventions.md +65 -0
  435. package/src/mod/docs/13-example.md +132 -0
  436. package/src/mod/docs/14-mod-format.md +304 -0
  437. package/src/mod/docs/15-documenting-types.md +156 -0
  438. package/src/mod/examples/ticker/seed.ts +19 -0
  439. package/src/mod/examples/ticker/service.ts +20 -0
  440. package/src/mod/examples/ticker/ticker.test.ts +18 -0
  441. package/src/mod/examples/ticker/types.ts +22 -0
  442. package/src/mod/examples/ticker/view.tsx +19 -0
  443. package/src/mod/index.ts +12 -0
  444. package/src/mod/loader.test.ts +168 -0
  445. package/src/mod/loader.ts +174 -0
  446. package/src/mod/optimistic.test.ts +446 -0
  447. package/src/mod/optimistic.ts +210 -0
  448. package/src/mod/prefab.ts +62 -0
  449. package/src/mod/tracking.test.ts +59 -0
  450. package/src/mod/tracking.ts +51 -0
  451. package/src/mod/types.ts +40 -0
  452. package/src/mod.ts +1 -0
  453. package/src/mods/autostart/CLAUDE.md +6 -0
  454. package/src/mods/autostart/autostart.test.ts +85 -0
  455. package/src/mods/autostart/server.ts +1 -0
  456. package/src/mods/autostart/service.ts +98 -0
  457. package/src/mods/llm/CLAUDE.md +6 -0
  458. package/src/mods/llm/index.ts +57 -0
  459. package/src/mods/llm/llm.test.ts +109 -0
  460. package/src/mods/llm/server.ts +1 -0
  461. package/src/mods/mcp/CLAUDE.md +6 -0
  462. package/src/mods/mcp/server.ts +2 -0
  463. package/src/mods/mcp/service.ts +19 -0
  464. package/src/mods/mcp/types.ts +7 -0
  465. package/src/mods/treenity/agent-port.ts +93 -0
  466. package/src/mods/treenity/groups.ts +19 -0
  467. package/src/mods/treenity/mod-type.ts +10 -0
  468. package/src/mods/treenity/seed.ts +56 -0
  469. package/src/mods/treenity/server.ts +4 -0
  470. package/src/mods/treenity/system.ts +70 -0
  471. package/src/mods/uix/CLAUDE.md +7 -0
  472. package/src/mods/uix/client.ts +117 -0
  473. package/src/mods/uix/compile.test.ts +228 -0
  474. package/src/mods/uix/compile.ts +110 -0
  475. package/src/mods/uix/jsx-parser.test.ts +554 -0
  476. package/src/mods/uix/jsx-parser.ts +489 -0
  477. package/src/mods/uix/lazy-load.test.ts +261 -0
  478. package/src/mods/uix/uix-repomix.md +3509 -0
  479. package/src/mods/uix/verify.ts +68 -0
  480. package/src/schema/CLAUDE.md +13 -0
  481. package/src/schema/catalog.ts +101 -0
  482. package/src/schema/extract-schemas.test.ts +84 -0
  483. package/src/schema/extract-schemas.ts +462 -0
  484. package/src/schema/generated/autostart.json +44 -0
  485. package/src/schema/generated/board.column.json +25 -0
  486. package/src/schema/generated/board.task.json +147 -0
  487. package/src/schema/generated/brahman.action.back.json +12 -0
  488. package/src/schema/generated/brahman.action.broadcast.json +31 -0
  489. package/src/schema/generated/brahman.action.call.json +57 -0
  490. package/src/schema/generated/brahman.action.emittext.json +23 -0
  491. package/src/schema/generated/brahman.action.eval.json +23 -0
  492. package/src/schema/generated/brahman.action.file.json +28 -0
  493. package/src/schema/generated/brahman.action.forward.json +29 -0
  494. package/src/schema/generated/brahman.action.getvalue.json +28 -0
  495. package/src/schema/generated/brahman.action.ifelse.json +42 -0
  496. package/src/schema/generated/brahman.action.keywordselect.json +46 -0
  497. package/src/schema/generated/brahman.action.message.json +127 -0
  498. package/src/schema/generated/brahman.action.onerror.json +29 -0
  499. package/src/schema/generated/brahman.action.page.json +22 -0
  500. package/src/schema/generated/brahman.action.params.json +36 -0
  501. package/src/schema/generated/brahman.action.question.json +43 -0
  502. package/src/schema/generated/brahman.action.remove.json +12 -0
  503. package/src/schema/generated/brahman.action.resethistory.json +12 -0
  504. package/src/schema/generated/brahman.action.resetsession.json +12 -0
  505. package/src/schema/generated/brahman.action.selectlang.json +20 -0
  506. package/src/schema/generated/brahman.action.setvalue.json +27 -0
  507. package/src/schema/generated/brahman.action.tag.json +27 -0
  508. package/src/schema/generated/brahman.bot.json +68 -0
  509. package/src/schema/generated/brahman.page.json +25 -0
  510. package/src/schema/generated/brahman.session.json +29 -0
  511. package/src/schema/generated/brahman.user.json +58 -0
  512. package/src/schema/generated/cafe.contact.json +56 -0
  513. package/src/schema/generated/cafe.mail.json +29 -0
  514. package/src/schema/generated/default.json +15 -0
  515. package/src/schema/generated/doc.page.json +23 -0
  516. package/src/schema/generated/examples.demo.generator.json +16 -0
  517. package/src/schema/generated/examples.demo.sensor.json +35 -0
  518. package/src/schema/generated/groups.json +20 -0
  519. package/src/schema/generated/launcher.json +91 -0
  520. package/src/schema/generated/mcp.server.json +15 -0
  521. package/src/schema/generated/mindmap.map.json +22 -0
  522. package/src/schema/generated/sim.agent.json +24 -0
  523. package/src/schema/generated/sim.ai.json +24 -0
  524. package/src/schema/generated/sim.config.json +38 -0
  525. package/src/schema/generated/sim.descriptive.json +26 -0
  526. package/src/schema/generated/sim.events.json +47 -0
  527. package/src/schema/generated/sim.item.json +20 -0
  528. package/src/schema/generated/sim.memory.json +17 -0
  529. package/src/schema/generated/sim.nearby.json +17 -0
  530. package/src/schema/generated/sim.position.json +25 -0
  531. package/src/schema/generated/sim.round.json +64 -0
  532. package/src/schema/generated/sim.world.json +32 -0
  533. package/src/schema/generated/t.agent.port.json +74 -0
  534. package/src/schema/generated/t.llm.json +20 -0
  535. package/src/schema/generated/t.mod.json +27 -0
  536. package/src/schema/generated/t3d.animator.json +46 -0
  537. package/src/schema/generated/t3d.audio.json +58 -0
  538. package/src/schema/generated/t3d.camera.json +50 -0
  539. package/src/schema/generated/t3d.collider.json +84 -0
  540. package/src/schema/generated/t3d.light.json +90 -0
  541. package/src/schema/generated/t3d.line.json +47 -0
  542. package/src/schema/generated/t3d.lod.json +28 -0
  543. package/src/schema/generated/t3d.material.json +131 -0
  544. package/src/schema/generated/t3d.mesh.json +65 -0
  545. package/src/schema/generated/t3d.object.json +64 -0
  546. package/src/schema/generated/t3d.particles.json +109 -0
  547. package/src/schema/generated/t3d.rigidbody.json +81 -0
  548. package/src/schema/generated/t3d.scene.json +7 -0
  549. package/src/schema/generated/t3d.script.json +23 -0
  550. package/src/schema/generated/t3d.text.json +86 -0
  551. package/src/schema/generated/t3d.trail.json +45 -0
  552. package/src/schema/generated/task.json +96 -0
  553. package/src/schema/generated/test.fixture.json +43 -0
  554. package/src/schema/generated/ticker.config.json +43 -0
  555. package/src/schema/generated/ticker.price.json +20 -0
  556. package/src/schema/generated/todo.item.json +25 -0
  557. package/src/schema/generated/todo.list.json +33 -0
  558. package/src/schema/generated/treenity.system.json +259 -0
  559. package/src/schema/generated/whisper.audio.json +25 -0
  560. package/src/schema/generated/whisper.checklist.json +17 -0
  561. package/src/schema/generated/whisper.config.json +30 -0
  562. package/src/schema/generated/whisper.inbox.json +24 -0
  563. package/src/schema/generated/whisper.meta.json +35 -0
  564. package/src/schema/generated/whisper.text.json +16 -0
  565. package/src/schema/load.ts +24 -0
  566. package/src/schema/schema.test.ts +86 -0
  567. package/src/schema/test-fixture.types.ts +21 -0
  568. package/src/schema/test-opaque.ts +42 -0
  569. package/src/schema/types.ts +33 -0
  570. package/src/server/CLAUDE.md +26 -0
  571. package/src/server/actions.test.ts +272 -0
  572. package/src/server/actions.ts +274 -0
  573. package/src/server/agent-sub.test.ts +90 -0
  574. package/src/server/agent.test.ts +305 -0
  575. package/src/server/agent.ts +17 -0
  576. package/src/server/api.test.ts +454 -0
  577. package/src/server/auth.test.ts +441 -0
  578. package/src/server/auth.ts +386 -0
  579. package/src/server/client.ts +24 -0
  580. package/src/server/conditions.test.ts +128 -0
  581. package/src/server/cookies.ts +25 -0
  582. package/src/server/coverage.test.ts +827 -0
  583. package/src/server/doc-index.ts +286 -0
  584. package/src/server/e2e.test.ts +966 -0
  585. package/src/server/errors.ts +11 -0
  586. package/src/server/factory.ts +99 -0
  587. package/src/server/main.ts +56 -0
  588. package/src/server/mcp.ts +326 -0
  589. package/src/server/migrate.test.ts +123 -0
  590. package/src/server/migrate.ts +62 -0
  591. package/src/server/mod-catalog.ts +59 -0
  592. package/src/server/mods-mount.ts +179 -0
  593. package/src/server/mount-adapters.ts +82 -0
  594. package/src/server/mount.parametrized.test.ts +52 -0
  595. package/src/server/mount.query.test.ts +127 -0
  596. package/src/server/mount.test.ts +497 -0
  597. package/src/server/mount.ts +208 -0
  598. package/src/server/prefab.test.ts +415 -0
  599. package/src/server/prefab.ts +104 -0
  600. package/src/server/seed/index.ts +24 -0
  601. package/src/server/server.ts +153 -0
  602. package/src/server/stress.test.ts +844 -0
  603. package/src/server/sub.test.ts +55 -0
  604. package/src/server/sub.ts +224 -0
  605. package/src/server/trpc.ts +369 -0
  606. package/src/server/types-mount.ts +142 -0
  607. package/src/server/validate.test.ts +91 -0
  608. package/src/server/validate.ts +22 -0
  609. package/src/server/volatile.test.ts +140 -0
  610. package/src/server/volatile.ts +32 -0
  611. package/src/server/watch.test.ts +594 -0
  612. package/src/server/watch.ts +202 -0
  613. package/src/server/workflow.test.ts +82 -0
  614. package/src/tree/CLAUDE.md +13 -0
  615. package/src/tree/cache.test.ts +213 -0
  616. package/src/tree/cache.ts +51 -0
  617. package/src/tree/fs.test.ts +247 -0
  618. package/src/tree/fs.ts +251 -0
  619. package/src/tree/index.test.ts +164 -0
  620. package/src/tree/index.ts +216 -0
  621. package/src/tree/inflight.ts +15 -0
  622. package/src/tree/json-codec.ts +16 -0
  623. package/src/tree/mimefs.test.ts +289 -0
  624. package/src/tree/mimefs.ts +142 -0
  625. package/src/tree/mongo.ts +125 -0
  626. package/src/tree/patch.test.ts +192 -0
  627. package/src/tree/patch.ts +133 -0
  628. package/src/tree/query.test.ts +110 -0
  629. package/src/tree/query.ts +70 -0
  630. package/src/tree/repath.test.ts +86 -0
  631. package/src/tree/repath.ts +53 -0
  632. package/src/tree-chain.test.ts +723 -0
  633. package/src/tree-chain.ts +144 -0
  634. package/src/tree.ts +1 -0
  635. package/src/uri.test.ts +86 -0
  636. package/src/uri.ts +82 -0
  637. package/CHANGELOG.md +0 -305
  638. package/README.md +0 -18
  639. package/dist/context.d.ts +0 -41
  640. package/dist/context.d.ts.map +0 -1
  641. package/dist/context.mjs +0 -81
  642. package/dist/context.mjs.map +0 -1
  643. package/dist/contexts/node-engine.d.ts +0 -12
  644. package/dist/contexts/node-engine.d.ts.map +0 -1
  645. package/dist/contexts/node-engine.mjs +0 -7
  646. package/dist/contexts/node-engine.mjs.map +0 -1
  647. package/dist/contexts/noflo/types.d.ts +0 -20
  648. package/dist/contexts/noflo/types.d.ts.map +0 -1
  649. package/dist/contexts/object.d.ts +0 -11
  650. package/dist/contexts/object.d.ts.map +0 -1
  651. package/dist/contexts/object.mjs +0 -15
  652. package/dist/contexts/object.mjs.map +0 -1
  653. package/dist/contexts/proto.d.ts +0 -11
  654. package/dist/contexts/proto.d.ts.map +0 -1
  655. package/dist/contexts/proto.mjs +0 -7
  656. package/dist/contexts/proto.mjs.map +0 -1
  657. package/dist/contexts/react-context.d.ts +0 -21
  658. package/dist/contexts/react-context.d.ts.map +0 -1
  659. package/dist/contexts/react-context.mjs +0 -24
  660. package/dist/contexts/react-context.mjs.map +0 -1
  661. package/dist/contexts/service.mjs +0 -7
  662. package/dist/contexts/service.mjs.map +0 -1
  663. package/dist/get-type-cache.d.ts +0 -2
  664. package/dist/get-type-cache.d.ts.map +0 -1
  665. package/dist/get-type-cache.mjs +0 -7
  666. package/dist/get-type-cache.mjs.map +0 -1
  667. package/dist/index.d.ts +0 -13
  668. package/dist/index.d.ts.map +0 -1
  669. package/dist/index.mjs +0 -10
  670. package/dist/index.mjs.map +0 -1
  671. package/dist/link/link.d.ts +0 -25
  672. package/dist/link/link.d.ts.map +0 -1
  673. package/dist/link/link.mjs +0 -72
  674. package/dist/link/link.mjs.map +0 -1
  675. package/dist/link/link.test.d.ts +0 -2
  676. package/dist/link/link.test.d.ts.map +0 -1
  677. package/dist/loading.d.ts +0 -9
  678. package/dist/loading.d.ts.map +0 -1
  679. package/dist/meta-type.d.ts +0 -58
  680. package/dist/meta-type.d.ts.map +0 -1
  681. package/dist/meta-type.mjs +0 -104
  682. package/dist/meta-type.mjs.map +0 -1
  683. package/dist/meta.d.ts +0 -20
  684. package/dist/meta.d.ts.map +0 -1
  685. package/dist/meta.mjs +0 -16
  686. package/dist/meta.mjs.map +0 -1
  687. package/dist/node/index.d.ts +0 -2
  688. package/dist/node/index.d.ts.map +0 -1
  689. package/dist/node/types.d.ts +0 -37
  690. package/dist/node/types.d.ts.map +0 -1
  691. package/dist/test/context.test.d.ts +0 -2
  692. package/dist/test/context.test.d.ts.map +0 -1
  693. package/dist/types.d.ts +0 -14
  694. package/dist/types.d.ts.map +0 -1
  695. package/dist/types.mjs +0 -16
  696. package/dist/types.mjs.map +0 -1
@@ -0,0 +1,723 @@
1
+ import assert from 'node:assert/strict'
2
+ import { describe, test } from 'node:test'
3
+ import { createMemoryTree } from '#tree'
4
+ import { register } from '#core'
5
+ import { registerType } from '#comp'
6
+ import { type TypedRef, refVal } from '#chain'
7
+ import { isRef } from '#core'
8
+ import type { Tree } from '#tree'
9
+
10
+ // ── Test types ──
11
+
12
+ class Scanner {
13
+ static $type = 'tch.scanner'
14
+ intervalMs = 900_000
15
+ maxRetries = 3
16
+ livePrices: TypedRef<LivePrices> = refVal(LivePrices)
17
+ }
18
+ registerType('tch.scanner', Scanner)
19
+
20
+ class LivePrices {
21
+ static $type = 'tch.live-prices'
22
+ feederUrl = 'ws://localhost:8090'
23
+ }
24
+ registerType('tch.live-prices', LivePrices)
25
+
26
+ class Profile {
27
+ static $type = 'tch.profile'
28
+ name = ''
29
+ balance = 0
30
+ }
31
+ registerType('tch.profile', Profile)
32
+
33
+ class Wallet {
34
+ static $type = 'tch.wallet'
35
+ address = ''
36
+ chain = ''
37
+ }
38
+ registerType('tch.wallet', Wallet)
39
+
40
+ // ── Register actions ──
41
+
42
+ register('tch.scanner', 'action:scan', () => ({ started: true }))
43
+ register('tch.scanner', 'action:configure', (_ctx: any, data: any) => data)
44
+ register('tch.live-prices', 'action:subscribe', (_ctx: any, data: any) =>
45
+ data.slugs.map((s: string) => ({ slug: s, bid: 0.6 })),
46
+ )
47
+
48
+ // ── Seed ──
49
+
50
+ async function seed(): Promise<Tree> {
51
+ const tree = createMemoryTree()
52
+
53
+ await tree.set({ $path: '/services', $type: 'dir' })
54
+ await tree.set({
55
+ $path: '/services/scanner',
56
+ $type: 'tch.scanner',
57
+ intervalMs: 900_000,
58
+ maxRetries: 3,
59
+ livePrices: { $type: 'ref', $ref: '/services/live-prices' },
60
+ })
61
+ await tree.set({
62
+ $path: '/services/live-prices',
63
+ $type: 'tch.live-prices',
64
+ feederUrl: 'ws://localhost:8090',
65
+ })
66
+
67
+ // Children of scanner
68
+ await tree.set({ $path: '/services/scanner/s1', $type: 'tch.scan-result', ts: 1000 })
69
+ await tree.set({ $path: '/services/scanner/s2', $type: 'tch.scan-result', ts: 2000 })
70
+
71
+ // Node with named component
72
+ await tree.set({
73
+ $path: '/users/alice',
74
+ $type: 'tch.profile',
75
+ name: 'Alice',
76
+ balance: 100,
77
+ wallet: { $type: 'tch.wallet', address: '0xabc', chain: 'eth' },
78
+ })
79
+
80
+ return tree
81
+ }
82
+
83
+ import { treeChain } from './tree-chain'
84
+
85
+ describe('treeChain — path building', () => {
86
+ test('$path from dot navigation', () => {
87
+ const c = treeChain(null as any)
88
+ assert.equal(c.services.scanner.$path, '/services/scanner')
89
+ })
90
+
91
+ test('$path from root', () => {
92
+ const c = treeChain(null as any)
93
+ assert.equal(c.$path, '/')
94
+ })
95
+
96
+ test('$path with basePath', () => {
97
+ const c = treeChain(null as any, '/services')
98
+ assert.equal(c.scanner.$path, '/services/scanner')
99
+ })
100
+
101
+ test('$path with bracket access', () => {
102
+ const c = treeChain(null as any)
103
+ assert.equal(c.services.scanner['s1'].$path, '/services/scanner/s1')
104
+ })
105
+ })
106
+
107
+ describe('treeChain — node materialization (await)', () => {
108
+ test('await returns node data', async () => {
109
+ const tree = await seed()
110
+ const c = treeChain(tree)
111
+ const node = await c.services.scanner
112
+ assert.equal(node.$type, 'tch.scanner')
113
+ assert.equal(node.intervalMs, 900_000)
114
+ })
115
+
116
+ test('await deep path', async () => {
117
+ const tree = await seed()
118
+ const node = await treeChain(tree).services.scanner['s1']
119
+ assert.equal(node.ts, 1000)
120
+ })
121
+
122
+ test('await missing node throws', async () => {
123
+ const tree = await seed()
124
+ await assert.rejects(async () => { await treeChain(tree).nothing.here })
125
+ })
126
+ })
127
+
128
+ describe('treeChain — $get (typed component)', () => {
129
+ test('$get returns typed fields', async () => {
130
+ const tree = await seed()
131
+ const scanner: Scanner = await treeChain(tree).services.scanner.$get(Scanner)
132
+ assert.equal(scanner.intervalMs, 900_000)
133
+ assert.equal(scanner.maxRetries, 3)
134
+ })
135
+
136
+ test('$get with named component', async () => {
137
+ const tree = await seed()
138
+ const wallet = await treeChain(tree).users.alice.$get(null, 'wallet')
139
+ assert.equal(wallet.address, '0xabc')
140
+ })
141
+
142
+ test('$get wrong type throws', async () => {
143
+ const tree = await seed()
144
+ await assert.rejects(async () => { await treeChain(tree).services.scanner.$get(LivePrices) })
145
+ })
146
+ })
147
+
148
+ describe('treeChain — (Class) bracket access', () => {
149
+ test('(Class) returns typed fields', async () => {
150
+ const tree = await seed()
151
+ const scanner: Scanner = await treeChain(tree).services.scanner(Scanner)
152
+ assert.equal(scanner.intervalMs, 900_000)
153
+ assert.equal(scanner.maxRetries, 3)
154
+ })
155
+
156
+ test('(Class) finds named component by type scan', async () => {
157
+ const tree = await seed()
158
+ const wallet = await treeChain(tree).users.alice(Wallet)
159
+ assert.equal(wallet.address, '0xabc')
160
+ })
161
+
162
+ test('(Class) wrong type throws', async () => {
163
+ const tree = await seed()
164
+ await assert.rejects(async () => { await treeChain(tree).services.scanner(LivePrices) })
165
+ })
166
+
167
+ test('(Class) then ref follow', async () => {
168
+ const tree = await seed()
169
+ const lp = await treeChain(tree).services.scanner(Scanner).livePrices
170
+ assert.equal(lp.feederUrl, 'ws://localhost:8090')
171
+ })
172
+
173
+ test('(Class) → ref → action', async () => {
174
+ const tree = await seed()
175
+ const result = await treeChain(tree)
176
+ .services.scanner(Scanner).livePrices
177
+ .subscribe({ slugs: ['btc'] })
178
+ assert.deepEqual(result, [{ slug: 'btc', bid: 0.6 }])
179
+ })
180
+ })
181
+
182
+ describe('treeChain — ref auto-follow', () => {
183
+ test('TypedRef field resolves to target node', async () => {
184
+ const tree = await seed()
185
+ // scanner.livePrices is { $ref: '/services/live-prices' }
186
+ // chain follows ref automatically
187
+ const lp = await treeChain(tree).services.scanner.$get(Scanner).livePrices
188
+ assert.equal(lp.feederUrl, 'ws://localhost:8090')
189
+ })
190
+
191
+ test('ref field then field access', async () => {
192
+ const tree = await seed()
193
+ const url = await treeChain(tree).services.scanner.$get(Scanner).livePrices.feederUrl
194
+ assert.equal(url, 'ws://localhost:8090')
195
+ })
196
+
197
+ test('missing ref throws', async () => {
198
+ const tree = await seed()
199
+ // Set scanner with broken ref
200
+ await tree.set({
201
+ $path: '/broken',
202
+ $type: 'tch.scanner',
203
+ livePrices: { $type: 'ref', $ref: '/nonexistent' },
204
+ })
205
+ await assert.rejects(async () => { await treeChain(tree).broken.$get(Scanner).livePrices })
206
+ })
207
+ })
208
+
209
+ describe('treeChain — actions', () => {
210
+ test('action call returns result', async () => {
211
+ const tree = await seed()
212
+ const result = await treeChain(tree).services.scanner(Scanner).scan()
213
+ assert.deepEqual(result, { started: true })
214
+ })
215
+
216
+ test('action with data', async () => {
217
+ const tree = await seed()
218
+ const result = await treeChain(tree).services.scanner(Scanner).configure({ interval: 5000 })
219
+ assert.deepEqual(result, { interval: 5000 })
220
+ })
221
+
222
+ test('action on ref target', async () => {
223
+ const tree = await seed()
224
+ const result = await treeChain(tree)
225
+ .services.scanner
226
+ .$get(Scanner).livePrices
227
+ .subscribe({ slugs: ['btc'] })
228
+ assert.deepEqual(result, [{ slug: 'btc', bid: 0.6 }])
229
+ })
230
+ })
231
+
232
+ describe('treeChain — $children', () => {
233
+ test('returns child nodes', async () => {
234
+ const tree = await seed()
235
+ const kids = await treeChain(tree).services.scanner.$children()
236
+ assert.equal(kids.length, 2)
237
+ })
238
+
239
+ test('with query filter', async () => {
240
+ const tree = await seed()
241
+ const kids = await treeChain(tree).services.scanner.$children({ ts: 1000 })
242
+ assert.equal(kids.length, 1)
243
+ assert.equal(kids[0].ts, 1000)
244
+ })
245
+
246
+ test('empty children', async () => {
247
+ const tree = await seed()
248
+ const kids = await treeChain(tree).services['live-prices'].$children()
249
+ assert.equal(kids.length, 0)
250
+ })
251
+ })
252
+
253
+ describe('treeChain — composition', () => {
254
+ test('chain is reusable (no state mutation)', async () => {
255
+ const tree = await seed()
256
+ const services = treeChain(tree).services
257
+ const a = await services.scanner
258
+ const b = await services['live-prices']
259
+ assert.equal(a.$type, 'tch.scanner')
260
+ assert.equal(b.$type, 'tch.live-prices')
261
+ })
262
+
263
+ test('chain from basePath', async () => {
264
+ const tree = await seed()
265
+ const scanner = await treeChain(tree, '/services/scanner')
266
+ assert.equal(scanner.$type, 'tch.scanner')
267
+ })
268
+
269
+ test('full pipeline: navigate → type → ref → action', async () => {
270
+ const tree = await seed()
271
+ const result = await treeChain(tree)
272
+ .services // → /services (child nav)
273
+ .scanner // → /services/scanner (child nav)
274
+ .$get(Scanner) // → typed as Scanner
275
+ .livePrices // → follow ref → /services/live-prices
276
+ .subscribe({ slugs: ['eth', 'btc'] }) // → action on LivePrices
277
+
278
+ assert.equal(result.length, 2)
279
+ assert.equal(result[0].slug, 'eth')
280
+ assert.equal(result[1].slug, 'btc')
281
+ })
282
+ })
283
+
284
+ // ── Real-world usage examples ──
285
+ // These show how treeChain would be used on a real Treenity tree.
286
+ // Seed mimics actual /board, /cafe, /agent structure.
287
+
288
+ class BoardTask {
289
+ static $type = 'tch.board.task'
290
+ title = ''
291
+ status = 'backlog'
292
+ priority = 'normal'
293
+ }
294
+ registerType('tch.board.task', BoardTask)
295
+
296
+ class BoardKanban {
297
+ static $type = 'tch.board.kanban'
298
+ }
299
+ registerType('tch.board.kanban', BoardKanban)
300
+
301
+ class CafeContact {
302
+ static $type = 'tch.cafe.contact'
303
+ phone = ''
304
+ address = ''
305
+ }
306
+ registerType('tch.cafe.contact', CafeContact)
307
+
308
+ class AgentConfig {
309
+ static $type = 'tch.agent.config'
310
+ model = ''
311
+ bot: TypedRef<BrahmanBot> = refVal(BrahmanBot)
312
+ }
313
+ registerType('tch.agent.config', AgentConfig)
314
+
315
+ class BrahmanBot {
316
+ static $type = 'tch.brahman.bot'
317
+ alias = ''
318
+ running = false
319
+ }
320
+ registerType('tch.brahman.bot', BrahmanBot)
321
+
322
+ register('tch.board.task', 'action:move', (_ctx: any, data: any) => ({ moved: data.status }))
323
+ register('tch.board.task', 'action:assign', (_ctx: any, data: any) => ({ assigned: data.to }))
324
+ register('tch.brahman.bot', 'action:restart', () => ({ restarted: true }))
325
+
326
+ async function seedRealWorld(): Promise<Tree> {
327
+ const tree = createMemoryTree()
328
+
329
+ // /board — kanban with task children
330
+ await tree.set({ $path: '/board', $type: 'tch.board.kanban' })
331
+ await tree.set({
332
+ $path: '/board/landing',
333
+ $type: 'tch.board.task',
334
+ title: 'Landing treenity.land',
335
+ status: 'doing',
336
+ priority: 'urgent',
337
+ })
338
+ await tree.set({
339
+ $path: '/board/npm-split',
340
+ $type: 'tch.board.task',
341
+ title: 'npm monorepo split',
342
+ status: 'done',
343
+ priority: 'high',
344
+ })
345
+ await tree.set({
346
+ $path: '/board/agent-toolkit',
347
+ $type: 'tch.board.task',
348
+ title: 'Agent Toolkit — MCP tools',
349
+ status: 'backlog',
350
+ priority: 'urgent',
351
+ })
352
+
353
+ // /cafe — contact with nested component
354
+ await tree.set({
355
+ $path: '/cafe/contact',
356
+ $type: 'tch.cafe.contact',
357
+ phone: '+7-999-123-4567',
358
+ address: 'Moscow, Tverskaya 1',
359
+ })
360
+
361
+ // /agent — config with ref to bot
362
+ await tree.set({
363
+ $path: '/agent',
364
+ $type: 'tch.agent.config',
365
+ model: 'claude-opus-4-6',
366
+ bot: { $type: 'ref', $ref: '/brahman' },
367
+ })
368
+ await tree.set({
369
+ $path: '/brahman',
370
+ $type: 'tch.brahman.bot',
371
+ alias: '@treenitybot',
372
+ running: true,
373
+ })
374
+
375
+ return tree
376
+ }
377
+
378
+ describe('real-world: board tasks', () => {
379
+ test('read task title by path', async () => {
380
+ const tree = await seedRealWorld()
381
+ const task = await treeChain(tree).board.landing
382
+ assert.equal(task.title, 'Landing treenity.land')
383
+ assert.equal(task.status, 'doing')
384
+ })
385
+
386
+ test('list all board tasks', async () => {
387
+ const tree = await seedRealWorld()
388
+ const tasks = await treeChain(tree).board.$children()
389
+ assert.equal(tasks.length, 3)
390
+ })
391
+
392
+ test('filter tasks by status', async () => {
393
+ const tree = await seedRealWorld()
394
+ const doing = await treeChain(tree).board.$children({ status: 'doing' })
395
+ assert.equal(doing.length, 1)
396
+ assert.equal(doing[0].title, 'Landing treenity.land')
397
+ })
398
+
399
+ test('move task via action', async () => {
400
+ const tree = await seedRealWorld()
401
+ const result = await treeChain(tree).board.landing(BoardTask).move({ status: 'review' })
402
+ assert.deepEqual(result, { moved: 'review' })
403
+ })
404
+
405
+ test('assign task', async () => {
406
+ const tree = await seedRealWorld()
407
+ const result = await treeChain(tree).board['agent-toolkit'](BoardTask).assign({ to: 'agent' })
408
+ assert.deepEqual(result, { assigned: 'agent' })
409
+ })
410
+
411
+ test('save chain as bookmark, reuse', async () => {
412
+ const tree = await seedRealWorld()
413
+ const board = treeChain(tree).board
414
+
415
+ const t1 = await board.landing
416
+ const t2 = await board['npm-split']
417
+ assert.equal(t1.priority, 'urgent')
418
+ assert.equal(t2.status, 'done')
419
+ })
420
+ })
421
+
422
+ describe('real-world: cross-node refs', () => {
423
+ test('agent → bot ref auto-follow', async () => {
424
+ const tree = await seedRealWorld()
425
+ const bot = await treeChain(tree).agent.$get(AgentConfig).bot
426
+ assert.equal(bot.alias, '@treenitybot')
427
+ assert.equal(bot.running, true)
428
+ })
429
+
430
+ test('action through ref: restart bot via agent', async () => {
431
+ const tree = await seedRealWorld()
432
+ const result = await treeChain(tree)
433
+ .agent
434
+ .$get(AgentConfig).bot
435
+ .restart()
436
+ assert.deepEqual(result, { restarted: true })
437
+ })
438
+
439
+ test('read field through ref', async () => {
440
+ const tree = await seedRealWorld()
441
+ const alias = await treeChain(tree).agent.$get(AgentConfig).bot.alias
442
+ assert.equal(alias, '@treenitybot')
443
+ })
444
+ })
445
+
446
+ describe('real-world: (Class) bracket access', () => {
447
+ test('agent(AgentConfig).bot auto-follows ref', async () => {
448
+ const tree = await seedRealWorld()
449
+ const bot = await treeChain(tree).agent(AgentConfig).bot
450
+ assert.equal(bot.alias, '@treenitybot')
451
+ assert.equal(bot.running, true)
452
+ })
453
+
454
+ test('(Class) → ref → action', async () => {
455
+ const tree = await seedRealWorld()
456
+ const result = await treeChain(tree).agent(AgentConfig).bot.restart()
457
+ assert.deepEqual(result, { restarted: true })
458
+ })
459
+
460
+ test('(Class) → ref → field', async () => {
461
+ const tree = await seedRealWorld()
462
+ const alias = await treeChain(tree).agent(AgentConfig).bot.alias
463
+ assert.equal(alias, '@treenitybot')
464
+ })
465
+ })
466
+
467
+ describe('real-world: ergonomics comparison', () => {
468
+ // These tests show the same operation done via treeChain vs old API
469
+ // to demonstrate the ergonomics gain.
470
+
471
+ test('old way vs new way: read nested data', async () => {
472
+ const tree = await seedRealWorld()
473
+
474
+ // OLD: 3 lines, manual path construction, no types
475
+ const node = await tree.get('/board/landing')
476
+ assert.ok(node)
477
+ const title = node.title
478
+
479
+ // NEW: 1 expression, dot navigation
480
+ const title2 = (await treeChain(tree).board.landing).title
481
+
482
+ assert.equal(title, title2)
483
+ })
484
+
485
+ test('old way vs new way: follow ref + action', async () => {
486
+ const tree = await seedRealWorld()
487
+
488
+ // OLD: manual ref resolution, 4+ lines
489
+ const agentNode = await tree.get('/agent')
490
+ assert.ok(agentNode)
491
+ const botRef = (agentNode as any).bot
492
+ assert.ok(isRef(botRef))
493
+ // would need: const bot = await tree.get(botRef.$ref)
494
+ // then: executeAction(tree, botRef.$ref, ..., 'restart')
495
+
496
+ // NEW: one chain — navigate, follow ref, call action
497
+ const result = await treeChain(tree).agent.$get(AgentConfig).bot.restart()
498
+ assert.deepEqual(result, { restarted: true })
499
+ })
500
+ })
501
+
502
+ describe('treeChain — $set', () => {
503
+ test('creates node with type from class', async () => {
504
+ const tree = createMemoryTree()
505
+ await treeChain(tree).status.$set(LivePrices, { feederUrl: 'ws://example.com' })
506
+ const node = await tree.get('/status')
507
+ assert.ok(node)
508
+ assert.equal(node.$type, 'tch.live-prices')
509
+ assert.equal(node.feederUrl, 'ws://example.com')
510
+ })
511
+
512
+ test('overwrites existing node', async () => {
513
+ const tree = await seed()
514
+ await treeChain(tree).services.scanner.$set(Scanner, { intervalMs: 5000, maxRetries: 1 })
515
+ const node = await tree.get('/services/scanner')
516
+ assert.equal(node!.intervalMs, 5000)
517
+ assert.equal(node!.maxRetries, 1)
518
+ })
519
+
520
+ test('deep path via dot navigation', async () => {
521
+ const tree = createMemoryTree()
522
+ await treeChain(tree).a.b.c.$set(Profile, { name: 'Deep', balance: 42 })
523
+ const node = await tree.get('/a/b/c')
524
+ assert.ok(node)
525
+ assert.equal(node.$type, 'tch.profile')
526
+ assert.equal(node.name, 'Deep')
527
+ assert.equal(node.balance, 42)
528
+ })
529
+
530
+ test('no data — creates node with just type', async () => {
531
+ const tree = createMemoryTree()
532
+ await treeChain(tree).board.$set(BoardKanban)
533
+ const node = await tree.get('/board')
534
+ assert.ok(node)
535
+ assert.equal(node.$type, 'tch.board.kanban')
536
+ })
537
+
538
+ test('$set then read back via chain', async () => {
539
+ const tree = createMemoryTree()
540
+ const t = treeChain(tree)
541
+ await t.users.bob.$set(Profile, { name: 'Bob', balance: 250 })
542
+ const bob = await t.users.bob
543
+ assert.equal(bob.name, 'Bob')
544
+ assert.equal(bob.balance, 250)
545
+ })
546
+
547
+ test('$set with ref field', async () => {
548
+ const tree = createMemoryTree()
549
+ await treeChain(tree).brahman.$set(BrahmanBot, { alias: '@bot', running: true })
550
+ await treeChain(tree).agent.$set(AgentConfig, {
551
+ model: 'opus',
552
+ bot: { $type: 'ref', $ref: '/brahman' },
553
+ })
554
+ const bot = await treeChain(tree).agent(AgentConfig).bot
555
+ assert.equal(bot.alias, '@bot')
556
+ })
557
+ })
558
+
559
+ describe('treeChain — Symbol traps', () => {
560
+ test('Symbol.toPrimitive returns TreeChain(path)', () => {
561
+ const c = treeChain(null as any)
562
+ assert.equal(c.services.scanner[Symbol.toPrimitive], 'TreeChain(/services/scanner)')
563
+ })
564
+
565
+ test('Symbol.toPrimitive on root', () => {
566
+ assert.equal(treeChain(null as any)[Symbol.toPrimitive], 'TreeChain(/)')
567
+ })
568
+
569
+ test('Symbol.toStringTag', () => {
570
+ const c = treeChain(null as any).foo
571
+ assert.equal(c[Symbol.toStringTag], 'TreeChain(/foo)')
572
+ })
573
+
574
+ test('other symbols return undefined', () => {
575
+ const c = treeChain(null as any)
576
+ assert.equal(c[Symbol.iterator], undefined)
577
+ assert.equal(c[Symbol.asyncIterator], undefined)
578
+ })
579
+ })
580
+
581
+ describe('treeChain — basePath edge cases', () => {
582
+ test('basePath without leading slash', () => {
583
+ const c = treeChain(null as any, 'services/scanner')
584
+ assert.equal(c.$path, '/services/scanner')
585
+ })
586
+
587
+ test('basePath await resolves directly', async () => {
588
+ const tree = await seed()
589
+ const node = await treeChain(tree, '/services/scanner')
590
+ assert.equal(node.$type, 'tch.scanner')
591
+ assert.equal(node.intervalMs, 900_000)
592
+ })
593
+
594
+ test('basePath + child nav', async () => {
595
+ const tree = await seed()
596
+ const node = await treeChain(tree, '/services').scanner
597
+ assert.equal(node.$type, 'tch.scanner')
598
+ })
599
+ })
600
+
601
+ describe('treeChain — error paths', () => {
602
+ test('action without (Class) throws', async () => {
603
+ const tree = await seed()
604
+ await assert.rejects(
605
+ async () => { await treeChain(tree).services.scanner.scan() },
606
+ (e: Error) => e.message.includes('Class'),
607
+ )
608
+ })
609
+
610
+ test('unregistered action throws', async () => {
611
+ const tree = await seed()
612
+ await assert.rejects(
613
+ async () => { await treeChain(tree).services.scanner(Scanner).nonexistent() },
614
+ (e: Error) => e.message.includes('action'),
615
+ )
616
+ })
617
+
618
+ test('null field in ops throws', async () => {
619
+ const tree = await seed()
620
+ await assert.rejects(
621
+ async () => { await treeChain(tree).services.scanner.$get(Scanner).noSuchField },
622
+ (e: Error) => e.message.includes('null'),
623
+ )
624
+ })
625
+
626
+ test('$get with missing named component throws', async () => {
627
+ const tree = await seed()
628
+ await assert.rejects(
629
+ async () => { await treeChain(tree).services.scanner.$get(null, 'ghost') },
630
+ (e: Error) => e.message.includes('ghost'),
631
+ )
632
+ })
633
+
634
+ test('await root of empty tree throws', async () => {
635
+ const tree = createMemoryTree()
636
+ await assert.rejects(async () => { await treeChain(tree) })
637
+ })
638
+ })
639
+
640
+ describe('treeChain — (Class) where node.$type matches', () => {
641
+ test('getComp returns node itself when $type matches', async () => {
642
+ const tree = await seed()
643
+ // scanner.$type === 'tch.scanner', Scanner.$type === 'tch.scanner'
644
+ // getComp returns node itself — all fields at node level
645
+ const scanner = await treeChain(tree).services.scanner(Scanner)
646
+ assert.equal(scanner.$type, 'tch.scanner')
647
+ assert.equal(scanner.intervalMs, 900_000)
648
+ assert.equal(scanner.$path, '/services/scanner')
649
+ })
650
+ })
651
+
652
+ describe('treeChain — ref edge cases', () => {
653
+ test('ref without $type field is still followed', async () => {
654
+ const tree = createMemoryTree()
655
+ await tree.set({
656
+ $path: '/target',
657
+ $type: 'tch.live-prices',
658
+ feederUrl: 'ws://bare-ref',
659
+ })
660
+ await tree.set({
661
+ $path: '/source',
662
+ $type: 'tch.scanner',
663
+ intervalMs: 1,
664
+ maxRetries: 1,
665
+ // ref without $type — isRef accepts { $ref: string }
666
+ livePrices: { $ref: '/target' },
667
+ })
668
+ const lp = await treeChain(tree).source.$get(Scanner).livePrices
669
+ assert.equal(lp.feederUrl, 'ws://bare-ref')
670
+ })
671
+
672
+ test('ref field → then read field on resolved target', async () => {
673
+ const tree = await seed()
674
+ const url = await treeChain(tree).services.scanner(Scanner).livePrices.feederUrl
675
+ assert.equal(url, 'ws://localhost:8090')
676
+ })
677
+ })
678
+
679
+ describe('treeChain — multiple ops chain', () => {
680
+ test('field → field reads chain correctly', async () => {
681
+ const tree = createMemoryTree()
682
+ await tree.set({
683
+ $path: '/config',
684
+ $type: 'tch.scanner',
685
+ intervalMs: 1,
686
+ maxRetries: 1,
687
+ livePrices: { $type: 'ref', $ref: '/lp' },
688
+ nested: { $type: 'tch.wallet', address: '0x123', chain: 'polygon' },
689
+ })
690
+ await tree.set({ $path: '/lp', $type: 'tch.live-prices', feederUrl: 'ws://chain' })
691
+
692
+ // $get → field (nested component, not a ref) → field
693
+ const chain = await treeChain(tree).config.$get(null, 'nested').chain
694
+ assert.equal(chain, 'polygon')
695
+ })
696
+ })
697
+
698
+ describe('treeChain — chain isolation', () => {
699
+ test('two chains from same root are independent', async () => {
700
+ const tree = await seed()
701
+ const t = treeChain(tree)
702
+
703
+ const chain1 = t.services.scanner.$get(Scanner)
704
+ const chain2 = t.services['live-prices']
705
+
706
+ const s = await chain1
707
+ const lp = await chain2
708
+ assert.equal(s.$type, 'tch.scanner')
709
+ assert.equal(lp.$type, 'tch.live-prices')
710
+ })
711
+
712
+ test('(Class) on one branch does not affect another', async () => {
713
+ const tree = await seed()
714
+ const services = treeChain(tree).services
715
+
716
+ const typed = await services.scanner(Scanner)
717
+ const raw = await services.scanner
718
+
719
+ assert.equal(typed.intervalMs, 900_000)
720
+ assert.equal(raw.intervalMs, 900_000)
721
+ assert.equal(raw.$type, 'tch.scanner')
722
+ })
723
+ })