You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(devframe): carry meta base for cross-base RPC inheritance; surface missing mountConnectionMeta
A mounted devframe SPA inherits the connection meta from a same-origin
parent window before it fetches its own `__connection.json`. The meta was
published with a relative `websocket.path` but without the base it was
resolved against, so a child mounted at a different base resolved the path
against its own mount and dialed the wrong endpoint. Publish the meta
paired with the absolute (proxy-safe) base it was resolved from, and have
the client inherit that base. Backward-compatible: a bare ConnectionMeta on
the shared key is still accepted. Exposes `readPublishedConnectionMeta` +
`PublishedConnectionMeta` so hosts can reuse the shape.
Also make a missing host `mountConnectionMeta` non-silent: mounting a
devframe with a servable distDir on a host lacking the hook previously fell
through to the HTML fallback and broke the SPA silently. Emit a new DF8106
diagnostic instead.
> The host cannot serve the RPC connection meta for devframe "`{name}`" (id "`{id}`") at "`{base}`" — its `DevframeHost` does not implement `mountConnectionMeta`.
10
+
11
+
## Cause
12
+
13
+
A mounted devframe's SPA loads in an iframe at its own base (e.g. `/__terminals/`) and calls `connectDevframe()`, which fetches `./__connection.json` relative to that base to discover the RPC/WebSocket endpoint. `mountDevframe` serves that file at each base by calling the host's `mountConnectionMeta(base)` alongside `mountStatic`.
14
+
15
+
This diagnostic is reported when a devframe with a servable `cli.distDir` is mounted on a `DevframeHost` that does not implement `mountConnectionMeta`. The SPA's `./__connection.json` fetch then falls through to the host's HTML fallback, so the SPA cannot discover the endpoint and its panel stays empty or stuck loading — previously a silent failure.
16
+
17
+
The SPA can still connect when it shares an origin with the hub UI, by inheriting the connection meta from the parent window. Cross-origin, sandboxed, or directly-opened iframes have no such parent to inherit from.
18
+
19
+
## Fix
20
+
21
+
Implement `mountConnectionMeta(base)` on your `DevframeHost` to serve the same connection meta you expose at the hub's own base:
22
+
23
+
```ts
24
+
const host:DevframeHost= {
25
+
mountStatic(base, distDir) { /* serve files */ },
26
+
mountConnectionMeta(base) {
27
+
// serve `${base}__connection.json` → { backend: 'websocket', websocket: port }
28
+
},
29
+
resolveOrigin() { /* … */ },
30
+
getStorageDir(scope) { /* … */ },
31
+
}
32
+
```
33
+
34
+
A static-snapshot host that bakes `__connection.json` into its served files can implement `mountConnectionMeta` as a no-op to acknowledge this intentionally and silence the diagnostic.
35
+
36
+
## Source
37
+
38
+
-[`packages/hub/src/node/mount-devframe.ts`](https://github.com/devframes/devframe/blob/main/packages/hub/src/node/mount-devframe.ts) — `mountDevframe()` emits this when a devframe with a servable `distDir` is mounted on a host lacking `mountConnectionMeta`.
Copy file name to clipboardExpand all lines: docs/guide/hub.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -55,7 +55,7 @@ const host: DevframeHost = {
55
55
}
56
56
```
57
57
58
-
Hosts that omit`mountConnectionMeta`fall back to same-origin window inheritance, which connects an embedded SPA only when it shares an origin with the hub UI.
58
+
A host that omits`mountConnectionMeta`while mounting a devframe with a servable `distDir` triggers a [`DF8106`](https://devfra.me/errors/DF8106) diagnostic and falls back to same-origin window inheritance, which connects an embedded SPA only when it shares an origin with the hub UI. When the hub mounts several devframe SPAs at different bases in the same page, inheritance still works: the connection meta is published together with the base it was resolved against, so each same-origin child resolves the RPC/WS endpoint against the publisher's base rather than its own.
why: (p: {id: string,name: string})=>`Devframe "${p.name}" (id "${p.id}") is already mounted on this hub`,
39
39
fix: 'Each devframe is deduplicated by id. Set `duplicationStrategy: "duplicate"` on the definition to let instances coexist, `"silent"` to drop duplicates quietly, or `"throw"` to surface them as errors.',
40
40
},
41
+
DF8106: {
42
+
why: (p: {id: string,name: string,base: string})=>`The host cannot serve the RPC connection meta for devframe "${p.name}" (id "${p.id}") at "${p.base}" — its \`DevframeHost\` does not implement \`mountConnectionMeta\`.`,
43
+
fix: 'Implement `mountConnectionMeta(base)` on your DevframeHost so it serves `__connection.json` at each mounted base. Without it, the devframe SPA connects only when it shares an origin with the hub UI (same-origin window inheritance); cross-origin, sandboxed, or directly-opened iframes stay disconnected. Static-snapshot hosts that bake the meta into the served files can implement it as a no-op to acknowledge this intentionally.',
44
+
},
41
45
DF8200: {
42
46
why: (p: {id: string})=>`Terminal session with id "${p.id}" already registered`,
0 commit comments