devframe 0.8.1 → 0.9.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_shared-CttmCMBi.mjs +70 -0
- package/dist/_shared-DmpWW-HH.d.mts +43 -0
- package/dist/adapters/build.d.mts +1 -1
- package/dist/adapters/build.mjs +6 -5
- package/dist/adapters/cac.d.mts +1 -1
- package/dist/adapters/cac.mjs +157 -1
- package/dist/adapters/dev.d.mts +25 -34
- package/dist/adapters/dev.mjs +2 -1
- package/dist/adapters/embedded.d.mts +1 -1
- package/dist/adapters/initiate.d.mts +223 -0
- package/dist/adapters/initiate.mjs +2 -0
- package/dist/adapters/mcp.d.mts +26 -2
- package/dist/adapters/mcp.mjs +2 -2
- package/dist/cli/main.mjs +2 -2
- package/dist/client/index.d.mts +70 -6
- package/dist/client/index.mjs +743 -408
- package/dist/constants.d.mts +19 -6
- package/dist/constants.mjs +19 -6
- package/dist/{context-CQefP2jR.mjs → context-C33rR7n0.mjs} +1 -1
- package/dist/{context-DFzmxCLa.d.mts → context-CSCwoABx.d.mts} +1 -1
- package/dist/{host-h3-Kz7t5Xab.mjs → context-Du11TLcO.mjs} +5 -255
- package/dist/dev-BEveeA5H.mjs +233 -0
- package/dist/{devframe-qgCKL683.d.mts → devframe-Bdd9YXTy.d.mts} +88 -25
- package/dist/{diagnostics-B5-qHeqD.mjs → diagnostics-DLYH5oD3.mjs} +20 -0
- package/dist/dist-D8jAMwxU.mjs +227 -0
- package/dist/helpers/vite.d.mts +43 -39
- package/dist/helpers/vite.mjs +26 -38
- package/dist/host-agent-CpbAoqBx.mjs +230 -0
- package/dist/host-h3-CzCZwtuV.mjs +26 -0
- package/dist/{fetch-CK0S253E.mjs → http-DLr_cJZ7.mjs} +42 -4
- package/dist/{index-B7RgLw--.d.mts → index-CZRd2K1C.d.mts} +2 -2
- package/dist/{index-Dbw1p5ch.d.mts → index-DSCq4M4q.d.mts} +2 -31
- package/dist/index.d.mts +9 -4
- package/dist/index.mjs +8 -1
- package/dist/{instance-registry-D6fxYu36.mjs → instance-registry-BQqGoDO9.mjs} +9 -2
- package/dist/instance-shell-DBTXTSjN.d.mts +264 -0
- package/dist/instance-shell-KRdee1QF.mjs +485 -0
- package/dist/internal/index.d.mts +150 -0
- package/dist/internal/index.mjs +7 -0
- package/dist/node/auth.d.mts +2 -2
- package/dist/node/hub-internals.d.mts +2 -14
- package/dist/node/hub-internals.mjs +2 -2
- package/dist/node/index.d.mts +3 -267
- package/dist/node/index.mjs +3 -5
- package/dist/recipes/common-rpc-functions.d.mts +3 -3
- package/dist/recipes/interactive-auth.d.mts +3 -3
- package/dist/recipes/interactive-auth.mjs +6 -6
- package/dist/rolldown-runtime-JspESFgx.mjs +35 -0
- package/dist/rpc/dump.d.mts +77 -1
- package/dist/rpc/dump.mjs +1 -1
- package/dist/rpc/index.d.mts +2 -2
- package/dist/rpc/index.mjs +3 -17
- package/dist/rpc/transports/sse-client.d.mts +2 -0
- package/dist/rpc/transports/sse-client.mjs +142 -0
- package/dist/rpc/transports/sse-server.d.mts +61 -0
- package/dist/rpc/transports/sse-server.mjs +209 -0
- package/dist/rpc/transports/ws-bun.d.mts +35 -0
- package/dist/rpc/transports/ws-bun.mjs +31 -0
- package/dist/rpc/transports/ws-client.d.mts +1 -1
- package/dist/rpc/transports/ws-client.mjs +10 -18
- package/dist/rpc/transports/ws-server.d.mts +2 -2
- package/dist/rpc/transports/ws-server.mjs +2 -214
- package/dist/rpc-core-CGctXToO.d.mts +48 -0
- package/dist/rpc-core-CqcJkAu9.mjs +81 -0
- package/dist/{serialization-C8Mnw9hK.mjs → serialization-BHY8M5NQ.mjs} +1 -1
- package/dist/{shared-state-6kHolYZy.mjs → shared-state-fRRbRUtD.mjs} +1 -1
- package/dist/sse-client-BsIK3hMD.d.mts +37 -0
- package/dist/{dump-CgZShDRB.mjs → static-CvjkO8QE.mjs} +2 -265
- package/dist/{storage-Dzoc3NVC.mjs → storage-BcmVEJRc.mjs} +2 -2
- package/dist/types/index.d.mts +3 -3
- package/dist/types/index.mjs +1 -6
- package/dist/utils/events.d.mts +1 -1
- package/dist/utils/launch-editor.mjs +1 -25
- package/dist/utils/open.mjs +1 -1
- package/dist/utils/serve-static.mjs +1 -1
- package/dist/utils/shared-state.d.mts +1 -1
- package/dist/utils/shared-state.mjs +1 -1
- package/dist/utils/simple-schema.d.mts +101 -1
- package/dist/utils/streaming-channel.d.mts +1 -1
- package/dist/validation-BiuDXTKW.mjs +266 -0
- package/dist/wire-codec-9VhIKnyp.mjs +58 -0
- package/dist/{ws-client-B6Tnr0ic.d.mts → ws-client-CdNuATYa.d.mts} +6 -1
- package/dist/ws-server-Bk1hOG3X.mjs +267 -0
- package/dist/{ws-server-J-zkiOyp.d.mts → ws-server-Ces08fjP.d.mts} +102 -13
- package/package.json +10 -9
- package/skills/devframe/SKILL.md +84 -85
- package/dist/_shared-bWRzeSa0.mjs +0 -19
- package/dist/adapters/cli.d.mts +0 -11
- package/dist/adapters/cli.mjs +0 -6
- package/dist/cac-B1LM3zit.mjs +0 -157
- package/dist/dev-BSHFZGZr.mjs +0 -437
- package/dist/http-Dvgxujcu.mjs +0 -38
- package/dist/index-vAX6bYuc.d.mts +0 -78
- package/dist/recipes/open-helpers.d.mts +0 -6
- package/dist/recipes/open-helpers.mjs +0 -6
- package/dist/server-CXaDDUl0.mjs +0 -148
- package/dist/server-E9z4ZWbd.d.mts +0 -132
- package/dist/simple-schema-BDzLeJDk.d.mts +0 -102
- package/dist/utils/promise.d.mts +0 -8
- package/dist/utils/promise.mjs +0 -15
- package/dist/utils/scope.d.mts +0 -11
- package/dist/utils/scope.mjs +0 -15
- package/dist/{open-Deb5xmIT.mjs → open-Dz4V4irZ.mjs} +1 -1
package/skills/devframe/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: devframe
|
|
3
3
|
description: >
|
|
4
|
-
Use when building a devtool with devframe
|
|
4
|
+
Use when building a devtool with devframe - the
|
|
5
5
|
framework- and build-tool-agnostic foundation for defining a
|
|
6
6
|
devtool once and serving it in many places. Covers
|
|
7
7
|
DevframeDefinition, picking the right deployment adapter
|
|
@@ -9,7 +9,7 @@ description: >
|
|
|
9
9
|
contracts, exposing an agent-native surface over MCP, and
|
|
10
10
|
wiring the author's SPA client. For host-level features (docks,
|
|
11
11
|
terminals, palette, etc.), the devframe can be mounted into a
|
|
12
|
-
host that provides them
|
|
12
|
+
host that provides them - Vite DevTools is one supported target,
|
|
13
13
|
reached via the `vite` adapter. Triggers on `devframe` imports,
|
|
14
14
|
`defineDevframe`, `createCac`, `createMcpServer`,
|
|
15
15
|
`connectDevframe`, and on migrations of existing inspectors
|
|
@@ -19,9 +19,9 @@ description: >
|
|
|
19
19
|
|
|
20
20
|
# devframe skill
|
|
21
21
|
|
|
22
|
-
**Devframe is an asset: define your devtool once, serve it anywhere.** A devtool built on devframe is a single `DevframeDefinition` plus an author-provided SPA
|
|
22
|
+
**Devframe is an asset: define your devtool once, serve it anywhere.** A devtool built on devframe is a single `DevframeDefinition` plus an author-provided SPA - the same definition deploys through a set of pluggable adapters (standalone CLI, static report, embedded SPA, MCP server, mounted into a host, etc.). Devframe is framework- and build-tool-agnostic; it has no Vite dependency and makes no UI-framework assumption.
|
|
23
23
|
|
|
24
|
-
Devframe describes one tool. If you need host-level features (cross-tool palette, integrated terminals, dock aggregation), mount the devframe into a host that provides them
|
|
24
|
+
Devframe describes one tool. If you need host-level features (cross-tool palette, integrated terminals, dock aggregation), mount the devframe into a host that provides them - [Vite DevTools](https://devtools.vite.dev/) is the canonical example, reached via the `vite` adapter - or build your own host adapter. `devframe` itself must not depend on Vite or any `@vitejs/*` package.
|
|
25
25
|
|
|
26
26
|
Full reference: [devfra.me/](https://devfra.me/).
|
|
27
27
|
|
|
@@ -38,9 +38,9 @@ All adapter factories share the shape `createXxx(devframeDef, options?)`.
|
|
|
38
38
|
| Register dynamically at runtime | `createEmbedded(def, { ctx })` | `devframe/adapters/embedded` |
|
|
39
39
|
| Expose to coding agents (MCP) | `createMcpServer(def, options?)` | `devframe/adapters/mcp` *(experimental)* |
|
|
40
40
|
|
|
41
|
-
The same `DevframeDefinition` runs under every adapter
|
|
41
|
+
The same `DevframeDefinition` runs under every adapter - pick based on deployment, not on what the tool does.
|
|
42
42
|
|
|
43
|
-
For Vite-based hosts that don't use the kit (Nuxt, Astro, SolidStart, plain Vite apps), `devframe/helpers/vite` exports `viteDevBridge(def, options?)`
|
|
43
|
+
For Vite-based hosts that don't use the kit (Nuxt, Astro, SolidStart, plain Vite apps), `devframe/helpers/vite` exports `viteDevBridge(def, options?)` - a Vite plugin that mounts the SPA (static mode) or starts the RPC + WS bridge alongside the host's dev server (`devMiddleware: true`). Not an adapter; just a Vite integration helper.
|
|
44
44
|
|
|
45
45
|
## Minimum viable devframe
|
|
46
46
|
|
|
@@ -57,7 +57,7 @@ export default defineDevframe({
|
|
|
57
57
|
icon: 'ph:magnifying-glass-duotone',
|
|
58
58
|
cli: { distDir: './client/dist' },
|
|
59
59
|
setup(ctx) {
|
|
60
|
-
const my = ctx.scope('my-inspector') // preferred
|
|
60
|
+
const my = ctx.scope('my-inspector') // preferred - auto-namespaces ids
|
|
61
61
|
my.rpc.register(defineRpcFunction({
|
|
62
62
|
name: 'get-stats', // stored as `my-inspector:get-stats`
|
|
63
63
|
type: 'static',
|
|
@@ -83,28 +83,28 @@ export default defineDevframe({
|
|
|
83
83
|
})
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
`setup(ctx)` registers RPC functions, shared state, diagnostics, and any other devframe-level wiring. Host adapters can augment `ctx` with extra surfaces
|
|
86
|
+
`setup(ctx)` registers RPC functions, shared state, diagnostics, and any other devframe-level wiring. Host adapters can augment `ctx` with extra surfaces - for example, mounting into Vite DevTools via `createPluginFromDevframe(d)` exposes `docks`, `terminals`, `messages`, and `commands` on the augmented context, and the kit auto-derives an iframe dock entry from `id` / `name` / `icon` / `basePath`. For richer host-side behaviour (custom-render, terminals, palette commands) pass `options.setup` to `createPluginFromDevframe`.
|
|
87
87
|
|
|
88
88
|
See `templates/counter-devframe.ts` for a runnable counter example, `templates/spa-devframe.ts` for an SPA-ready shape, and `templates/vite-client.ts` for the author's client entry.
|
|
89
89
|
|
|
90
90
|
## Scoped context (preferred)
|
|
91
91
|
|
|
92
|
-
`ctx.scope(id)` (server) and `client.scope(id)` (browser) return a namespace-scoped view that auto-prefixes every RPC id, shared-state key, and streaming channel with `id:`, and adds a top-level persisted `settings` store. Prefer it over the raw `ctx.rpc` / client
|
|
92
|
+
`ctx.scope(id)` (server) and `client.scope(id)` (browser) return a namespace-scoped view that auto-prefixes every RPC id, shared-state key, and streaming channel with `id:`, and adds a top-level persisted `settings` store. Prefer it over the raw `ctx.rpc` / client - you name the namespace once and register / call by bare name.
|
|
93
93
|
|
|
94
94
|
```ts
|
|
95
|
-
// server
|
|
95
|
+
// server - setup(ctx)
|
|
96
96
|
const my = ctx.scope('my-inspector')
|
|
97
97
|
my.rpc.register(getStats) // -> my-inspector:get-stats
|
|
98
98
|
await my.rpc.call('get-stats') // invokeLocal, namespaced
|
|
99
99
|
const state = await my.rpc.sharedState('view') // -> my-inspector:view
|
|
100
100
|
await my.settings.project.set('theme', 'dark')
|
|
101
101
|
|
|
102
|
-
// browser
|
|
102
|
+
// browser - connectDevframe()
|
|
103
103
|
const my = (await connectDevframe()).scope('my-inspector')
|
|
104
104
|
const stats = await my.rpc.call('get-stats')
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
- **Auto-namespacing.** Bare names get `id:` prepended; a name already containing `:` is treated as fully-qualified and passed through (so `my.rpc.call('other-tool:fn')` works). `register` only accepts bare names
|
|
107
|
+
- **Auto-namespacing.** Bare names get `id:` prepended; a name already containing `:` is treated as fully-qualified and passed through (so `my.rpc.call('other-tool:fn')` works). `register` only accepts bare names - passing a namespaced one throws `DF0034`.
|
|
108
108
|
- **Typed bare calls.** Define functions with bare names and augment the registry with `RpcDefinitionsToFunctionsWithNamespace<'my-inspector', typeof serverFunctions>` so the registry keys match the namespaced runtime ids; scoped `call('get-stats')` then stays typed.
|
|
109
109
|
- **`base`.** The scoped context keeps the raw context as `my.base` (and re-exposes `views` / `diagnostics` / `agent` / `host` / `cwd` / `mode` on the server).
|
|
110
110
|
|
|
@@ -112,8 +112,8 @@ const stats = await my.rpc.call('get-stats')
|
|
|
112
112
|
|
|
113
113
|
`my.settings` is a persisted key-value store at the **top level** of the scoped context (a sibling of `my.rpc`, not under it). Two scopes:
|
|
114
114
|
|
|
115
|
-
- `project`
|
|
116
|
-
- `global`
|
|
115
|
+
- `project` - per-workspace, persisted under the host's `workspace` storage dir.
|
|
116
|
+
- `global` - per-user, persisted under the host's `global` storage dir.
|
|
117
117
|
|
|
118
118
|
Both are file-backed on the server and synced to clients over the shared-state protocol, so a `set` on either side propagates everywhere and survives restarts. All methods are async.
|
|
119
119
|
|
|
@@ -137,7 +137,7 @@ declare module 'devframe' {
|
|
|
137
137
|
|
|
138
138
|
## Project layout
|
|
139
139
|
|
|
140
|
-
Once a devframe grows past a handful of RPC functions, split them out
|
|
140
|
+
Once a devframe grows past a handful of RPC functions, split them out - one file per function under `src/rpc/functions/`, with `src/rpc/index.ts` as the barrel. The `functions/` subdirectory leaves room for sibling files like `src/rpc/utils.ts` (helpers, type aliases) as the surface grows. Each function file exports a named const with a **bare** name; the barrel collects them into a `const serverFunctions = [...] as const` and feeds the type-safe client registry recipe with the namespace-aware helper `RpcDefinitionsToFunctionsWithNamespace<'my-tool', typeof serverFunctions>` (it prefixes each bare name to match the namespaced runtime id the scope registers).
|
|
141
141
|
|
|
142
142
|
```ts
|
|
143
143
|
// src/rpc/functions/list-files.ts
|
|
@@ -145,7 +145,7 @@ import { defineRpcFunction } from 'devframe'
|
|
|
145
145
|
import { getMyToolContext } from '../../context'
|
|
146
146
|
|
|
147
147
|
export const listFiles = defineRpcFunction({
|
|
148
|
-
name: 'list-files', // bare
|
|
148
|
+
name: 'list-files', // bare - the scope namespaces it to `my-tool:list-files`
|
|
149
149
|
type: 'query',
|
|
150
150
|
jsonSerializable: true,
|
|
151
151
|
setup: (ctx) => {
|
|
@@ -170,7 +170,7 @@ declare module 'devframe' {
|
|
|
170
170
|
|
|
171
171
|
```ts
|
|
172
172
|
// src/devframe.ts
|
|
173
|
-
import { defineDevframe } from 'devframe
|
|
173
|
+
import { defineDevframe } from 'devframe'
|
|
174
174
|
import pkg from '../package.json' with { type: 'json' }
|
|
175
175
|
import { setMyToolContext } from './context'
|
|
176
176
|
import { serverFunctions } from './rpc'
|
|
@@ -190,15 +190,15 @@ export default defineDevframe({
|
|
|
190
190
|
})
|
|
191
191
|
```
|
|
192
192
|
|
|
193
|
-
Note `setMyToolContext(ctx, …)` keys off the raw `ctx` (the same object the function `setup(ctx)` receives)
|
|
193
|
+
Note `setMyToolContext(ctx, …)` keys off the raw `ctx` (the same object the function `setup(ctx)` receives) - store the per-tool context on `ctx`, register through `my.rpc`.
|
|
194
194
|
|
|
195
195
|
### Sharing setup-time state via `src/context.ts`
|
|
196
196
|
|
|
197
|
-
When per-file RPCs need access to runtime values that `setup(ctx)` constructs once
|
|
197
|
+
When per-file RPCs need access to runtime values that `setup(ctx)` constructs once - streaming channels, shared state handles, watchers, loaders, caches - expose them through a `WeakMap<DevframeNodeContext, T>` in a sibling `src/context.ts`. This mirrors the framework's own `internalContextMap` in `packages/devframe/src/node/hub-internals/context.ts`. The WeakMap keys off the existing `DevframeNodeContext` so contexts are garbage-collected automatically when the host tears down.
|
|
198
198
|
|
|
199
199
|
```ts
|
|
200
200
|
// src/context.ts
|
|
201
|
-
import type { DevframeNodeContext } from 'devframe
|
|
201
|
+
import type { DevframeNodeContext } from 'devframe'
|
|
202
202
|
|
|
203
203
|
export interface MyToolContext {
|
|
204
204
|
loaders: { list: () => Promise<string[]> }
|
|
@@ -214,12 +214,12 @@ export function setMyToolContext(ctx: DevframeNodeContext, value: MyToolContext)
|
|
|
214
214
|
export function getMyToolContext(ctx: DevframeNodeContext): MyToolContext {
|
|
215
215
|
const value = map.get(ctx)
|
|
216
216
|
if (!value)
|
|
217
|
-
throw new Error('my-tool context not initialised
|
|
217
|
+
throw new Error('my-tool context not initialised - call setMyToolContext in devframe.setup')
|
|
218
218
|
return value
|
|
219
219
|
}
|
|
220
220
|
```
|
|
221
221
|
|
|
222
|
-
Stateless RPCs and tiny demos can keep the inline shorthand inside `setup(ctx)`
|
|
222
|
+
Stateless RPCs and tiny demos can keep the inline shorthand inside `setup(ctx)` - reach for `src/rpc/functions/` and `src/context.ts` once you have more than one or two functions, or any shared setup state.
|
|
223
223
|
|
|
224
224
|
## Namespacing
|
|
225
225
|
|
|
@@ -228,10 +228,10 @@ Stateless RPCs and tiny demos can keep the inline shorthand inside `setup(ctx)`
|
|
|
228
228
|
```ts
|
|
229
229
|
'my-inspector:get-modules' // ✓
|
|
230
230
|
'my-inspector:state' // ✓
|
|
231
|
-
'get-modules' // ✗
|
|
231
|
+
'get-modules' // ✗ - may collide with other devframes sharing the host
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
-
A [scoped context](#scoped-context-preferred) applies this prefix for you
|
|
234
|
+
A [scoped context](#scoped-context-preferred) applies this prefix for you - `ctx.scope('my-inspector').rpc.register({ name: 'get-modules' })` registers `my-inspector:get-modules`. Define and call by bare name through the scope; reach for full ids only via `ctx.base` or when targeting another tool. Dock / command IDs are host-level (not part of the scoped `rpc` surface) - prefix those by hand.
|
|
235
235
|
|
|
236
236
|
## DevframeNodeContext at a glance
|
|
237
237
|
|
|
@@ -239,15 +239,15 @@ A [scoped context](#scoped-context-preferred) applies this prefix for you — `c
|
|
|
239
239
|
|
|
240
240
|
| Host | Purpose |
|
|
241
241
|
|------|---------|
|
|
242
|
-
| `ctx.scope(id)` | **Preferred** namespace-scoped view
|
|
242
|
+
| `ctx.scope(id)` | **Preferred** namespace-scoped view - auto-prefixed `rpc` + top-level `settings` store |
|
|
243
243
|
| `ctx.rpc` | Register RPC functions, broadcast, shared state, streaming channels |
|
|
244
244
|
| `ctx.views` | Serve static files via `hostStatic(base, distDir)` |
|
|
245
|
-
| `ctx.diagnostics` | Structured diagnostics host (nostics)
|
|
245
|
+
| `ctx.diagnostics` | Structured diagnostics host (nostics) - register custom error codes |
|
|
246
246
|
| `ctx.agent` | Expose tools + resources to coding agents (experimental) |
|
|
247
|
-
| `ctx.host` | Runtime abstraction
|
|
248
|
-
| `ctx.mode` | `'dev'` or `'build'`
|
|
247
|
+
| `ctx.host` | Runtime abstraction - `mountStatic`, `resolveOrigin`, `getStorageDir` |
|
|
248
|
+
| `ctx.mode` | `'dev'` or `'build'` - gate setup work per runtime |
|
|
249
249
|
|
|
250
|
-
> Hosts can augment `ctx` with additional surfaces (e.g. Vite DevTools' `docks`, `terminals`, `messages`, `commands
|
|
250
|
+
> Hosts can augment `ctx` with additional surfaces (e.g. Vite DevTools' `docks`, `terminals`, `messages`, `commands`). Consult the host's docs - for Vite DevTools, see the [`vite-devtools-kit` skill](../../skills/vite-devtools-kit).
|
|
251
251
|
|
|
252
252
|
## RPC contracts
|
|
253
253
|
|
|
@@ -256,7 +256,7 @@ import { defineRpcFunction } from 'devframe'
|
|
|
256
256
|
import * as v from 'valibot'
|
|
257
257
|
|
|
258
258
|
const getModules = defineRpcFunction({
|
|
259
|
-
name: 'get-modules', // bare
|
|
259
|
+
name: 'get-modules', // bare - registered via `ctx.scope('my-inspector').rpc.register`
|
|
260
260
|
type: 'query',
|
|
261
261
|
jsonSerializable: true,
|
|
262
262
|
args: [v.object({ limit: v.number() })],
|
|
@@ -269,12 +269,12 @@ const getModules = defineRpcFunction({
|
|
|
269
269
|
|
|
270
270
|
| Type | Use when | Cached | Static dump |
|
|
271
271
|
|------|----------|--------|-------------|
|
|
272
|
-
| `'static'` | Data constant for a given input
|
|
272
|
+
| `'static'` | Data constant for a given input - dump at build time | Indefinitely | Automatic |
|
|
273
273
|
| `'query'` | Read that may change; optional `dump` for build adapters | Opt-in via `cacheable` | Manual |
|
|
274
274
|
| `'action'` | Server-state mutation | Never | Never |
|
|
275
275
|
| `'event'` | Fire-and-forget; no response | Never | Never |
|
|
276
276
|
|
|
277
|
-
Add valibot schemas when the RPC is user-facing, when you want static dumps, or when you expose it to agents. Prefer a **single object arg** (`args: [v.object({ ... })]`) over positional args
|
|
277
|
+
Add valibot schemas when the RPC is user-facing, when you want static dumps, or when you expose it to agents. Prefer a **single object arg** (`args: [v.object({ ... })]`) over positional args - property names self-document and agents rely on them.
|
|
278
278
|
|
|
279
279
|
### `jsonSerializable` (wire + dump format)
|
|
280
280
|
|
|
@@ -285,9 +285,9 @@ Add valibot schemas when the RPC is user-facing, when you want static dumps, or
|
|
|
285
285
|
| `false` (default) | `structured-clone-es` | `s:` | `Map`, `Set`, `Date`, `BigInt`, cycles, class instances |
|
|
286
286
|
| `true` (opt-in) | strict `JSON.stringify` | _(unprefixed)_ | JSON-only |
|
|
287
287
|
|
|
288
|
-
Set `jsonSerializable: true` when your handler returns plain JSON shapes
|
|
288
|
+
Set `jsonSerializable: true` when your handler returns plain JSON shapes - the strict serializer **throws `DF0020`** synchronously on the offending call when it sees a value JSON cannot round-trip (Map/Set/Date/BigInt/class instance/`undefined`-in-array). Errors surface in dev next to the call that introduced them, not silently at build time.
|
|
289
289
|
|
|
290
|
-
`agent: {...}` requires `jsonSerializable: true` (registration throws `DF0019` otherwise). MCP tools speak JSON
|
|
290
|
+
`agent: {...}` requires `jsonSerializable: true` (registration throws `DF0019` otherwise). MCP tools speak JSON - opting into the agent surface is also opting into JSON-only data.
|
|
291
291
|
|
|
292
292
|
Through the scope, `my.rpc.broadcast({ method, args, optional?, event?, filter? })` pushes to every connected client (method name namespaced), and `my.rpc.call(name, ...args)` invokes a server function locally without going through transport (the scoped form of `ctx.rpc.invokeLocal`, useful for cross-function composition).
|
|
293
293
|
|
|
@@ -305,13 +305,13 @@ state.mutate((draft) => {
|
|
|
305
305
|
})
|
|
306
306
|
```
|
|
307
307
|
|
|
308
|
-
- Values must be serializable
|
|
308
|
+
- Values must be serializable - no functions, no circular refs.
|
|
309
309
|
- Mutations round-trip to all clients; the host tracks `syncIds` to avoid replay loops.
|
|
310
310
|
- Prefer shared state over ad-hoc RPC events for UI that must reappear after reconnect.
|
|
311
311
|
|
|
312
312
|
## Streaming channels
|
|
313
313
|
|
|
314
|
-
For chunk-style data flowing in either direction
|
|
314
|
+
For chunk-style data flowing in either direction - LLM deltas, log tails, build progress, file uploads, mic / screen-share frames - use a streaming channel instead of inventing `action + delta/end` events. The same `channel` object handles both directions:
|
|
315
315
|
|
|
316
316
|
```ts
|
|
317
317
|
const my = ctx.scope('my-inspector')
|
|
@@ -324,18 +324,18 @@ const channel = my.rpc.streaming.create<string>('tokens', { // -> my-inspector:t
|
|
|
324
324
|
### Server-to-client (the common case)
|
|
325
325
|
|
|
326
326
|
```ts
|
|
327
|
-
// Server
|
|
327
|
+
// Server - typically inside an action handler that returns the stream id
|
|
328
328
|
const stream = channel.start({ id: 'optional-stream-id' })
|
|
329
329
|
stream.write(token) // imperative
|
|
330
330
|
stream.error(err) // terminal failure
|
|
331
331
|
stream.close() // terminal success
|
|
332
|
-
stream.signal // AbortSignal
|
|
332
|
+
stream.signal // AbortSignal - flips when consumers cancel or all subscribers drop
|
|
333
333
|
stream.writable // WritableStream<T> for `pipeTo`-style consumption
|
|
334
334
|
|
|
335
|
-
// Convenience
|
|
335
|
+
// Convenience - start + pipe in one call:
|
|
336
336
|
await channel.pipeFrom(sourceReadable, { id: 'optional' })
|
|
337
337
|
|
|
338
|
-
// Client
|
|
338
|
+
// Client - my = (await connectDevframe()).scope('my-inspector')
|
|
339
339
|
const reader = my.rpc.streaming.subscribe<string>('tokens', streamId) // -> my-inspector:tokens
|
|
340
340
|
for await (const token of reader) renderToken(token)
|
|
341
341
|
// Or: reader.readable.pipeTo(domWritable)
|
|
@@ -347,7 +347,7 @@ reader.cancel() // server `stream.signal` aborts
|
|
|
347
347
|
The same channel exposes `openInbound()` for the server side of a client→server upload. Pair it with a normal action that returns the id:
|
|
348
348
|
|
|
349
349
|
```ts
|
|
350
|
-
// Server
|
|
350
|
+
// Server - my = ctx.scope('my-inspector')
|
|
351
351
|
my.rpc.register(defineRpcFunction({
|
|
352
352
|
name: 'upload-file', // -> my-inspector:upload-file
|
|
353
353
|
type: 'action',
|
|
@@ -362,7 +362,7 @@ my.rpc.register(defineRpcFunction({
|
|
|
362
362
|
},
|
|
363
363
|
}))
|
|
364
364
|
|
|
365
|
-
// Client
|
|
365
|
+
// Client - my = (await connectDevframe()).scope('my-inspector')
|
|
366
366
|
const { uploadId } = await my.rpc.call('upload-file', { name: 'foo' })
|
|
367
367
|
const upload = my.rpc.streaming.upload<Uint8Array>('files', uploadId) // -> my-inspector:files
|
|
368
368
|
fileReadable.pipeTo(upload.writable, { signal: upload.signal })
|
|
@@ -403,7 +403,7 @@ For chat-style UIs that combine both: keep the **conversation log** in shared st
|
|
|
403
403
|
|
|
404
404
|
## Mounting into a host (Vite DevTools example)
|
|
405
405
|
|
|
406
|
-
A portable devframe can be mounted into any host that ships an adapter for it. Vite DevTools is one supported target
|
|
406
|
+
A portable devframe can be mounted into any host that ships an adapter for it. Vite DevTools is one supported target - `createPluginFromDevframe` is the Vite-DevTools-specific bridge; other hosts can implement equivalent factories. Example:
|
|
407
407
|
|
|
408
408
|
```ts
|
|
409
409
|
// vite.config.ts
|
|
@@ -413,7 +413,7 @@ import myInspector from './my-inspector'
|
|
|
413
413
|
export default {
|
|
414
414
|
plugins: [
|
|
415
415
|
createPluginFromDevframe(myInspector, {
|
|
416
|
-
// Optional kit-only setup
|
|
416
|
+
// Optional kit-only setup - runs after the auto-derived dock entry.
|
|
417
417
|
setup(kitCtx) {
|
|
418
418
|
kitCtx.commands.register({
|
|
419
419
|
id: 'my-inspector:clear-cache',
|
|
@@ -426,11 +426,11 @@ export default {
|
|
|
426
426
|
}
|
|
427
427
|
```
|
|
428
428
|
|
|
429
|
-
The kit auto-derives an iframe dock entry from `id` / `name` / `icon` / `basePath`. For dock variations (custom-render, launcher, action, json-render), terminals, palette commands, and toasts, use the `options.setup` hook
|
|
429
|
+
The kit auto-derives an iframe dock entry from `id` / `name` / `icon` / `basePath`. For dock variations (custom-render, launcher, action, json-render), terminals, palette commands, and toasts, use the `options.setup` hook - those APIs live on the host-augmented context, not on the devframe-level `setup`. See the [`vite-devtools-kit` skill](../../skills/vite-devtools-kit) for the Vite-DevTools-specific reference.
|
|
430
430
|
|
|
431
431
|
## When clauses
|
|
432
432
|
|
|
433
|
-
Gate kit-side dock / command visibility with VS Code-style expressions. The runtime + types ship bundled from `devframe/utils/when`
|
|
433
|
+
Gate kit-side dock / command visibility with VS Code-style expressions. The runtime + types ship bundled from `devframe/utils/when` - no separate install. The consumers (`when` field on docks and commands) live in the kit:
|
|
434
434
|
|
|
435
435
|
```ts
|
|
436
436
|
when: 'clientType == embedded'
|
|
@@ -442,7 +442,7 @@ Built-in context: `clientType` (`'embedded' | 'standalone'`), `dockOpen`, `palet
|
|
|
442
442
|
|
|
443
443
|
## Agent-native surface (experimental)
|
|
444
444
|
|
|
445
|
-
Opt an RPC function into the agent surface with an `agent` field
|
|
445
|
+
Opt an RPC function into the agent surface with an `agent` field - default-deny otherwise. Agent-exposed functions **must declare `jsonSerializable: true`** (registration throws `DF0019` otherwise):
|
|
446
446
|
|
|
447
447
|
```ts
|
|
448
448
|
defineRpcFunction({
|
|
@@ -485,7 +485,7 @@ import { createMcpServer } from 'devframe/adapters/mcp'
|
|
|
485
485
|
await createMcpServer(devframe, { transport: 'stdio' })
|
|
486
486
|
```
|
|
487
487
|
|
|
488
|
-
`@modelcontextprotocol/server` is a peer dependency. The CLI adapter also exposes `my-devframe mcp`
|
|
488
|
+
`@modelcontextprotocol/server` is a peer dependency. The CLI adapter also exposes `my-devframe mcp` - route host logs to stderr (stdout is the MCP transport). Safety classifications (`'read' | 'action' | 'destructive'`) drive MCP hint annotations that agent clients use to prompt for confirmation.
|
|
489
489
|
|
|
490
490
|
## Author SPA
|
|
491
491
|
|
|
@@ -495,16 +495,16 @@ Authors bring their own SPA (any framework or plain HTML). Client entry:
|
|
|
495
495
|
import { connectDevframe } from 'devframe/client'
|
|
496
496
|
|
|
497
497
|
const client = await connectDevframe()
|
|
498
|
-
// await client.ensureTrusted() // WS mode only
|
|
499
|
-
const my = client.scope('my-inspector') // preferred
|
|
498
|
+
// await client.ensureTrusted() // WS mode only - blocks until server accepts
|
|
499
|
+
const my = client.scope('my-inspector') // preferred - namespaced calls
|
|
500
500
|
|
|
501
501
|
const data = await my.rpc.call('get-stats', { limit: 10 })
|
|
502
502
|
```
|
|
503
503
|
|
|
504
504
|
`connectDevframe` auto-detects the backend via `/.devframe/.connection.json`:
|
|
505
505
|
|
|
506
|
-
- **websocket** (dev mode)
|
|
507
|
-
- **static** (build / spa output)
|
|
506
|
+
- **websocket** (dev mode) - full read/write, requires auth handshake. Listen for token updates on the `devframe-auth` BroadcastChannel.
|
|
507
|
+
- **static** (build / spa output) - read-only, resolves calls from the baked RPC dump.
|
|
508
508
|
|
|
509
509
|
Use `my.rpc.sharedState(key)` for observable state, `my.rpc.register(defineRpcFunction(...))` to receive server broadcasts, `my.rpc.callOptional(...)` when a missing handler should resolve to `undefined` instead of throwing, and `my.settings.{project,global}` for persisted per-workspace / per-user settings synced from the server.
|
|
510
510
|
|
|
@@ -534,46 +534,45 @@ At runtime, static clients look up the argument hash in the dump; misses resolve
|
|
|
534
534
|
|
|
535
535
|
| Subcommand | Action |
|
|
536
536
|
|------------|--------|
|
|
537
|
-
| *(default)* | Dev server on port 9999 (or `--port`)
|
|
537
|
+
| *(default)* | Dev server on port 9999 (or `--port`) - WebSocket RPC, `cli.distDir` served at `/.devframe/` |
|
|
538
538
|
| `build` | Static snapshot → `./dist-static/` (configurable via `--out-dir`) |
|
|
539
539
|
| `spa` | Deployable SPA → `./dist-spa/` |
|
|
540
540
|
| `mcp` | stdio MCP server (experimental) |
|
|
541
541
|
|
|
542
|
-
**Bring your own CLI framework?** `createCac` (`devframe/adapters/cac`) is just a cac wrapper around three peer factories
|
|
542
|
+
**Bring your own CLI framework?** `createCac` (`devframe/adapters/cac`) is just a cac wrapper around three peer factories - `createDevServer` (`devframe/adapters/dev`), `createBuild` (`devframe/adapters/build`), and `createMcpServer` (`devframe/adapters/mcp`). Use them directly with commander/yargs/oclif when `createCac`'s baked-in command structure doesn't fit. `cac` is an optional peer dependency pulled in only through `devframe/adapters/cac`, so bring-your-own-CLI tools run without installing it. `createDevServer` returns a `StartedServer` handle (`origin`, `port`, `app`, `wss`, `close()`) so you can wire SIGINT / hot-reload teardown into the surrounding program. `parseCliFlags(schema, raw)` and `defineCliFlags(...)` (both from `devframe/adapters/cac`) validate an arbitrary flag bag against a `CliFlagsSchema` - the helpers are framework-agnostic.
|
|
543
543
|
|
|
544
544
|
## Bundled utilities
|
|
545
545
|
|
|
546
|
-
Devframe re-exports a curated set of helpers under `devframe/utils/*`. They are bundled
|
|
546
|
+
Devframe re-exports a curated set of helpers under `devframe/utils/*`. They are bundled - never add the underlying packages to a devtool's own `package.json`:
|
|
547
547
|
|
|
548
548
|
| Import | Wraps | Use for |
|
|
549
549
|
|--------|-------|---------|
|
|
550
550
|
| `colors` from `devframe/utils/colors` | `ansis` | Terminal ANSI colors (`c.red`, `c.green`, tagged templates) |
|
|
551
551
|
| `open` from `devframe/utils/open` | `open` | Open URLs / files in the OS default handler |
|
|
552
552
|
| `launchEditor` from `devframe/utils/launch-editor` | `launch-editor` | Open `file:line:column` in the user's editor (optional `editor` arg) |
|
|
553
|
-
| `hash` from `devframe/utils/hash` | `ohash` | Stable structural hash
|
|
553
|
+
| `hash` from `devframe/utils/hash` | `ohash` | Stable structural hash - cache keys, dedup |
|
|
554
554
|
| `structuredClone{Serialize,Deserialize,Stringify,Parse}` from `devframe/utils/structured-clone` | `structured-clone-es` | JSON-safe round-trip of `Map` / `Set` / `Date` / `BigInt` / cycles |
|
|
555
555
|
| `nanoid` from `devframe/utils/nanoid` | (vendored) | URL-safe random IDs |
|
|
556
556
|
| `randomToken` / `randomDigits` / `timingSafeEqual` from `devframe/utils/crypto-token` | (native WebCrypto) | CSPRNG bearer tokens, one-time codes, constant-time compare |
|
|
557
|
-
| `
|
|
558
|
-
| `createEventEmitter` from `devframe/utils/events` | — | Typed event bus |
|
|
557
|
+
| `createEventEmitter` from `devframe/utils/events` | - | Typed event bus |
|
|
559
558
|
| `createSharedState` from `devframe/utils/shared-state` | (immer internal) | Immutable state container (see `ctx.rpc.sharedState`) |
|
|
560
|
-
| `createStreamSink` / `createStreamReader` from `devframe/utils/streaming-channel` |
|
|
559
|
+
| `createStreamSink` / `createStreamReader` from `devframe/utils/streaming-channel` | - | Low-level streaming primitives |
|
|
561
560
|
| `evaluateWhen` / `WhenExpression` from `devframe/utils/when` | `whenexpr` | When-clause expressions |
|
|
562
561
|
|
|
563
|
-
For "open file in editor" + "reveal in finder", prefer the prebuilt `commonRpcFunctions` RPC recipe (`devframe/recipes/common-rpc-functions`)
|
|
562
|
+
For "open file in editor" + "reveal in finder", prefer the prebuilt `commonRpcFunctions` RPC recipe (`devframe/recipes/common-rpc-functions`) - it wires the two utilities into named RPC functions ready to register.
|
|
564
563
|
|
|
565
564
|
## Security (secure by default)
|
|
566
565
|
|
|
567
566
|
RPC handlers run with the full privileges of the host process, so the boundary that matters is who may connect. Keep that boundary tight:
|
|
568
567
|
|
|
569
|
-
- **`auth` defaults to `true`**
|
|
568
|
+
- **`auth` defaults to `true`** - dev-mode connections must authenticate before calls are accepted. Devframe ships the node primitives (`exchangeTempAuthCode`, `verifyAuthToken` in `devframe/node/auth`); the host adapter (e.g. Vite DevTools) provides the interactive `devframe:anonymous:auth` + `devframe:auth:exchange` handlers and auth UI.
|
|
570
569
|
- **`auth: false` trusts every reachable connection.** Use it only for single-user `localhost` tools. Never combine it with a non-loopback bind host, a tunnel, or a shared/CI environment. The default bind host is already `localhost`.
|
|
571
|
-
- **Authentication** exchanges a 6-digit one-time code (shown in the developer's terminal) for a node-issued bearer token via `requestTrustWithCode(code)`. The code is single-use, expires in 5 min, compared in constant time, and rotates after repeated failures
|
|
572
|
-
- **Magic-link (optional):** print `buildOtpAuthUrl(origin)`
|
|
573
|
-
- **Tokens are secrets.** The bearer token rides the WS URL (`?devframe_auth_token=…`)
|
|
574
|
-
- **Authorize handlers.** Any trusted client can call any registered function
|
|
575
|
-
- **Origin-lock remote docks** (`originLock`, on by default) so a dock's session token is honored only on a connection whose `Origin` matches the dock
|
|
576
|
-
- **The MCP route requires an Origin.** The route-based MCP server (`cli.mcp`, `viteDevBridge`/Next handler `mcp`, `createMcpFetchHandler`) rejects `Origin`-less requests
|
|
570
|
+
- **Authentication** exchanges a 6-digit one-time code (shown in the developer's terminal) for a node-issued bearer token via `requestTrustWithCode(code)`. The code is single-use, expires in 5 min, compared in constant time, and rotates after repeated failures - show it only in the terminal, never over the network.
|
|
571
|
+
- **Magic-link (optional):** print `buildOtpAuthUrl(origin)` - `<origin>/#devframe_otp=<code>`. The code rides the URL **fragment**, which the browser never sends to the server, so it stays out of access logs and `Referer`. `connectDevframe` reads the code, exchanges it, and strips it from the URL. Integrations can opt out (`otpParam: false`) and drive it via the exposed `authenticateWithUrlOtp(rpc)` / `consumeOtpFromUrl()` client utilities. Only the single-use code rides the URL, never the bearer; treat the printed link like the code itself. The standalone CLI's `--open` does this automatically via `DevframeAuthHandler.buildOpenUrl` - the launched tab already carries the OTP, no prompt needed.
|
|
572
|
+
- **Tokens are secrets.** The bearer token rides the WS URL (`?devframe_auth_token=…`) - serve over `wss://`/`https://` beyond loopback. Never log the token or code, never bake them into build output. Revoke via `revokeAuthToken(...)`; clients drop to untrusted on `devframe:auth:revoked`.
|
|
573
|
+
- **Authorize handlers.** Any trusted client can call any registered function - validate inputs, and mark state-changing functions `type: 'destructive'` so MCP/agent clients prompt first.
|
|
574
|
+
- **Origin-lock remote docks** (`originLock`, on by default) so a dock's session token is honored only on a connection whose `Origin` matches the dock - the connect-time gate enforces it.
|
|
575
|
+
- **The MCP route requires an Origin.** The route-based MCP server (`cli.mcp`, `viteDevBridge`/Next handler `mcp`, `createMcpFetchHandler`) rejects `Origin`-less requests - a request must carry a loopback (or allow-listed) `Origin`, so it isn't reachable by an arbitrary local process. `devframe connect` sends each instance's own loopback origin automatically.
|
|
577
576
|
|
|
578
577
|
See [Security](https://devfra.me/security) for the full reference.
|
|
579
578
|
|
|
@@ -587,23 +586,23 @@ See [Security](https://devfra.me/security) for the full reference.
|
|
|
587
586
|
|
|
588
587
|
Devframe-level pages (one-tool, portable surface):
|
|
589
588
|
|
|
590
|
-
- [Devframe Definition](https://devfra.me/devframe-definition)
|
|
591
|
-
- [Scoped Context](https://devfra.me/scoped-context)
|
|
592
|
-
- [Adapters](https://devfra.me/adapters)
|
|
593
|
-
- [RPC](https://devfra.me/rpc)
|
|
594
|
-
- [Shared State](https://devfra.me/shared-state)
|
|
595
|
-
- [Streaming](https://devfra.me/streaming)
|
|
596
|
-
- [When Clauses](https://devfra.me/when-clauses)
|
|
597
|
-
- [Structured Diagnostics](https://devfra.me/diagnostics)
|
|
598
|
-
- [Utilities](https://devfra.me/utilities)
|
|
599
|
-
- [Client](https://devfra.me/client)
|
|
600
|
-
- [Security](https://devfra.me/security)
|
|
601
|
-
- [Agent-Native](https://devfra.me/agent-native)
|
|
602
|
-
|
|
603
|
-
Host-specific extras (when mounting into Vite DevTools
|
|
589
|
+
- [Devframe Definition](https://devfra.me/devframe-definition) - fields, runtime flags, multi-adapter wiring
|
|
590
|
+
- [Scoped Context](https://devfra.me/scoped-context) - `ctx.scope(id)`, auto-namespacing, the `settings` store
|
|
591
|
+
- [Adapters](https://devfra.me/adapters) - full reference for all deployment adapters
|
|
592
|
+
- [RPC](https://devfra.me/rpc) - types, schema, broadcasts, dumps
|
|
593
|
+
- [Shared State](https://devfra.me/shared-state) - patches, events, client-side mutation
|
|
594
|
+
- [Streaming](https://devfra.me/streaming) - chunked feeds, uploads, replay, Web/Node Streams interop
|
|
595
|
+
- [When Clauses](https://devfra.me/when-clauses) - syntax, context, type-safe wrappers
|
|
596
|
+
- [Structured Diagnostics](https://devfra.me/diagnostics) - coded errors via `ctx.diagnostics`, register custom codes
|
|
597
|
+
- [Utilities](https://devfra.me/utilities) - bundled `devframe/utils/*` helpers (colors, hash, launchEditor, structured-clone, …)
|
|
598
|
+
- [Client](https://devfra.me/client) - auth handshake, modes, discovery
|
|
599
|
+
- [Security](https://devfra.me/security) - trust model, authentication, secure-by-default practices
|
|
600
|
+
- [Agent-Native](https://devfra.me/agent-native) - agent field, tools/resources, MCP + Claude Desktop
|
|
601
|
+
|
|
602
|
+
Host-specific extras (when mounting into Vite DevTools - other hosts have their own equivalents):
|
|
604
603
|
|
|
605
604
|
- [Vite DevTools Kit overview](https://devtools.vite.dev/kit/)
|
|
606
|
-
- [Dock System](https://devtools.vite.dev/kit/dock-system)
|
|
607
|
-
- [Commands](https://devtools.vite.dev/kit/commands)
|
|
608
|
-
- [Messages & Notifications](https://devtools.vite.dev/kit/messages)
|
|
609
|
-
- [Terminals](https://devtools.vite.dev/kit/terminals)
|
|
605
|
+
- [Dock System](https://devtools.vite.dev/kit/dock-system) - every entry type + remote docks
|
|
606
|
+
- [Commands](https://devtools.vite.dev/kit/commands) - palette, keybindings, sub-commands
|
|
607
|
+
- [Messages & Notifications](https://devtools.vite.dev/kit/messages) - entry fields, positional hints
|
|
608
|
+
- [Terminals](https://devtools.vite.dev/kit/terminals) - child processes, external sessions
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { cleanDoubleSlashes, withLeadingSlash, withTrailingSlash } from "ufo";
|
|
2
|
-
//#region src/adapters/_shared.ts
|
|
3
|
-
/**
|
|
4
|
-
* Resolve the mount base path for a devframe's SPA. Hosted adapters
|
|
5
|
-
* (`vite`, `embedded`) default to `/__<id>/` so they don't collide
|
|
6
|
-
* with the host app; standalone adapters (`cli`, `spa`, `build`)
|
|
7
|
-
* default to `/` because they own the origin.
|
|
8
|
-
*
|
|
9
|
-
* The devframe author can override with `basePath` on the definition.
|
|
10
|
-
*/
|
|
11
|
-
function resolveBasePath(def, kind) {
|
|
12
|
-
if (def.basePath) return normalizeBasePath(def.basePath);
|
|
13
|
-
return kind === "standalone" ? "/" : `/__${def.id}/`;
|
|
14
|
-
}
|
|
15
|
-
function normalizeBasePath(base) {
|
|
16
|
-
return cleanDoubleSlashes(withTrailingSlash(withLeadingSlash(base)));
|
|
17
|
-
}
|
|
18
|
-
//#endregion
|
|
19
|
-
export { resolveBasePath as n, normalizeBasePath as t };
|
package/dist/adapters/cli.d.mts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Ft as InferCliFlags, It as defineCliFlags, Lt as parseCliFlags, Pt as CliFlagsSchema } from "../devframe-qgCKL683.mjs";
|
|
2
|
-
import { CacHandle, CreateCacOptions, createCac } from "./cac.mjs";
|
|
3
|
-
//#region src/adapters/cli.d.ts
|
|
4
|
-
/** @deprecated Use `createCac` from `devframe/adapters/cac` instead. */
|
|
5
|
-
declare const createCli: typeof createCac;
|
|
6
|
-
/** @deprecated Use `CreateCacOptions` from `devframe/adapters/cac` instead. */
|
|
7
|
-
type CreateCliOptions = CreateCacOptions;
|
|
8
|
-
/** @deprecated Use `CacHandle` from `devframe/adapters/cac` instead. */
|
|
9
|
-
type CliHandle = CacHandle;
|
|
10
|
-
//#endregion
|
|
11
|
-
export { type CliFlagsSchema, CliHandle, CreateCliOptions, type InferCliFlags, createCli, defineCliFlags, parseCliFlags };
|
package/dist/adapters/cli.mjs
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { n as defineCliFlags, r as parseCliFlags, t as createCac } from "../cac-B1LM3zit.mjs";
|
|
2
|
-
//#region src/adapters/cli.ts
|
|
3
|
-
/** @deprecated Use `createCac` from `devframe/adapters/cac` instead. */
|
|
4
|
-
const createCli = createCac;
|
|
5
|
-
//#endregion
|
|
6
|
-
export { createCli, defineCliFlags, parseCliFlags };
|