Skip to content

Commit 35e6c0f

Browse files
committed
refactor(devframe)!: make cac an optional peer dependency of the cli adapter
cac is now an optional peer dependency, pulled in only through the devframe/adapters/cli entry. Tools that assemble their own command-line shell from the createDevServer / createBuild / createMcpServer factories run without installing cac. A new cac-free devframe/adapters/flags entry exposes the typed-flag helpers (defineCliFlags / parseCliFlags) so bring-your-own-CLI tools get flag validation without depending on cac. The helpers stay re-exported from adapters/cli for back-compat. Plugins and examples that ship a createCli-backed binary now declare cac directly. PR created with the help of an agent.
1 parent ed42a4a commit 35e6c0f

20 files changed

Lines changed: 100 additions & 38 deletions

File tree

‎docs/adapters/cli.md‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ outline: deep
66

77
The CLI adapter wraps a `DevframeDefinition` in a `cac`-powered command-line interface. From one entry it spins up an `h3` dev server with WebSocket RPC, builds static snapshots, builds SPA bundles, or starts an MCP server.
88

9+
`cac` is an optional peer dependency, pulled in only through this adapter — install it alongside `devframe` to opt into `createCli`:
10+
11+
```sh
12+
npm install devframe cac
13+
```
14+
15+
Tools that assemble their own command-line shell from the [lower-level factories](#use-your-own-cli-framework) never import this adapter, so they run without `cac`.
16+
917
```ts
1018
import { defineDevframe } from 'devframe'
1119
import { createCli } from 'devframe/adapters/cli'
@@ -105,6 +113,6 @@ To integrate devframe into an existing commander / yargs program — or to expos
105113
| [`createDevServer(def, opts?)`](./dev) | `devframe/adapters/dev` | h3 + WebSocket RPC + SPA mount |
106114
| [`createBuild(def, opts?)`](./build) | `devframe/adapters/build` | Static deploy |
107115
| [`createMcpServer(def, opts?)`](./mcp) | `devframe/adapters/mcp` | stdio MCP server |
108-
| `parseCliFlags(schema, raw)` | `devframe/adapters/cli` | Validate a flag bag against a `CliFlagsSchema` |
116+
| `parseCliFlags(schema, raw)` | `devframe/adapters/flags` | Validate a flag bag against a `CliFlagsSchema` (no `cac` required) |
109117

110118
See the [Standalone CLI guide](/guide/standalone-cli#use-your-own-cli-framework) for a worked commander example.

‎docs/adapters/index.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ outline: deep
66

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

9-
Every adapter factory has the shape `createXxx(devframeDef, options?)`.
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: `cli` pulls in [`cac`](https://github.com/cacjs/cac), and `mcp` pulls in [`@modelcontextprotocol/sdk`](https://github.com/modelcontextprotocol/typescript-sdk).
1010

1111
## Comparison
1212

‎docs/guide/standalone-cli.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ await program.parseAsync()
342342

343343
`createDevServer` returns the underlying `StartedServer` handle (`origin`, `port`, `app`, `ws`, `rpcGroup`, `connectionMeta()`, `close()`) so the surrounding program can drive graceful shutdown — SIGINT, hot reload, integration tests.
344344

345-
For typed flag schemas, `parseCliFlags(schema, rawBag)` (from `devframe/adapters/cli`) validates a commander/yargs flag bag against a `CliFlagsSchema` (the same `defineCliFlags(...)` value you'd put on `cli.flags`). Typed-schema validation works with any CLI framework.
345+
For typed flag schemas, `parseCliFlags(schema, rawBag)` (from `devframe/adapters/flags`) validates a commander/yargs flag bag against a `CliFlagsSchema` (the same `defineCliFlags(...)` value you'd put on `cli.flags`). This entry carries no `cac` dependency, so typed-schema validation works with any CLI framework.
346346

347347
## Why this shape
348348

‎examples/files-inspector/package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
},
1919
"dependencies": {
2020
"@antfu/design": "catalog:frontend",
21+
"cac": "catalog:deps",
2122
"colorjs.io": "catalog:frontend",
2223
"devframe": "workspace:*",
2324
"preact": "catalog:frontend",

‎examples/next-runtime-snapshot/package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
},
2020
"dependencies": {
2121
"@antfu/design": "catalog:frontend",
22+
"cac": "catalog:deps",
2223
"colorjs.io": "catalog:frontend",
2324
"devframe": "workspace:*",
2425
"next": "catalog:frontend",

‎examples/streaming-chat/package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
},
1919
"dependencies": {
2020
"@antfu/design": "catalog:frontend",
21+
"cac": "catalog:deps",
2122
"colorjs.io": "catalog:frontend",
2223
"devframe": "workspace:*",
2324
"preact": "catalog:frontend"

‎packages/devframe/package.json‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"./adapters/cli": "./dist/adapters/cli.mjs",
2525
"./adapters/dev": "./dist/adapters/dev.mjs",
2626
"./adapters/embedded": "./dist/adapters/embedded.mjs",
27+
"./adapters/flags": "./dist/adapters/flags.mjs",
2728
"./adapters/mcp": "./dist/adapters/mcp.mjs",
2829
"./client": "./dist/client/index.mjs",
2930
"./constants": "./dist/constants.mjs",
@@ -68,17 +69,20 @@
6869
"prepack": "pnpm build && mkdir -p ./skills && cp -r ../../skills/devframe ./skills/devframe"
6970
},
7071
"peerDependencies": {
71-
"@modelcontextprotocol/sdk": "^1.0.0"
72+
"@modelcontextprotocol/sdk": "^1.0.0",
73+
"cac": "^7.0.0"
7274
},
7375
"peerDependenciesMeta": {
7476
"@modelcontextprotocol/sdk": {
7577
"optional": true
78+
},
79+
"cac": {
80+
"optional": true
7681
}
7782
},
7883
"dependencies": {
7984
"@valibot/to-json-schema": "catalog:deps",
8085
"birpc": "catalog:deps",
81-
"cac": "catalog:deps",
8286
"crossws": "catalog:deps",
8387
"destr": "catalog:deps",
8488
"h3": "catalog:deps",
@@ -90,6 +94,7 @@
9094
},
9195
"devDependencies": {
9296
"@modelcontextprotocol/sdk": "catalog:deps",
97+
"cac": "catalog:deps",
9398
"get-port-please": "catalog:deps",
9499
"immer": "catalog:deps",
95100
"launch-editor": "catalog:deps",

‎packages/devframe/src/adapters/cli.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
// The `cac` command-line framework is an optional peer dependency: it's
2+
// only pulled in through this adapter entry, so tools that assemble their
3+
// own CLI from the lower-level `createDevServer` / `createBuild` /
4+
// `createMcpServer` factories never need it installed. Install `cac`
5+
// alongside `devframe` to opt into `createCli`; importing this entry
6+
// without it throws at load time with the usual Node module-not-found
7+
// error. The cac-independent flag helpers are re-exported below for
8+
// convenience, and also ship from the cac-free `devframe/adapters/flags`
9+
// entry for tools that only want typed-flag validation.
110
import type { CAC } from 'cac'
211
import type { H3 } from 'h3'
312
import type { DevframeDefinition } from '../types/devframe'

‎packages/devframe/tsdown.config.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ const serverEntries = {
8989
'utils/open': 'src/utils/open.ts',
9090
'utils/serve-static': 'src/utils/serve-static.ts',
9191
'adapters/cli': 'src/adapters/cli.ts',
92+
'adapters/flags': 'src/adapters/flags.ts',
9293
'adapters/dev': 'src/adapters/dev.ts',
9394
'adapters/build': 'src/adapters/build.ts',
9495
'adapters/embedded': 'src/adapters/embedded.ts',

‎plugins/a11y/package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
},
6464
"dependencies": {
6565
"axe-core": "catalog:frontend",
66+
"cac": "catalog:deps",
6667
"solid-js": "catalog:frontend"
6768
},
6869
"devDependencies": {

0 commit comments

Comments
 (0)