Skip to content

Commit f526013

Browse files
committed
docs: trim never-landed churn from the 0.9 migration guide and add an overview
The 0.8.x→0.9 guide documented six sections of before/after churn on initDevframe/initHub, hub-ui, and the client renderer registry — all APIs introduced within the unreleased 0.9 line and absent at v0.8.2, so their migration framing described changes that never net-landed for a 0.8.2 user. Drop those sections, correct the devframe/internal move table (createContextRpcServer is new, not moved), and lead the page with an at-a-glance overview of the genuine deltas grouped by package.
1 parent 369cb55 commit f526013

1 file changed

Lines changed: 27 additions & 112 deletions

File tree

docs/guide/migration-0.9.md

Lines changed: 27 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,31 @@ outline: deep
66

77
0.9 removes the compatibility shims that were deprecated across the 0.7 series and trims the public API surface of `devframe` and `@devframes/hub` down to what integrations actually consume. Each change has a drop-in replacement, so migrating is a matter of updating import paths and a handful of call sites. This page covers the changes between 0.8.x and 0.9.
88

9+
## Overview
10+
11+
Every entry below has a drop-in replacement. At a glance:
12+
13+
**`devframe`**
14+
15+
| Removed / moved | Replacement |
16+
|---|---|
17+
| `devframe/adapters/cli` (`createCli`, `CreateCliOptions`, `CliHandle`) | `devframe/adapters/cac` (`createCac`, …) |
18+
| `devframe/recipes/open-helpers` | `devframe/recipes/common-rpc-functions` |
19+
| dump re-exports on the `devframe/rpc` barrel | `devframe/rpc/dump` |
20+
| `defineDevframe` on `devframe/types` | `defineDevframe` on `devframe` |
21+
| `devframe/utils/promise`, `devframe/utils/scope` | `Promise.withResolvers()` / inline the check |
22+
| host implementations + low-level factories on `devframe/node` | slimmed to `createHostContext` / `createStorage` |
23+
| cross-package internals on `devframe/node` | `devframe/internal` (unstable) |
24+
| `startHttpAndWs` | `createDevServer` / `devframe/initiate` |
25+
26+
**`@devframes/hub`**
27+
28+
| Removed / moved | Replacement |
29+
|---|---|
30+
| json-render shims (`defineJsonRenderSpec`, `ctx.createJsonRenderer`, …) | `@devframes/json-render` |
31+
| `mountDevframe` | `ctx.install` |
32+
| `DEFAULT_CATEGORIES_ORDER` re-exports | `@devframes/hub/constants` |
33+
934
## `devframe/adapters/cli` is removed
1035

1136
The CLI adapter was renamed to `cac` in 0.7. The `devframe/adapters/cli` entry - `createCli`, `CreateCliOptions`, and `CliHandle` - is now gone. Import from `devframe/adapters/cac` instead:
@@ -145,14 +170,13 @@ The low-level primitives shared between `devframe` and its first-party integrati
145170
| Moved | From | To |
146171
|---|---|---|
147172
| `createH3DevframeHost` (+ `CreateH3DevframeHostOptions`) | `devframe/node` | `devframe/internal` |
148-
| `createContextRpcServer` (+ `ContextRpcServer`, `CreateContextRpcServerOptions`) | `devframe/node` | `devframe/internal` |
149173
| `StartedServer` (the `createDevServer` return handle) | `devframe/node` | `devframe/internal` |
150174
| `DevframeAgentHost` (class) | `devframe/node` | `devframe/internal` |
151175
| `coerceAgentPositionalArgs` (+ `AgentArgsFallback`) | `devframe/node` | `devframe/internal` |
152176
| `registerDevframeInstance` / `listLiveDevframeInstances` (+ `DevframeInstanceRecord`, `DevframeInstanceRegistration`) | `devframe/node` | `devframe/internal` |
153177
| `normalizeHttpServerUrl` | `devframe/node` | `devframe/internal` |
154178

155-
A host that stands up its own server composes from `devframe/internal` - `createH3DevframeHost` for the node `DevframeHost`, `createContextRpcServer` + `devframe/rpc/transports/*` to bind a transport - plus `devframe/node`'s `createHostContext` and `devframe/node/hub-internals`. This is the path `@devframes/hub`'s `initHub` takes. A custom host advertises itself with `registerDevframeInstance` (or the new `register` flag, below), and a devtool enumerates running instances with `listLiveDevframeInstances`. Application code should prefer the adapters and `devframe/initiate`.
179+
A host that stands up its own server composes from `devframe/internal` - `createH3DevframeHost` for the node `DevframeHost`, plus `createContextRpcServer` and a transport from `devframe/rpc/transports/*` to bind the RPC socket - alongside `devframe/node`'s `createHostContext` and `devframe/node/hub-internals`. A custom host advertises itself with `registerDevframeInstance`, and a devtool enumerates running instances with `listLiveDevframeInstances`. Application code should prefer the adapters and `devframe/initiate`.
156180

157181
## `startHttpAndWs` is removed
158182

@@ -163,7 +187,7 @@ The low-level "listen on a port + attach the WS transport" primitive is gone. `c
163187
| `startHttpAndWs({ context, port, ... })` for a standalone tool | `createDevServer(def, { port, ... })` |
164188
| `startHttpAndWs(...)` inside a framework host | `initDevframe(def, { base, ... })` / `initHub({ base, ... })` |
165189

166-
A host that genuinely binds its own transport - a bare RPC socket, or a server it wires itself - composes the two public primitives `startHttpAndWs` used underneath: `createContextRpcServer` (`devframe/internal`) for the session/auth wiring, and a transport from `devframe/rpc/transports/*`.
190+
A host that genuinely binds its own transport - a bare RPC socket, or a server it wires itself - composes the two primitives the adapters use underneath: `createContextRpcServer` (`devframe/internal`) for the session/auth wiring, and a transport from `devframe/rpc/transports/*`.
167191

168192
```ts
169193
// 0.9 - bind the RPC socket onto a server you own
@@ -211,112 +235,3 @@ await ctx.install(myDevframe)
211235
// 0.9
212236
import { DEFAULT_CATEGORIES_ORDER } from '@devframes/hub/constants'
213237
```
214-
215-
## `initDevframe` / `initHub` bind no WebSocket server on their own
216-
217-
Both factories used to start a side-car WebSocket server when no transport option was given. In 0.9 a side-car is opt-in, so creating an instance never binds a port by itself. The binding resolves `ws.port` > `server` > `ws.sidecar` > the host's own upgrades:
218-
219-
| 0.8.x | 0.9 |
220-
|-------|-----|
221-
| `initHub({ base })` (implicit side-car) | `initHub({ base, ws: { sidecar: true } })` |
222-
| `initDevframe(def, { base })` (implicit side-car) | `initDevframe(def, { base, ws: { sidecar: true } })` |
223-
| - | `hub.attach(server)` / `hub.handleUpgrade(req, socket, head)` - serve the socket from a server the host owns |
224-
225-
Hosts already passing `server`, `ws.port` or `ws.url` are unaffected. Hosts whose handlers never see upgrades (Next.js route handlers, Nitro, Rsbuild) add `ws: { sidecar: true }`; hosts that get their `node:http` server *after* the instance exists - a Hono app served by `@hono/node-server`, for instance - hand it over with `attach`, which returns a detach function:
226-
227-
```ts
228-
// 0.9
229-
import { serve } from '@hono/node-server'
230-
231-
const hub = initHub({ base: DEVFRAMES_HUB_BASE })
232-
const detach = hub.attach(serve({ fetch: app.fetch, port: 3000 }))
233-
```
234-
235-
Calling `attach` / `handleUpgrade` on an instance that already owns a transport reports [`DF0055`](/errors/DF0055), and on the advertise-only `ws.url` tier [`DF0056`](/errors/DF0056).
236-
237-
## `initDevframe` / `initHub` can register themselves
238-
239-
An in-process host used to call `registerDevframeInstance` by hand to appear in the global instance registry (`~/.devframe/instances/`, read by `devframe connect` and the inspect plugin's Instances tab). Both factories now take an opt-in `register` flag that does it for them: a dynamic import that writes the record once the public origin resolves and removes it on `close()`. `createDevServer` registers this way automatically.
240-
241-
| 0.8.x | 0.9 |
242-
|---|---|
243-
| manual `registerDevframeInstance({ pid, port, origin, … })` + `unregister()` on every close path | `initHub({ base, register: true })` / `initDevframe(def, { base, register: true })` |
244-
245-
Pass an object to override individual record fields - `register: { id, name, rootDir }`. `registerDevframeInstance` / `listLiveDevframeInstances` remain on `devframe/internal` for hosts that drive the registry directly.
246-
247-
## The `key` option is removed; memoize on `globalThis`
248-
249-
`initDevframe` and `initHub` no longer memoize instances under a `key` (and the `DF0053` / `DF8001` replacement diagnostics are gone with it). A host that re-evaluates its modules in dev owns the memo, which makes the lifecycle visible at the call site:
250-
251-
```ts
252-
// 0.8.x
253-
export const hub = initHub({ key: 'devtools', base: DEVFRAMES_HUB_BASE, devframes })
254-
```
255-
256-
```ts
257-
// 0.9
258-
const g = globalThis as { hub?: HubInstance }
259-
export const hub = g.hub ??= initHub({ base: DEVFRAMES_HUB_BASE, devframes })
260-
```
261-
262-
`@devframes/next`'s `createDevframeNextHandler` keeps its own `key` option and memoizes for you, so Next hosts using it need no change.
263-
264-
## The Bun WebSocket tier moves out of the instances
265-
266-
`initDevframe` / `initHub` no longer detect Bun and complete fetch upgrades themselves, so `instance.websocket` and `handler`'s second (`server`) argument are gone - `handler` is now exactly `(request: Request) => Promise<Response>`. A Bun host binds the transport itself, with the same public primitives the instances used underneath:
267-
268-
```ts
269-
// 0.9
270-
import { createContextRpcServer } from 'devframe/internal'
271-
import { attachBunWsTransport } from 'devframe/rpc/transports/ws-bun'
272-
273-
const core = createContextRpcServer({ context: await hub.context, auth: false })
274-
const tier = await attachBunWsTransport(core)
275-
276-
Bun.serve({
277-
port: 3000,
278-
fetch(request, server) {
279-
const { pathname } = new URL(request.url)
280-
if (pathname === `${hub.base}__ws` && request.headers.get('upgrade')?.toLowerCase() === 'websocket')
281-
return tier.handleUpgrade(request, server)
282-
return app.fetch(request)
283-
},
284-
websocket: tier.websocket as never,
285-
})
286-
```
287-
288-
`examples/hub-hono-minimal` ships this wiring in [`src/bun.ts`](https://github.com/devframes/devframe/blob/main/examples/hub-hono-minimal/src/bun.ts), next to the Node entry's `hub.attach(server)`.
289-
290-
## `renderers.mount()` resolves a typed result
291-
292-
The client renderer registry's `mount()` previously resolved a bare disposer - and silently no-opped when no renderer covered the dock type. It now resolves a discriminated `DockRendererMountResult`, so viewers can show a visible fallback instead of a dead panel:
293-
294-
```ts
295-
// 0.8.x
296-
const dispose = await context.renderers.mount(entry, container)
297-
298-
// 0.9
299-
const result = await context.renderers.mount(entry, container)
300-
if (result.status === 'mounted')
301-
const dispose = result.dispose
302-
else if (result.status === 'missing-renderer')
303-
showFallback(`No renderer for "${entry.type}" in the current environment`)
304-
else // 'load-error'
305-
showError(result.error)
306-
```
307-
308-
`renderers.has(type)` now also answers `true` for types covered by the hub's [renderer manifest](./hub-initiate#renderer-modules) (`initHub({ renderers })`), whose modules `mount()` imports lazily; renderers registered locally keep precedence.
309-
310-
## `@devframes/hub-ui` renders json-render docks through the registry
311-
312-
hub-ui's bundled Vue json-render components are removed. A `json-render` dock (and any other non-native dock type) now renders through the dock-renderer registry - compose a frontend on the hub:
313-
314-
```ts
315-
// 0.9
316-
import { createUi } from '@devframes/hub-ui'
317-
import { jsonRenderUiRenderer } from '@devframes/json-render-ui/hub'
318-
319-
initHub({ ui: createUi(), renderers: [jsonRenderUiRenderer()] })
320-
```
321-
322-
Without a registration for the type, hub-ui shows its missing-renderer fallback view. Behavior also improves with the reference module: prop validation with per-element error isolation, action error surfacing, and static-mode handling - see [JSON-Render](./json-render#rendering-inside-a-hub).

0 commit comments

Comments
 (0)