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
feat!: reduce devframe + @devframes/hub public API surface for 0.9
Trim both packages' published surface down to what integrations actually
consume, and move the primary authoring helper to the package root.
devframe:
- Move `defineDevframe` onto the `devframe` root entry (next to
`defineRpcFunction`); `devframe/types` is now strictly type-only. `devframe`
is the canonical import for both values and types.
- Remove dead subpaths: `devframe/adapters/embedded` (a one-line wrapper around
`def.setup(ctx)`), `devframe/utils/hash`, `devframe/utils/promise`,
`devframe/utils/scope` (no integration consumers).
- Slim `devframe/node` to the server-assembly surface, dropping 9 internal
exports (diagnostics/services/views host classes, the shared-state/streaming/
scope/settings factories, and the toDialableHost/formatHostForUrl helpers).
`createContextRpcServer`, `DevframeAgentHost`, and `coerceAgentPositionalArgs`
stay public — `@devframes/hub`'s `initHub` composes its own hand-rolled server
and command host on them.
@devframes/hub:
- Export `DEFAULT_CATEGORIES_ORDER` only from `@devframes/hub/constants`; drop
the redundant re-exports from `.`, `/node`, and `/client`.
All in-repo consumers (plugins, examples, packages) are migrated to the new
import paths, docs/skill/templates are swept, and `docs/guide/migration-0.9.md`
documents every change. `devframe/rpc/transports/ws-bun` is retained (the hub
uses it) despite the original plan flagging it for removal.
Co-authored-by: opencode <noreply@opencode.ai>
Copy file name to clipboardExpand all lines: docs/adapters/index.md
+2-3Lines changed: 2 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ outline: deep
4
4
5
5
# Adapters
6
6
7
-
An adapter takes a `DevframeDefinition` and deploys it into a specific runtime — a standalone CLI, a Vite plugin, a static snapshot, an embedded host, or an MCP server. Each adapter ships at its own entry point (`devframe/adapters/<name>`); the bundler pulls in only the ones you use.
7
+
An adapter takes a `DevframeDefinition` and deploys it into a specific runtime — a standalone CLI, a Vite plugin, a static snapshot, or an MCP server. Each adapter ships at its own entry point (`devframe/adapters/<name>`); the bundler pulls in only the ones you use. To register a definition into an already-running host, call its `setup` directly: `await def.setup(ctx)`.
8
8
9
9
Every adapter factory has the shape `createXxx(devframeDef, options?)`. Some adapters draw on an optional peer dependency, installed only when you opt into that adapter: `cac` pulls in [`cac`](https://github.com/cacjs/cac), and `mcp` pulls in [`@modelcontextprotocol/server`](https://github.com/modelcontextprotocol/typescript-sdk).
10
10
@@ -16,7 +16,6 @@ Every adapter factory has the shape `createXxx(devframeDef, options?)`. Some ada
16
16
|[`dev`](./dev)|`devframe/adapters/dev`|`createDevServer(def, options?)`| Run the dev server programmatically — drive it from any CLI framework |
17
17
|[`build`](./build)|`devframe/adapters/build`|`createBuild(def, options?)`| Offline reports, CI artifacts, deployable SPA snapshots |
18
18
|[`vite`](./vite)|`@vitejs/devtools-kit/node`|`createPluginFromDevframe(def, options?)`| Mount the definition into Vite DevTools (or any compatible host) |
19
-
|[`embedded`](./embedded)|`devframe/adapters/embedded`|`createEmbedded(def, { ctx })`| Runtime registration into an already-running host |
20
19
|[`mcp`](./mcp)|`devframe/adapters/mcp`|`createMcpServer(def, options?)`| Exposing a devframe to coding agents |
21
20
22
21
## Mount paths
@@ -26,7 +25,7 @@ A devframe's SPA basePath depends on which adapter is running it:
26
25
| Adapter kind | Default basePath | Reason |
27
26
|--------------|------------------|--------|
28
27
|`cli`, `spa`, `build` (standalone) |`/`| The devframe owns the origin. |
29
-
|`vite`, `embedded` (hosted) |`/__<id>/`| The devframe shares the origin with a host app and namespaces itself. |
28
+
|`vite`, embedding hosts (hosted) |`/__<id>/`| The devframe shares the origin with a host app and namespaces itself. |
30
29
31
30
Override either side explicitly with `DevframeDefinition.basePath`:
Copy file name to clipboardExpand all lines: docs/guide/index.md
+4-3Lines changed: 4 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,7 +15,7 @@ Devframe keeps its surface focused on one tool, so the same definition stays por
15
15
-**One tool per definition.** A devframe describes a single integration. Deploy it through any adapter; host-level features that only matter when several tools share a UI (palettes, cross-tool toasts, unified terminals) come from whichever host you mount into — Vite DevTools is one example.
16
16
-**Headless.** Hook into `onReady`, `cli.configure`, and friends to print your own startup banners and styling — Devframe stays out of the way.
17
17
-**App-owned file watching.** Wire your own watcher (chokidar, fs.watch, …) and signal change via `ctx.rpc.sharedState.set(...)` or event-typed RPCs.
18
-
-**Context-aware mount paths.** Standalone adapters (`cli`, `spa`, `build`) serve at `/` by default; hosted adapters (`vite`, `embedded`) serve at `/.<id>/`. Override via `DevframeDefinition.basePath`.
18
+
-**Context-aware mount paths.** Standalone adapters (`cli`, `spa`, `build`) serve at `/` by default; hosted contexts (`vite`, or a host that calls `setup`) serve at `/.<id>/`. Override via `DevframeDefinition.basePath`.
19
19
-**SPAs own their base at runtime.** Build with relative asset paths (`vite.base: './'`); `connectDevframe` discovers the effective base from the executing script's location.
20
20
-**CLI flags compose.** The `cac` instance is exposed to both the devframe (`cli.configure`) and the caller of `createCac`, so capability flags and app flags merge cleanly.
node ./my-devframe.js mcp # stdio MCP server (experimental)
85
85
```
86
86
87
-
The CLI adapter serves the SPA at `/` by default. When the same devframe is embedded inside a host (`vite`, `embedded`), the default becomes `/.my-devframe/`. Override either side via `defineDevframe({ basePath })`.
87
+
The CLI adapter serves the SPA at `/` by default. When the same devframe is embedded inside a host (`vite`, or a host that calls `setup`), the default becomes `/.my-devframe/`. Override either side via `defineDevframe({ basePath })`.
88
88
89
89
## Adapters at a glance
90
90
@@ -95,9 +95,10 @@ Devframe deploys the same `DevframeDefinition` through one of these adapters:
95
95
|`cli`|`createCac(d).parse()`| Standalone CLI with dev / build / mcp subcommands |
96
96
|`vite`|`createPluginFromDevframe(d, opts?)`*(from `@vitejs/devtools-kit/node`)*| Mount the devframe into Vite DevTools (or another compatible host) |
97
97
|`build`|`createBuild(d, opts?)`| Self-contained static deploy with baked RPC dumps |
98
-
|`embedded`|`createEmbedded(d, { ctx })`| Runtime registration into an existing host |
99
98
|`mcp`|`createMcpServer(d, opts)`| Model Context Protocol server |
100
99
100
+
To register a definition into an already-running host, call `await d.setup(ctx)` directly.
101
+
101
102
See [Adapters](/adapters/) for the full reference.
Copy file name to clipboardExpand all lines: docs/guide/migration-0.9.md
+72-1Lines changed: 72 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ outline: deep
4
4
5
5
# Migrating to 0.9
6
6
7
-
0.9 removes the compatibility shims that were deprecated across the 0.7 series. Each removed export has a drop-in replacement that has shipped alongside it since 0.7, 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.
7
+
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.
`createJsonRenderView` returns a view carrying a serializable `ref` (a shared-state key or an inline spec). Project it onto a hub dock with `toJsonRenderDockEntry` from `@devframes/json-render/hub`, which contributes the `'json-render'` dock type to the hub's open dock union. A dock entry now carries that serializable `view` ref rather than a live renderer handle — a client reads `entry.view.stateKey` (or `entry.view.spec`) to render it.
97
97
98
98
See [JSON-Render](./json-render) for the full integration reference.
99
+
100
+
## `defineDevframe` moves to the package root
101
+
102
+
`defineDevframe` — the primary authoring helper — now lives on the `devframe` entry point alongside `defineRpcFunction`. `devframe/types` is now strictly type-only. Import both values and types from `devframe`:
103
+
104
+
| 0.8.x | 0.9 |
105
+
|-------|-----|
106
+
|`import { defineDevframe } from 'devframe/types'`|`import { defineDevframe } from 'devframe'`|
107
+
|`import type { DevframeNodeContext } from 'devframe/types'`|`import type { DevframeNodeContext } from 'devframe'`|
`devframe/types` still resolves as the type-only subpath — useful for `declare module 'devframe/types'` augmentations — but `devframe` is the canonical import for both values and types.
116
+
117
+
## `devframe/adapters/embedded` is removed
118
+
119
+
`createEmbedded(def, { ctx })` was a one-line wrapper around the definition's own `setup`. Call `setup` directly to register a devframe into an already-running host context:
In a hub, `mountDevframe(ctx, def)` (from `@devframes/hub/node`) remains the way to register a devframe with the hub's dock/command wiring.
134
+
135
+
## `devframe/utils/{hash,promise,scope}` are removed
136
+
137
+
Three utility subpaths with no integration consumers are removed:
138
+
139
+
| Removed | Replacement |
140
+
|---------|-------------|
141
+
|`import { promiseWithResolver } from 'devframe/utils/promise'`|`Promise.withResolvers()` (native) |
142
+
|`import { hash } from 'devframe/utils/hash'`| Any structural-hash library (e.g. `ohash`) |
143
+
|`import { isQualifiedName, qualifyName } from 'devframe/utils/scope'`| Inline the check (`name.includes(':')`) |
144
+
145
+
The other `devframe/utils/*` helpers — `colors`, `open`, `launch-editor`, `nanoid`, `crypto-token`, `structured-clone`, `events`, `shared-state`, `streaming-channel`, `when`, `simple-schema`, `serve-static`, `agent-tool-name` — are unchanged.
146
+
147
+
## `devframe/node` is slimmed to the server-assembly surface
148
+
149
+
`devframe/node` keeps the API that hosts wiring up their own runtime actually use — `createHostContext`, `createH3DevframeHost`, `startHttpAndWs`, `createContextRpcServer`, `createStorage`, `registerDevframeInstance` / `listLiveDevframeInstances`, `DevframeAgentHost`, `coerceAgentPositionalArgs`, `isObject`, `normalizeHttpServerUrl`, and the `RpcFunctionsHost` / instance-record types.
150
+
151
+
The internal host implementations and low-level factories are no longer exported:
152
+
153
+
| Removed from `devframe/node`| Notes |
154
+
|---|---|
155
+
|`DevframeDiagnosticsHost`, `DevframeServicesHostImpl`, `DevframeViewHost` (classes) | Internal host implementations. The same-named **types** remain on `devframe/types`. |
156
+
|`createRpcSharedStateServerHost`, `createRpcStreamingServerHost`| Wired internally by `createContextRpcServer`. |
157
+
|`createScopedNodeContext`, `createNodeSettings`| Internal to context assembly. |
A host that binds its own transport composes from `createContextRpcServer` (`devframe/node`) plus `devframe/rpc/server`, `devframe/rpc/transports/*`, and `devframe/node/hub-internals` — the path `@devframes/hub`'s `initHub` and `@vitejs/devtools` both take.
161
+
162
+
## `@devframes/hub` category order lives only on `/constants`
163
+
164
+
`DEFAULT_CATEGORIES_ORDER` is now exported only from `@devframes/hub/constants` (its documented single source of truth). The redundant re-exports from `@devframes/hub`, `@devframes/hub/node`, and `@devframes/hub/client` are removed:
Copy file name to clipboardExpand all lines: docs/helpers/utilities.md
+2-22Lines changed: 2 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ outline: deep
4
4
5
5
# Utilities
6
6
7
-
Devframe ships a set of small, stable helpers under the `devframe/utils/*` subpaths. They cover the most common ancillary tasks a devtool needs — colorising terminal output, hashing arbitrary values, opening files in an editor — without forcing every author to pick (and install) their own library.
7
+
Devframe ships a set of small, stable helpers under the `devframe/utils/*` subpaths. They cover the most common ancillary tasks a devtool needs — colorising terminal output, opening files in an editor, generating IDs and tokens — without forcing every author to pick (and install) their own library.
8
8
9
9
Each helper is bundled inside devframe. Importing from `devframe/utils/*` is enough — there's no separate `npm install` for these dependencies.
The auto-detection reads the `LAUNCH_EDITOR` environment variable and falls back to common defaults. Most devframes consume this through the prebuilt `openInEditor` recipe — see [Common RPC Functions](./common-rpc-functions).
50
50
51
-
### `devframe/utils/hash`
52
-
53
-
Stable, deterministic hash of any structured-cloneable value. Useful for cache keys and dedup.
54
-
55
-
```ts
56
-
import { hash } from'devframe/utils/hash'
57
-
58
-
const key =hash({ functionName, args })
59
-
```
60
-
61
51
### `devframe/utils/structured-clone`
62
52
63
53
JSON-safe serialization for the structured-clone algorithm — round-trips `Map`, `Set`, `Date`, `BigInt`, cycles, and class instances. Used internally by the RPC wire format; exposed for tools that need the same encoding.
Generic typed event emitter — `on(event, cb)` returns an unsubscribe function. Used as the eventing primitive across devframe's hosts.
@@ -147,6 +127,6 @@ Statically-validated when-clause expressions for conditional UI visibility. The
147
127
The utilities are exposed as **stable wrappers over their underlying libraries** rather than bare re-exports. Two consequences:
148
128
149
129
-**One install.** Consumers do not list these libraries in their own `package.json`. Bundling them inside devframe means version drift across devtools is impossible.
150
-
-**Swappable internals.** The wrapper signatures are deliberately narrower than upstream. Devframe can change the implementation (`ansis` → `picocolors`, `ohash` → `crypto.subtle.digest`, …) without a breaking change to dependent devtools.
130
+
-**Swappable internals.** The wrapper signatures are deliberately narrower than upstream. Devframe can change the implementation (`ansis` → `picocolors`, …) without a breaking change to dependent devtools.
151
131
152
132
When you need a feature outside the wrapper's minimal surface, prefer extending the wrapper inside devframe over bypassing it.
0 commit comments