@astrale-os/shell-react 0.2.9 → 0.2.10-beta.3

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 (335) hide show
  1. package/dist/application/apps/app-host.d.ts +4 -15
  2. package/dist/application/apps/app-host.d.ts.map +1 -1
  3. package/dist/application/apps/app-host.js +1 -1
  4. package/dist/application/apps/apps.hook.d.ts +7 -4
  5. package/dist/application/apps/apps.hook.d.ts.map +1 -1
  6. package/dist/application/apps/apps.hook.js +10 -2
  7. package/dist/application/apps/domains.hook.d.ts +1 -1
  8. package/dist/application/apps/domains.hook.d.ts.map +1 -1
  9. package/dist/application/apps/domains.hook.js +1 -1
  10. package/dist/application/apps/open-app.hook.d.ts +2 -3
  11. package/dist/application/apps/open-app.hook.d.ts.map +1 -1
  12. package/dist/application/index.d.ts +2 -4
  13. package/dist/application/index.d.ts.map +1 -1
  14. package/dist/application/index.js +2 -3
  15. package/dist/application/spaces/space.hook.d.ts +2 -2
  16. package/dist/application/spaces/space.hook.d.ts.map +1 -1
  17. package/dist/application/spaces/space.hook.js +2 -2
  18. package/dist/application/spaces/spaces.hook.d.ts +2 -3
  19. package/dist/application/spaces/spaces.hook.d.ts.map +1 -1
  20. package/dist/application/spaces/spaces.hook.js +10 -3
  21. package/dist/auth/act-as.context.d.ts +15 -32
  22. package/dist/auth/act-as.context.d.ts.map +1 -1
  23. package/dist/auth/act-as.context.js +22 -66
  24. package/dist/auth/auth.hook.d.ts +1 -0
  25. package/dist/auth/auth.hook.d.ts.map +1 -1
  26. package/dist/auth/auth.hook.js +2 -22
  27. package/dist/auth/can.hook.d.ts +10 -38
  28. package/dist/auth/can.hook.d.ts.map +1 -1
  29. package/dist/auth/can.hook.js +35 -110
  30. package/dist/auth/index.d.ts +1 -0
  31. package/dist/auth/index.d.ts.map +1 -1
  32. package/dist/auth/self.hook.d.ts +2 -2
  33. package/dist/auth/self.hook.d.ts.map +1 -1
  34. package/dist/auth/self.hook.js +0 -7
  35. package/dist/auth/session-kernel.d.ts +2 -3
  36. package/dist/auth/session-kernel.d.ts.map +1 -1
  37. package/dist/auth/session-kernel.js +4 -13
  38. package/dist/components/astrale.d.ts +14 -0
  39. package/dist/components/astrale.d.ts.map +1 -0
  40. package/dist/components/astrale.js +12 -0
  41. package/dist/components/boundaries.d.ts +47 -0
  42. package/dist/components/boundaries.d.ts.map +1 -0
  43. package/dist/components/boundaries.js +55 -0
  44. package/dist/components/can.d.ts +11 -0
  45. package/dist/components/can.d.ts.map +1 -0
  46. package/dist/components/can.js +5 -0
  47. package/dist/components/index.d.ts +6 -0
  48. package/dist/components/index.d.ts.map +1 -0
  49. package/dist/components/index.js +3 -0
  50. package/dist/graph/call/call.hook.d.ts +8 -18
  51. package/dist/graph/call/call.hook.d.ts.map +1 -1
  52. package/dist/graph/call/call.hook.js +7 -13
  53. package/dist/graph/call/stream.hook.d.ts +12 -20
  54. package/dist/graph/call/stream.hook.d.ts.map +1 -1
  55. package/dist/graph/call/stream.hook.js +55 -111
  56. package/dist/graph/graph.context.d.ts +4 -3
  57. package/dist/graph/graph.context.d.ts.map +1 -1
  58. package/dist/graph/graph.context.js +2 -8
  59. package/dist/graph/guards.error.d.ts +7 -8
  60. package/dist/graph/guards.error.d.ts.map +1 -1
  61. package/dist/graph/guards.error.js +11 -7
  62. package/dist/graph/index.d.ts +8 -16
  63. package/dist/graph/index.d.ts.map +1 -1
  64. package/dist/graph/index.js +3 -7
  65. package/dist/graph/memory/read/envelope.d.ts +22 -54
  66. package/dist/graph/memory/read/envelope.d.ts.map +1 -1
  67. package/dist/graph/memory/read/envelope.js +26 -20
  68. package/dist/graph/memory/read/idle.d.ts +1 -15
  69. package/dist/graph/memory/read/idle.d.ts.map +1 -1
  70. package/dist/graph/memory/read/idle.js +4 -13
  71. package/dist/graph/query-definition.hook.d.ts +11 -0
  72. package/dist/graph/query-definition.hook.d.ts.map +1 -0
  73. package/dist/graph/query-definition.hook.js +205 -0
  74. package/dist/graph/resource.d.ts +34 -0
  75. package/dist/graph/resource.d.ts.map +1 -0
  76. package/dist/graph/resource.js +244 -0
  77. package/dist/graph/store.d.ts +25 -0
  78. package/dist/graph/store.d.ts.map +1 -0
  79. package/dist/graph/store.js +69 -0
  80. package/dist/host/actions.hook.d.ts +34 -0
  81. package/dist/host/actions.hook.d.ts.map +1 -0
  82. package/dist/host/actions.hook.js +125 -0
  83. package/dist/host/components.d.ts +15 -0
  84. package/dist/host/components.d.ts.map +1 -0
  85. package/dist/host/components.js +14 -0
  86. package/dist/host/index.d.ts +5 -0
  87. package/dist/host/index.d.ts.map +1 -0
  88. package/dist/host/index.js +3 -0
  89. package/dist/index.d.ts +26 -37
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +20 -31
  92. package/dist/intents/envelope.d.ts +7 -19
  93. package/dist/intents/envelope.d.ts.map +1 -1
  94. package/dist/intents/envelope.js +2 -3
  95. package/dist/intents/send-intent.hook.d.ts +5 -7
  96. package/dist/intents/send-intent.hook.d.ts.map +1 -1
  97. package/dist/intents/send-intent.hook.js +17 -75
  98. package/dist/navigation/adapters/adapter.d.ts +5 -0
  99. package/dist/navigation/adapters/adapter.d.ts.map +1 -1
  100. package/dist/navigation/adapters/memory.adapter.d.ts.map +1 -1
  101. package/dist/navigation/adapters/memory.adapter.js +4 -0
  102. package/dist/navigation/adapters/url.adapter.d.ts.map +1 -1
  103. package/dist/navigation/adapters/url.adapter.js +57 -10
  104. package/dist/navigation/codec.d.ts +60 -0
  105. package/dist/navigation/codec.d.ts.map +1 -0
  106. package/dist/navigation/codec.js +121 -0
  107. package/dist/navigation/history.d.ts +11 -9
  108. package/dist/navigation/history.d.ts.map +1 -1
  109. package/dist/navigation/history.js +6 -8
  110. package/dist/navigation/hooks/ancestors.hook.d.ts +5 -7
  111. package/dist/navigation/hooks/ancestors.hook.d.ts.map +1 -1
  112. package/dist/navigation/hooks/ancestors.hook.js +7 -51
  113. package/dist/navigation/hooks/location.hook.d.ts.map +1 -1
  114. package/dist/navigation/hooks/location.hook.js +4 -6
  115. package/dist/navigation/hooks/scope.hook.d.ts.map +1 -1
  116. package/dist/navigation/hooks/scope.hook.js +4 -6
  117. package/dist/navigation/index.d.ts +4 -2
  118. package/dist/navigation/index.d.ts.map +1 -1
  119. package/dist/navigation/index.js +2 -1
  120. package/dist/navigation/link.d.ts +12 -0
  121. package/dist/navigation/link.d.ts.map +1 -1
  122. package/dist/navigation/link.js +13 -2
  123. package/dist/navigation/location.d.ts +13 -40
  124. package/dist/navigation/location.d.ts.map +1 -1
  125. package/dist/navigation/location.js +14 -76
  126. package/dist/navigation/scope.context.d.ts +17 -26
  127. package/dist/navigation/scope.context.d.ts.map +1 -1
  128. package/dist/navigation/scope.context.js +140 -108
  129. package/dist/navigation/snapshot.d.ts +14 -19
  130. package/dist/navigation/snapshot.d.ts.map +1 -1
  131. package/dist/navigation/snapshot.js +48 -44
  132. package/dist/schema/action.hook.d.ts +44 -0
  133. package/dist/schema/action.hook.d.ts.map +1 -0
  134. package/dist/schema/action.hook.js +72 -0
  135. package/dist/schema/domain.hook.d.ts +12 -7
  136. package/dist/schema/domain.hook.d.ts.map +1 -1
  137. package/dist/schema/domain.hook.js +101 -4
  138. package/dist/schema/index.d.ts +9 -8
  139. package/dist/schema/index.d.ts.map +1 -1
  140. package/dist/schema/index.js +5 -7
  141. package/dist/schema/kernel.hook.d.ts +4 -9
  142. package/dist/schema/kernel.hook.d.ts.map +1 -1
  143. package/dist/schema/kernel.hook.js +4 -6
  144. package/dist/schema/mutation.hook.d.ts +9 -0
  145. package/dist/schema/mutation.hook.d.ts.map +1 -0
  146. package/dist/schema/mutation.hook.js +41 -0
  147. package/dist/schema/object.hook.d.ts +16 -0
  148. package/dist/schema/object.hook.d.ts.map +1 -0
  149. package/dist/schema/object.hook.js +46 -0
  150. package/dist/schema/relation.hook.d.ts +46 -0
  151. package/dist/schema/relation.hook.d.ts.map +1 -0
  152. package/dist/schema/relation.hook.js +136 -0
  153. package/dist/selection/live.d.ts +9 -17
  154. package/dist/selection/live.d.ts.map +1 -1
  155. package/dist/selection/live.js +65 -112
  156. package/dist/selection/scope.context.js +5 -4
  157. package/dist/session/boot/boot.d.ts +1 -13
  158. package/dist/session/boot/boot.d.ts.map +1 -1
  159. package/dist/session/boot/boot.js +9 -27
  160. package/dist/session/index.d.ts +1 -0
  161. package/dist/session/index.d.ts.map +1 -1
  162. package/dist/session/kernel-instance.hook.d.ts +1 -4
  163. package/dist/session/kernel-instance.hook.d.ts.map +1 -1
  164. package/dist/session/kernel-instance.hook.js +1 -5
  165. package/dist/session/provider.d.ts +9 -23
  166. package/dist/session/provider.d.ts.map +1 -1
  167. package/dist/session/provider.js +29 -75
  168. package/dist/session/session.context.d.ts +5 -0
  169. package/dist/session/session.context.d.ts.map +1 -1
  170. package/dist/window/adopt.d.ts +0 -1
  171. package/dist/window/adopt.d.ts.map +1 -1
  172. package/dist/window/hooks/target-node.hook.d.ts +10 -6
  173. package/dist/window/hooks/target-node.hook.d.ts.map +1 -1
  174. package/dist/window/hooks/target-node.hook.js +14 -72
  175. package/dist/window/hooks/views-for.hook.d.ts +4 -3
  176. package/dist/window/hooks/views-for.hook.d.ts.map +1 -1
  177. package/dist/window/hooks/views-for.hook.js +6 -22
  178. package/dist/window/hooks/windows.hook.d.ts.map +1 -1
  179. package/dist/window/hooks/windows.hook.js +3 -4
  180. package/dist/window/host.d.ts +9 -11
  181. package/dist/window/host.d.ts.map +1 -1
  182. package/dist/window/host.js +26 -62
  183. package/dist/window/hub.d.ts +2 -0
  184. package/dist/window/hub.d.ts.map +1 -1
  185. package/dist/window/hub.js +33 -0
  186. package/dist/window/index.d.ts +2 -2
  187. package/dist/window/index.d.ts.map +1 -1
  188. package/dist/window/index.js +2 -2
  189. package/dist/window/lifecycle/mount.d.ts +5 -44
  190. package/dist/window/lifecycle/mount.d.ts.map +1 -1
  191. package/dist/window/lifecycle/mount.js +14 -120
  192. package/dist/window/lifecycle/states.d.ts +0 -5
  193. package/dist/window/lifecycle/states.d.ts.map +1 -1
  194. package/package.json +20 -8
  195. package/src/application/apps/app-host.tsx +11 -15
  196. package/src/application/apps/apps.hook.ts +13 -6
  197. package/src/application/apps/domains.hook.ts +1 -1
  198. package/src/application/apps/open-app.hook.ts +3 -4
  199. package/src/application/index.ts +4 -6
  200. package/src/application/spaces/space.hook.ts +5 -6
  201. package/src/application/spaces/spaces.hook.ts +14 -9
  202. package/src/auth/act-as.context.tsx +37 -91
  203. package/src/auth/auth.hook.ts +2 -30
  204. package/src/auth/can.hook.ts +44 -135
  205. package/src/auth/index.ts +1 -0
  206. package/src/auth/self.hook.ts +2 -9
  207. package/src/auth/session-kernel.ts +6 -16
  208. package/src/components/astrale.tsx +40 -0
  209. package/src/components/boundaries.tsx +113 -0
  210. package/src/components/can.tsx +16 -0
  211. package/src/components/index.ts +13 -0
  212. package/src/graph/call/call.hook.ts +22 -27
  213. package/src/graph/call/stream.hook.ts +66 -143
  214. package/src/graph/graph.context.ts +6 -11
  215. package/src/graph/guards.error.ts +17 -55
  216. package/src/graph/index.ts +23 -17
  217. package/src/graph/memory/read/envelope.ts +40 -65
  218. package/src/graph/memory/read/idle.ts +5 -18
  219. package/src/graph/query-definition.hook.ts +270 -0
  220. package/src/graph/resource.ts +358 -0
  221. package/src/graph/store.ts +97 -0
  222. package/src/host/actions.hook.ts +165 -0
  223. package/src/host/components.tsx +29 -0
  224. package/src/host/index.ts +17 -0
  225. package/src/index.ts +131 -124
  226. package/src/intents/envelope.ts +7 -23
  227. package/src/intents/send-intent.hook.ts +24 -79
  228. package/src/navigation/adapters/adapter.ts +3 -0
  229. package/src/navigation/adapters/memory.adapter.ts +4 -0
  230. package/src/navigation/adapters/url.adapter.ts +48 -8
  231. package/src/navigation/codec.ts +190 -0
  232. package/src/navigation/history.ts +20 -11
  233. package/src/navigation/hooks/ancestors.hook.ts +10 -60
  234. package/src/navigation/hooks/location.hook.ts +4 -6
  235. package/src/navigation/hooks/scope.hook.ts +4 -6
  236. package/src/navigation/index.ts +18 -2
  237. package/src/navigation/link.tsx +27 -2
  238. package/src/navigation/location.ts +26 -93
  239. package/src/navigation/scope.context.tsx +151 -136
  240. package/src/navigation/snapshot.ts +69 -50
  241. package/src/schema/action.hook.ts +146 -0
  242. package/src/schema/domain.hook.ts +127 -11
  243. package/src/schema/index.ts +9 -30
  244. package/src/schema/kernel.hook.ts +6 -13
  245. package/src/schema/mutation.hook.ts +63 -0
  246. package/src/schema/object.hook.ts +85 -0
  247. package/src/schema/relation.hook.ts +253 -0
  248. package/src/selection/live.ts +75 -125
  249. package/src/selection/scope.context.tsx +4 -4
  250. package/src/session/boot/boot.ts +8 -33
  251. package/src/session/index.ts +1 -0
  252. package/src/session/kernel-instance.hook.ts +2 -11
  253. package/src/session/provider.tsx +34 -103
  254. package/src/session/session.context.ts +6 -0
  255. package/src/window/adopt.ts +0 -1
  256. package/src/window/hooks/target-node.hook.ts +20 -85
  257. package/src/window/hooks/views-for.hook.ts +12 -25
  258. package/src/window/hooks/windows.hook.ts +3 -4
  259. package/src/window/host.tsx +35 -77
  260. package/src/window/hub.ts +33 -0
  261. package/src/window/index.ts +3 -3
  262. package/src/window/lifecycle/mount.ts +15 -160
  263. package/src/window/lifecycle/states.ts +1 -5
  264. package/dist/application/roles.hook.d.ts +0 -7
  265. package/dist/application/roles.hook.d.ts.map +0 -1
  266. package/dist/application/roles.hook.js +0 -23
  267. package/dist/graph/memory/base.d.ts +0 -21
  268. package/dist/graph/memory/base.d.ts.map +0 -1
  269. package/dist/graph/memory/base.js +0 -33
  270. package/dist/graph/memory/read/read.d.ts +0 -9
  271. package/dist/graph/memory/read/read.d.ts.map +0 -1
  272. package/dist/graph/memory/read/read.js +0 -87
  273. package/dist/graph/memory/scope.d.ts +0 -7
  274. package/dist/graph/memory/scope.d.ts.map +0 -1
  275. package/dist/graph/memory/scope.js +0 -25
  276. package/dist/graph/mutate/move.hook.d.ts +0 -7
  277. package/dist/graph/mutate/move.hook.d.ts.map +0 -1
  278. package/dist/graph/mutate/move.hook.js +0 -49
  279. package/dist/graph/mutate/mutate.hook.d.ts +0 -17
  280. package/dist/graph/mutate/mutate.hook.d.ts.map +0 -1
  281. package/dist/graph/mutate/mutate.hook.js +0 -45
  282. package/dist/graph/query/children.hook.d.ts +0 -29
  283. package/dist/graph/query/children.hook.d.ts.map +0 -1
  284. package/dist/graph/query/children.hook.js +0 -64
  285. package/dist/graph/query/graph.hook.d.ts +0 -9
  286. package/dist/graph/query/graph.hook.d.ts.map +0 -1
  287. package/dist/graph/query/graph.hook.js +0 -5
  288. package/dist/graph/query/neighbors.hook.d.ts +0 -7
  289. package/dist/graph/query/neighbors.hook.d.ts.map +0 -1
  290. package/dist/graph/query/neighbors.hook.js +0 -104
  291. package/dist/graph/query/node.hook.d.ts +0 -14
  292. package/dist/graph/query/node.hook.d.ts.map +0 -1
  293. package/dist/graph/query/node.hook.js +0 -43
  294. package/dist/graph/query/query.hook.d.ts +0 -14
  295. package/dist/graph/query/query.hook.d.ts.map +0 -1
  296. package/dist/graph/query/query.hook.js +0 -23
  297. package/dist/schema/bind-read.d.ts +0 -37
  298. package/dist/schema/bind-read.d.ts.map +0 -1
  299. package/dist/schema/bind-read.js +0 -205
  300. package/dist/schema/binding.d.ts +0 -21
  301. package/dist/schema/binding.d.ts.map +0 -1
  302. package/dist/schema/binding.js +0 -99
  303. package/dist/schema/function.hook.d.ts +0 -9
  304. package/dist/schema/function.hook.d.ts.map +0 -1
  305. package/dist/schema/function.hook.js +0 -40
  306. package/dist/schema/method.hook.d.ts +0 -14
  307. package/dist/schema/method.hook.d.ts.map +0 -1
  308. package/dist/schema/method.hook.js +0 -49
  309. package/dist/schema/tag.d.ts +0 -11
  310. package/dist/schema/tag.d.ts.map +0 -1
  311. package/dist/schema/tag.js +0 -11
  312. package/dist/schema/types.d.ts +0 -73
  313. package/dist/schema/types.d.ts.map +0 -1
  314. package/dist/schema/types.js +0 -1
  315. package/dist/schema/write.d.ts +0 -16
  316. package/dist/schema/write.d.ts.map +0 -1
  317. package/dist/schema/write.js +0 -56
  318. package/src/application/roles.hook.ts +0 -41
  319. package/src/graph/memory/base.ts +0 -50
  320. package/src/graph/memory/read/read.ts +0 -103
  321. package/src/graph/memory/scope.ts +0 -29
  322. package/src/graph/mutate/move.hook.ts +0 -70
  323. package/src/graph/mutate/mutate.hook.ts +0 -69
  324. package/src/graph/query/children.hook.ts +0 -136
  325. package/src/graph/query/graph.hook.ts +0 -13
  326. package/src/graph/query/neighbors.hook.ts +0 -159
  327. package/src/graph/query/node.hook.ts +0 -83
  328. package/src/graph/query/query.hook.ts +0 -42
  329. package/src/schema/bind-read.ts +0 -319
  330. package/src/schema/binding.ts +0 -146
  331. package/src/schema/function.hook.ts +0 -68
  332. package/src/schema/method.hook.ts +0 -103
  333. package/src/schema/tag.ts +0 -19
  334. package/src/schema/types.ts +0 -150
  335. package/src/schema/write.ts +0 -96
@@ -1,56 +0,0 @@
1
- const writableCache = new WeakMap();
2
- export function writableFor(kernel, memory) {
3
- let entry = writableCache.get(kernel);
4
- if (entry === undefined) {
5
- const nodeIndex = new Map();
6
- entry = { writable: withMemoryWrites(kernel, memory, nodeIndex), nodeIndex };
7
- writableCache.set(kernel, entry);
8
- }
9
- return entry;
10
- }
11
- /**
12
- * Wrap a session view so `updateNode`/`createNode` route through the memory's
13
- * optimistic write shorthands. `BoundNode.update` addresses a node by `@<id>`,
14
- * but the memory needs the node's class and tree path — so an `@<id>` ref is translated
15
- * through `nodeIndex` (populated at bind time). A ref that is NOT indexed (a node
16
- * that was never bound) falls back to the raw kernel-client floor:
17
- * it still dispatches, just without the overlay — matching the imperative floor.
18
- */
19
- function withMemoryWrites(kernel, memory, nodeIndex) {
20
- const base = kernel;
21
- const rawUpdate = base.updateNode.bind(base);
22
- return extendCapabilities(kernel, {
23
- updateNode: (cls, ref, props) => {
24
- const node = indexedNode(nodeIndex, ref);
25
- return node !== null ? memory.update(node, props) : rawUpdate(cls, ref, props);
26
- },
27
- createNode: (cls, at, props) => memory.create(cls, at, props),
28
- // Credential rebind stays on the raw kernel-client floor (§6 note).
29
- as: (cred) => base.as(cred),
30
- });
31
- }
32
- /** Overlay memory writes without materializing a possibly virtual session surface. */
33
- function extendCapabilities(base, extension) {
34
- return new Proxy(base, {
35
- get(target, prop, receiver) {
36
- return Object.prototype.hasOwnProperty.call(extension, prop)
37
- ? Reflect.get(extension, prop, extension)
38
- : Reflect.get(target, prop, receiver);
39
- },
40
- });
41
- }
42
- /** The tree path an `@<id>` write ref maps to, via the bind-time index; else null. */
43
- function indexedNode(nodeIndex, ref) {
44
- if (typeof ref !== 'string' || !ref.startsWith('@'))
45
- return null;
46
- return nodeIndex.get(ref.slice(1)) ?? null;
47
- }
48
- /** Record a bound node's raw value so the write cap retains its class and tree path. */
49
- export function recordNode(nodeIndex, node) {
50
- const wrapped = node;
51
- const candidate = wrapped?.raw !== null && typeof wrapped?.raw === 'object' ? wrapped.raw : node;
52
- const n = candidate;
53
- if (n !== null && typeof n.id === 'string' && typeof n.path?.raw === 'string') {
54
- nodeIndex.set(n.id, candidate);
55
- }
56
- }
@@ -1,41 +0,0 @@
1
- import type { RoleNode } from '@astrale-os/shell'
2
-
3
- /**
4
- * useRoles (API §12.2) — the roles self holds (`has_role` out-edges), over the
5
- * async OS namespace (one-shot today, §12 flag).
6
- */
7
- import { useMemo } from 'react'
8
-
9
- import type { ReadState } from '../graph/memory/read/envelope.js'
10
-
11
- import { useAsyncResource } from '../graph/async.js'
12
- import { useShell } from '../session/shell.hook.js'
13
- import { isOsPlaneAvailable } from './user/user.store.js'
14
-
15
- const NO_ROLES: readonly RoleNode[] = []
16
-
17
- export interface RolesResult extends ReadState {
18
- readonly roles: readonly RoleNode[]
19
- }
20
-
21
- export function useRoles(): RolesResult {
22
- const shell = useShell()
23
- // OS plane unavailable (§12.2) → idle: no roles read.
24
- const available = isOsPlaneAvailable(shell)
25
- const res = useAsyncResource<readonly RoleNode[]>(
26
- available ? () => shell.user.roles() : null,
27
- NO_ROLES,
28
- [shell, available],
29
- )
30
- return useMemo(
31
- () => ({
32
- roles: res.data,
33
- pending: res.pending,
34
- error: res.error,
35
- live: false,
36
- seq: 0,
37
- refetch: res.refetch,
38
- }),
39
- [res],
40
- )
41
- }
@@ -1,50 +0,0 @@
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
- }
@@ -1,103 +0,0 @@
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.js'
18
-
19
- import { useMemory } from '../scope.js'
20
- import { EMPTY_PENDING, IDLE_READ, withPending } from './envelope.js'
21
- import { isIdleInput } from './idle.js'
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
- }
@@ -1,29 +0,0 @@
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.js'
13
- import { ShellContext } from '../../session/session.context.js'
14
- import { baseMemoryFor } from './base.js'
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
- }
@@ -1,70 +0,0 @@
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.js'
15
- import type { Node } from '../memory/read/envelope.js'
16
-
17
- import { useSessionKernel } from '../../auth/session-kernel.js'
18
- import { useAction } from '../action.js'
19
- import { useMemory } from '../memory/scope.js'
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
- }
@@ -1,69 +0,0 @@
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.js'
13
-
14
- import { useAction } from '../action.js'
15
- import { useMemory } from '../memory/scope.js'
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
- }
@@ -1,136 +0,0 @@
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.js'
21
- import type { ReadState, Node, ReadOptions, Windowed } from '../memory/read/envelope.js'
22
-
23
- import { useChildren as useChildrenTyped } from '../../schema/bind-read.js'
24
- import { useRead } from '../memory/read/read.js'
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
- }
@@ -1,13 +0,0 @@
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.js'
9
-
10
- /** The memory for this subtree — the raw floor plus optimistic-auto shorthands (§5). */
11
- export function useGraph(): GraphMemory {
12
- return useMemory()
13
- }