@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
@@ -4,12 +4,13 @@ import { jsx as _jsx } from "react/jsx-runtime";
4
4
  * projects that box onto a stage slot (ResizeObserver); the iframe lives in the
5
5
  * stage, so reorder/re-key never reloads a healthy frame. It drives the
6
6
  * `WindowState` machine, owns teardown (unmount closes its window), survives
7
- * StrictMode double-mount, and downgrades a fallbackable handshake to plain.
7
+ * StrictMode double-mount. The complete target-bound View is the sole source
8
+ * of mount identity, route, target, and handshake behavior.
8
9
  */
9
10
  import { forwardRef, useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, } from 'react';
10
11
  import { useShell } from '../session/shell.hook.js';
11
12
  import { getStageHub } from './hub.js';
12
- import { isFallbackableHandshakeError, refToId, resolveSource, sendSetTarget, sourceKey, } from './lifecycle/mount.js';
13
+ import { viewMountKey } from './lifecycle/mount.js';
13
14
  import { rectOf, sameRect } from './placement.js';
14
15
  const MOUNTING = { phase: 'mounting' };
15
16
  export const ViewHost = forwardRef(function ViewHost(props, ref) {
@@ -30,9 +31,7 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
30
31
  propsRef.current = props;
31
32
  const [state, setState] = useState(MOUNTING);
32
33
  const [refreshNonce, setRefreshNonce] = useState(0);
33
- const mountKey = sourceKey(props);
34
- const targetId = refToId(props.node);
35
- const lastTargetRef = useRef(undefined);
34
+ const mountKey = viewMountKey(props.view);
36
35
  const setStateSafe = (next) => {
37
36
  if (!aliveRef.current)
38
37
  return;
@@ -83,10 +82,9 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
83
82
  lastRectRef.current = rect;
84
83
  slot.place(rect);
85
84
  }, []);
86
- // ── Mount lifecycle. Keyed on the source identity + refresh nonce only — a
87
- // node (targetNodeId) change retargets via setTarget, never a remount. A
88
- // re-key/re-parent unmount+remount ADOPTS the live window through the hub
89
- // (deferred close), so a healthy iframe is never reloaded (§10).
85
+ // ── Mount lifecycle. Keyed on complete target + route provenance and
86
+ // refresh nonce. A same-selection re-key/re-parent can adopt the live
87
+ // window; any target or provenance change necessarily remounts.
90
88
  useEffect(() => {
91
89
  let cancelled = false;
92
90
  let controllerWaiter = null;
@@ -123,7 +121,6 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
123
121
  window: live.window,
124
122
  slot,
125
123
  state: live.state,
126
- targetId: live.targetId,
127
124
  dispose: () => closeAndRelease(live.windowId, slot),
128
125
  };
129
126
  if (refreshingRef.current)
@@ -149,9 +146,7 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
149
146
  windowId: adopted.windowId,
150
147
  window: adopted.window,
151
148
  state: adopted.state,
152
- targetId: adopted.targetId,
153
149
  };
154
- lastTargetRef.current = adopted.targetId;
155
150
  hub.registry.upsert(adopted.windowId, adopted.window, adopted.state);
156
151
  lastRectRef.current = null;
157
152
  measure(); // reposition the surviving slot onto this host's anchor
@@ -159,28 +154,11 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
159
154
  return cleanup;
160
155
  }
161
156
  }
162
- async function mountWith(handshake, downgraded) {
157
+ async function mountView() {
163
158
  const p = propsRef.current;
164
- let resolved;
165
- try {
166
- resolved = await resolveSource(shell.kernel, sourceOf(p));
167
- }
168
- catch (err) {
169
- // No window yet (source resolution failed) — windowId honestly absent.
170
- if (!cancelled)
171
- crashAndRelease(err);
172
- return;
173
- }
174
- if (cancelled)
175
- return;
176
- const usedHandshake = handshake === 'none' ? 'none' : resolved.handshake;
177
- const deliveredTarget = refToId(p.node);
178
159
  let sandbox;
179
160
  try {
180
- sandbox =
181
- typeof p.sandbox === 'function'
182
- ? p.sandbox({ ...resolved, handshake: usedHandshake })
183
- : p.sandbox;
161
+ sandbox = typeof p.sandbox === 'function' ? p.sandbox(p.view) : p.sandbox;
184
162
  }
185
163
  catch (err) {
186
164
  if (!cancelled)
@@ -189,16 +167,25 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
189
167
  }
190
168
  const params = {
191
169
  host: slotRef.current.element,
192
- url: resolved.url,
193
- functionId: resolved.functionId,
194
- capabilities: { intents: p.capabilities?.intents ?? [] },
195
- targetNodeId: deliveredTarget,
170
+ view: p.view,
171
+ capabilities: p.capabilities ?? {
172
+ version: 1,
173
+ navigation: {},
174
+ actions: {},
175
+ browser: {},
176
+ access: {},
177
+ },
196
178
  sandbox,
197
- handshake: usedHandshake,
198
179
  credential: p.credential,
180
+ ...(p.handshakeTimeoutMs === undefined
181
+ ? {}
182
+ : { handshakeTimeoutMs: p.handshakeTimeoutMs }),
183
+ ...(p.delegationTtlSeconds === undefined
184
+ ? {}
185
+ : { delegationTtlSeconds: p.delegationTtlSeconds }),
199
186
  };
200
187
  try {
201
- const win = await shell.mount(params);
188
+ const win = await shell.openView(params);
202
189
  // A StrictMode cleanup (or refresh) fired before mount resolved: adopt
203
190
  // then immediately close so no orphan window survives.
204
191
  if (cancelled) {
@@ -206,15 +193,11 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
206
193
  return;
207
194
  }
208
195
  windowIdRef.current = win.windowId;
209
- lastTargetRef.current = deliveredTarget;
210
- const ready = downgraded
211
- ? { phase: 'ready', windowId: win.windowId, downgraded: true }
212
- : { phase: 'ready', windowId: win.windowId };
196
+ const ready = { phase: 'ready', windowId: win.windowId };
213
197
  liveRef.current = {
214
198
  windowId: win.windowId,
215
199
  window: win.window,
216
200
  state: ready,
217
- targetId: deliveredTarget,
218
201
  };
219
202
  hub.registry.upsert(win.windowId, win.window, ready);
220
203
  setStateSafe(ready);
@@ -222,10 +205,6 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
222
205
  catch (err) {
223
206
  if (cancelled)
224
207
  return;
225
- if (usedHandshake === 'shell' && isFallbackableHandshakeError(err)) {
226
- await mountWith('none', true);
227
- return;
228
- }
229
208
  crashAndRelease(err);
230
209
  }
231
210
  }
@@ -237,7 +216,7 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
237
216
  lastRectRef.current = null;
238
217
  measure();
239
218
  setStateSafe(MOUNTING);
240
- void mountWith('shell', false);
219
+ void mountView();
241
220
  }
242
221
  const existing = hub.getController();
243
222
  if (existing !== null)
@@ -251,17 +230,6 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
251
230
  return cleanup;
252
231
  // eslint-disable-next-line react-hooks/exhaustive-deps
253
232
  }, [hub, shell, mountKey, refreshNonce]);
254
- // ── Retarget: a node change after ready hot-swaps via setTarget (no remount).
255
- useEffect(() => {
256
- if (state.phase !== 'ready')
257
- return;
258
- if (targetId === lastTargetRef.current)
259
- return;
260
- lastTargetRef.current = targetId;
261
- if (targetId === undefined)
262
- return;
263
- sendSetTarget(shell, state.windowId, targetId);
264
- }, [shell, state, targetId]);
265
233
  // ── Placement observers: reposition on resize/scroll/anchor-resize.
266
234
  useLayoutEffect(() => {
267
235
  measure();
@@ -284,7 +252,3 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
284
252
  });
285
253
  return (_jsx("div", { ref: anchorRef, className: props.className, style: props.style, children: state.phase !== 'ready' ? props.fallback?.(state) : null }));
286
254
  });
287
- /** Narrow props back to the bare `ViewSource` discriminated union. */
288
- function sourceOf(props) {
289
- return 'url' in props ? { url: props.url } : { view: props.view };
290
- }
@@ -23,6 +23,8 @@ export interface WindowRegistry {
23
23
  upsert(windowId: string, window: Window, state: WindowState): void;
24
24
  patch(windowId: string, state: WindowState): void;
25
25
  remove(windowId: string): void;
26
+ /** Shell writes: replace host and imperatively mounted windows from authoritative snapshots. */
27
+ sync(windows: ReadonlyMap<string, Window>): void;
26
28
  }
27
29
  export interface StageHub {
28
30
  readonly registry: WindowRegistry;
@@ -1 +1 @@
1
- {"version":3,"file":"hub.d.ts","sourceRoot":"","sources":["../../src/window/hub.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAYrD,qFAAqF;AACrF,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAA;AAEzE,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,WAAW,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,4EAA4E;IAC5E,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,CAAA;IAC3C,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;IAC3C,sDAAsD;IACtD,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IAClE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACjD,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B;AAqED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,aAAa,IAAI,eAAe,GAAG,IAAI,CAAA;IACvC,uEAAuE;IACvE,aAAa,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAAA;IACvD,4EAA4E;IAC5E,YAAY,CAAC,EAAE,EAAE,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IAC1E,yFAAyF;IACzF,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;IACrD,yFAAyF;IACzF,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAA;CAC3C;AAID,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,CAkClD"}
1
+ {"version":3,"file":"hub.d.ts","sourceRoot":"","sources":["../../src/window/hub.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAYrD,qFAAqF;AACrF,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAA;AAEzE,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,WAAW,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,4EAA4E;IAC5E,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,CAAA;IAC3C,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;IAC3C,sDAAsD;IACtD,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IAClE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACjD,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,gGAAgG;IAChG,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;CACjD;AAkGD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,aAAa,IAAI,eAAe,GAAG,IAAI,CAAA;IACvC,uEAAuE;IACvE,aAAa,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAAA;IACvD,4EAA4E;IAC5E,YAAY,CAAC,EAAE,EAAE,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IAC1E,yFAAyF;IACzF,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;IACrD,yFAAyF;IACzF,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAA;CAC3C;AAID,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,CAoClD"}
@@ -58,8 +58,39 @@ function createWindowRegistry() {
58
58
  return;
59
59
  invalidate();
60
60
  },
61
+ sync(windows) {
62
+ let changed = false;
63
+ for (const windowId of entries.keys()) {
64
+ if (!windows.has(windowId)) {
65
+ entries.delete(windowId);
66
+ changed = true;
67
+ }
68
+ }
69
+ for (const [windowId, window] of windows) {
70
+ const current = entries.get(windowId);
71
+ if (current?.window === window)
72
+ continue;
73
+ entries.set(windowId, {
74
+ window,
75
+ state: current?.state ?? phaseFor(window),
76
+ });
77
+ changed = true;
78
+ }
79
+ if (changed)
80
+ invalidate();
81
+ },
61
82
  };
62
83
  }
84
+ function phaseFor(window) {
85
+ if (window.state === 'opening')
86
+ return { phase: 'mounting' };
87
+ if (window.state === 'failed') {
88
+ return { phase: 'crashed', windowId: window.windowId };
89
+ }
90
+ if (window.state === 'closed')
91
+ return { phase: 'closed', windowId: window.windowId };
92
+ return { phase: 'ready', windowId: window.windowId };
93
+ }
63
94
  const HUBS = new WeakMap();
64
95
  /** The windows hub for a shell — one per shell object, created on first touch. */
65
96
  export function getStageHub(shell) {
@@ -95,6 +126,8 @@ export function getStageHub(shell) {
95
126
  return adopt.take(key);
96
127
  },
97
128
  };
129
+ registry.sync(shell.windows);
130
+ shell.onWindowChange(() => registry.sync(shell.windows));
98
131
  HUBS.set(shell, hub);
99
132
  return hub;
100
133
  }
@@ -7,9 +7,9 @@ export { useWindow } from './hooks/window.hook.js';
7
7
  export type { WindowView } from './hub.js';
8
8
  export { useViewsFor } from './hooks/views-for.hook.js';
9
9
  export type { ViewsForResult } from './hooks/views-for.hook.js';
10
- export { useTargetNode } from './hooks/target-node.hook.js';
10
+ export { useTargetNode, useTargetPath } from './hooks/target-node.hook.js';
11
11
  export { useCloseGuard } from './hooks/close-guard.hook.js';
12
12
  export type { CloseGuard, CloseVerdict } from './hooks/close-guard.hook.js';
13
- export type { ResolvedSource, ViewDescriptor, ViewSource, Node } from './lifecycle/mount.js';
14
13
  export type { WindowState } from './lifecycle/states.js';
14
+ export type { ResolvedView } from '@astrale-os/shell';
15
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/window/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC7E,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACnE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAC3E,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC5F,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/window/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC7E,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACnE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAClD,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAC3E,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACxD,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA"}
@@ -1,10 +1,10 @@
1
1
  // window — API §10. ViewStage/ViewHost (the physical iframe-slot layer + a host
2
- // that projects placement into a slot), the reactive window hooks, the child-side
2
+ // that projects stage geometry into a slot), the reactive window hooks, the child-side
3
3
  // target-node + close-guard, and the (G5) view-resolution hook.
4
4
  export { ViewStage } from './stage.js';
5
5
  export { ViewHost } from './host.js';
6
6
  export { useWindows, useWindowList } from './hooks/windows.hook.js';
7
7
  export { useWindow } from './hooks/window.hook.js';
8
8
  export { useViewsFor } from './hooks/views-for.hook.js';
9
- export { useTargetNode } from './hooks/target-node.hook.js';
9
+ export { useTargetNode, useTargetPath } from './hooks/target-node.hook.js';
10
10
  export { useCloseGuard } from './hooks/close-guard.hook.js';
@@ -1,47 +1,8 @@
1
- import type { NodeRefInput } from '@astrale-os/kernel-client';
1
+ import type { ResolvedView } from '@astrale-os/shell';
2
2
  /**
3
- * Mount orchestration (API §10) — resolve a `ViewSource` to something `shell.mount`
4
- * accepts (url + handshake + functionId), the stable remount key, the delivered
5
- * target id, the handshake-fallback predicate, and the parent→child setTarget
6
- * hot-swap. A one-call `View.resolve` kernel contract does not exist yet — the
7
- * bare-ref path is the honest subset, G5.
3
+ * Stable identity for one target-bound, provenance-complete View route.
4
+ * A change to any routing or semantic witness forces a fresh mount; an old
5
+ * iframe and credential can never be adopted under a different route.
8
6
  */
9
- import type { KernelClient, Shell } from '@astrale-os/shell';
10
- /** A live graph node, derived from the shell kernel read surface (G8 seam). */
11
- export type Node = NonNullable<Awaited<ReturnType<KernelClient['get']>>>;
12
- /** A View function resolved to something mountable (url + optional handshake). */
13
- export interface ViewDescriptor {
14
- readonly id: string;
15
- readonly path: string;
16
- readonly url?: string;
17
- readonly handshake?: string;
18
- }
19
- /**
20
- * What a `ViewHost` mounts:
21
- * - `{ view }` — a View function (descriptor or ref), resolved to url + handshake.
22
- * - `{ url }` — a handshake-less hosted view; mounts immediately (no 5s wait).
23
- */
24
- export type ViewSource = {
25
- readonly view: NodeRefInput | ViewDescriptor;
26
- } | {
27
- readonly url: string;
28
- };
29
- export interface ResolvedSource {
30
- readonly url: string;
31
- readonly handshake: 'shell' | 'none';
32
- readonly functionId: string;
33
- }
34
- /** Resolve a source; may hit the kernel for a bare/urless View ref (G5). */
35
- export declare function resolveSource(kernel: KernelClient, source: ViewSource): Promise<ResolvedSource>;
36
- /** A stable remount key: the same source identity must not remount. */
37
- export declare function sourceKey(source: ViewSource): string;
38
- /** The bare node id delivered as `targetNodeId` at mount / retarget. */
39
- export declare function refToId(ref: NodeRefInput | undefined): string | undefined;
40
- /**
41
- * Fallbackable = the view didn't speak the shell protocol (timeout/failed), not a
42
- * security refusal (origin mismatch) — only the former downgrades to plain.
43
- */
44
- export declare function isFallbackableHandshakeError(err: unknown): boolean;
45
- /** Parent → child hot-swap of the target node (no remount) — API §10 setTarget. */
46
- export declare function sendSetTarget(shell: Shell, windowId: string, nodeId: string): void;
7
+ export declare function viewMountKey(view: ResolvedView): string;
47
8
  //# sourceMappingURL=mount.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../../src/window/lifecycle/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAE5D,+EAA+E;AAC/E,MAAM,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;AAExE,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpG,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AA2ED,4EAA4E;AAC5E,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,cAAc,CAAC,CAgBzB;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAOpD;AAED,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAKzE;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAGlE;AAED,mFAAmF;AACnF,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAMlF"}
1
+ {"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../../src/window/lifecycle/mount.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAWvD"}
@@ -1,123 +1,17 @@
1
- function isViewDescriptor(view) {
2
- return typeof view === 'object' && view !== null && 'id' in view && 'path' in view;
3
- }
4
- /** Last path segment or host, alnum-only — a stable-ish functionId from a url. */
5
- function slugOfUrl(url) {
6
- const trimmed = url.replace(/[#?].*$/, '').replace(/\/+$/, '');
7
- const tail = trimmed.split('/').filter(Boolean).pop() ?? 'view';
8
- return tail.replace(/[^a-z0-9]/gi, '').slice(-32) || 'view';
9
- }
10
- /** A ref addressable by the kernel read surface (`get`). `@<id>` for bare ids. */
11
- function toPath(ref) {
12
- if (typeof ref === 'string') {
13
- return ref.startsWith('/') || ref.startsWith('@') ? ref : `@${ref}`;
14
- }
15
- const obj = ref;
16
- if (obj.path?.raw !== undefined)
17
- return obj.path.raw;
18
- if (obj.id !== undefined)
19
- return `@${obj.id}`;
20
- throw new Error('ViewHost: unresolvable view ref');
21
- }
22
- async function resolveViewRef(kernel, ref, handshakeHint) {
23
- const node = await kernel.get(toPath(ref));
24
- if (node === null)
25
- throw new Error(`ViewHost: view not found (${toPath(ref)})`);
26
- const props = node.props ?? {};
27
- const url = viewUrl(props);
28
- if (typeof url !== 'string' || url.length === 0) {
29
- throw new Error('ViewHost: resolved view has no url');
30
- }
31
- const handshake = normalizeHandshake(handshakeHint ?? props.handshake);
32
- const id = node.id ?? slugOfUrl(url);
33
- return { url, handshake, functionId: id };
34
- }
35
- /** Resolve both the legacy flat url and the canonical Function binding. */
36
- function viewUrl(props) {
37
- if (typeof props.url === 'string' && props.url.length > 0)
38
- return props.url;
39
- const direct = remoteUrlOf(props.binding);
40
- if (direct !== undefined)
41
- return direct;
42
- // Raw graph props can be keyed by the property's canonical graph key rather
43
- // than its local slug. The binding value remains self-describing.
44
- for (const value of Object.values(props)) {
45
- const remoteUrl = remoteUrlOf(value);
46
- if (remoteUrl !== undefined)
47
- return remoteUrl;
48
- }
49
- return undefined;
50
- }
51
- function remoteUrlOf(value) {
52
- let binding = value;
53
- if (typeof binding === 'string') {
54
- try {
55
- binding = JSON.parse(binding);
56
- }
57
- catch {
58
- return undefined;
59
- }
60
- }
61
- if (binding === null || typeof binding !== 'object')
62
- return undefined;
63
- const remoteUrl = binding.remoteUrl;
64
- return typeof remoteUrl === 'string' && remoteUrl.length > 0 ? remoteUrl : undefined;
65
- }
66
- function normalizeHandshake(value) {
67
- return value === 'none' ? 'none' : 'shell';
68
- }
69
- /** Resolve a source; may hit the kernel for a bare/urless View ref (G5). */
70
- export async function resolveSource(kernel, source) {
71
- if ('url' in source) {
72
- return { url: source.url, handshake: 'none', functionId: slugOfUrl(source.url) };
73
- }
74
- const view = source.view;
75
- if (isViewDescriptor(view)) {
76
- if (view.url !== undefined && view.url.length > 0) {
77
- return {
78
- url: view.url,
79
- handshake: normalizeHandshake(view.handshake),
80
- functionId: view.id,
81
- };
82
- }
83
- return resolveViewRef(kernel, view.id, view.handshake);
84
- }
85
- return resolveViewRef(kernel, view);
86
- }
87
- /** A stable remount key: the same source identity must not remount. */
88
- export function sourceKey(source) {
89
- if ('url' in source)
90
- return `url:${source.url}`;
91
- const view = source.view;
92
- if (isViewDescriptor(view))
93
- return `view:${view.id}:${view.url ?? ''}:${view.handshake ?? ''}`;
94
- if (typeof view === 'string')
95
- return `ref:${view}`;
96
- const obj = view;
97
- return `ref:${obj.id ?? obj.path?.raw ?? '?'}`;
98
- }
99
- /** The bare node id delivered as `targetNodeId` at mount / retarget. */
100
- export function refToId(ref) {
101
- if (ref === undefined)
102
- return undefined;
103
- if (typeof ref === 'string')
104
- return ref.startsWith('@') ? ref.slice(1) : ref;
105
- const obj = ref;
106
- return obj.id;
107
- }
108
1
  /**
109
- * Fallbackable = the view didn't speak the shell protocol (timeout/failed), not a
110
- * security refusal (origin mismatch) — only the former downgrades to plain.
2
+ * Stable identity for one target-bound, provenance-complete View route.
3
+ * A change to any routing or semantic witness forces a fresh mount; an old
4
+ * iframe and credential can never be adopted under a different route.
111
5
  */
112
- export function isFallbackableHandshakeError(err) {
113
- const code = err?.code;
114
- return code === 'HANDSHAKE_TIMEOUT' || code === 'HANDSHAKE_FAILED';
115
- }
116
- /** Parent → child hot-swap of the target node (no remount) — API §10 setTarget. */
117
- export function sendSetTarget(shell, windowId, nodeId) {
118
- shell.children.send(windowId, {
119
- type: 'intent',
120
- version: 1,
121
- envelope: { name: 'setTarget', payload: { nodeId }, sender: { windowId: '<parent>' } },
122
- });
6
+ export function viewMountKey(view) {
7
+ const { route, target } = view;
8
+ return [
9
+ target,
10
+ route.key,
11
+ route.href,
12
+ route.handshake,
13
+ route.issuer,
14
+ route.etag,
15
+ route.revision,
16
+ ].join('\u0000');
123
17
  }
@@ -7,10 +7,6 @@
7
7
  /**
8
8
  * Lifecycle of a hosted view as the React face observes it (API §10).
9
9
  *
10
- * `ready.downgraded` marks a mount that fell back to a plain iframe after a
11
- * fallbackable handshake error. It rides here (not on the shell `Window`) until
12
- * the shell `Window` grows a first-class flag — flagged in the module report.
13
- *
14
10
  * `crashed.windowId` is OPTIONAL: a crash before a window exists (a session-open
15
11
  * failure, a pre-mount source-resolution failure) has no id to report — the type
16
12
  * says so rather than carrying a placeholder `''`.
@@ -20,7 +16,6 @@ export type WindowState = {
20
16
  } | {
21
17
  readonly phase: 'ready';
22
18
  readonly windowId: string;
23
- readonly downgraded?: boolean;
24
19
  } | {
25
20
  readonly phase: 'crashed';
26
21
  readonly windowId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"states.d.ts","sourceRoot":"","sources":["../../../src/window/lifecycle/states.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACrF;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GACnF;IAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA"}
1
+ {"version":3,"file":"states.d.ts","sourceRoot":"","sources":["../../../src/window/lifecycle/states.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GACnF;IAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrale-os/shell-react",
3
- "version": "0.2.9",
3
+ "version": "0.2.10-beta.3",
4
4
  "description": "Astrale shell-react — the React face of the shell (provider, hooks, view components)",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -25,16 +25,19 @@
25
25
  "access": "public"
26
26
  },
27
27
  "dependencies": {
28
- "@astrale-domains/shell-schema": ">=0.3.2 <1.0.0",
29
- "@astrale-os/kernel-client": ">=0.4.7 <1.0.0",
30
- "@astrale-os/kernel-core": ">=0.7.5 <1.0.0",
31
- "@astrale-os/kernel-dsl": ">=0.1.4 <1.0.0",
32
28
  "jose": "^6.2.3",
33
29
  "zod": "^4.3.6"
34
30
  },
35
31
  "devDependencies": {
32
+ "@astrale-os/kernel-client": ">=0.6.0-beta.8 <1.0.0",
33
+ "@astrale-os/kernel-core": ">=0.9.0-beta.7 <1.0.0",
34
+ "@astrale-os/kernel-dsl": ">=0.2.0-beta.5 <1.0.0",
35
+ "@astrale-os/kernel-protocol": ">=0.5.0-beta.7 <1.0.0",
36
+ "@astrale-os/kernel-server": ">=0.5.0-beta.8 <1.0.0",
37
+ "@astrale-os/sdk": ">=0.5.0-beta.14 <1.0.0",
36
38
  "@testing-library/dom": "^10.4.0",
37
39
  "@testing-library/react": "^16.3.0",
40
+ "@types/node": "^26.0.0",
38
41
  "@types/react": "^19.2.0",
39
42
  "@types/react-dom": "^19.2.0",
40
43
  "@typescript/native-preview": "latest",
@@ -43,14 +46,23 @@
43
46
  "react": "^19.2.0",
44
47
  "react-dom": "^19.2.0",
45
48
  "typescript": "~6.0.1-rc",
49
+ "vite": "^7.3.6",
46
50
  "vitest": "^3.2.4",
47
- "@astrale-os/shell": "0.3.7"
51
+ "@astrale-os/shell": "0.3.8-beta.3"
48
52
  },
49
53
  "peerDependencies": {
50
- "@astrale-os/shell": ">=0.2.0 <1.0.0",
51
- "react": ">=18"
54
+ "@astrale-os/kernel-client": ">=0.6.0-beta.8 <1.0.0",
55
+ "@astrale-os/kernel-core": ">=0.9.0-beta.7 <1.0.0",
56
+ "@astrale-os/kernel-dsl": ">=0.2.0-beta.5 <1.0.0",
57
+ "@astrale-os/kernel-protocol": ">=0.5.0-beta.7 <1.0.0",
58
+ "@astrale-os/kernel-server": ">=0.5.0-beta.8 <1.0.0",
59
+ "@astrale-os/sdk": ">=0.5.0-beta.14 <1.0.0",
60
+ "@astrale-os/shell": ">=0.3.8-beta.3 <1.0.0",
61
+ "react": ">=18",
62
+ "react-dom": ">=18"
52
63
  },
53
64
  "scripts": {
65
+ "prebuild": "pnpm clean",
54
66
  "build": "tsgo",
55
67
  "clean": "rm -rf dist *.tsbuildinfo",
56
68
  "typecheck": "tsgo --noEmit && tsgo --noEmit -p tsconfig.test.json",
@@ -1,5 +1,10 @@
1
- import type { NodeRefInput } from '@astrale-os/kernel-client'
2
- import type { ApplicationNode, AppSession, IntentRegistry } from '@astrale-os/shell'
1
+ import type {
2
+ ApplicationNode,
3
+ AppSession,
4
+ HostCapabilities,
5
+ NodeTarget,
6
+ ResolvedView,
7
+ } from '@astrale-os/shell'
3
8
  import type { CSSProperties, ReactElement, ReactNode } from 'react'
4
9
 
5
10
  /**
@@ -12,7 +17,6 @@ import type { CSSProperties, ReactElement, ReactNode } from 'react'
12
17
  import { forwardRef, useEffect, useRef, useState } from 'react'
13
18
 
14
19
  import type { SandboxPolicy, ViewHostHandle } from '../../window/host.js'
15
- import type { ViewDescriptor } from '../../window/lifecycle/mount.js'
16
20
  import type { WindowState } from '../../window/lifecycle/states.js'
17
21
 
18
22
  import { ViewHost } from '../../window/host.js'
@@ -26,17 +30,10 @@ export type AppHostFallbackState =
26
30
  | { readonly phase: 'no-view' }
27
31
 
28
32
  export interface AppHostProps {
29
- app: ApplicationNode | NodeRefInput
33
+ app: ApplicationNode | NodeTarget
30
34
  /** Override the entry View while keeping the application's delegated session alive. */
31
- view?: NodeRefInput | ViewDescriptor
32
- /**
33
- * Default target node delivered to the app's view as `targetNodeId` (API §12.2).
34
- * Container-anchored apps need one — the dock passes the current space. A deeper
35
- * fix (an install-time app data container + `app::open` returning a default
36
- * target) is a tracked domain-modeling question; until then the host supplies it.
37
- */
38
- node?: NodeRefInput
39
- capabilities?: { intents: readonly (keyof IntentRegistry)[] }
35
+ view?: ResolvedView
36
+ capabilities?: HostCapabilities
40
37
  sandbox?: SandboxPolicy
41
38
  fallback?: (state: AppHostFallbackState) => ReactNode
42
39
  onSession?: (session: AppSession) => void
@@ -103,9 +100,8 @@ export const AppHost = forwardRef<ViewHostHandle, AppHostProps>(
103
100
  <ViewHost
104
101
  ref={ref}
105
102
  view={view}
106
- node={props.node}
107
103
  credential={session.credential}
108
- capabilities={props.capabilities ?? { intents: [] }}
104
+ capabilities={props.capabilities}
109
105
  sandbox={props.sandbox}
110
106
  fallback={fallback ? (s: WindowState) => fallback(s) : undefined}
111
107
  className={className}