@astrale-os/shell-react 0.2.8 → 0.2.10-beta.2
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 +7 -15
- package/dist/application/apps/app-host.d.ts.map +1 -1
- package/dist/application/apps/app-host.js +3 -2
- 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/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 +7 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +4 -0
- package/dist/components/mount-domain-frontend.d.ts +22 -0
- package/dist/components/mount-domain-frontend.d.ts.map +1 -0
- package/dist/components/mount-domain-frontend.js +85 -0
- package/dist/components/view-app.d.ts +16 -0
- package/dist/components/view-app.d.ts.map +1 -0
- package/dist/components/view-app.js +16 -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 +11 -11
- package/dist/window/host.d.ts.map +1 -1
- package/dist/window/host.js +38 -54
- 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 +3 -3
- 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/dist/window/stage.d.ts.map +1 -1
- package/dist/window/stage.js +1 -0
- package/package.json +9 -8
- package/src/application/apps/app-host.tsx +17 -18
- 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/boundaries.tsx +113 -0
- package/src/components/can.tsx +16 -0
- package/src/components/index.ts +14 -0
- package/src/components/mount-domain-frontend.tsx +158 -0
- package/src/components/view-app.tsx +49 -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 +137 -123
- 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 +51 -68
- package/src/window/hub.ts +33 -0
- package/src/window/index.ts +4 -4
- package/src/window/lifecycle/mount.ts +15 -160
- package/src/window/lifecycle/states.ts +1 -5
- package/src/window/stage.tsx +1 -0
- 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)
|
|
@@ -131,6 +128,14 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
|
|
|
131
128
|
else
|
|
132
129
|
hub.stashForAdopt(mountKey, record);
|
|
133
130
|
}
|
|
131
|
+
/** A pre-ready failure must not leave an empty stage slot over the fallback UI. */
|
|
132
|
+
function crashAndRelease(error) {
|
|
133
|
+
const slot = slotRef.current;
|
|
134
|
+
slotRef.current = null;
|
|
135
|
+
lastRectRef.current = null;
|
|
136
|
+
slot?.release();
|
|
137
|
+
setStateSafe({ phase: 'crashed', windowId: windowIdRef.current ?? undefined, error });
|
|
138
|
+
}
|
|
134
139
|
// Adopt a live window a just-unmounted same-source host left behind.
|
|
135
140
|
if (!wasRefresh) {
|
|
136
141
|
const adopted = hub.takeAdopt(mountKey);
|
|
@@ -141,9 +146,7 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
|
|
|
141
146
|
windowId: adopted.windowId,
|
|
142
147
|
window: adopted.window,
|
|
143
148
|
state: adopted.state,
|
|
144
|
-
targetId: adopted.targetId,
|
|
145
149
|
};
|
|
146
|
-
lastTargetRef.current = adopted.targetId;
|
|
147
150
|
hub.registry.upsert(adopted.windowId, adopted.window, adopted.state);
|
|
148
151
|
lastRectRef.current = null;
|
|
149
152
|
measure(); // reposition the surviving slot onto this host's anchor
|
|
@@ -151,34 +154,38 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
|
|
|
151
154
|
return cleanup;
|
|
152
155
|
}
|
|
153
156
|
}
|
|
154
|
-
async function
|
|
157
|
+
async function mountView() {
|
|
155
158
|
const p = propsRef.current;
|
|
156
|
-
let
|
|
159
|
+
let sandbox;
|
|
157
160
|
try {
|
|
158
|
-
|
|
161
|
+
sandbox = typeof p.sandbox === 'function' ? p.sandbox(p.view) : p.sandbox;
|
|
159
162
|
}
|
|
160
163
|
catch (err) {
|
|
161
|
-
// No window yet (source resolution failed) — windowId honestly absent.
|
|
162
164
|
if (!cancelled)
|
|
163
|
-
|
|
165
|
+
crashAndRelease(err);
|
|
164
166
|
return;
|
|
165
167
|
}
|
|
166
|
-
if (cancelled)
|
|
167
|
-
return;
|
|
168
|
-
const usedHandshake = handshake === 'none' ? 'none' : resolved.handshake;
|
|
169
|
-
const deliveredTarget = refToId(p.node);
|
|
170
168
|
const params = {
|
|
171
169
|
host: slotRef.current.element,
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
170
|
+
view: p.view,
|
|
171
|
+
capabilities: p.capabilities ?? {
|
|
172
|
+
version: 1,
|
|
173
|
+
navigation: {},
|
|
174
|
+
actions: {},
|
|
175
|
+
browser: {},
|
|
176
|
+
access: {},
|
|
177
|
+
},
|
|
178
|
+
sandbox,
|
|
178
179
|
credential: p.credential,
|
|
180
|
+
...(p.handshakeTimeoutMs === undefined
|
|
181
|
+
? {}
|
|
182
|
+
: { handshakeTimeoutMs: p.handshakeTimeoutMs }),
|
|
183
|
+
...(p.delegationTtlSeconds === undefined
|
|
184
|
+
? {}
|
|
185
|
+
: { delegationTtlSeconds: p.delegationTtlSeconds }),
|
|
179
186
|
};
|
|
180
187
|
try {
|
|
181
|
-
const win = await shell.
|
|
188
|
+
const win = await shell.openView(params);
|
|
182
189
|
// A StrictMode cleanup (or refresh) fired before mount resolved: adopt
|
|
183
190
|
// then immediately close so no orphan window survives.
|
|
184
191
|
if (cancelled) {
|
|
@@ -186,15 +193,11 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
|
|
|
186
193
|
return;
|
|
187
194
|
}
|
|
188
195
|
windowIdRef.current = win.windowId;
|
|
189
|
-
|
|
190
|
-
const ready = downgraded
|
|
191
|
-
? { phase: 'ready', windowId: win.windowId, downgraded: true }
|
|
192
|
-
: { phase: 'ready', windowId: win.windowId };
|
|
196
|
+
const ready = { phase: 'ready', windowId: win.windowId };
|
|
193
197
|
liveRef.current = {
|
|
194
198
|
windowId: win.windowId,
|
|
195
199
|
window: win.window,
|
|
196
200
|
state: ready,
|
|
197
|
-
targetId: deliveredTarget,
|
|
198
201
|
};
|
|
199
202
|
hub.registry.upsert(win.windowId, win.window, ready);
|
|
200
203
|
setStateSafe(ready);
|
|
@@ -202,11 +205,7 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
|
|
|
202
205
|
catch (err) {
|
|
203
206
|
if (cancelled)
|
|
204
207
|
return;
|
|
205
|
-
|
|
206
|
-
await mountWith('none', true);
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
setStateSafe({ phase: 'crashed', windowId: windowIdRef.current ?? undefined, error: err });
|
|
208
|
+
crashAndRelease(err);
|
|
210
209
|
}
|
|
211
210
|
}
|
|
212
211
|
function begin(controller) {
|
|
@@ -217,7 +216,7 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
|
|
|
217
216
|
lastRectRef.current = null;
|
|
218
217
|
measure();
|
|
219
218
|
setStateSafe(MOUNTING);
|
|
220
|
-
void
|
|
219
|
+
void mountView();
|
|
221
220
|
}
|
|
222
221
|
const existing = hub.getController();
|
|
223
222
|
if (existing !== null)
|
|
@@ -231,17 +230,6 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
|
|
|
231
230
|
return cleanup;
|
|
232
231
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
233
232
|
}, [hub, shell, mountKey, refreshNonce]);
|
|
234
|
-
// ── Retarget: a node change after ready hot-swaps via setTarget (no remount).
|
|
235
|
-
useEffect(() => {
|
|
236
|
-
if (state.phase !== 'ready')
|
|
237
|
-
return;
|
|
238
|
-
if (targetId === lastTargetRef.current)
|
|
239
|
-
return;
|
|
240
|
-
lastTargetRef.current = targetId;
|
|
241
|
-
if (targetId === undefined)
|
|
242
|
-
return;
|
|
243
|
-
sendSetTarget(shell, state.windowId, targetId);
|
|
244
|
-
}, [shell, state, targetId]);
|
|
245
233
|
// ── Placement observers: reposition on resize/scroll/anchor-resize.
|
|
246
234
|
useLayoutEffect(() => {
|
|
247
235
|
measure();
|
|
@@ -264,7 +252,3 @@ export const ViewHost = forwardRef(function ViewHost(props, ref) {
|
|
|
264
252
|
});
|
|
265
253
|
return (_jsx("div", { ref: anchorRef, className: props.className, style: props.style, children: state.phase !== 'ready' ? props.fallback?.(state) : null }));
|
|
266
254
|
});
|
|
267
|
-
/** Narrow props back to the bare `ViewSource` discriminated union. */
|
|
268
|
-
function sourceOf(props) {
|
|
269
|
-
return 'url' in props ? { url: props.url } : { view: props.view };
|
|
270
|
-
}
|
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
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
export { ViewStage } from './stage.js';
|
|
2
2
|
export { ViewHost } from './host.js';
|
|
3
|
-
export type { ViewHostProps, ViewHostHandle } from './host.js';
|
|
3
|
+
export type { SandboxPolicy, ViewHostProps, ViewHostHandle } from './host.js';
|
|
4
4
|
export { useWindows, useWindowList } from './hooks/windows.hook.js';
|
|
5
5
|
export type { WindowListEntry } from './hooks/windows.hook.js';
|
|
6
6
|
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 { 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,cAAc,EAAE,MAAM,WAAW,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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stage.d.ts","sourceRoot":"","sources":["../../src/window/stage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"stage.d.ts","sourceRoot":"","sources":["../../src/window/stage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAA;AA6BxD,wBAAgB,SAAS,IAAI,YAAY,CAiBxC"}
|
package/dist/window/stage.js
CHANGED
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.2",
|
|
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,10 +25,8 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@astrale-
|
|
29
|
-
"@astrale-os/
|
|
30
|
-
"@astrale-os/kernel-core": ">=0.7.5 <1.0.0",
|
|
31
|
-
"@astrale-os/kernel-dsl": ">=0.1.4 <1.0.0",
|
|
28
|
+
"@astrale-os/kernel-client": ">=0.6.0-beta.4 <1.0.0",
|
|
29
|
+
"@astrale-os/sdk": ">=0.5.0-beta.4 <1.0.0",
|
|
32
30
|
"jose": "^6.2.3",
|
|
33
31
|
"zod": "^4.3.6"
|
|
34
32
|
},
|
|
@@ -43,14 +41,17 @@
|
|
|
43
41
|
"react": "^19.2.0",
|
|
44
42
|
"react-dom": "^19.2.0",
|
|
45
43
|
"typescript": "~6.0.1-rc",
|
|
44
|
+
"vite": "^7.3.6",
|
|
46
45
|
"vitest": "^3.2.4",
|
|
47
|
-
"@astrale-os/shell": "0.3.
|
|
46
|
+
"@astrale-os/shell": "0.3.8-beta.2"
|
|
48
47
|
},
|
|
49
48
|
"peerDependencies": {
|
|
50
|
-
"@astrale-os/shell": ">=0.2
|
|
51
|
-
"react": ">=18"
|
|
49
|
+
"@astrale-os/shell": ">=0.3.8-beta.2 <1.0.0",
|
|
50
|
+
"react": ">=18",
|
|
51
|
+
"react-dom": ">=18"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
|
+
"prebuild": "pnpm clean",
|
|
54
55
|
"build": "tsgo",
|
|
55
56
|
"clean": "rm -rf dist *.tsbuildinfo",
|
|
56
57
|
"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
|
/**
|
|
@@ -11,8 +16,7 @@ import type { CSSProperties, ReactElement, ReactNode } from 'react'
|
|
|
11
16
|
*/
|
|
12
17
|
import { forwardRef, useEffect, useRef, useState } from 'react'
|
|
13
18
|
|
|
14
|
-
import type { ViewHostHandle } from '../../window/host.js'
|
|
15
|
-
import type { ViewDescriptor } from '../../window/lifecycle/mount.js'
|
|
19
|
+
import type { SandboxPolicy, ViewHostHandle } from '../../window/host.js'
|
|
16
20
|
import type { WindowState } from '../../window/lifecycle/states.js'
|
|
17
21
|
|
|
18
22
|
import { ViewHost } from '../../window/host.js'
|
|
@@ -26,16 +30,11 @@ export type AppHostFallbackState =
|
|
|
26
30
|
| { readonly phase: 'no-view' }
|
|
27
31
|
|
|
28
32
|
export interface AppHostProps {
|
|
29
|
-
app: ApplicationNode |
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
* target) is a tracked domain-modeling question; until then the host supplies it.
|
|
35
|
-
*/
|
|
36
|
-
node?: NodeRefInput
|
|
37
|
-
capabilities?: { intents: readonly (keyof IntentRegistry)[] }
|
|
38
|
-
sandbox?: SandboxProfile | null
|
|
33
|
+
app: ApplicationNode | NodeTarget
|
|
34
|
+
/** Override the entry View while keeping the application's delegated session alive. */
|
|
35
|
+
view?: ResolvedView
|
|
36
|
+
capabilities?: HostCapabilities
|
|
37
|
+
sandbox?: SandboxPolicy
|
|
39
38
|
fallback?: (state: AppHostFallbackState) => ReactNode
|
|
40
39
|
onSession?: (session: AppSession) => void
|
|
41
40
|
className?: string
|
|
@@ -94,15 +93,15 @@ export const AppHost = forwardRef<ViewHostHandle, AppHostProps>(
|
|
|
94
93
|
// A session-open failure has no window yet — `windowId` is honestly absent (§10).
|
|
95
94
|
if (error !== undefined) return box(fallback?.({ phase: 'crashed', error }) ?? null)
|
|
96
95
|
if (session === null) return box(fallback?.({ phase: 'opening' }) ?? null)
|
|
97
|
-
|
|
96
|
+
const view = props.view ?? session.view
|
|
97
|
+
if (view === null) return box(fallback?.({ phase: 'no-view' }) ?? null)
|
|
98
98
|
|
|
99
99
|
return (
|
|
100
100
|
<ViewHost
|
|
101
101
|
ref={ref}
|
|
102
|
-
view={
|
|
103
|
-
node={props.node}
|
|
102
|
+
view={view}
|
|
104
103
|
credential={session.credential}
|
|
105
|
-
capabilities={props.capabilities
|
|
104
|
+
capabilities={props.capabilities}
|
|
106
105
|
sandbox={props.sandbox}
|
|
107
106
|
fallback={fallback ? (s: WindowState) => fallback(s) : undefined}
|
|
108
107
|
className={className}
|