Skip to content

Commit b32a0da

Browse files
committed
test: make page-script mount assertion cross-platform; trim comments
Use pathe consistently in the install-devframe test so the served-dir assertion matches the implementation's normalized path on Windows. Trim the verbose comments/descriptions added across the change per review.
1 parent 5b43bcd commit b32a0da

11 files changed

Lines changed: 37 additions & 75 deletions

File tree

examples/a11y-messages-playground/README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ The window is split in two:
5656

5757
`src/a11y-messages-playground.ts` is the entire host-framework integration - a ~120-line Vite plugin
5858
that runs `@devframes/hub` in the dev server and mounts the two devframes as docks.
59-
The a11y inspector declares its own page script as the a11y dock's `clientScript`, so
60-
the hub serves it same-origin and boots it - the host passes only the devframes:
59+
The a11y inspector declares its own page script, so the host passes only the devframes:
6160

6261
```ts
6362
a11yMessagesPlayground({
@@ -77,7 +76,7 @@ the focused dock - the same path a manual dock click takes.
7776
| File | Role |
7877
|---|---|
7978
| `src/a11y-messages-playground.ts` | The Vite host - hub context, static + connection-meta mounts, side-car WS, instance-registry registration |
80-
| `vite.config.ts` | Mounts a11y + messages (the a11y page script rides along as its dock's declared `clientScript`) |
79+
| `vite.config.ts` | Mounts a11y + messages |
8180
| `src/client/main.ts` | Boots the client runtime, renders the dock rail + iframe stage |
8281
| `src/client/app-under-test.ts` | The intentionally-broken, multi-route app the page script scans |
8382
| `src/client/icons.ts` | Offline Phosphor icons for the dock rail |

examples/a11y-messages-playground/src/a11y-messages-playground.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ export interface A11yMessagesPlaygroundOptions {
2121
* playground pairs (a11y + messages). One `initHub()` call assembles the whole
2222
* hub: it mounts each devframe as a dock, shares the WebSocket with Vite's own
2323
* server, serves the discovery endpoints, and registers the playground in the
24-
* global instance registry. The a11y inspector declares its own page script
25-
* (its dock's `clientScript`), so the hub serves it same-origin and boots it -
26-
* no client-script wiring here.
24+
* global instance registry.
2725
*/
2826
export function a11yMessagesPlayground(options: A11yMessagesPlaygroundOptions = {}): Plugin {
2927
const base = normalizeBase(options.base ?? '/__hub/')

examples/a11y-messages-playground/vite.config.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ export default defineConfig({
1414
optimizeDeps: { exclude: ['@antfu/design'] },
1515
plugins: [
1616
UnoCSS(),
17-
// The a11y inspector ships its own page script (its dock's `clientScript`),
18-
// so the hub serves it same-origin and boots it - the panel scans this page
19-
// live with no wiring here.
2017
a11yMessagesPlayground({
2118
devframes: [a11yDevframe, messagesDevframe],
2219
}),

examples/hub-next/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ The built-in devframes run node-side (child processes, the native `zigpty` PTY b
5757

5858
| File | Role |
5959
|---|---|
60-
| `src/client/devframe/next-devframe-hub.ts` | The Next host - one `initHub()` call: devframes (the a11y page script rides along automatically as its dock's declared `clientScript`), hub RPCs, commands, the json-render dock + renderer manifest, instance-registry registration |
60+
| `src/client/devframe/next-devframe-hub.ts` | The Next host - one `initHub()` call: devframes, hub RPCs, commands, the json-render dock + renderer manifest, instance-registry registration |
6161
| `src/client/devframe/unrendered-dock.ts` | A dock type registered with no renderer on purpose - the missing-renderer fallback witness |
6262
| `../demo-dock-client/` | The shared demo client script, consumed here as a statically-mounted self-contained bundle |
6363
| `src/client/app/%5F_devframes/[[...path]]/route.ts` | The one catch-all - delegates every `/__devframes/*` request to the instance's `handler` |

examples/hub-next/src/client/devframe/next-devframe-hub.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -186,15 +186,11 @@ export async function nextDevframeHub(
186186
// way so its `import.meta.url` bundle path resolves to the published `dist`.
187187
const jsonRenderRenderer = await loadJsonRenderUiRenderer()
188188

189-
// Demo devframes alongside the dogfooded built-in plugin packages. The a11y
190-
// inspector declares its own page script (its dock's `clientScript`) by path,
191-
// so the hub serves it same-origin and the hub client runtime booted in
192-
// `app/page.tsx` imports it into the host page automatically - it scans this
193-
// hub live with no host-side wiring. The shared-iframe soft-navigation demo
194-
// mounts as a `subTabs` anchor (a shared `frameId` + the postmessage
195-
// protocol) so the client host attaches the frame-nav adapter, materializing
196-
// one client-only dock per tab the SPA's shim reports - all sharing one
197-
// iframe.
189+
// Demo devframes alongside the dogfooded built-in plugin packages. The
190+
// shared-iframe soft-navigation demo mounts as a `subTabs` anchor (a shared
191+
// `frameId` + the postmessage protocol) so the client host attaches the
192+
// frame-nav adapter, materializing one client-only dock per tab the SPA's
193+
// shim reports - all sharing one iframe.
198194
const devframes: (DevframeDefinition | HubDevframeEntry)[] = [
199195
demoDevframe,
200196
...await loadBuiltinPlugins(),

examples/hub-vite/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ The dock UI is plain DOM in `src/client/`. To skin your own hub UI provider, rea
4545
| File | Role |
4646
|---|---|
4747
| `src/vite-devframe-hub.ts` | The Vite host - one `initHub()` call mounted as connect middleware, plus instance-registry registration |
48-
| `vite.config.ts` | Passes the built-in and demo devframes to the hub's `devframes` option (the a11y page script rides along automatically as its dock's declared `clientScript`); composes the json-render frontend via `renderers` |
48+
| `vite.config.ts` | Passes the built-in and demo devframes to the hub's `devframes` option; composes the json-render frontend via `renderers` |
4949
| `src/unrendered-dock.ts` | A dock type registered with no renderer on purpose - the missing-renderer fallback witness |
5050
| `../demo-dock-client/` | The shared demo client script, consumed here via bare specifier (`action: { importFrom: 'demo-dock-client' }`) |
5151
| `src/client/main.ts` | The browser UI that consumes the hub protocol, including the interactive-OTP authorization view |

examples/hub-vite/vite.config.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,6 @@ export default defineConfig({
142142
},
143143
},
144144
],
145-
// The a11y inspector declares its own page script (its dock's
146-
// `clientScript`) by path, so the hub serves it same-origin and the hub
147-
// client runtime (booted in src/client/main.ts) imports it into this page
148-
// automatically - the docked panel scans the host live with no host-side
149-
// wiring.
150145
// Serve the reference json-render frontend as a prebuilt renderer
151146
// module: the hub publishes it in the renderer manifest and the client
152147
// (src/client/main.ts) imports it lazily the first time a

packages/devframe/src/types/devframe.ts

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -265,22 +265,12 @@ export interface DevframeDockDefaults {
265265
groupId?: string
266266
/**
267267
* A client script the hub imports into the host page for this devframe (its
268-
* **page script**) — the mechanism a devframe like the a11y inspector uses to
269-
* run its scan loop in the user app's page. `importFrom` is one of:
270-
*
271-
* - an **absolute filesystem path** to a built, self-contained ES module (e.g.
272-
* the plugin's `dist/inject/inject.js`, named from its own `import.meta.url`).
273-
* The hub install path serves the file's directory under the devframe's mount
274-
* base and rewrites `importFrom` to that served URL, so a definition can name
275-
* its page script itself and `devframes: ['@devframes/plugin-x']` works with
276-
* no host-side wiring;
277-
* - a **URL** the host already serves (`/@fs/<abs>` under Vite, a
278-
* statically-mounted bundle path); or
279-
* - a **bare npm specifier**, resolved through the host-advertised
280-
* `clientModuleResolution` template.
281-
*
282-
* URL and bare-specifier values pass through untouched — only an absolute path
283-
* is mounted and rewritten.
268+
* **page script**). `importFrom` is an **absolute filesystem path** to a built
269+
* ES module, a **URL** the host serves, or a **bare npm specifier**. An
270+
* absolute path is served by the hub install path (its directory mounted under
271+
* the devframe's mount base, `importFrom` rewritten to the served URL), so a
272+
* definition names its own page script and mounting by package name needs no
273+
* host wiring; URL and bare-specifier values pass through untouched.
284274
*/
285275
clientScript?: {
286276
/** What to import: an absolute filesystem path, a served URL, or a bare npm specifier. */

packages/hub/src/node/__tests__/install-devframe.test.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import type { DevframeDefinition, DevframeDuplicationStrategy } from 'devframe/t
22
import type { DevframeHubContext } from '../context'
33
import { mkdtempSync, writeFileSync } from 'node:fs'
44
import { tmpdir } from 'node:os'
5-
import { join } from 'node:path'
65
import { defineDevframe } from 'devframe'
6+
import { dirname, join } from 'pathe'
77
import { afterEach, describe, expect, it, vi } from 'vitest'
88
import { DevframeDocksHost } from '../host-docks'
99
import { installDevframe } from '../install-devframe'
@@ -165,15 +165,14 @@ describe('ctx.install', () => {
165165

166166
it('serves an absolute-path page script under the mount base and rewrites it to the served URL', async () => {
167167
const ctx = createContext()
168-
const dir = mkdtempSync(join(tmpdir(), 'devframe-page-script-'))
169-
const scriptPath = join(dir, 'inject.js')
168+
const scriptPath = join(mkdtempSync(join(tmpdir(), 'devframe-page-script-')), 'inject.js')
170169
writeFileSync(scriptPath, 'export default () => {}')
171170

172171
await ctx.install(makeDevframe({
173172
dock: { clientScript: { importFrom: scriptPath } },
174173
}))
175174

176-
expect(ctx.host.mountStatic).toHaveBeenCalledWith('/__demo/__page-script/', dir)
175+
expect(ctx.host.mountStatic).toHaveBeenCalledWith('/__demo/__page-script/', dirname(scriptPath))
177176
expect(ctx.docks.views.get('demo')).toMatchObject({
178177
clientScript: { importFrom: '/__demo/__page-script/inject.js' },
179178
})

packages/hub/src/node/install-devframe.ts

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,11 @@ function nextAvailableDockId(views: DevframeHubContext['docks']['views'], baseId
4040
}
4141

4242
/**
43-
* Resolve a dock's `clientScript` (its **page script**) into one importable by
44-
* the host page. When `importFrom` names an **absolute filesystem path** to a
45-
* built module, serve its directory under the devframe's mount base
46-
* (`<base>__page-script/`) and rewrite `importFrom` to that served URL — so a
47-
* definition can name its page script by path and every host gets a URL for
48-
* free. A URL or bare-specifier `importFrom` (or no client script) passes
49-
* through untouched.
50-
*
51-
* The distinction between a filesystem path and an already-servable root path
52-
* (`/@fs/…`, `/mounted/bundle.js`) is that only the former exists on disk, so
53-
* that is the test used.
43+
* When a dock's `clientScript.importFrom` names an **absolute filesystem path**
44+
* to a built module, serve its directory under the devframe's mount base
45+
* (`<base>__page-script/`) and rewrite `importFrom` to that served URL. A URL or
46+
* bare specifier (distinguished by not existing on disk) passes through
47+
* untouched, as does an absent client script.
5448
*/
5549
async function resolvePageScriptClientScript(
5650
ctx: DevframeHubContext,
@@ -117,9 +111,9 @@ export async function prepareDevframe(
117111
? resolveBasePath(d, 'hosted')
118112
: resolveBasePath({ ...d, id, basePath: undefined }, 'hosted'))
119113

120-
// The effective dock defaults: definition-level `dock` beneath per-mount
121-
// `options.dock`. Resolved here (before the SPA mount) so a page script
122-
// declared as an absolute path can be served ahead of the SPA catch-all.
114+
// Definition-level `dock` beneath per-mount `options.dock`. Resolved before
115+
// the SPA mount so an absolute-path page script is served ahead of the SPA
116+
// catch-all.
123117
const dockDefaults = { ...d.dock, ...options.dock }
124118
const clientScript = await resolvePageScriptClientScript(ctx, dockDefaults.clientScript, base)
125119
if (clientScript)
@@ -152,11 +146,9 @@ export async function prepareDevframe(
152146
id,
153147
title: d.name,
154148
icon: d.icon,
155-
// Definition-level `dock` defaults sit above the name/icon-derived
156-
// defaults; per-mount `options.dock` overrides them (both folded into
157-
// `dockDefaults`, with an absolute-path page script already served and
158-
// rewritten to a URL); `type`/`url` (and `id`) stay locked, derived from
159-
// the definition.
149+
// Dock defaults (definition + per-mount, folded into `dockDefaults`) sit
150+
// above the name/icon-derived defaults; `type`/`url` (and `id`) stay locked,
151+
// derived from the definition.
160152
...dockDefaults,
161153
type: 'iframe',
162154
url: base,

0 commit comments

Comments
 (0)