@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.
- package/dist/application/apps/app-host.d.ts +4 -15
- package/dist/application/apps/app-host.d.ts.map +1 -1
- package/dist/application/apps/app-host.js +1 -1
- package/dist/application/apps/apps.hook.d.ts +7 -4
- package/dist/application/apps/apps.hook.d.ts.map +1 -1
- package/dist/application/apps/apps.hook.js +10 -2
- package/dist/application/apps/domains.hook.d.ts +1 -1
- package/dist/application/apps/domains.hook.d.ts.map +1 -1
- package/dist/application/apps/domains.hook.js +1 -1
- package/dist/application/apps/open-app.hook.d.ts +2 -3
- package/dist/application/apps/open-app.hook.d.ts.map +1 -1
- package/dist/application/index.d.ts +2 -4
- package/dist/application/index.d.ts.map +1 -1
- package/dist/application/index.js +2 -3
- package/dist/application/spaces/space.hook.d.ts +2 -2
- package/dist/application/spaces/space.hook.d.ts.map +1 -1
- package/dist/application/spaces/space.hook.js +2 -2
- package/dist/application/spaces/spaces.hook.d.ts +2 -3
- package/dist/application/spaces/spaces.hook.d.ts.map +1 -1
- package/dist/application/spaces/spaces.hook.js +10 -3
- package/dist/auth/act-as.context.d.ts +15 -32
- package/dist/auth/act-as.context.d.ts.map +1 -1
- package/dist/auth/act-as.context.js +22 -66
- package/dist/auth/auth.hook.d.ts +1 -0
- package/dist/auth/auth.hook.d.ts.map +1 -1
- package/dist/auth/auth.hook.js +2 -22
- package/dist/auth/can.hook.d.ts +10 -38
- package/dist/auth/can.hook.d.ts.map +1 -1
- package/dist/auth/can.hook.js +35 -110
- package/dist/auth/index.d.ts +1 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/self.hook.d.ts +2 -2
- package/dist/auth/self.hook.d.ts.map +1 -1
- package/dist/auth/self.hook.js +0 -7
- package/dist/auth/session-kernel.d.ts +2 -3
- package/dist/auth/session-kernel.d.ts.map +1 -1
- package/dist/auth/session-kernel.js +4 -13
- package/dist/components/astrale.d.ts +14 -0
- package/dist/components/astrale.d.ts.map +1 -0
- package/dist/components/astrale.js +12 -0
- package/dist/components/boundaries.d.ts +47 -0
- package/dist/components/boundaries.d.ts.map +1 -0
- package/dist/components/boundaries.js +55 -0
- package/dist/components/can.d.ts +11 -0
- package/dist/components/can.d.ts.map +1 -0
- package/dist/components/can.js +5 -0
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +3 -0
- package/dist/graph/call/call.hook.d.ts +8 -18
- package/dist/graph/call/call.hook.d.ts.map +1 -1
- package/dist/graph/call/call.hook.js +7 -13
- package/dist/graph/call/stream.hook.d.ts +12 -20
- package/dist/graph/call/stream.hook.d.ts.map +1 -1
- package/dist/graph/call/stream.hook.js +55 -111
- package/dist/graph/graph.context.d.ts +4 -3
- package/dist/graph/graph.context.d.ts.map +1 -1
- package/dist/graph/graph.context.js +2 -8
- package/dist/graph/guards.error.d.ts +7 -8
- package/dist/graph/guards.error.d.ts.map +1 -1
- package/dist/graph/guards.error.js +11 -7
- package/dist/graph/index.d.ts +8 -16
- package/dist/graph/index.d.ts.map +1 -1
- package/dist/graph/index.js +3 -7
- package/dist/graph/memory/read/envelope.d.ts +22 -54
- package/dist/graph/memory/read/envelope.d.ts.map +1 -1
- package/dist/graph/memory/read/envelope.js +26 -20
- package/dist/graph/memory/read/idle.d.ts +1 -15
- package/dist/graph/memory/read/idle.d.ts.map +1 -1
- package/dist/graph/memory/read/idle.js +4 -13
- package/dist/graph/query-definition.hook.d.ts +11 -0
- package/dist/graph/query-definition.hook.d.ts.map +1 -0
- package/dist/graph/query-definition.hook.js +205 -0
- package/dist/graph/resource.d.ts +34 -0
- package/dist/graph/resource.d.ts.map +1 -0
- package/dist/graph/resource.js +244 -0
- package/dist/graph/store.d.ts +25 -0
- package/dist/graph/store.d.ts.map +1 -0
- package/dist/graph/store.js +69 -0
- package/dist/host/actions.hook.d.ts +34 -0
- package/dist/host/actions.hook.d.ts.map +1 -0
- package/dist/host/actions.hook.js +125 -0
- package/dist/host/components.d.ts +15 -0
- package/dist/host/components.d.ts.map +1 -0
- package/dist/host/components.js +14 -0
- package/dist/host/index.d.ts +5 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.js +3 -0
- package/dist/index.d.ts +26 -37
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -31
- package/dist/intents/envelope.d.ts +7 -19
- package/dist/intents/envelope.d.ts.map +1 -1
- package/dist/intents/envelope.js +2 -3
- package/dist/intents/send-intent.hook.d.ts +5 -7
- package/dist/intents/send-intent.hook.d.ts.map +1 -1
- package/dist/intents/send-intent.hook.js +17 -75
- package/dist/navigation/adapters/adapter.d.ts +5 -0
- package/dist/navigation/adapters/adapter.d.ts.map +1 -1
- package/dist/navigation/adapters/memory.adapter.d.ts.map +1 -1
- package/dist/navigation/adapters/memory.adapter.js +4 -0
- package/dist/navigation/adapters/url.adapter.d.ts.map +1 -1
- package/dist/navigation/adapters/url.adapter.js +57 -10
- package/dist/navigation/codec.d.ts +60 -0
- package/dist/navigation/codec.d.ts.map +1 -0
- package/dist/navigation/codec.js +121 -0
- package/dist/navigation/history.d.ts +11 -9
- package/dist/navigation/history.d.ts.map +1 -1
- package/dist/navigation/history.js +6 -8
- package/dist/navigation/hooks/ancestors.hook.d.ts +5 -7
- package/dist/navigation/hooks/ancestors.hook.d.ts.map +1 -1
- package/dist/navigation/hooks/ancestors.hook.js +7 -51
- package/dist/navigation/hooks/location.hook.d.ts.map +1 -1
- package/dist/navigation/hooks/location.hook.js +4 -6
- package/dist/navigation/hooks/scope.hook.d.ts.map +1 -1
- package/dist/navigation/hooks/scope.hook.js +4 -6
- package/dist/navigation/index.d.ts +4 -2
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +2 -1
- package/dist/navigation/link.d.ts +12 -0
- package/dist/navigation/link.d.ts.map +1 -1
- package/dist/navigation/link.js +13 -2
- package/dist/navigation/location.d.ts +13 -40
- package/dist/navigation/location.d.ts.map +1 -1
- package/dist/navigation/location.js +14 -76
- package/dist/navigation/scope.context.d.ts +17 -26
- package/dist/navigation/scope.context.d.ts.map +1 -1
- package/dist/navigation/scope.context.js +140 -108
- package/dist/navigation/snapshot.d.ts +14 -19
- package/dist/navigation/snapshot.d.ts.map +1 -1
- package/dist/navigation/snapshot.js +48 -44
- package/dist/schema/action.hook.d.ts +44 -0
- package/dist/schema/action.hook.d.ts.map +1 -0
- package/dist/schema/action.hook.js +72 -0
- package/dist/schema/domain.hook.d.ts +12 -7
- package/dist/schema/domain.hook.d.ts.map +1 -1
- package/dist/schema/domain.hook.js +101 -4
- package/dist/schema/index.d.ts +9 -8
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +5 -7
- package/dist/schema/kernel.hook.d.ts +4 -9
- package/dist/schema/kernel.hook.d.ts.map +1 -1
- package/dist/schema/kernel.hook.js +4 -6
- package/dist/schema/mutation.hook.d.ts +9 -0
- package/dist/schema/mutation.hook.d.ts.map +1 -0
- package/dist/schema/mutation.hook.js +41 -0
- package/dist/schema/object.hook.d.ts +16 -0
- package/dist/schema/object.hook.d.ts.map +1 -0
- package/dist/schema/object.hook.js +46 -0
- package/dist/schema/relation.hook.d.ts +46 -0
- package/dist/schema/relation.hook.d.ts.map +1 -0
- package/dist/schema/relation.hook.js +136 -0
- package/dist/selection/live.d.ts +9 -17
- package/dist/selection/live.d.ts.map +1 -1
- package/dist/selection/live.js +65 -112
- package/dist/selection/scope.context.js +5 -4
- package/dist/session/boot/boot.d.ts +1 -13
- package/dist/session/boot/boot.d.ts.map +1 -1
- package/dist/session/boot/boot.js +9 -27
- package/dist/session/index.d.ts +1 -0
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/kernel-instance.hook.d.ts +1 -4
- package/dist/session/kernel-instance.hook.d.ts.map +1 -1
- package/dist/session/kernel-instance.hook.js +1 -5
- package/dist/session/provider.d.ts +9 -23
- package/dist/session/provider.d.ts.map +1 -1
- package/dist/session/provider.js +29 -75
- package/dist/session/session.context.d.ts +5 -0
- package/dist/session/session.context.d.ts.map +1 -1
- package/dist/window/adopt.d.ts +0 -1
- package/dist/window/adopt.d.ts.map +1 -1
- package/dist/window/hooks/target-node.hook.d.ts +10 -6
- package/dist/window/hooks/target-node.hook.d.ts.map +1 -1
- package/dist/window/hooks/target-node.hook.js +14 -72
- package/dist/window/hooks/views-for.hook.d.ts +4 -3
- package/dist/window/hooks/views-for.hook.d.ts.map +1 -1
- package/dist/window/hooks/views-for.hook.js +6 -22
- package/dist/window/hooks/windows.hook.d.ts.map +1 -1
- package/dist/window/hooks/windows.hook.js +3 -4
- package/dist/window/host.d.ts +9 -11
- package/dist/window/host.d.ts.map +1 -1
- package/dist/window/host.js +26 -62
- package/dist/window/hub.d.ts +2 -0
- package/dist/window/hub.d.ts.map +1 -1
- package/dist/window/hub.js +33 -0
- package/dist/window/index.d.ts +2 -2
- package/dist/window/index.d.ts.map +1 -1
- package/dist/window/index.js +2 -2
- package/dist/window/lifecycle/mount.d.ts +5 -44
- package/dist/window/lifecycle/mount.d.ts.map +1 -1
- package/dist/window/lifecycle/mount.js +14 -120
- package/dist/window/lifecycle/states.d.ts +0 -5
- package/dist/window/lifecycle/states.d.ts.map +1 -1
- package/package.json +20 -8
- package/src/application/apps/app-host.tsx +11 -15
- package/src/application/apps/apps.hook.ts +13 -6
- package/src/application/apps/domains.hook.ts +1 -1
- package/src/application/apps/open-app.hook.ts +3 -4
- package/src/application/index.ts +4 -6
- package/src/application/spaces/space.hook.ts +5 -6
- package/src/application/spaces/spaces.hook.ts +14 -9
- package/src/auth/act-as.context.tsx +37 -91
- package/src/auth/auth.hook.ts +2 -30
- package/src/auth/can.hook.ts +44 -135
- package/src/auth/index.ts +1 -0
- package/src/auth/self.hook.ts +2 -9
- package/src/auth/session-kernel.ts +6 -16
- package/src/components/astrale.tsx +40 -0
- package/src/components/boundaries.tsx +113 -0
- package/src/components/can.tsx +16 -0
- package/src/components/index.ts +13 -0
- package/src/graph/call/call.hook.ts +22 -27
- package/src/graph/call/stream.hook.ts +66 -143
- package/src/graph/graph.context.ts +6 -11
- package/src/graph/guards.error.ts +17 -55
- package/src/graph/index.ts +23 -17
- package/src/graph/memory/read/envelope.ts +40 -65
- package/src/graph/memory/read/idle.ts +5 -18
- package/src/graph/query-definition.hook.ts +270 -0
- package/src/graph/resource.ts +358 -0
- package/src/graph/store.ts +97 -0
- package/src/host/actions.hook.ts +165 -0
- package/src/host/components.tsx +29 -0
- package/src/host/index.ts +17 -0
- package/src/index.ts +131 -124
- package/src/intents/envelope.ts +7 -23
- package/src/intents/send-intent.hook.ts +24 -79
- package/src/navigation/adapters/adapter.ts +3 -0
- package/src/navigation/adapters/memory.adapter.ts +4 -0
- package/src/navigation/adapters/url.adapter.ts +48 -8
- package/src/navigation/codec.ts +190 -0
- package/src/navigation/history.ts +20 -11
- package/src/navigation/hooks/ancestors.hook.ts +10 -60
- package/src/navigation/hooks/location.hook.ts +4 -6
- package/src/navigation/hooks/scope.hook.ts +4 -6
- package/src/navigation/index.ts +18 -2
- package/src/navigation/link.tsx +27 -2
- package/src/navigation/location.ts +26 -93
- package/src/navigation/scope.context.tsx +151 -136
- package/src/navigation/snapshot.ts +69 -50
- package/src/schema/action.hook.ts +146 -0
- package/src/schema/domain.hook.ts +127 -11
- package/src/schema/index.ts +9 -30
- package/src/schema/kernel.hook.ts +6 -13
- package/src/schema/mutation.hook.ts +63 -0
- package/src/schema/object.hook.ts +85 -0
- package/src/schema/relation.hook.ts +253 -0
- package/src/selection/live.ts +75 -125
- package/src/selection/scope.context.tsx +4 -4
- package/src/session/boot/boot.ts +8 -33
- package/src/session/index.ts +1 -0
- package/src/session/kernel-instance.hook.ts +2 -11
- package/src/session/provider.tsx +34 -103
- package/src/session/session.context.ts +6 -0
- package/src/window/adopt.ts +0 -1
- package/src/window/hooks/target-node.hook.ts +20 -85
- package/src/window/hooks/views-for.hook.ts +12 -25
- package/src/window/hooks/windows.hook.ts +3 -4
- package/src/window/host.tsx +35 -77
- package/src/window/hub.ts +33 -0
- package/src/window/index.ts +3 -3
- package/src/window/lifecycle/mount.ts +15 -160
- package/src/window/lifecycle/states.ts +1 -5
- package/dist/application/roles.hook.d.ts +0 -7
- package/dist/application/roles.hook.d.ts.map +0 -1
- package/dist/application/roles.hook.js +0 -23
- package/dist/graph/memory/base.d.ts +0 -21
- package/dist/graph/memory/base.d.ts.map +0 -1
- package/dist/graph/memory/base.js +0 -33
- package/dist/graph/memory/read/read.d.ts +0 -9
- package/dist/graph/memory/read/read.d.ts.map +0 -1
- package/dist/graph/memory/read/read.js +0 -87
- package/dist/graph/memory/scope.d.ts +0 -7
- package/dist/graph/memory/scope.d.ts.map +0 -1
- package/dist/graph/memory/scope.js +0 -25
- package/dist/graph/mutate/move.hook.d.ts +0 -7
- package/dist/graph/mutate/move.hook.d.ts.map +0 -1
- package/dist/graph/mutate/move.hook.js +0 -49
- package/dist/graph/mutate/mutate.hook.d.ts +0 -17
- package/dist/graph/mutate/mutate.hook.d.ts.map +0 -1
- package/dist/graph/mutate/mutate.hook.js +0 -45
- package/dist/graph/query/children.hook.d.ts +0 -29
- package/dist/graph/query/children.hook.d.ts.map +0 -1
- package/dist/graph/query/children.hook.js +0 -64
- package/dist/graph/query/graph.hook.d.ts +0 -9
- package/dist/graph/query/graph.hook.d.ts.map +0 -1
- package/dist/graph/query/graph.hook.js +0 -5
- package/dist/graph/query/neighbors.hook.d.ts +0 -7
- package/dist/graph/query/neighbors.hook.d.ts.map +0 -1
- package/dist/graph/query/neighbors.hook.js +0 -104
- package/dist/graph/query/node.hook.d.ts +0 -14
- package/dist/graph/query/node.hook.d.ts.map +0 -1
- package/dist/graph/query/node.hook.js +0 -43
- package/dist/graph/query/query.hook.d.ts +0 -14
- package/dist/graph/query/query.hook.d.ts.map +0 -1
- package/dist/graph/query/query.hook.js +0 -23
- package/dist/schema/bind-read.d.ts +0 -37
- package/dist/schema/bind-read.d.ts.map +0 -1
- package/dist/schema/bind-read.js +0 -205
- package/dist/schema/binding.d.ts +0 -21
- package/dist/schema/binding.d.ts.map +0 -1
- package/dist/schema/binding.js +0 -99
- package/dist/schema/function.hook.d.ts +0 -9
- package/dist/schema/function.hook.d.ts.map +0 -1
- package/dist/schema/function.hook.js +0 -40
- package/dist/schema/method.hook.d.ts +0 -14
- package/dist/schema/method.hook.d.ts.map +0 -1
- package/dist/schema/method.hook.js +0 -49
- package/dist/schema/tag.d.ts +0 -11
- package/dist/schema/tag.d.ts.map +0 -1
- package/dist/schema/tag.js +0 -11
- package/dist/schema/types.d.ts +0 -73
- package/dist/schema/types.d.ts.map +0 -1
- package/dist/schema/types.js +0 -1
- package/dist/schema/write.d.ts +0 -16
- package/dist/schema/write.d.ts.map +0 -1
- package/dist/schema/write.js +0 -56
- package/src/application/roles.hook.ts +0 -41
- package/src/graph/memory/base.ts +0 -50
- package/src/graph/memory/read/read.ts +0 -103
- package/src/graph/memory/scope.ts +0 -29
- package/src/graph/mutate/move.hook.ts +0 -70
- package/src/graph/mutate/mutate.hook.ts +0 -69
- package/src/graph/query/children.hook.ts +0 -136
- package/src/graph/query/graph.hook.ts +0 -13
- package/src/graph/query/neighbors.hook.ts +0 -159
- package/src/graph/query/node.hook.ts +0 -83
- package/src/graph/query/query.hook.ts +0 -42
- package/src/schema/bind-read.ts +0 -319
- package/src/schema/binding.ts +0 -146
- package/src/schema/function.hook.ts +0 -68
- package/src/schema/method.hook.ts +0 -103
- package/src/schema/tag.ts +0 -19
- package/src/schema/types.ts +0 -150
- package/src/schema/write.ts +0 -96
package/dist/window/host.js
CHANGED
|
@@ -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
|
|
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 {
|
|
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 =
|
|
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
|
|
87
|
-
//
|
|
88
|
-
//
|
|
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
|
|
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
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
-
}
|
package/dist/window/hub.d.ts
CHANGED
|
@@ -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;
|
package/dist/window/hub.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/window/hub.js
CHANGED
|
@@ -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
|
}
|
package/dist/window/index.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/window/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// window — API §10. ViewStage/ViewHost (the physical iframe-slot layer + a host
|
|
2
|
-
// that projects
|
|
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 {
|
|
1
|
+
import type { ResolvedView } from '@astrale-os/shell';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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
|
-
|
|
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,
|
|
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
|
-
*
|
|
110
|
-
*
|
|
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
|
|
113
|
-
const
|
|
114
|
-
return
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
|
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.
|
|
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.
|
|
51
|
+
"@astrale-os/shell": "0.3.8-beta.3"
|
|
48
52
|
},
|
|
49
53
|
"peerDependencies": {
|
|
50
|
-
"@astrale-os/
|
|
51
|
-
"
|
|
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 {
|
|
2
|
-
|
|
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 |
|
|
33
|
+
app: ApplicationNode | NodeTarget
|
|
30
34
|
/** Override the entry View while keeping the application's delegated session alive. */
|
|
31
|
-
view?:
|
|
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
|
|
104
|
+
capabilities={props.capabilities}
|
|
109
105
|
sandbox={props.sandbox}
|
|
110
106
|
fallback={fallback ? (s: WindowState) => fallback(s) : undefined}
|
|
111
107
|
className={className}
|