Skip to content

Commit 89bfb29

Browse files
antfubotopencode
andcommitted
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>
1 parent eaeb1f6 commit 89bfb29

130 files changed

Lines changed: 239 additions & 349 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

alias.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,10 @@ export const alias = {
2323
'devframe/utils/colors': r('devframe/src/utils/colors.ts'),
2424
'devframe/utils/crypto-token': r('devframe/src/utils/crypto-token.ts'),
2525
'devframe/utils/events': r('devframe/src/utils/events.ts'),
26-
'devframe/utils/hash': r('devframe/src/utils/hash.ts'),
2726
'devframe/utils/launch-editor': r('devframe/src/utils/launch-editor.ts'),
2827
'devframe/utils/nanoid': r('devframe/src/utils/nanoid.ts'),
2928
'devframe/utils/open': r('devframe/src/utils/open.ts'),
30-
'devframe/utils/promise': r('devframe/src/utils/promise.ts'),
3129
'devframe/utils/simple-schema': r('devframe/src/utils/simple-schema.ts'),
32-
'devframe/utils/scope': r('devframe/src/utils/scope.ts'),
3330
'devframe/utils/serve-static': r('devframe/src/utils/serve-static.ts'),
3431
'devframe/utils/shared-state': r('devframe/src/utils/shared-state.ts'),
3532
'devframe/utils/streaming-channel': r('devframe/src/utils/streaming-channel.ts'),
@@ -39,7 +36,6 @@ export const alias = {
3936
'devframe/adapters/dev': r('devframe/src/adapters/dev.ts'),
4037
'devframe/adapters/build': r('devframe/src/adapters/build.ts'),
4138
'devframe/helpers/vite': r('devframe/src/helpers/vite.ts'),
42-
'devframe/adapters/embedded': r('devframe/src/adapters/embedded.ts'),
4339
'devframe/initiate': r('devframe/src/adapters/initiate.ts'),
4440
'devframe/adapters/mcp': r('devframe/src/adapters/mcp/index.ts'),
4541
'@devframes/hub/client': r('hub/src/client/index.ts'),

docs/.vitepress/config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ function adaptersItems(prefix: string) {
4747
{ text: 'Initiate (middleware)', link: `${prefix}/adapters/initiate` },
4848
{ text: 'Build', link: `${prefix}/adapters/build` },
4949
{ text: 'Vite', link: `${prefix}/adapters/vite` },
50-
{ text: 'Embedded', link: `${prefix}/adapters/embedded` },
5150
{ text: 'MCP', link: `${prefix}/adapters/mcp` },
5251
] satisfies DefaultTheme.NavItemWithLink[]
5352
}

docs/adapters/embedded.md

Lines changed: 0 additions & 20 deletions
This file was deleted.

docs/adapters/index.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ outline: deep
44

55
# Adapters
66

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)`.
88

99
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).
1010

@@ -16,7 +16,6 @@ Every adapter factory has the shape `createXxx(devframeDef, options?)`. Some ada
1616
| [`dev`](./dev) | `devframe/adapters/dev` | `createDevServer(def, options?)` | Run the dev server programmatically — drive it from any CLI framework |
1717
| [`build`](./build) | `devframe/adapters/build` | `createBuild(def, options?)` | Offline reports, CI artifacts, deployable SPA snapshots |
1818
| [`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 |
2019
| [`mcp`](./mcp) | `devframe/adapters/mcp` | `createMcpServer(def, options?)` | Exposing a devframe to coding agents |
2120

2221
## Mount paths
@@ -26,7 +25,7 @@ A devframe's SPA basePath depends on which adapter is running it:
2625
| Adapter kind | Default basePath | Reason |
2726
|--------------|------------------|--------|
2827
| `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. |
3029

3130
Override either side explicitly with `DevframeDefinition.basePath`:
3231

docs/guide/index.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Devframe keeps its surface focused on one tool, so the same definition stays por
1515
- **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.
1616
- **Headless.** Hook into `onReady`, `cli.configure`, and friends to print your own startup banners and styling — Devframe stays out of the way.
1717
- **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`.
1919
- **SPAs own their base at runtime.** Build with relative asset paths (`vite.base: './'`); `connectDevframe` discovers the effective base from the executing script's location.
2020
- **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.
2121

@@ -84,7 +84,7 @@ node ./my-devframe.js build # self-contained static deploy in dist-static/
8484
node ./my-devframe.js mcp # stdio MCP server (experimental)
8585
```
8686

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 })`.
8888

8989
## Adapters at a glance
9090

@@ -95,9 +95,10 @@ Devframe deploys the same `DevframeDefinition` through one of these adapters:
9595
| `cli` | `createCac(d).parse()` | Standalone CLI with dev / build / mcp subcommands |
9696
| `vite` | `createPluginFromDevframe(d, opts?)` *(from `@vitejs/devtools-kit/node`)* | Mount the devframe into Vite DevTools (or another compatible host) |
9797
| `build` | `createBuild(d, opts?)` | Self-contained static deploy with baked RPC dumps |
98-
| `embedded` | `createEmbedded(d, { ctx })` | Runtime registration into an existing host |
9998
| `mcp` | `createMcpServer(d, opts)` | Model Context Protocol server |
10099

100+
To register a definition into an already-running host, call `await d.setup(ctx)` directly.
101+
101102
See [Adapters](/adapters/) for the full reference.
102103

103104
## Framework- and build-tool-agnostic

docs/guide/migration-0.9.md

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ outline: deep
44

55
# Migrating to 0.9
66

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.
88

99
## `devframe/adapters/cli` is removed
1010

@@ -96,3 +96,74 @@ const view = createJsonRenderView(ctx, {
9696
`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.
9797

9898
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'` |
108+
109+
```ts
110+
import type { DevframeNodeContext } from 'devframe'
111+
// 0.9
112+
import { defineDevframe, defineRpcFunction } from 'devframe'
113+
```
114+
115+
`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:
120+
121+
```ts
122+
// 0.8.x
123+
import { createEmbedded } from 'devframe/adapters/embedded'
124+
125+
await createEmbedded(def, { ctx })
126+
```
127+
128+
```ts
129+
// 0.9
130+
await def.setup(ctx)
131+
```
132+
133+
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. |
158+
| `toDialableHost`, `formatHostForUrl` | Internal host-URL helpers. |
159+
160+
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:
165+
166+
```ts
167+
// 0.9
168+
import { DEFAULT_CATEGORIES_ORDER } from '@devframes/hub/constants'
169+
```

docs/helpers/utilities.md

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ outline: deep
44

55
# Utilities
66

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.
88

99
Each helper is bundled inside devframe. Importing from `devframe/utils/*` is enough — there's no separate `npm install` for these dependencies.
1010

@@ -48,16 +48,6 @@ launchEditor('src/main.ts:42:7', 'code')
4848

4949
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).
5050

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-
6151
### `devframe/utils/structured-clone`
6252

6353
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.
@@ -97,16 +87,6 @@ randomDigits(6) // '047204' — uniform, leading zeros preserved
9787
timingSafeEqual(input, secret) // constant-time string comparison
9888
```
9989

100-
### `devframe/utils/promise`
101-
102-
Promise constructor with externally-controlled resolution.
103-
104-
```ts
105-
import { promiseWithResolver } from 'devframe/utils/promise'
106-
107-
const { promise, resolve, reject } = promiseWithResolver<number>()
108-
```
109-
11090
### `devframe/utils/events`
11191

11292
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
147127
The utilities are exposed as **stable wrappers over their underlying libraries** rather than bare re-exports. Two consequences:
148128

149129
- **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.
151131

152132
When you need a feature outside the wrapper's minimal surface, prefer extending the wrapper inside devframe over bypassing it.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { DevframeHubContext } from '@devframes/hub/node'
22
import type { ClientScriptEntry } from '@devframes/hub/types'
3+
import type { DevframeDefinition, DevframeHost } from 'devframe'
34
import type { DevframeInstanceRegistration } from 'devframe/node'
4-
import type { DevframeDefinition, DevframeHost } from 'devframe/types'
55
import type { Plugin, ResolvedConfig, ViteDevServer } from 'vite'
66
import { homedir } from 'node:os'
77
import process from 'node:process'

examples/files-inspector/src/devframe.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { fileURLToPath } from 'node:url'
2-
import { defineDevframe } from 'devframe/types'
2+
import { defineDevframe } from 'devframe'
33
import pkg from '../package.json' with { type: 'json' }
44
import { NAMESPACE, serverFunctions } from './rpc/index.ts'
55

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { createUi as CreateUi } from '@devframes/hub-ui'
22
import type { HubInstance } from '@devframes/hub/initiate'
3-
import type { DevframeDefinition } from 'devframe/types'
3+
import type { DevframeDefinition } from 'devframe'
44
import { DEVFRAMES_HUB_BASE, initHub } from '@devframes/hub/initiate'
55

66
// The plugin packages and `@devframes/hub-ui` resolve their prebuilt `dist`

0 commit comments

Comments
 (0)