@astrale-os/shell-react 0.1.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 (378) hide show
  1. package/LICENSE +202 -0
  2. package/dist/application/apps/app-host.d.ts +31 -0
  3. package/dist/application/apps/app-host.d.ts.map +1 -0
  4. package/dist/application/apps/app-host.js +59 -0
  5. package/dist/application/apps/app-logo.d.ts +19 -0
  6. package/dist/application/apps/app-logo.d.ts.map +1 -0
  7. package/dist/application/apps/app-logo.js +31 -0
  8. package/dist/application/apps/apps.hook.d.ts +12 -0
  9. package/dist/application/apps/apps.hook.d.ts.map +1 -0
  10. package/dist/application/apps/apps.hook.js +51 -0
  11. package/dist/application/apps/open-app.hook.d.ts +10 -0
  12. package/dist/application/apps/open-app.hook.d.ts.map +1 -0
  13. package/dist/application/apps/open-app.hook.js +7 -0
  14. package/dist/application/index.d.ts +18 -0
  15. package/dist/application/index.d.ts.map +1 -0
  16. package/dist/application/index.js +12 -0
  17. package/dist/application/roles.hook.d.ts +7 -0
  18. package/dist/application/roles.hook.d.ts.map +1 -0
  19. package/dist/application/roles.hook.js +23 -0
  20. package/dist/application/spaces/current-space.hook.d.ts +7 -0
  21. package/dist/application/spaces/current-space.hook.d.ts.map +1 -0
  22. package/dist/application/spaces/current-space.hook.js +27 -0
  23. package/dist/application/spaces/current-space.store.d.ts +32 -0
  24. package/dist/application/spaces/current-space.store.d.ts.map +1 -0
  25. package/dist/application/spaces/current-space.store.js +79 -0
  26. package/dist/application/spaces/space.hook.d.ts +5 -0
  27. package/dist/application/spaces/space.hook.d.ts.map +1 -0
  28. package/dist/application/spaces/space.hook.js +25 -0
  29. package/dist/application/spaces/spaces.hook.d.ts +14 -0
  30. package/dist/application/spaces/spaces.hook.d.ts.map +1 -0
  31. package/dist/application/spaces/spaces.hook.js +82 -0
  32. package/dist/application/user/user.hook.d.ts +10 -0
  33. package/dist/application/user/user.hook.d.ts.map +1 -0
  34. package/dist/application/user/user.hook.js +19 -0
  35. package/dist/application/user/user.store.d.ts +35 -0
  36. package/dist/application/user/user.store.d.ts.map +1 -0
  37. package/dist/application/user/user.store.js +51 -0
  38. package/dist/auth/act-as.context.d.ts +40 -0
  39. package/dist/auth/act-as.context.d.ts.map +1 -0
  40. package/dist/auth/act-as.context.js +84 -0
  41. package/dist/auth/auth.hook.d.ts +3 -0
  42. package/dist/auth/auth.hook.d.ts.map +1 -0
  43. package/dist/auth/auth.hook.js +25 -0
  44. package/dist/auth/can.hook.d.ts +40 -0
  45. package/dist/auth/can.hook.d.ts.map +1 -0
  46. package/dist/auth/can.hook.js +119 -0
  47. package/dist/auth/index.d.ts +6 -0
  48. package/dist/auth/index.d.ts.map +1 -0
  49. package/dist/auth/index.js +5 -0
  50. package/dist/auth/self.hook.d.ts +3 -0
  51. package/dist/auth/self.hook.d.ts.map +1 -0
  52. package/dist/auth/self.hook.js +11 -0
  53. package/dist/auth/session-kernel.d.ts +4 -0
  54. package/dist/auth/session-kernel.d.ts.map +1 -0
  55. package/dist/auth/session-kernel.js +21 -0
  56. package/dist/graph/action.d.ts +22 -0
  57. package/dist/graph/action.d.ts.map +1 -0
  58. package/dist/graph/action.js +85 -0
  59. package/dist/graph/async.d.ts +11 -0
  60. package/dist/graph/async.d.ts.map +1 -0
  61. package/dist/graph/async.js +60 -0
  62. package/dist/graph/call/call.hook.d.ts +21 -0
  63. package/dist/graph/call/call.hook.d.ts.map +1 -0
  64. package/dist/graph/call/call.hook.js +23 -0
  65. package/dist/graph/call/stream.hook.d.ts +28 -0
  66. package/dist/graph/call/stream.hook.d.ts.map +1 -0
  67. package/dist/graph/call/stream.hook.js +137 -0
  68. package/dist/graph/graph.context.d.ts +4 -0
  69. package/dist/graph/graph.context.d.ts.map +1 -0
  70. package/dist/graph/graph.context.js +10 -0
  71. package/dist/graph/guards.error.d.ts +9 -0
  72. package/dist/graph/guards.error.d.ts.map +1 -0
  73. package/dist/graph/guards.error.js +7 -0
  74. package/dist/graph/index.d.ts +20 -0
  75. package/dist/graph/index.d.ts.map +1 -0
  76. package/dist/graph/index.js +9 -0
  77. package/dist/graph/memory/base.d.ts +21 -0
  78. package/dist/graph/memory/base.d.ts.map +1 -0
  79. package/dist/graph/memory/base.js +33 -0
  80. package/dist/graph/memory/read/envelope.d.ts +71 -0
  81. package/dist/graph/memory/read/envelope.d.ts.map +1 -0
  82. package/dist/graph/memory/read/envelope.js +29 -0
  83. package/dist/graph/memory/read/idle.d.ts +18 -0
  84. package/dist/graph/memory/read/idle.d.ts.map +1 -0
  85. package/dist/graph/memory/read/idle.js +16 -0
  86. package/dist/graph/memory/read/read.d.ts +9 -0
  87. package/dist/graph/memory/read/read.d.ts.map +1 -0
  88. package/dist/graph/memory/read/read.js +87 -0
  89. package/dist/graph/memory/scope.d.ts +7 -0
  90. package/dist/graph/memory/scope.d.ts.map +1 -0
  91. package/dist/graph/memory/scope.js +25 -0
  92. package/dist/graph/mutate/move.hook.d.ts +7 -0
  93. package/dist/graph/mutate/move.hook.d.ts.map +1 -0
  94. package/dist/graph/mutate/move.hook.js +49 -0
  95. package/dist/graph/mutate/mutate.hook.d.ts +17 -0
  96. package/dist/graph/mutate/mutate.hook.d.ts.map +1 -0
  97. package/dist/graph/mutate/mutate.hook.js +45 -0
  98. package/dist/graph/query/children.hook.d.ts +29 -0
  99. package/dist/graph/query/children.hook.d.ts.map +1 -0
  100. package/dist/graph/query/children.hook.js +64 -0
  101. package/dist/graph/query/graph.hook.d.ts +9 -0
  102. package/dist/graph/query/graph.hook.d.ts.map +1 -0
  103. package/dist/graph/query/graph.hook.js +5 -0
  104. package/dist/graph/query/neighbors.hook.d.ts +7 -0
  105. package/dist/graph/query/neighbors.hook.d.ts.map +1 -0
  106. package/dist/graph/query/neighbors.hook.js +79 -0
  107. package/dist/graph/query/node.hook.d.ts +14 -0
  108. package/dist/graph/query/node.hook.d.ts.map +1 -0
  109. package/dist/graph/query/node.hook.js +43 -0
  110. package/dist/graph/query/query.hook.d.ts +14 -0
  111. package/dist/graph/query/query.hook.d.ts.map +1 -0
  112. package/dist/graph/query/query.hook.js +23 -0
  113. package/dist/index.d.ts +43 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +34 -0
  116. package/dist/intents/envelope.d.ts +33 -0
  117. package/dist/intents/envelope.d.ts.map +1 -0
  118. package/dist/intents/envelope.js +19 -0
  119. package/dist/intents/index.d.ts +6 -0
  120. package/dist/intents/index.d.ts.map +1 -0
  121. package/dist/intents/index.js +3 -0
  122. package/dist/intents/listen-intent.hook.d.ts +16 -0
  123. package/dist/intents/listen-intent.hook.d.ts.map +1 -0
  124. package/dist/intents/listen-intent.hook.js +75 -0
  125. package/dist/intents/reply.d.ts +9 -0
  126. package/dist/intents/reply.d.ts.map +1 -0
  127. package/dist/intents/reply.js +14 -0
  128. package/dist/intents/send-intent.hook.d.ts +12 -0
  129. package/dist/intents/send-intent.hook.d.ts.map +1 -0
  130. package/dist/intents/send-intent.hook.js +86 -0
  131. package/dist/navigation/adapters/adapter.d.ts +15 -0
  132. package/dist/navigation/adapters/adapter.d.ts.map +1 -0
  133. package/dist/navigation/adapters/adapter.js +1 -0
  134. package/dist/navigation/adapters/memory.adapter.d.ts +9 -0
  135. package/dist/navigation/adapters/memory.adapter.d.ts.map +1 -0
  136. package/dist/navigation/adapters/memory.adapter.js +15 -0
  137. package/dist/navigation/adapters/url.adapter.d.ts +6 -0
  138. package/dist/navigation/adapters/url.adapter.d.ts.map +1 -0
  139. package/dist/navigation/adapters/url.adapter.js +59 -0
  140. package/dist/navigation/history.d.ts +63 -0
  141. package/dist/navigation/history.d.ts.map +1 -0
  142. package/dist/navigation/history.js +144 -0
  143. package/dist/navigation/hooks/ancestors.hook.d.ts +13 -0
  144. package/dist/navigation/hooks/ancestors.hook.d.ts.map +1 -0
  145. package/dist/navigation/hooks/ancestors.hook.js +56 -0
  146. package/dist/navigation/hooks/location.hook.d.ts +4 -0
  147. package/dist/navigation/hooks/location.hook.d.ts.map +1 -0
  148. package/dist/navigation/hooks/location.hook.js +17 -0
  149. package/dist/navigation/hooks/navigate.hook.d.ts +12 -0
  150. package/dist/navigation/hooks/navigate.hook.d.ts.map +1 -0
  151. package/dist/navigation/hooks/navigate.hook.js +33 -0
  152. package/dist/navigation/hooks/scope.hook.d.ts +12 -0
  153. package/dist/navigation/hooks/scope.hook.d.ts.map +1 -0
  154. package/dist/navigation/hooks/scope.hook.js +21 -0
  155. package/dist/navigation/index.d.ts +16 -0
  156. package/dist/navigation/index.d.ts.map +1 -0
  157. package/dist/navigation/index.js +10 -0
  158. package/dist/navigation/link.d.ts +11 -0
  159. package/dist/navigation/link.d.ts.map +1 -0
  160. package/dist/navigation/link.js +62 -0
  161. package/dist/navigation/location.d.ts +48 -0
  162. package/dist/navigation/location.d.ts.map +1 -0
  163. package/dist/navigation/location.js +88 -0
  164. package/dist/navigation/scope.context.d.ts +64 -0
  165. package/dist/navigation/scope.context.d.ts.map +1 -0
  166. package/dist/navigation/scope.context.js +178 -0
  167. package/dist/navigation/snapshot.d.ts +22 -0
  168. package/dist/navigation/snapshot.d.ts.map +1 -0
  169. package/dist/navigation/snapshot.js +65 -0
  170. package/dist/schema/bind-read.d.ts +37 -0
  171. package/dist/schema/bind-read.d.ts.map +1 -0
  172. package/dist/schema/bind-read.js +205 -0
  173. package/dist/schema/binding.d.ts +21 -0
  174. package/dist/schema/binding.d.ts.map +1 -0
  175. package/dist/schema/binding.js +55 -0
  176. package/dist/schema/domain.hook.d.ts +10 -0
  177. package/dist/schema/domain.hook.d.ts.map +1 -0
  178. package/dist/schema/domain.hook.js +7 -0
  179. package/dist/schema/function.hook.d.ts +9 -0
  180. package/dist/schema/function.hook.d.ts.map +1 -0
  181. package/dist/schema/function.hook.js +40 -0
  182. package/dist/schema/index.d.ts +10 -0
  183. package/dist/schema/index.d.ts.map +1 -0
  184. package/dist/schema/index.js +8 -0
  185. package/dist/schema/kernel.hook.d.ts +10 -0
  186. package/dist/schema/kernel.hook.d.ts.map +1 -0
  187. package/dist/schema/kernel.hook.js +8 -0
  188. package/dist/schema/method.hook.d.ts +14 -0
  189. package/dist/schema/method.hook.d.ts.map +1 -0
  190. package/dist/schema/method.hook.js +49 -0
  191. package/dist/schema/tag.d.ts +11 -0
  192. package/dist/schema/tag.d.ts.map +1 -0
  193. package/dist/schema/tag.js +11 -0
  194. package/dist/schema/types.d.ts +73 -0
  195. package/dist/schema/types.d.ts.map +1 -0
  196. package/dist/schema/types.js +1 -0
  197. package/dist/schema/write.d.ts +15 -0
  198. package/dist/schema/write.d.ts.map +1 -0
  199. package/dist/schema/write.js +45 -0
  200. package/dist/selection/index.d.ts +4 -0
  201. package/dist/selection/index.d.ts.map +1 -0
  202. package/dist/selection/index.js +4 -0
  203. package/dist/selection/live.d.ts +21 -0
  204. package/dist/selection/live.d.ts.map +1 -0
  205. package/dist/selection/live.js +116 -0
  206. package/dist/selection/scope.context.d.ts +26 -0
  207. package/dist/selection/scope.context.d.ts.map +1 -0
  208. package/dist/selection/scope.context.js +100 -0
  209. package/dist/selection/selection.hook.d.ts +4 -0
  210. package/dist/selection/selection.hook.d.ts.map +1 -0
  211. package/dist/selection/selection.hook.js +14 -0
  212. package/dist/session/boot/boot.d.ts +19 -0
  213. package/dist/session/boot/boot.d.ts.map +1 -0
  214. package/dist/session/boot/boot.js +45 -0
  215. package/dist/session/boot/ownership.d.ts +18 -0
  216. package/dist/session/boot/ownership.d.ts.map +1 -0
  217. package/dist/session/boot/ownership.js +39 -0
  218. package/dist/session/boot/status.d.ts +24 -0
  219. package/dist/session/boot/status.d.ts.map +1 -0
  220. package/dist/session/boot/status.js +11 -0
  221. package/dist/session/connection/connection.hook.d.ts +3 -0
  222. package/dist/session/connection/connection.hook.d.ts.map +1 -0
  223. package/dist/session/connection/connection.hook.js +12 -0
  224. package/dist/session/connection/connection.store.d.ts +24 -0
  225. package/dist/session/connection/connection.store.d.ts.map +1 -0
  226. package/dist/session/connection/connection.store.js +31 -0
  227. package/dist/session/index.d.ts +8 -0
  228. package/dist/session/index.d.ts.map +1 -0
  229. package/dist/session/index.js +6 -0
  230. package/dist/session/kernel-client.hook.d.ts +9 -0
  231. package/dist/session/kernel-client.hook.d.ts.map +1 -0
  232. package/dist/session/kernel-client.hook.js +5 -0
  233. package/dist/session/kernel-instance.hook.d.ts +9 -0
  234. package/dist/session/kernel-instance.hook.d.ts.map +1 -0
  235. package/dist/session/kernel-instance.hook.js +10 -0
  236. package/dist/session/provider.d.ts +31 -0
  237. package/dist/session/provider.d.ts.map +1 -0
  238. package/dist/session/provider.js +165 -0
  239. package/dist/session/session.context.d.ts +18 -0
  240. package/dist/session/session.context.d.ts.map +1 -0
  241. package/dist/session/session.context.js +8 -0
  242. package/dist/session/shell.hook.d.ts +4 -0
  243. package/dist/session/shell.hook.d.ts.map +1 -0
  244. package/dist/session/shell.hook.js +15 -0
  245. package/dist/window/adopt.d.ts +27 -0
  246. package/dist/window/adopt.d.ts.map +1 -0
  247. package/dist/window/adopt.js +27 -0
  248. package/dist/window/hooks/close-guard.hook.d.ts +6 -0
  249. package/dist/window/hooks/close-guard.hook.d.ts.map +1 -0
  250. package/dist/window/hooks/close-guard.hook.js +90 -0
  251. package/dist/window/hooks/target-node.hook.d.ts +7 -0
  252. package/dist/window/hooks/target-node.hook.d.ts.map +1 -0
  253. package/dist/window/hooks/target-node.hook.js +77 -0
  254. package/dist/window/hooks/views-for.hook.d.ts +8 -0
  255. package/dist/window/hooks/views-for.hook.d.ts.map +1 -0
  256. package/dist/window/hooks/views-for.hook.js +51 -0
  257. package/dist/window/hooks/window.hook.d.ts +4 -0
  258. package/dist/window/hooks/window.hook.d.ts.map +1 -0
  259. package/dist/window/hooks/window.hook.js +14 -0
  260. package/dist/window/hooks/windows.hook.d.ts +15 -0
  261. package/dist/window/hooks/windows.hook.d.ts.map +1 -0
  262. package/dist/window/hooks/windows.hook.js +25 -0
  263. package/dist/window/host.d.ts +31 -0
  264. package/dist/window/host.d.ts.map +1 -0
  265. package/dist/window/host.js +270 -0
  266. package/dist/window/hub.d.ts +41 -0
  267. package/dist/window/hub.d.ts.map +1 -0
  268. package/dist/window/hub.js +100 -0
  269. package/dist/window/index.d.ts +15 -0
  270. package/dist/window/index.d.ts.map +1 -0
  271. package/dist/window/index.js +10 -0
  272. package/dist/window/lifecycle/mount.d.ts +47 -0
  273. package/dist/window/lifecycle/mount.d.ts.map +1 -0
  274. package/dist/window/lifecycle/mount.js +92 -0
  275. package/dist/window/lifecycle/states.d.ts +33 -0
  276. package/dist/window/lifecycle/states.d.ts.map +1 -0
  277. package/dist/window/lifecycle/states.js +7 -0
  278. package/dist/window/placement.d.ts +33 -0
  279. package/dist/window/placement.d.ts.map +1 -0
  280. package/dist/window/placement.js +57 -0
  281. package/dist/window/stage.d.ts +3 -0
  282. package/dist/window/stage.d.ts.map +1 -0
  283. package/dist/window/stage.js +41 -0
  284. package/package.json +59 -0
  285. package/src/application/apps/app-host.tsx +113 -0
  286. package/src/application/apps/app-logo.tsx +56 -0
  287. package/src/application/apps/apps.hook.ts +81 -0
  288. package/src/application/apps/open-app.hook.ts +18 -0
  289. package/src/application/index.ts +22 -0
  290. package/src/application/roles.hook.ts +41 -0
  291. package/src/application/spaces/current-space.hook.ts +43 -0
  292. package/src/application/spaces/current-space.store.ts +110 -0
  293. package/src/application/spaces/space.hook.ts +41 -0
  294. package/src/application/spaces/spaces.hook.ts +113 -0
  295. package/src/application/user/user.hook.ts +27 -0
  296. package/src/application/user/user.store.ts +85 -0
  297. package/src/auth/act-as.context.tsx +124 -0
  298. package/src/auth/auth.hook.ts +36 -0
  299. package/src/auth/can.hook.ts +149 -0
  300. package/src/auth/index.ts +6 -0
  301. package/src/auth/self.hook.ts +14 -0
  302. package/src/auth/session-kernel.ts +24 -0
  303. package/src/graph/action.ts +127 -0
  304. package/src/graph/async.ts +87 -0
  305. package/src/graph/call/call.hook.ts +42 -0
  306. package/src/graph/call/stream.hook.ts +200 -0
  307. package/src/graph/graph.context.ts +14 -0
  308. package/src/graph/guards.error.ts +58 -0
  309. package/src/graph/index.ts +20 -0
  310. package/src/graph/memory/base.ts +50 -0
  311. package/src/graph/memory/read/envelope.ts +98 -0
  312. package/src/graph/memory/read/idle.ts +24 -0
  313. package/src/graph/memory/read/read.ts +103 -0
  314. package/src/graph/memory/scope.ts +29 -0
  315. package/src/graph/mutate/move.hook.ts +70 -0
  316. package/src/graph/mutate/mutate.hook.ts +69 -0
  317. package/src/graph/query/children.hook.ts +136 -0
  318. package/src/graph/query/graph.hook.ts +13 -0
  319. package/src/graph/query/neighbors.hook.ts +124 -0
  320. package/src/graph/query/node.hook.ts +83 -0
  321. package/src/graph/query/query.hook.ts +42 -0
  322. package/src/index.ts +202 -0
  323. package/src/intents/envelope.ts +52 -0
  324. package/src/intents/index.ts +6 -0
  325. package/src/intents/listen-intent.hook.ts +92 -0
  326. package/src/intents/reply.ts +24 -0
  327. package/src/intents/send-intent.hook.ts +111 -0
  328. package/src/navigation/adapters/adapter.ts +13 -0
  329. package/src/navigation/adapters/memory.adapter.ts +22 -0
  330. package/src/navigation/adapters/url.adapter.ts +61 -0
  331. package/src/navigation/history.ts +170 -0
  332. package/src/navigation/hooks/ancestors.hook.ts +71 -0
  333. package/src/navigation/hooks/location.hook.ts +21 -0
  334. package/src/navigation/hooks/navigate.hook.ts +43 -0
  335. package/src/navigation/hooks/scope.hook.ts +34 -0
  336. package/src/navigation/index.ts +17 -0
  337. package/src/navigation/link.tsx +110 -0
  338. package/src/navigation/location.ts +122 -0
  339. package/src/navigation/scope.context.tsx +267 -0
  340. package/src/navigation/snapshot.ts +79 -0
  341. package/src/schema/bind-read.ts +319 -0
  342. package/src/schema/binding.ts +91 -0
  343. package/src/schema/domain.hook.ts +16 -0
  344. package/src/schema/function.hook.ts +68 -0
  345. package/src/schema/index.ts +25 -0
  346. package/src/schema/kernel.hook.ts +17 -0
  347. package/src/schema/method.hook.ts +103 -0
  348. package/src/schema/tag.ts +19 -0
  349. package/src/schema/types.ts +150 -0
  350. package/src/schema/write.ts +80 -0
  351. package/src/selection/index.ts +5 -0
  352. package/src/selection/live.ts +142 -0
  353. package/src/selection/scope.context.tsx +151 -0
  354. package/src/selection/selection.hook.ts +18 -0
  355. package/src/session/boot/boot.ts +57 -0
  356. package/src/session/boot/ownership.ts +54 -0
  357. package/src/session/boot/status.ts +32 -0
  358. package/src/session/connection/connection.hook.ts +16 -0
  359. package/src/session/connection/connection.store.ts +58 -0
  360. package/src/session/index.ts +8 -0
  361. package/src/session/kernel-client.hook.ts +13 -0
  362. package/src/session/kernel-instance.hook.ts +22 -0
  363. package/src/session/provider.tsx +205 -0
  364. package/src/session/session.context.ts +27 -0
  365. package/src/session/shell.hook.ts +19 -0
  366. package/src/window/adopt.ts +57 -0
  367. package/src/window/hooks/close-guard.hook.ts +100 -0
  368. package/src/window/hooks/target-node.hook.ts +94 -0
  369. package/src/window/hooks/views-for.hook.ts +82 -0
  370. package/src/window/hooks/window.hook.ts +18 -0
  371. package/src/window/hooks/windows.hook.ts +40 -0
  372. package/src/window/host.tsx +347 -0
  373. package/src/window/hub.ts +156 -0
  374. package/src/window/index.ts +17 -0
  375. package/src/window/lifecycle/mount.ts +134 -0
  376. package/src/window/lifecycle/states.ts +23 -0
  377. package/src/window/placement.ts +84 -0
  378. package/src/window/stage.tsx +46 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Error taxonomy (API §1.4) — re-exported from kernel-client so shell-react
3
+ * consumers narrow dispatch failures through the single import surface. The
4
+ * dispatched kernel call stays the source of truth; these guards drive UI
5
+ * affordances (retry, request-access, toast). Names match kernel-client exactly.
6
+ */
7
+ export {
8
+ AuthBatchError,
9
+ AuthenticationError,
10
+ ClientSessionError,
11
+ ConnectionError,
12
+ DisconnectedError,
13
+ InvalidTransportError,
14
+ InvariantViolationError,
15
+ KernelError,
16
+ NodeUnavailableError,
17
+ NotFoundError,
18
+ PermissionDeniedError,
19
+ TimeoutError,
20
+ UnsupportedTransportError,
21
+ ValidationError,
22
+ WebOSError,
23
+ classifyKernelError,
24
+ isAuthBatchError,
25
+ isAuthenticationError,
26
+ isClientSessionError,
27
+ isDelegationMintError,
28
+ isDelegationPolicyError,
29
+ isDelegationRefusedError,
30
+ isHopLimitExceededError,
31
+ isIdentityError,
32
+ isInternalKernelError,
33
+ isInvalidRequestError,
34
+ isInvalidTransportError,
35
+ isInvariantViolationError,
36
+ isKernelError,
37
+ isNodeUnavailableError,
38
+ isNotFoundError,
39
+ isParseError,
40
+ isPermissionDeniedError,
41
+ isPersistenceLoadFailedError,
42
+ isPoolClosedError,
43
+ isRedirectPolicyError,
44
+ isRedirectRefusedError,
45
+ isRegistryWriteFailedError,
46
+ isSchemaOwnershipConflictError,
47
+ isTransportError,
48
+ isUnsupportedTransportError,
49
+ isValidationError,
50
+ isWebOSError,
51
+ } from '@astrale-os/kernel-client'
52
+ export type {
53
+ AuthReason,
54
+ ClientErrorDetails,
55
+ IdentityError,
56
+ KernelErrorKind,
57
+ TransportError,
58
+ } from '@astrale-os/kernel-client'
@@ -0,0 +1,20 @@
1
+ // graph — the graph plane (API §5 + §7). Merged read hooks, writes, dispatch.
2
+ export { useNode } from './query/node.hook'
3
+ export type { NodeResult } from './query/node.hook'
4
+ export { useChildren } from './query/children.hook'
5
+ export type { ChildrenOptions, ChildrenResult } from './query/children.hook'
6
+ export { useQuery } from './query/query.hook'
7
+ export type { QueryResult } from './query/query.hook'
8
+ export { useGraph } from './query/graph.hook'
9
+ export { useMutate } from './mutate/mutate.hook'
10
+ export type { UseMutateOptions } from './mutate/mutate.hook'
11
+ export { useMove } from './mutate/move.hook'
12
+ export type { MoveAction } from './mutate/move.hook'
13
+ export { useCall } from './call/call.hook'
14
+ export type { CallOptions } from './call/call.hook'
15
+ export { useStream } from './call/stream.hook'
16
+ export type { StreamHandle, StreamOptions } from './call/stream.hook'
17
+ export type { Action } from './action'
18
+ export type { ReadState, ReadOptions, Windowed, Node } from './memory/read/envelope'
19
+ export type { GraphMemory } from './graph.context'
20
+ export type { ShapeInput } from '@astrale-os/kernel-client/store'
@@ -0,0 +1,50 @@
1
+ import type { GraphApi } from '@astrale-os/kernel-client/graph'
2
+ import type { GraphMemory, MemoryEvent } from '@astrale-os/kernel-client/store'
3
+ /**
4
+ * The base memory (API §5.4). One `GraphMemory` per live Shell — the partial
5
+ * client copy of the graph every graph/schema/nav hook reads through, so they all
6
+ * share one cache, one dedupe, one optimistic overlay. Derived from `shell.kernel`
7
+ * and memoized on the Shell object. Its `onError` fans out through a per-Shell
8
+ * sink the provider registers, so warm-refresh failures and rolled-back mutations
9
+ * reach the provider's `onError` channel (§2).
10
+ */
11
+ import type { Shell } from '@astrale-os/shell'
12
+
13
+ import { createMemory } from '@astrale-os/kernel-client/store'
14
+
15
+ /** One memory per Shell reference — shared by every hook under that provider. */
16
+ const memoryByShell = new WeakMap<Shell, GraphMemory>()
17
+
18
+ /**
19
+ * Per-Shell error sink (API §2/§8). The provider registers a bridge here; the
20
+ * memory emits refresh/mutation/divergence events through it, read lazily at
21
+ * emit time so registration order doesn't matter. Cleared on provider unmount.
22
+ */
23
+ const errorSinks = new WeakMap<Shell, (event: MemoryEvent) => void>()
24
+
25
+ /** Register (or clear) the provider's memory-event bridge for a Shell. */
26
+ export function setMemoryErrorSink(
27
+ shell: Shell,
28
+ sink: ((event: MemoryEvent) => void) | null,
29
+ ): void {
30
+ if (sink === null) errorSinks.delete(shell)
31
+ else errorSinks.set(shell, sink)
32
+ }
33
+
34
+ /**
35
+ * The base (default-scope) memory for a Shell — the SAME instance every graph/
36
+ * schema/nav hook reads through `useMemory`, so the provider can seat it in
37
+ * `GraphContext` (selection's liveness source) without minting a rival copy.
38
+ * Its `onError` fans out through the per-Shell sink so warm-refresh failures and
39
+ * rolled-back mutations reach `ShellProvider`'s `onError` channel (§2).
40
+ */
41
+ export function baseMemoryFor(shell: Shell): GraphMemory {
42
+ let memory = memoryByShell.get(shell)
43
+ if (memory === undefined) {
44
+ memory = createMemory(shell.kernel as GraphApi, {
45
+ onError: (event) => errorSinks.get(shell)?.(event),
46
+ })
47
+ memoryByShell.set(shell, memory)
48
+ }
49
+ return memory
50
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * The read envelope (API §1.1, §1.5) — the shape every read hook's result
3
+ * extends (`ReadState` + `Windowed`), the `ReadOptions` accepted by every read,
4
+ * and the assembly of the unified `RawRead` projection over a memory shape
5
+ * (empty/idle/keep-previous builders). Dependency-light so every context can
6
+ * consume it without a cycle.
7
+ */
8
+ import type { LiveResult } from '@astrale-os/kernel-client/store'
9
+
10
+ // ── Read envelope (§1.1) ─────────────────────────────────────────────────────
11
+
12
+ /** Base of every read hook's result — stale-while-revalidate + liveness + seq. */
13
+ export interface ReadState {
14
+ /** A (re)validation is in flight; data shown alongside is last-good. */
15
+ readonly pending: boolean
16
+ /** Last refresh failure; last-good data is retained. Cleared on next success. */
17
+ readonly error: unknown
18
+ /** A watch subscription is active for this shape (Tier ≥ 1), or Tier-0 only. */
19
+ readonly live: boolean
20
+ /** Journal position this result reflects (FRONTEND spec §6.1). 0 until known. */
21
+ readonly seq: number
22
+ /** Manual revalidate. Rarely needed; kept for tooling and non-live reads. */
23
+ refetch(): Promise<void>
24
+ }
25
+
26
+ /** Windowed reads add a cursor-fold `more`. */
27
+ export interface Windowed {
28
+ readonly more: {
29
+ readonly has: boolean
30
+ load(): Promise<void>
31
+ readonly pending: boolean
32
+ }
33
+ }
34
+
35
+ /** Options accepted by every read hook (§1.5). */
36
+ export interface ReadOptions {
37
+ /** default true; false = one-shot snapshot. */
38
+ live?: boolean
39
+ /** default true; false → pending-without-data on cold. */
40
+ suspend?: boolean
41
+ /** default false; show previous shape's data while a new one confirms. */
42
+ keepPrevious?: boolean
43
+ /** Visibility permission on the underlying AST — a kernel permission bitmask. */
44
+ with?: number
45
+ }
46
+
47
+ /** A graph node — derived from the memory result so no direct kernel-core import is needed. */
48
+ export type Node = NonNullable<LiveResult['node']>
49
+
50
+ /** Read options plus the windowing lever `useChildren`/`useQuery` add. */
51
+ export type CoreReadOptions = ReadOptions & { window?: 'append' | 'paged' }
52
+
53
+ /**
54
+ * The unified read projection: every data arm the memory materializes, over
55
+ * the shell-react read envelope (`ReadState` + `Windowed`). Each hook narrows
56
+ * to the arms it exposes. The store's `LiveResult` is a structural superset, so
57
+ * the warm path returns it directly (stable ref).
58
+ */
59
+ export interface RawRead extends ReadState, Windowed {
60
+ readonly nodes: readonly Node[]
61
+ readonly roots: readonly Node[]
62
+ readonly first: Node | null
63
+ readonly children: readonly Node[]
64
+ gathered(alias: string): { readonly nodes: readonly Node[]; readonly first: Node | null }
65
+ }
66
+
67
+ export const EMPTY: readonly Node[] = []
68
+
69
+ const idleGathered = (): { readonly nodes: readonly Node[]; readonly first: Node | null } => ({
70
+ nodes: EMPTY,
71
+ first: null,
72
+ })
73
+ const idleMore: Windowed['more'] = { has: false, pending: false, load: () => Promise.resolve() }
74
+
75
+ export function emptyRead(pending: boolean): RawRead {
76
+ return {
77
+ nodes: EMPTY,
78
+ roots: EMPTY,
79
+ first: null,
80
+ children: EMPTY,
81
+ gathered: idleGathered,
82
+ pending,
83
+ error: undefined,
84
+ live: false,
85
+ seq: 0,
86
+ more: idleMore,
87
+ refetch: () => Promise.resolve(),
88
+ }
89
+ }
90
+ /** The result for a null/undefined subject (§1.3) — settled, empty, no I/O. */
91
+ export const IDLE_READ = emptyRead(false)
92
+ /** Cold shape with `suspend:false` (§1.4) — empty data, pending true. */
93
+ export const EMPTY_PENDING = emptyRead(true)
94
+
95
+ /** Previous shape's data while a new one confirms (§1.5 `keepPrevious`). */
96
+ export function withPending(prev: LiveResult): RawRead {
97
+ return { ...prev, pending: true }
98
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The idle-input rule (API §1.3). A read hook's `null | undefined` subject is
3
+ * inert: `isIdleInput` is the one gate every read branches on, and
4
+ * `idleReadState` is the settled, not-live, seq-0 envelope it returns.
5
+ */
6
+ import type { ReadState } from './envelope'
7
+
8
+ /**
9
+ * The chaining rule: every read hook accepts `null | undefined` for its subject
10
+ * and returns an *idle* result (empty data, no I/O). This predicate is the one
11
+ * gate — read hooks branch on it before touching the memory.
12
+ */
13
+ export function isIdleInput(subject: unknown): subject is null | undefined {
14
+ return subject === null || subject === undefined
15
+ }
16
+
17
+ /**
18
+ * The idle `ReadState` a read hook returns for a `null`/`undefined` subject:
19
+ * settled, not live, seq 0, `refetch` a resolved no-op.
20
+ */
21
+ export function idleReadState(): ReadState {
22
+ return { pending: false, error: undefined, live: false, seq: 0, refetch: idleRefetch }
23
+ }
24
+ const idleRefetch = (): Promise<void> => Promise.resolve()
@@ -0,0 +1,103 @@
1
+ import type {
2
+ LiveResult,
3
+ ReadOptions as StoreReadOptions,
4
+ ShapeInput,
5
+ } from '@astrale-os/kernel-client/store'
6
+
7
+ import { canonicalizeAST, shapeInputToAST, stableStringify } from '@astrale-os/kernel-client/store'
8
+ /**
9
+ * The shared read substrate (API §1, §5). One `useSyncExternalStore` binding over
10
+ * a memory shape — the substrate every graph read hook narrows. Handles the four
11
+ * cross-cutting concerns once: idle inputs (§1.3), suspense-first on a cold shape
12
+ * (§1.4), stale-while-revalidate + `keepPrevious` (§1.5), and referential
13
+ * stability (§1.7 — an unchanged shape returns the store's own stable snapshot).
14
+ */
15
+ import { useCallback, useRef, useSyncExternalStore } from 'react'
16
+
17
+ import type { CoreReadOptions, RawRead } from './envelope'
18
+
19
+ import { useMemory } from '../scope'
20
+ import { EMPTY_PENDING, IDLE_READ, withPending } from './envelope'
21
+ import { isIdleInput } from './idle'
22
+
23
+ const NOOP_UNSUB = (): void => {}
24
+ const IDLE_TOKEN = ' idle'
25
+
26
+ /** Project shell-react read options onto the store's — `with`/`window`/`live` key the shape. */
27
+ function storeReadOptions(opts?: CoreReadOptions): StoreReadOptions | undefined {
28
+ if (opts === undefined) return undefined
29
+ const out: StoreReadOptions = {}
30
+ if (opts.live !== undefined) out.live = opts.live
31
+ if (opts.window !== undefined) out.window = opts.window
32
+ // `with` is a PermName at the store/kernel (READ lit-up today); the public
33
+ // `PermMask` typing reconciles with the grant epoch (API §14 G7).
34
+ if (opts.with !== undefined) out.with = opts.with as unknown as StoreReadOptions['with']
35
+ return out
36
+ }
37
+
38
+ /**
39
+ * A stable per-render key for a shape input + its keying options, so the
40
+ * subscription/snapshot closures only re-bind when the LOGICAL read changes
41
+ * (not when an inline builder closure is re-created each render).
42
+ */
43
+ function shapeToken(shape: ShapeInput, opts?: CoreReadOptions): string {
44
+ const canon = stableStringify(canonicalizeAST(shapeInputToAST(shape)))
45
+ return `${canon}#w=${String(opts?.with ?? '')}#win=${opts?.window ?? ''}#live=${
46
+ opts?.live === false ? '0' : '1'
47
+ }`
48
+ }
49
+
50
+ /**
51
+ * Subscribe to a memory shape and project it. `null`/`undefined` shape → idle.
52
+ * Cold + `suspend` (default) throws the cold-shape promise; `suspend:false`
53
+ * returns empty-pending; `keepPrevious` returns the last data while confirming.
54
+ */
55
+ export function useRead(shape: ShapeInput | null | undefined, opts?: CoreReadOptions): RawRead {
56
+ const memory = useMemory()
57
+ const idle = isIdleInput(shape)
58
+
59
+ const shapeRef = useRef<ShapeInput | null | undefined>(shape)
60
+ shapeRef.current = shape
61
+ const optsRef = useRef<CoreReadOptions | undefined>(opts)
62
+ optsRef.current = opts
63
+
64
+ const token = idle ? IDLE_TOKEN : shapeToken(shape as ShapeInput, opts)
65
+
66
+ const subscribe = useCallback(
67
+ (onStoreChange: () => void) => {
68
+ const s = shapeRef.current
69
+ if (token === IDLE_TOKEN || s === null || s === undefined) return NOOP_UNSUB
70
+ return memory.subscribe(s, onStoreChange, storeReadOptions(optsRef.current))
71
+ },
72
+ [memory, token],
73
+ )
74
+ const getSnapshot = useCallback((): LiveResult | null => {
75
+ const s = shapeRef.current
76
+ if (token === IDLE_TOKEN || s === null || s === undefined) return null
77
+ return memory.getSnapshot(s, storeReadOptions(optsRef.current))
78
+ }, [memory, token])
79
+
80
+ const snap = useSyncExternalStore(subscribe, getSnapshot, getSnapshot)
81
+ const prevRef = useRef<LiveResult | null>(null)
82
+
83
+ if (idle) return IDLE_READ
84
+
85
+ const warm = memory.peek(shape as ShapeInput, storeReadOptions(opts)) !== null
86
+ if (warm && snap !== null) {
87
+ prevRef.current = snap
88
+ return snap
89
+ }
90
+ if (opts?.keepPrevious === true && prevRef.current !== null) {
91
+ return withPending(prevRef.current)
92
+ }
93
+ if (opts?.suspend !== false) {
94
+ // Cold FAILURE (§1.4): the shape fetched and rejected with no data to show —
95
+ // throw the error to the nearest boundary. Re-throwing the promise here would
96
+ // re-arm a fresh fetch every retry (the entry's inflight was cleared on
97
+ // failure), looping render→fetch→reject forever. This breaks that loop.
98
+ if (snap !== null && snap.error !== undefined) throw snap.error
99
+ // Cold shape: suspend on the first-confirmed-data promise (§1.4).
100
+ throw memory.promise(shape as ShapeInput, storeReadOptions(opts))
101
+ }
102
+ return EMPTY_PENDING
103
+ }
@@ -0,0 +1,29 @@
1
+ import type { GraphApi } from '@astrale-os/kernel-client/graph'
2
+ import type { GraphMemory } from '@astrale-os/kernel-client/store'
3
+
4
+ /**
5
+ * Memory scope resolution (API §5.4). `useMemory` returns the memory for this
6
+ * subtree: the base memory derived from the provider's Shell, re-scoped (and
7
+ * re-api'd) to the `<ActAs>` principal via `forScope` when an identity binding is
8
+ * present — so a principal never shares cached results with another.
9
+ */
10
+ import { useContext, useMemo } from 'react'
11
+
12
+ import { IdentityContext } from '../../auth/act-as.context'
13
+ import { ShellContext } from '../../session/session.context'
14
+ import { baseMemoryFor } from './base'
15
+
16
+ /**
17
+ * The memory for this subtree. Throws outside a `<ShellProvider>`. Above any
18
+ * `<ActAs>` it is the base memory; inside one it is scoped by the binding.
19
+ */
20
+ export function useMemory(): GraphMemory {
21
+ const runtime = useContext(ShellContext)
22
+ const binding = useContext(IdentityContext)
23
+ const shell = runtime?.shell ?? null
24
+ return useMemo(() => {
25
+ if (shell === null) throw new Error('graph hooks must be used within a <ShellProvider>')
26
+ const base = baseMemoryFor(shell)
27
+ return binding === null ? base : base.forScope(binding.scope, binding.kernel as GraphApi)
28
+ }, [shell, binding])
29
+ }
@@ -0,0 +1,70 @@
1
+ import type { NodeRefInput } from '@astrale-os/kernel-client'
2
+ import type { PathLike } from '@astrale-os/kernel-client/graph'
3
+ import type { GraphMemory } from '@astrale-os/kernel-client/store'
4
+
5
+ import { rawOf } from '@astrale-os/kernel-client/graph'
6
+ /**
7
+ * useMove (API §5, the G1 seam) — dispatch the sealed `node::move` method (the one
8
+ * tree op no patch arm can express). PESSIMISTIC today (honest `pending`); affected
9
+ * container shapes revalidate on settlement. Turns optimistic when the `nodes.move`
10
+ * patch arm lands, with zero consumer change.
11
+ */
12
+ import { useCallback } from 'react'
13
+
14
+ import type { Action } from '../action'
15
+ import type { Node } from '../memory/read/envelope'
16
+
17
+ import { useSessionKernel } from '../../auth/session-kernel'
18
+ import { useAction } from '../action'
19
+ import { useMemory } from '../memory/scope'
20
+
21
+ export type MoveAction = Action<[node: Node | NodeRefInput, to: PathLike], void>
22
+
23
+ export function useMove(): MoveAction {
24
+ const kernel = useSessionKernel()
25
+ const memory = useMemory()
26
+ const run = useCallback(
27
+ async (node: Node | NodeRefInput, to: PathLike): Promise<void> => {
28
+ const method = isNode(node) ? `@${node.id}::move` : `${rawOf(node)}::move`
29
+ await kernel.call(method, { to: rawOf(to) })
30
+ await reconcileMove(memory, node, to)
31
+ },
32
+ [kernel, memory],
33
+ )
34
+ return useAction(run)
35
+ }
36
+
37
+ function isNode(x: Node | NodeRefInput): x is Node {
38
+ return typeof x === 'object' && x !== null && 'id' in x && 'class' in x && 'path' in x
39
+ }
40
+
41
+ /** Root-first parent of a raw absolute path, or `null` at the root. */
42
+ function parentPathOf(raw: string): string | null {
43
+ const trimmed = raw.replace(/\/+$/, '')
44
+ const i = trimmed.lastIndexOf('/')
45
+ if (i < 0) return null
46
+ return i === 0 ? '/' : trimmed.slice(0, i)
47
+ }
48
+
49
+ /**
50
+ * Best-effort settlement reconciliation (Tier 0): refetch the source and
51
+ * destination container's default `children` shapes when they are observed. A
52
+ * custom-ordered/filtered children shape is keyed distinctly and is not reached
53
+ * here — consumers get honest `pending` and reconcile on G1.
54
+ */
55
+ async function reconcileMove(
56
+ memory: GraphMemory,
57
+ node: Node | NodeRefInput,
58
+ to: PathLike,
59
+ ): Promise<void> {
60
+ const path = isNode(node) ? rawOf(node.path) : rawOf(node)
61
+ const containers = new Set<string>([rawOf(to)])
62
+ const old = parentPathOf(path)
63
+ if (old !== null) containers.add(old)
64
+ await Promise.allSettled(
65
+ [...containers].map((c) => {
66
+ const snap = memory.peek((q) => q.from(c).children())
67
+ return snap !== null ? snap.refetch() : Promise.resolve()
68
+ }),
69
+ )
70
+ }
@@ -0,0 +1,69 @@
1
+ import type { PatchBuilder } from '@astrale-os/kernel-client/graph'
2
+ import type { GraphMemory } from '@astrale-os/kernel-client/store'
3
+
4
+ /**
5
+ * useMutate (API 5/1.6) - build a graph-scoped Action. The callback receives
6
+ * this subtree's GraphMemory, so callers do not need a separate useGraph() just
7
+ * to author the mutation. Patch-shaped writes are optimistic via their own
8
+ * overlay; pass a function `optimistic` to preview an opaque dispatch effect.
9
+ */
10
+ import { useCallback, useRef } from 'react'
11
+
12
+ import type { Action } from '../action'
13
+
14
+ import { useAction } from '../action'
15
+ import { useMemory } from '../memory/scope'
16
+
17
+ export interface UseMutateOptions<A extends unknown[], R> {
18
+ /**
19
+ * `'auto'` (default) / `false`: the write's own overlay governs optimism - the
20
+ * callback's graph writes apply the authored patch. A function opens a
21
+ * MANUAL overlay decoupled from what the callback dispatches.
22
+ */
23
+ optimistic?: 'auto' | false | ((overlay: PatchBuilder, ...args: A) => void)
24
+ /** default 'auto'. false = keep the manual overlay on failure (caller reconciles). */
25
+ rollback?: 'auto' | false
26
+ onCommit?: (result: R) => void
27
+ onError?: (error: unknown) => void
28
+ }
29
+
30
+ export function useMutate<A extends unknown[], R>(
31
+ fn: (graph: GraphMemory, ...args: A) => Promise<R>,
32
+ opts?: UseMutateOptions<A, R>,
33
+ ): Action<A, R> {
34
+ const memory = useMemory()
35
+ const fnRef = useRef(fn)
36
+ fnRef.current = fn
37
+ const optsRef = useRef(opts)
38
+ optsRef.current = opts
39
+
40
+ const run = useCallback(
41
+ async (...args: A): Promise<R> => {
42
+ const o = optsRef.current
43
+ const optimistic = o?.optimistic
44
+ if (typeof optimistic === 'function') {
45
+ const overlay = memory.overlay((m) => optimistic(m, ...args))
46
+ try {
47
+ const result = await fnRef.current(memory, ...args)
48
+ overlay.commit()
49
+ o?.onCommit?.(result)
50
+ return result
51
+ } catch (error) {
52
+ if (o?.rollback !== false) overlay.rollback()
53
+ o?.onError?.(error)
54
+ throw error
55
+ }
56
+ }
57
+ try {
58
+ const result = await fnRef.current(memory, ...args)
59
+ o?.onCommit?.(result)
60
+ return result
61
+ } catch (error) {
62
+ o?.onError?.(error)
63
+ throw error
64
+ }
65
+ },
66
+ [memory],
67
+ )
68
+ return useAction(run)
69
+ }
@@ -0,0 +1,136 @@
1
+ import type { AnyBoundNode, TypeNames } from '@astrale-os/kernel-client'
2
+ import type {
3
+ GatherBuilder,
4
+ OrderInput,
5
+ PathLike,
6
+ QuerySource,
7
+ WalkOpts,
8
+ } from '@astrale-os/kernel-client/graph'
9
+ import type { Schema } from '@astrale-os/kernel-dsl'
10
+
11
+ import { rawOf } from '@astrale-os/kernel-client/graph'
12
+ /**
13
+ * useChildren (API §5 + §6) — ONE public symbol, overloaded: pass `opts.type`
14
+ * (over a `BoundNode` parent) for the typed children, or a bare parent for the
15
+ * untyped children. Both ride the SAME windowed memory shape. The untyped floor
16
+ * is a windowed, live read of a node's direct children; the typed twin binds them.
17
+ */
18
+ import { useMemo } from 'react'
19
+
20
+ import type { TypedChildrenResult } from '../../schema/types'
21
+ import type { ReadState, Node, ReadOptions, Windowed } from '../memory/read/envelope'
22
+
23
+ import { useChildren as useChildrenTyped } from '../../schema/bind-read'
24
+ import { useRead } from '../memory/read/read'
25
+
26
+ export interface ChildrenOptions extends ReadOptions {
27
+ /** Restrict to these classes (dual-path descent filter). */
28
+ classes?: PathLike[]
29
+ /** Server-ordered by a node prop / `id`. */
30
+ order?: OrderInput
31
+ /** Page size; `more.load()` extends. */
32
+ limit?: number
33
+ /** `append` (default, infinite) vs `paged` (replace). */
34
+ window?: 'append' | 'paged'
35
+ }
36
+
37
+ export interface ChildrenResult extends ReadState, Windowed {
38
+ /** Ordered, all loaded pages, parent excluded. */
39
+ readonly children: readonly Node[]
40
+ }
41
+
42
+ /** A node's direct children — windowed, live; `null` parent is idle (§1.3). */
43
+ function useChildrenUntyped(
44
+ parent: Node | PathLike | null | undefined,
45
+ opts?: ChildrenOptions,
46
+ ): ChildrenResult {
47
+ const shape = isIdle(parent) ? null : childrenShape(parent, opts)
48
+ const r = useRead(shape, opts)
49
+ return useMemo(
50
+ () => ({
51
+ pending: r.pending,
52
+ error: r.error,
53
+ live: r.live,
54
+ seq: r.seq,
55
+ refetch: r.refetch,
56
+ children: r.children,
57
+ more: r.more,
58
+ }),
59
+ [r],
60
+ )
61
+ }
62
+
63
+ /** Typed: a bound node's children of `opts.type`. */
64
+ export function useChildren<S extends Schema, T extends TypeNames<S>>(
65
+ parent: AnyBoundNode<S> | null | undefined,
66
+ opts: ReadOptions & {
67
+ type: T
68
+ order?: OrderInput
69
+ limit?: number
70
+ window?: 'append' | 'paged'
71
+ },
72
+ ): TypedChildrenResult<S, T>
73
+ /** Untyped: a node's direct children — windowed, live; `null` parent is idle (§1.3). */
74
+ export function useChildren(
75
+ parent: Node | PathLike | null | undefined,
76
+ opts?: ChildrenOptions,
77
+ ): ChildrenResult
78
+ export function useChildren(
79
+ parent: unknown,
80
+ opts?: unknown,
81
+ ): ReadState & Windowed & { readonly children: readonly unknown[] } {
82
+ if (hasType(opts)) {
83
+ return useChildrenTyped(
84
+ parent as AnyBoundNode<Schema> | null | undefined,
85
+ opts as ReadOptions & { type: string },
86
+ )
87
+ }
88
+ return useChildrenUntyped(
89
+ parent as Node | PathLike | null | undefined,
90
+ opts as ChildrenOptions | undefined,
91
+ )
92
+ }
93
+
94
+ function hasType(opts: unknown): opts is { type: string } {
95
+ return (
96
+ typeof opts === 'object' &&
97
+ opts !== null &&
98
+ 'type' in opts &&
99
+ (opts as { type?: unknown }).type !== undefined
100
+ )
101
+ }
102
+
103
+ // ── internals ────────────────────────────────────────────────────────────────
104
+
105
+ function isIdle(x: unknown): x is null | undefined {
106
+ return x === null || x === undefined
107
+ }
108
+
109
+ function isNode(x: Node | PathLike): x is Node {
110
+ return typeof x === 'object' && x !== null && 'id' in x && 'class' in x && 'path' in x
111
+ }
112
+
113
+ /** A parent ref anchored on the node id (stable across rename) or the raw path. */
114
+ function refOf(parent: Node | PathLike): PathLike {
115
+ return isNode(parent) ? `@${parent.id}` : parent
116
+ }
117
+
118
+ function walkOptsOf(opts?: ChildrenOptions): WalkOpts | undefined {
119
+ if (opts === undefined) return undefined
120
+ const { classes, order, limit } = opts
121
+ if (classes === undefined && order === undefined && limit === undefined) return undefined
122
+ return {
123
+ ...(classes !== undefined ? { classes: classes.map((c) => rawOf(c)) } : {}),
124
+ ...(order !== undefined ? { order } : {}),
125
+ ...(limit !== undefined ? { limit } : {}),
126
+ }
127
+ }
128
+
129
+ function childrenShape(
130
+ parent: Node | PathLike,
131
+ opts?: ChildrenOptions,
132
+ ): (q: QuerySource) => GatherBuilder {
133
+ const ref = refOf(parent)
134
+ const walk = walkOptsOf(opts)
135
+ return (q) => q.from(ref).children(walk)
136
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * useGraph (API §5) — the memory handle for this subtree (the raw floor plus the
3
+ * memory's optimistic-auto write shorthands). The same scoped memory every
4
+ * graph/schema/nav hook reads.
5
+ */
6
+ import type { GraphMemory } from '@astrale-os/kernel-client/store'
7
+
8
+ import { useMemory } from '../memory/scope'
9
+
10
+ /** The memory for this subtree — the raw floor plus optimistic-auto shorthands (§5). */
11
+ export function useGraph(): GraphMemory {
12
+ return useMemory()
13
+ }