diff --git a/AGENTS.md b/AGENTS.md index f13c6404..a9809d72 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -62,7 +62,7 @@ These reinforce devframe's positioning as "the container for one devtool integra - **Headless by default.** No default startup banners, no opinionated logging to stdout, no default styling. Provide hooks (`onReady`, `cli.configure`, etc.); let the application print its own branding. Structured diagnostics via `nostics` are fine — ad-hoc `console.log`s baked into adapters are not. - **Mount path depends on adapter context.** Given `id: 'foo'`, the default mount path is `/__foo/` for *hosted* adapters (`vite`, `embedded`) and `/` for *standalone* adapters (`cli`, `spa`, `build`). Authors override via `DevframeDefinition.basePath`. Don't hardcode mount paths in adapter code paths that may run standalone. - **SPAs own their basePath at runtime.** Build SPAs with relative asset paths (`vite.base: './'`); discover the effective base in the browser from the executing script's location / `document.baseURI`. `createBuild` / `createSpa` copy SPA output verbatim — no HTML rewriting, no build-time `--base` injection. The client (`connectDevframe`) resolves `.connection.json` relative to the runtime base automatically. -- **CLI flags compose from both sides.** The `cac` instance backing `createCli` is exposed both to the `DevframeDefinition` (`cli.configure(cli)`) — for capabilities contributed by the tool itself — and to the `createCli` caller — for flags added at the final assembly stage. Parsed flag values are forwarded to `setup(ctx, { flags })`. Never hardcode domain-specific flags into `createCli`. +- **CLI flags compose from both sides.** The `cac` instance backing `createCac` is exposed both to the `DevframeDefinition` (`cli.configure(cli)`) — for capabilities contributed by the tool itself — and to the `createCac` caller — for flags added at the final assembly stage. Parsed flag values are forwarded to `setup(ctx, { flags })`. Never hardcode domain-specific flags into `createCac`. ## Structured Diagnostics (Error Codes) diff --git a/alias.ts b/alias.ts index cd8f234a..77aecb64 100644 --- a/alias.ts +++ b/alias.ts @@ -32,6 +32,7 @@ export const alias = { 'devframe/utils/streaming-channel': r('devframe/src/utils/streaming-channel.ts'), 'devframe/utils/structured-clone': r('devframe/src/utils/structured-clone.ts'), 'devframe/utils/when': r('devframe/src/utils/when.ts'), + 'devframe/adapters/cac': r('devframe/src/adapters/cac.ts'), 'devframe/adapters/cli': r('devframe/src/adapters/cli.ts'), 'devframe/adapters/dev': r('devframe/src/adapters/dev.ts'), 'devframe/adapters/build': r('devframe/src/adapters/build.ts'), diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 68658b5b..8f7a7d59 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -38,7 +38,7 @@ function guideItems(prefix: string) { function adaptersItems(prefix: string) { return [ { text: 'Overview', link: `${prefix}/adapters/` }, - { text: 'CLI', link: `${prefix}/adapters/cli` }, + { text: 'CLI (cac)', link: `${prefix}/adapters/cac` }, { text: 'Dev', link: `${prefix}/adapters/dev` }, { text: 'Build', link: `${prefix}/adapters/build` }, { text: 'Vite', link: `${prefix}/adapters/vite` }, diff --git a/docs/adapters/cli.md b/docs/adapters/cac.md similarity index 75% rename from docs/adapters/cli.md rename to docs/adapters/cac.md index 3e363f87..3a0d22f2 100644 --- a/docs/adapters/cli.md +++ b/docs/adapters/cac.md @@ -2,13 +2,21 @@ outline: deep --- -# CLI +# CLI (cac) -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. +The cac adapter wraps a `DevframeDefinition` in a [`cac`](https://github.com/cacjs/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. + +`cac` is an optional peer dependency, pulled in only through this adapter — install it alongside `devframe` to opt into `createCac`: + +```sh +npm install devframe cac +``` + +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`. ```ts import { defineDevframe } from 'devframe' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' const devframe = defineDevframe({ id: 'my-devframe', @@ -17,9 +25,11 @@ const devframe = defineDevframe({ setup(ctx) { /* register docks, RPC, etc. */ }, }) -await createCli(devframe).parse() +await createCac(devframe).parse() ``` +The `devframe/adapters/cli` entry (`createCli`) remains as a deprecated alias for this module — new code should import `createCac` from `devframe/adapters/cac`. + Running the resulting binary: ```sh @@ -34,7 +44,7 @@ Standalone CLI serves the SPA at `/` by default. The `/__devframe/` prefix is fo ## Options -`createCli(def, options?)` accepts: +`createCac(def, options?)` accepts: | Option | Default | Description | |--------|---------|-------------| @@ -42,10 +52,10 @@ Standalone CLI serves the SPA at `/` by default. The `/__devframe/` prefix is fo | `configureCli` | — | `(cli: CAC) => void` — final hook to add commands/flags at the assembly stage, after the definition's `cli.configure` runs. | | `onReady` | — | `(info: { origin, port, app }) => void \| Promise` — called once the dev server is listening. Use this to print your own startup banner. | -`createCli` returns a `CliHandle`: +`createCac` returns a `CacHandle`: ```ts -interface CliHandle { +interface CacHandle { cli: CAC // raw cac instance — mutate before calling parse() parse: (argv?: string[]) => Promise } @@ -80,14 +90,14 @@ defineDevframe({ }) ``` -`distDir` is the only required field; everything else has sensible defaults. The `configure` hook runs *before* the `configureCli` option passed to `createCli`, so the final tool author always has the last word on flags. +`distDir` is the only required field; everything else has sensible defaults. The `configure` hook runs *before* the `configureCli` option passed to `createCac`, so the final tool author always has the last word on flags. ## Headless logging Devframe leaves startup output to the application. Wire `onReady` to print your own banner: ```ts -await createCli(devframe, { +await createCac(devframe, { onReady({ origin }) { console.log(`ESLint Config Inspector ready at ${origin}`) }, @@ -98,13 +108,13 @@ Structured diagnostics (via `nostics`) continue to surface through their normal ## Use your own CLI framework -To integrate devframe into an existing commander / yargs program — or to expose a different command structure than `createCli`'s `dev` / `build` / `mcp` triplet — drop down to the peer factories. Same `DevframeDefinition`, different shell: +To integrate devframe into an existing commander / yargs program — or to expose a different command structure than `createCac`'s `dev` / `build` / `mcp` triplet — drop down to the peer factories. Same `DevframeDefinition`, different shell: | Building block | Entry | Purpose | |----------------|-------|---------| | [`createDevServer(def, opts?)`](./dev) | `devframe/adapters/dev` | h3 + WebSocket RPC + SPA mount | | [`createBuild(def, opts?)`](./build) | `devframe/adapters/build` | Static deploy | | [`createMcpServer(def, opts?)`](./mcp) | `devframe/adapters/mcp` | stdio MCP server | -| `parseCliFlags(schema, raw)` | `devframe/adapters/cli` | Validate a flag bag against a `CliFlagsSchema` | +| `parseCliFlags(schema, raw)` | `devframe/adapters/cac` | Validate a flag bag against a `CliFlagsSchema` | See the [Standalone CLI guide](/guide/standalone-cli#use-your-own-cli-framework) for a worked commander example. diff --git a/docs/adapters/dev.md b/docs/adapters/dev.md index 727509a1..ebc1b5ab 100644 --- a/docs/adapters/dev.md +++ b/docs/adapters/dev.md @@ -4,7 +4,7 @@ outline: deep # Dev -The `dev` adapter is the building block `createCli` uses internally — h3 + WebSocket RPC + the author's SPA mounted at the resolved base path. Reach for it directly to mount the dev server inside an existing CLI program (commander, yargs, hand-rolled CAC) or to attach custom middleware to the underlying h3 app. +The `dev` adapter is the building block `createCac` uses internally — h3 + WebSocket RPC + the author's SPA mounted at the resolved base path. Reach for it directly to mount the dev server inside an existing CLI program (commander, yargs, hand-rolled CAC) or to attach custom middleware to the underlying h3 app. ```ts import { createDevServer } from 'devframe/adapters/dev' diff --git a/docs/adapters/index.md b/docs/adapters/index.md index 958c4a5f..30dd58e4 100644 --- a/docs/adapters/index.md +++ b/docs/adapters/index.md @@ -6,13 +6,13 @@ outline: deep 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/`); the bundler pulls in only the ones you use. -Every adapter factory has the shape `createXxx(devframeDef, options?)`. +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/sdk`](https://github.com/modelcontextprotocol/typescript-sdk). ## Comparison | Adapter | Entry | Factory | Best for | |---------|-------|---------|----------| -| [`cli`](./cli) | `devframe/adapters/cli` | `createCli(def, options?)` | Standalone tools run via `node ./my-tool.js` | +| [`cac`](./cac) | `devframe/adapters/cac` | `createCac(def, options?)` | Standalone tools run via `node ./my-tool.js` | | [`dev`](./dev) | `devframe/adapters/dev` | `createDevServer(def, options?)` | Run the dev server programmatically — drive it from any CLI framework | | [`build`](./build) | `devframe/adapters/build` | `createBuild(def, options?)` | Offline reports, CI artifacts, deployable SPA snapshots | | [`vite`](./vite) | `@vitejs/devtools-kit/node` | `createPluginFromDevframe(def, options?)` | Mount the definition into Vite DevTools (or any compatible host) | diff --git a/docs/guide/client.md b/docs/guide/client.md index facad417..26a64d7b 100644 --- a/docs/guide/client.md +++ b/docs/guide/client.md @@ -59,7 +59,7 @@ The client runs in one of two modes depending on the backend advertised in `__de | Backend | When | Capabilities | |---------|------|--------------| -| `websocket` | Dev mode (`createCli`, Kit) | Full read/write, broadcasts, shared-state mutation. Requires auth. | +| `websocket` | Dev mode (`createCac`, Kit) | Full read/write, broadcasts, shared-state mutation. Requires auth. | | `static` | Build / SPA output | Read-only — all calls resolve against the baked RPC dump. | The client picks a mode automatically from the backend field. Mode-specific code paths like `broadcast` are scoped to `websocket`. diff --git a/docs/guide/devframe-definition.md b/docs/guide/devframe-definition.md index bc9f27de..32804192 100644 --- a/docs/guide/devframe-definition.md +++ b/docs/guide/devframe-definition.md @@ -4,7 +4,7 @@ outline: deep # Devframe Definition -Every Devframe tool starts with a single `defineDevframe` call. The returned `DevframeDefinition` is a portable value that any of the [adapters](/adapters/) can consume — the same definition runs under `createCli`, `createBuild`, `createMcpServer`, the `vite` adapter's `createPluginFromDevframe`, and so on. +Every Devframe tool starts with a single `defineDevframe` call. The returned `DevframeDefinition` is a portable value that any of the [adapters](/adapters/) can consume — the same definition runs under `createCac`, `createBuild`, `createMcpServer`, the `vite` adapter's `createPluginFromDevframe`, and so on. ## Minimal definition @@ -51,7 +51,7 @@ export default defineDevframe({ | `basePath` | `string` | Optional mount path override. Defaults depend on the adapter: `/` for standalone (`cli` / `spa` / `build`), `/./` for hosted (`vite` / `embedded`). | | `duplicationStrategy` | `'warn' \| 'silent' \| 'throw' \| 'duplicate'` | How a hub reacts when another devframe sharing this `id` is mounted onto the same hub. Defaults to `'warn'`. See [Hub](./hub). Hub adapters consult it; standalone adapters ignore it. | | `capabilities` | `{ dev?, build?, spa? }` | Per-runtime feature flags. A `boolean` applies to the runtime as a whole; an object enables individual features. | -| `setup` | `(ctx, info?) => void \| Promise` | **Required.** Server-side entry point. Runs in every runtime. The optional second argument carries runtime metadata — most notably the parsed CLI `flags` when running under `createCli`. | +| `setup` | `(ctx, info?) => void \| Promise` | **Required.** Server-side entry point. Runs in every runtime. The optional second argument carries runtime metadata — most notably the parsed CLI `flags` when running under `createCac`. | | `setupBrowser` | `(ctx) => void \| Promise` | Browser-only entry used by the SPA adapter. | | `cli` | `DevframeCliOptions` | Defaults for the CLI adapter. See [CLI options](#cli-options) below. | | `spa` | `DevframeSpaOptions` | Defaults for the SPA adapter (`base`, `loader`). | @@ -185,7 +185,7 @@ defineDevframe({ | `host` | `string` | Default bind host. | | `open` | `boolean \| string` | `true` opens the origin, a string opens a specific path, `false` disables. Matches the `--open` / `--no-open` flags. | | `auth` | `boolean` | Disable the WS trust flow when the tool is localhost-only and single-user. Default `true`. | -| `configure` | `(cli: CAC) => void` | Contribute capability flags/commands. Runs before `createCli`'s `configureCli` option so the final tool author always has the last word. | +| `configure` | `(cli: CAC) => void` | Contribute capability flags/commands. Runs before `createCac`'s `configureCli` option so the final tool author always has the last word. | `setup(ctx, info)` receives `info.flags` populated from both devframe's built-in flags and any you declared via `configure` — saves duplicating flag parsing. @@ -210,12 +210,12 @@ The definition is a plain value, so wire it into multiple adapters from the same ```ts import { createPluginFromDevframe } from '@vitejs/devtools-kit/node' import { createBuild } from 'devframe/adapters/build' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' const devframe = defineDevframe({ id: 'my-devframe', name: 'My Devframe', setup() {} }) // 1. Standalone CLI: -await createCli(devframe).parse() +await createCac(devframe).parse() // 2. Offline snapshot: await createBuild(devframe, { outDir: 'dist-static' }) diff --git a/docs/guide/index.md b/docs/guide/index.md index 99447841..fc13211d 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -17,7 +17,7 @@ Devframe keeps its surface focused on one tool, so the same definition stays por - **App-owned file watching.** Wire your own watcher (chokidar, fs.watch, …) and signal change via `ctx.rpc.sharedState.set(...)` or event-typed RPCs. - **Context-aware mount paths.** Standalone adapters (`cli`, `spa`, `build`) serve at `/` by default; hosted adapters (`vite`, `embedded`) serve at `/./`. Override via `DevframeDefinition.basePath`. - **SPAs own their base at runtime.** Build with relative asset paths (`vite.base: './'`); `connectDevframe` discovers the effective base from the executing script's location. -- **CLI flags compose.** The `cac` instance is exposed to both the devframe (`cli.configure`) and the caller of `createCli`, so capability flags and app flags merge cleanly. +- **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. ## What Devframe provides @@ -47,7 +47,7 @@ A minimal devframe with a CLI entry point: ```ts twoslash import { defineDevframe, defineRpcFunction } from 'devframe' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' const devframe = defineDevframe({ id: 'my-devframe', @@ -70,7 +70,7 @@ const devframe = defineDevframe({ }, }) -await createCli(devframe).parse() +await createCac(devframe).parse() ``` The same definition can also be deployed through any of the other adapters — for example, mounted into Vite DevTools via the [`vite` adapter](/adapters/vite). @@ -91,7 +91,7 @@ Devframe deploys the same `DevframeDefinition` through one of these adapters: | Adapter | Entry | Target | |---------|-------|--------| -| `cli` | `createCli(d).parse()` | Standalone CLI with dev / build / mcp subcommands | +| `cli` | `createCac(d).parse()` | Standalone CLI with dev / build / mcp subcommands | | `vite` | `createPluginFromDevframe(d, opts?)` *(from `@vitejs/devtools-kit/node`)* | Mount the devframe into Vite DevTools (or another compatible host) | | `build` | `createBuild(d, opts?)` | Self-contained static deploy with baked RPC dumps | | `embedded` | `createEmbedded(d, { ctx })` | Runtime registration into an existing host | diff --git a/docs/guide/standalone-cli.md b/docs/guide/standalone-cli.md index fc1cff65..f641745e 100644 --- a/docs/guide/standalone-cli.md +++ b/docs/guide/standalone-cli.md @@ -14,7 +14,7 @@ It's the pattern used by tools like an ESLint config inspector or a bundler-conf my-tool/ ├── bin.mjs # shebang + import './dist/cli.mjs' ├── src/ -│ ├── cli.ts # defineDevframe + createCli +│ ├── cli.ts # defineDevframe + createCac │ ├── rpc.ts # your RPC function definitions │ └── data.ts # your domain-specific logic ├── app/ # Nuxt / Vue / React SPA source @@ -29,7 +29,7 @@ my-tool/ ```ts [src/cli.ts] import process from 'node:process' import { defineDevframe, defineRpcFunction } from 'devframe' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' import { colors as c } from 'devframe/utils/colors' import { resolve } from 'pathe' @@ -66,7 +66,7 @@ const devframe = defineDevframe({ }, }) -await createCli(devframe, { +await createCac(devframe, { onReady({ origin }) { console.log(c.green`My Tool ready at ${origin}`) }, @@ -94,7 +94,7 @@ export default defineNuxtConfig({ modules: ['@devframes/nuxt'], nitro: { preset: 'static', - output: { dir: './dist' }, // matches createCli's distDir of ./dist/public + output: { dir: './dist' }, // matches createCac's distDir of ./dist/public }, }) ``` @@ -172,9 +172,9 @@ const payload = await my.rpc.call('get-payload') For flags that are specific to your tool, declare them as valibot schemas so they're validated at parse time and typed at the call site: ```ts -import type { InferCliFlags } from 'devframe/adapters/cli' +import type { InferCliFlags } from 'devframe/adapters/cac' import { defineDevframe } from 'devframe' -import { defineCliFlags } from 'devframe/adapters/cli' +import { defineCliFlags } from 'devframe/adapters/cac' import * as v from 'valibot' const appFlags = defineCliFlags({ @@ -293,7 +293,7 @@ version.on('updated', () => fetchPayload().then(setData)) ## Use your own CLI framework -`createCli` is a convenience wrapper around three lower-level factories — reach for them directly when you already own a CLI framework (commander, yargs, oclif, hand-rolled cac) or want a different command structure: +`createCac` is a convenience wrapper around three lower-level factories — reach for them directly when you already own a CLI framework (commander, yargs, oclif, hand-rolled cac) or want a different command structure: | Building block | Entry | |----------------|-------| @@ -301,7 +301,7 @@ version.on('updated', () => fetchPayload().then(setData)) | `createBuild(def, opts?)` | `devframe/adapters/build` | | `createMcpServer(def, opts?)` | `devframe/adapters/mcp` | -Each one runs against the same `DevframeDefinition` you'd pass to `createCli`. A commander example: +Each one runs against the same `DevframeDefinition` you'd pass to `createCac`. A commander example: ```ts [src/cli.ts] import process from 'node:process' @@ -342,11 +342,11 @@ await program.parseAsync() `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. -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. +For typed flag schemas, `parseCliFlags(schema, rawBag)` (from `devframe/adapters/cac`) validates a commander/yargs flag bag against a `CliFlagsSchema` (the same `defineCliFlags(...)` value you'd put on `cli.flags`). The helper is framework-agnostic, so typed-schema validation works with any CLI framework. ## Why this shape -- **One command, one binary.** `createCli` is a complete CLI — dev, build, spa, mcp all from a single `defineDevframe` value. +- **One command, one binary.** `createCac` is a complete CLI — dev, build, spa, mcp all from a single `defineDevframe` value. - **Headless.** Your `onReady` callback owns startup output, so your tool's stdout stays yours. - **Base-agnostic.** Same SPA build works at `/` (dev, standalone static) and at any deployment base. - **Typed end-to-end.** RPC function definitions flow their types through to the client `rpc.call` site. @@ -355,7 +355,7 @@ For typed flag schemas, `parseCliFlags(schema, rawBag)` (from `devframe/adapters ## See also - [Devframe Definition](./devframe-definition) — field reference -- [Adapters → CLI](/adapters/cli) — full CLI adapter reference including `configureCli` and mount-path rules +- [Adapters → CLI (cac)](/adapters/cac) — full CLI adapter reference including `configureCli` and mount-path rules - [Adapters → Dev](/adapters/dev) — `createDevServer` reference for bring-your-own-CLI integration - [Client](./client) — `connectDevframe`, shared state, caching - [Agent-Native](./agent-native) — exposing your tool to Claude Desktop, Cursor, etc. diff --git a/docs/helpers/nuxt.md b/docs/helpers/nuxt.md index e70da892..6fac8504 100644 --- a/docs/helpers/nuxt.md +++ b/docs/helpers/nuxt.md @@ -96,13 +96,13 @@ export default defineNuxtConfig({ - **`host`** controls the bridge bind host. Defaults to `nuxt.options.devServer.host ?? devframe.cli?.host ?? 'localhost'`, so `nuxt dev --host` propagates automatically. Set this manually when your Nuxt server config doesn't surface `host` (e.g. custom listen options). - **`flags`** is forwarded to `devframe.setup(ctx, { flags })`. Use it to pass env-derived configuration into the RPC layer. -### Relationship to `createCli` +### Relationship to `createCac` -The bridge handles the **dev workflow**. Production deploys still go through `createCli` (or `createBuild`), which produces a static `__connection.json` + `__rpc-dump/` snapshot from `cli.distDir`: +The bridge handles the **dev workflow**. Production deploys still go through `createCac` (or `createBuild`), which produces a static `__connection.json` + `__rpc-dump/` snapshot from `cli.distDir`: ``` my-tool/ -├── bin.mjs # createCli(devframe).parse() +├── bin.mjs # createCac(devframe).parse() ├── src/ │ ├── devframe.ts # defineDevframe + setup(ctx) { ctx.rpc.register(...) } │ └── app/ # Nuxt SPA — uses `@devframes/nuxt` diff --git a/docs/plugins/git.md b/docs/plugins/git.md index 85e319e2..ba7938c6 100644 --- a/docs/plugins/git.md +++ b/docs/plugins/git.md @@ -26,9 +26,9 @@ npx @devframes/plugin-git build # static deploy → dist-static/ ```ts import { createGitDevframe } from '@devframes/plugin-git' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' -await createCli(createGitDevframe({ repoRoot: process.cwd() })).parse() +await createCac(createGitDevframe({ repoRoot: process.cwd() })).parse() ``` | Option | Default | Description | diff --git a/docs/plugins/inspect.md b/docs/plugins/inspect.md index ddf68ea4..23a68f90 100644 --- a/docs/plugins/inspect.md +++ b/docs/plugins/inspect.md @@ -45,9 +45,9 @@ export default defineConfig({ ```ts import { createInspectDevframe } from '@devframes/plugin-inspect' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' -await createCli(createInspectDevframe({ port: 9100 })).parse() +await createCac(createInspectDevframe({ port: 9100 })).parse() ``` ## RPC surface diff --git a/examples/files-inspector/README.md b/examples/files-inspector/README.md index 1c59ad2d..5057ab44 100644 --- a/examples/files-inspector/README.md +++ b/examples/files-inspector/README.md @@ -27,5 +27,5 @@ pnpm -C examples/files-inspector run test # E2E tests |------|---------| | `src/devframe.ts` | The single `DevframeDefinition` consumed by every adapter. | | `src/client/` | Preact SPA: `index.html`, `main.tsx`, `app.tsx`, `routes/*`, `vite.config.ts`. | -| `bin.mjs` | `createCli(devframe).parse()` — exposes `dev`, `build`, `spa`, `mcp`. | +| `bin.mjs` | `createCac(devframe).parse()` — exposes `dev`, `build`, `spa`, `mcp`. | | `tests/` | E2E tests for CLI dev server and static build. | diff --git a/examples/files-inspector/bin.mjs b/examples/files-inspector/bin.mjs index e760d992..d35b5779 100755 --- a/examples/files-inspector/bin.mjs +++ b/examples/files-inspector/bin.mjs @@ -1,10 +1,10 @@ #!/usr/bin/env node import process from 'node:process' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' import devframe from './src/devframe.ts' async function main() { - const cli = createCli(devframe) + const cli = createCac(devframe) await cli.parse() } diff --git a/examples/files-inspector/package.json b/examples/files-inspector/package.json index 9454b917..0f7151df 100644 --- a/examples/files-inspector/package.json +++ b/examples/files-inspector/package.json @@ -18,6 +18,7 @@ }, "dependencies": { "@antfu/design": "catalog:frontend", + "cac": "catalog:deps", "colorjs.io": "catalog:frontend", "devframe": "workspace:*", "preact": "catalog:frontend", diff --git a/examples/next-runtime-snapshot/bin.mjs b/examples/next-runtime-snapshot/bin.mjs index e760d992..d35b5779 100755 --- a/examples/next-runtime-snapshot/bin.mjs +++ b/examples/next-runtime-snapshot/bin.mjs @@ -1,10 +1,10 @@ #!/usr/bin/env node import process from 'node:process' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' import devframe from './src/devframe.ts' async function main() { - const cli = createCli(devframe) + const cli = createCac(devframe) await cli.parse() } diff --git a/examples/next-runtime-snapshot/package.json b/examples/next-runtime-snapshot/package.json index 218b9026..2871b0fe 100644 --- a/examples/next-runtime-snapshot/package.json +++ b/examples/next-runtime-snapshot/package.json @@ -19,6 +19,7 @@ }, "dependencies": { "@antfu/design": "catalog:frontend", + "cac": "catalog:deps", "colorjs.io": "catalog:frontend", "devframe": "workspace:*", "next": "catalog:frontend", diff --git a/examples/streaming-chat/bin.mjs b/examples/streaming-chat/bin.mjs index e760d992..d35b5779 100755 --- a/examples/streaming-chat/bin.mjs +++ b/examples/streaming-chat/bin.mjs @@ -1,10 +1,10 @@ #!/usr/bin/env node import process from 'node:process' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' import devframe from './src/devframe.ts' async function main() { - const cli = createCli(devframe) + const cli = createCac(devframe) await cli.parse() } diff --git a/examples/streaming-chat/package.json b/examples/streaming-chat/package.json index 6df526cd..a6874b90 100644 --- a/examples/streaming-chat/package.json +++ b/examples/streaming-chat/package.json @@ -18,6 +18,7 @@ }, "dependencies": { "@antfu/design": "catalog:frontend", + "cac": "catalog:deps", "colorjs.io": "catalog:frontend", "devframe": "workspace:*", "preact": "catalog:frontend" diff --git a/packages/devframe/package.json b/packages/devframe/package.json index 67498765..2bdce82e 100644 --- a/packages/devframe/package.json +++ b/packages/devframe/package.json @@ -21,6 +21,7 @@ "exports": { ".": "./dist/index.mjs", "./adapters/build": "./dist/adapters/build.mjs", + "./adapters/cac": "./dist/adapters/cac.mjs", "./adapters/cli": "./dist/adapters/cli.mjs", "./adapters/dev": "./dist/adapters/dev.mjs", "./adapters/embedded": "./dist/adapters/embedded.mjs", @@ -68,17 +69,20 @@ "prepack": "pnpm build && mkdir -p ./skills && cp -r ../../skills/devframe ./skills/devframe" }, "peerDependencies": { - "@modelcontextprotocol/sdk": "^1.0.0" + "@modelcontextprotocol/sdk": "^1.0.0", + "cac": "^7.0.0" }, "peerDependenciesMeta": { "@modelcontextprotocol/sdk": { "optional": true + }, + "cac": { + "optional": true } }, "dependencies": { "@valibot/to-json-schema": "catalog:deps", "birpc": "catalog:deps", - "cac": "catalog:deps", "crossws": "catalog:deps", "destr": "catalog:deps", "h3": "catalog:deps", @@ -90,6 +94,7 @@ }, "devDependencies": { "@modelcontextprotocol/sdk": "catalog:deps", + "cac": "catalog:deps", "get-port-please": "catalog:deps", "immer": "catalog:deps", "launch-editor": "catalog:deps", diff --git a/packages/devframe/src/adapters/cac.ts b/packages/devframe/src/adapters/cac.ts new file mode 100644 index 00000000..804cab35 --- /dev/null +++ b/packages/devframe/src/adapters/cac.ts @@ -0,0 +1,165 @@ +// The `cac` command-line framework is an optional peer dependency: it's +// only pulled in through this adapter entry, so tools that assemble their +// own CLI from the lower-level `createDevServer` / `createBuild` / +// `createMcpServer` factories never need it installed. Install `cac` +// alongside `devframe` to opt into `createCac`; importing this entry +// without it throws at load time with the usual Node module-not-found +// error. The typed-flag helpers (`defineCliFlags` / `parseCliFlags`) are +// re-exported below so they live alongside the CLI adapter. +// +// The historical `devframe/adapters/cli` entry (`createCli`) re-exports +// this module under deprecated aliases for backward compatibility. +import type { CAC } from 'cac' +import type { H3 } from 'h3' +import type { DevframeDefinition } from '../types/devframe' +import process from 'node:process' +import cac from 'cac' +import { colors as c } from 'devframe/utils/colors' +import { createBuild } from './build' +import { createDevServer, resolveDevServerPort } from './dev' +import { flagKeyToOption, isBooleanFlag, parseCliFlags } from './flags' + +export { defineCliFlags, parseCliFlags } from './flags' +export type { CliFlagsSchema, InferCliFlags } from './flags' + +export interface CreateCacOptions { + /** Default port for `dev` (default: 9999). */ + defaultPort?: number + /** + * Final CAC hook invoked after devframe's built-in subcommands and + * after the definition's `cli.configure`. Use this to add app-level + * flags and commands at the assembly stage. + */ + configureCli?: (cli: CAC) => void + /** + * Called once the dev server is listening. Use this to print a + * startup banner or trigger side-effects that depend on the live URL. + */ + onReady?: (info: { origin: string, port: number, app: H3 }) => void | Promise +} + +export interface CacHandle { + /** + * Raw CAC instance. Mutate before calling `parse()` for last-mile + * flag or command additions that don't fit `configureCli`. + */ + cli: CAC + parse: (argv?: string[]) => Promise +} + +/** + * Wrap a {@link DevframeDefinition} in a `cac`-powered command-line + * interface exposing `dev` / `build` / `mcp` subcommands. + * + * Requires the optional `cac` peer dependency. + */ +export function createCac(d: DevframeDefinition, options: CreateCacOptions = {}): CacHandle { + const defaultPort = options.defaultPort ?? d.cli?.port ?? 9999 + const defaultHost = d.cli?.host ?? 'localhost' + const command = d.cli?.command ?? d.id + + const cli = cac(command) + + const devCommand = cli + .command('[...args]', 'Start a local dev server') + .option('--port ', 'Port to listen on') + .option('--host ', 'Host to bind to', { default: defaultHost }) + .option('--open', 'Open the browser on start') + .option('--no-open', 'Do not open the browser') + // Only `--mcp` is declared: CAC's `--no-*` auto-negation would inject a + // `true` default, silently enabling MCP. Declaring just `--mcp` yields the + // opt-in tri-state — absent → `undefined` (falls through to `cli.mcp`), + // `--mcp` → `true`, `--no-mcp` → `false` (handled by CAC's `--no-` prefix). + .option('--mcp', 'Expose an MCP server over HTTP at /__mcp (use --no-mcp to disable) [experimental]') + + // Register typed flags from the definition ahead of `cli.configure` + // so authors can still override or augment via the escape hatch. + if (d.cli?.flags) { + for (const [key, schema] of Object.entries(d.cli.flags)) { + const optionName = flagKeyToOption(key) + const description = (schema as any).description ?? '' + if (isBooleanFlag(schema)) { + devCommand.option(`--${optionName}`, description) + } + else { + devCommand.option(`--${optionName} `, description) + } + } + } + + devCommand.action(async (_args: unknown, rawFlags: CliFlags) => { + const flags = resolveTypedFlags(d, rawFlags) as CliFlags + const host = (flags.host as string | undefined) ?? defaultHost + const port = (flags.port as number | undefined) ?? await resolveDevServerPort(d, { host, defaultPort }) + // `--mcp` / `--no-mcp` map to a boolean override; when neither is + // passed CAC leaves `mcp` undefined so `createDevServer` falls through + // to `def.cli?.mcp`. + const mcp = flags.mcp as boolean | undefined + await createDevServer(d, { + host, + port, + flags, + mcp, + onReady: options.onReady, + }) + }) + + cli + .command('build', 'Build a self-contained static deploy of the devframe') + .option('--out-dir ', 'Output directory', { default: 'dist-static' }) + .option('--base ', 'URL base', { default: '/' }) + .option('--pretty', 'Pretty-print dump JSON (larger on disk)') + .action(async (flags: { outDir: string, base?: string, pretty?: boolean }) => { + await createBuild(d, { outDir: flags.outDir, base: flags.base, pretty: flags.pretty }) + }) + + cli + .command('mcp', 'Start an MCP server exposing agent-facing tools (stdio) [experimental]') + .action(async () => { + // MCP clients expect JSON-RPC on stdout — route welcome/logging + // noise out of the way. Logs-SDK diagnostics land on stderr by + // default, so nothing extra needed beyond not printing here. + const { createMcpServer } = await import('./mcp') + await createMcpServer(d, { + transport: 'stdio', + // Deliberately go to stderr: stdout is the MCP transport. + onReady: ({ transport }) => { + console.error(`[devframe] "${d.id}" MCP server ready (${transport})`) + }, + }) + }) + + // Definition-level capability hook first, then assembly-level hook. + d.cli?.configure?.(cli) + options.configureCli?.(cli) + + cli.help() + cli.version('0.0.0') + + return { + cli, + async parse(argv = process.argv) { + cli.parse(argv, { run: false }) + await cli.runMatchedCommand() + }, + } +} + +interface CliFlags { + host?: string + port?: number + open?: boolean + [key: string]: unknown +} + +function resolveTypedFlags(d: DevframeDefinition, raw: Record): Record { + if (!d.cli?.flags) + return raw + const { flags, issues } = parseCliFlags(d.cli.flags, raw) + if (issues?.length) { + for (const issue of issues) + console.error(c.red`[devframe] invalid flag — ${issue}`) + process.exit(1) + } + return flags +} diff --git a/packages/devframe/src/adapters/cli.ts b/packages/devframe/src/adapters/cli.ts index a1f0a79c..bebadd05 100644 --- a/packages/devframe/src/adapters/cli.ts +++ b/packages/devframe/src/adapters/cli.ts @@ -1,148 +1,20 @@ -import type { CAC } from 'cac' -import type { H3 } from 'h3' -import type { DevframeDefinition } from '../types/devframe' -import process from 'node:process' -import cac from 'cac' -import { colors as c } from 'devframe/utils/colors' -import { createBuild } from './build' -import { createDevServer, resolveDevServerPort } from './dev' -import { flagKeyToOption, isBooleanFlag, parseCliFlags } from './flags' +// Deprecated compatibility shim for the cac adapter. +// +// Prefer the canonical `devframe/adapters/cac` entry (`createCac`). This +// module re-exports the same implementation under the historical `cli` +// names so existing imports keep working. It will be removed in a future +// major release. +import type { CacHandle, CreateCacOptions } from './cac' +import { createCac } from './cac' export { defineCliFlags, parseCliFlags } from './flags' export type { CliFlagsSchema, InferCliFlags } from './flags' -export interface CreateCliOptions { - /** Default port for `dev` (default: 9999). */ - defaultPort?: number - /** - * Final CAC hook invoked after devframe's built-in subcommands and - * after the definition's `cli.configure`. Use this to add app-level - * flags and commands at the assembly stage. - */ - configureCli?: (cli: CAC) => void - /** - * Called once the dev server is listening. Use this to print a - * startup banner or trigger side-effects that depend on the live URL. - */ - onReady?: (info: { origin: string, port: number, app: H3 }) => void | Promise -} +/** @deprecated Use `createCac` from `devframe/adapters/cac` instead. */ +export const createCli: typeof createCac = createCac -export interface CliHandle { - /** - * Raw CAC instance. Mutate before calling `parse()` for last-mile - * flag or command additions that don't fit `configureCli`. - */ - cli: CAC - parse: (argv?: string[]) => Promise -} +/** @deprecated Use `CreateCacOptions` from `devframe/adapters/cac` instead. */ +export type CreateCliOptions = CreateCacOptions -export function createCli(d: DevframeDefinition, options: CreateCliOptions = {}): CliHandle { - const defaultPort = options.defaultPort ?? d.cli?.port ?? 9999 - const defaultHost = d.cli?.host ?? 'localhost' - const command = d.cli?.command ?? d.id - - const cli = cac(command) - - const devCommand = cli - .command('[...args]', 'Start a local dev server') - .option('--port ', 'Port to listen on') - .option('--host ', 'Host to bind to', { default: defaultHost }) - .option('--open', 'Open the browser on start') - .option('--no-open', 'Do not open the browser') - // Only `--mcp` is declared: CAC's `--no-*` auto-negation would inject a - // `true` default, silently enabling MCP. Declaring just `--mcp` yields the - // opt-in tri-state — absent → `undefined` (falls through to `cli.mcp`), - // `--mcp` → `true`, `--no-mcp` → `false` (handled by CAC's `--no-` prefix). - .option('--mcp', 'Expose an MCP server over HTTP at /__mcp (use --no-mcp to disable) [experimental]') - - // Register typed flags from the definition ahead of `cli.configure` - // so authors can still override or augment via the escape hatch. - if (d.cli?.flags) { - for (const [key, schema] of Object.entries(d.cli.flags)) { - const optionName = flagKeyToOption(key) - const description = (schema as any).description ?? '' - if (isBooleanFlag(schema)) { - devCommand.option(`--${optionName}`, description) - } - else { - devCommand.option(`--${optionName} `, description) - } - } - } - - devCommand.action(async (_args: unknown, rawFlags: CliFlags) => { - const flags = resolveTypedFlags(d, rawFlags) as CliFlags - const host = (flags.host as string | undefined) ?? defaultHost - const port = (flags.port as number | undefined) ?? await resolveDevServerPort(d, { host, defaultPort }) - // `--mcp` / `--no-mcp` map to a boolean override; when neither is - // passed CAC leaves `mcp` undefined so `createDevServer` falls through - // to `def.cli?.mcp`. - const mcp = flags.mcp as boolean | undefined - await createDevServer(d, { - host, - port, - flags, - mcp, - onReady: options.onReady, - }) - }) - - cli - .command('build', 'Build a self-contained static deploy of the devframe') - .option('--out-dir ', 'Output directory', { default: 'dist-static' }) - .option('--base ', 'URL base', { default: '/' }) - .option('--pretty', 'Pretty-print dump JSON (larger on disk)') - .action(async (flags: { outDir: string, base?: string, pretty?: boolean }) => { - await createBuild(d, { outDir: flags.outDir, base: flags.base, pretty: flags.pretty }) - }) - - cli - .command('mcp', 'Start an MCP server exposing agent-facing tools (stdio) [experimental]') - .action(async () => { - // MCP clients expect JSON-RPC on stdout — route welcome/logging - // noise out of the way. Logs-SDK diagnostics land on stderr by - // default, so nothing extra needed beyond not printing here. - const { createMcpServer } = await import('./mcp') - await createMcpServer(d, { - transport: 'stdio', - // Deliberately go to stderr: stdout is the MCP transport. - onReady: ({ transport }) => { - console.error(`[devframe] "${d.id}" MCP server ready (${transport})`) - }, - }) - }) - - // Definition-level capability hook first, then assembly-level hook. - d.cli?.configure?.(cli) - options.configureCli?.(cli) - - cli.help() - cli.version('0.0.0') - - return { - cli, - async parse(argv = process.argv) { - cli.parse(argv, { run: false }) - await cli.runMatchedCommand() - }, - } -} - -interface CliFlags { - host?: string - port?: number - open?: boolean - [key: string]: unknown -} - -function resolveTypedFlags(d: DevframeDefinition, raw: Record): Record { - if (!d.cli?.flags) - return raw - const { flags, issues } = parseCliFlags(d.cli.flags, raw) - if (issues?.length) { - for (const issue of issues) - console.error(c.red`[devframe] invalid flag — ${issue}`) - process.exit(1) - } - return flags -} +/** @deprecated Use `CacHandle` from `devframe/adapters/cac` instead. */ +export type CliHandle = CacHandle diff --git a/packages/devframe/src/adapters/dev.ts b/packages/devframe/src/adapters/dev.ts index 31fb927c..7ede0194 100644 --- a/packages/devframe/src/adapters/dev.ts +++ b/packages/devframe/src/adapters/dev.ts @@ -127,7 +127,7 @@ export async function resolveDevServerPort( * * Use this directly when integrating devframe into an existing CLI * framework (commander, yargs, hand-rolled CAC). For the all-in-one - * `dev` / `build` / `mcp` shell, reach for {@link createCli} instead. + * `dev` / `build` / `mcp` shell, reach for {@link createCac} instead. */ export async function createDevServer( def: DevframeDefinition, diff --git a/packages/devframe/src/helpers/vite.ts b/packages/devframe/src/helpers/vite.ts index 25218a6b..57f00f21 100644 --- a/packages/devframe/src/helpers/vite.ts +++ b/packages/devframe/src/helpers/vite.ts @@ -64,7 +64,7 @@ export interface DevframeVitePlugin { * * Use bridge mode when integrating with frameworks that own the SPA * (Nuxt, Astro, SolidStart, plain Vite apps). For the all-in-one - * `dev` / `build` / `mcp` shell, reach for {@link createCli} instead. + * `dev` / `build` / `mcp` shell, reach for {@link createCac} instead. */ export function viteDevBridge(d: DevframeDefinition, options: ViteDevBridgeOptions = {}): DevframeVitePlugin { const base = normalizeMountBase(options.base ?? resolveBasePath(d, 'hosted')) diff --git a/packages/devframe/src/types/devframe.ts b/packages/devframe/src/types/devframe.ts index 6709fe43..b6a04208 100644 --- a/packages/devframe/src/types/devframe.ts +++ b/packages/devframe/src/types/devframe.ts @@ -143,7 +143,7 @@ export interface DevframeCliOptions { /** * Capability-side CAC hook. Called with the CAC instance after the * adapter registers its built-in commands (`build` / `spa` / `mcp`) - * but before `createCli`'s own `configureCli` caller. Use this to + * but before `createCac`'s own `configureCli` caller. Use this to * contribute tool-specific flags and subcommands from the definition * itself. */ @@ -232,7 +232,7 @@ export interface DevframeBrowserContext { /** * Runtime information threaded into `setup(ctx, info)`. Adapters * populate the fields that make sense for their deployment. In - * particular, `createCli` fills `flags` with the parsed CAC bag. + * particular, `createCac` fills `flags` with the parsed CAC bag. */ export interface DevframeSetupInfo { /** Parsed CLI flags, populated by the CLI adapter. */ diff --git a/packages/devframe/tsdown.config.ts b/packages/devframe/tsdown.config.ts index 73c7a8d3..d357750b 100644 --- a/packages/devframe/tsdown.config.ts +++ b/packages/devframe/tsdown.config.ts @@ -88,6 +88,7 @@ const serverEntries = { 'utils/launch-editor': 'src/utils/launch-editor.ts', 'utils/open': 'src/utils/open.ts', 'utils/serve-static': 'src/utils/serve-static.ts', + 'adapters/cac': 'src/adapters/cac.ts', 'adapters/cli': 'src/adapters/cli.ts', 'adapters/dev': 'src/adapters/dev.ts', 'adapters/build': 'src/adapters/build.ts', diff --git a/plugins/a11y/package.json b/plugins/a11y/package.json index 070438a4..acc2c7c3 100644 --- a/plugins/a11y/package.json +++ b/plugins/a11y/package.json @@ -63,6 +63,7 @@ }, "dependencies": { "axe-core": "catalog:frontend", + "cac": "catalog:deps", "solid-js": "catalog:frontend" }, "devDependencies": { diff --git a/plugins/a11y/src/cli.ts b/plugins/a11y/src/cli.ts index 0e2351ba..9f153b34 100644 --- a/plugins/a11y/src/cli.ts +++ b/plugins/a11y/src/cli.ts @@ -1,5 +1,5 @@ -import type { CliHandle } from 'devframe/adapters/cli' -import { createCli } from 'devframe/adapters/cli' +import type { CacHandle } from 'devframe/adapters/cac' +import { createCac } from 'devframe/adapters/cac' import a11yDevframe from './index.ts' /** @@ -8,6 +8,6 @@ import a11yDevframe from './index.ts' * default {@link createA11yDevframe} definition with devframe's * `dev` / `build` / `spa` command shell. */ -export function createA11yCli(): CliHandle { - return createCli(a11yDevframe) +export function createA11yCli(): CacHandle { + return createCac(a11yDevframe) } diff --git a/plugins/code-server/package.json b/plugins/code-server/package.json index 076e150b..8a4ea60e 100644 --- a/plugins/code-server/package.json +++ b/plugins/code-server/package.json @@ -59,6 +59,7 @@ } }, "dependencies": { + "cac": "catalog:deps", "get-port-please": "catalog:deps", "iframe-pane": "catalog:frontend", "nostics": "catalog:deps" diff --git a/plugins/code-server/src/cli.ts b/plugins/code-server/src/cli.ts index aef8a580..9d1232d5 100644 --- a/plugins/code-server/src/cli.ts +++ b/plugins/code-server/src/cli.ts @@ -1,6 +1,6 @@ -import type { CliHandle, CreateCliOptions } from 'devframe/adapters/cli' +import type { CacHandle, CreateCacOptions } from 'devframe/adapters/cac' import type { CodeServerOptions } from './types' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' import { createCodeServerDevframe } from './index' /** @@ -10,7 +10,7 @@ import { createCodeServerDevframe } from './index' */ export function createCodeServerCli( options: CodeServerOptions = {}, - cliOptions: CreateCliOptions = {}, -): CliHandle { - return createCli(createCodeServerDevframe(options), cliOptions) + cliOptions: CreateCacOptions = {}, +): CacHandle { + return createCac(createCodeServerDevframe(options), cliOptions) } diff --git a/plugins/code-server/src/index.ts b/plugins/code-server/src/index.ts index a9130f65..f7f54020 100644 --- a/plugins/code-server/src/index.ts +++ b/plugins/code-server/src/index.ts @@ -22,7 +22,7 @@ const distDir = fileURLToPath(new URL('../dist/spa', import.meta.url)) /** * Build a {@link DevframeDefinition} for the code-server panel. The same - * definition runs standalone (`createCli`), mounts into a Vite host + * definition runs standalone (`createCac`), mounts into a Vite host * (`/vite`), or docks inside a hub — its `setup` only relies on the core * devframe RPC + shared-state surface. * diff --git a/plugins/git/README.md b/plugins/git/README.md index 8cbef0f5..73dc2493 100644 --- a/plugins/git/README.md +++ b/plugins/git/README.md @@ -37,9 +37,9 @@ any host with devframe's adapters, or drive yourself. ```ts import { createGitDevframe } from '@devframes/plugin-git' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' -await createCli(createGitDevframe({ repoRoot: process.cwd() })).parse() +await createCac(createGitDevframe({ repoRoot: process.cwd() })).parse() ``` | Option | Default | Description | diff --git a/plugins/git/package.json b/plugins/git/package.json index 8bde7469..84710afe 100644 --- a/plugins/git/package.json +++ b/plugins/git/package.json @@ -47,6 +47,7 @@ "test": "vitest run" }, "dependencies": { + "cac": "catalog:deps", "devframe": "workspace:*", "pathe": "catalog:deps" }, diff --git a/plugins/git/src/cli.ts b/plugins/git/src/cli.ts index 57bd3830..f7e36745 100644 --- a/plugins/git/src/cli.ts +++ b/plugins/git/src/cli.ts @@ -1,8 +1,8 @@ import process from 'node:process' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' import { createGitDevframe } from './index.ts' -const cli = createCli(createGitDevframe(), { +const cli = createCac(createGitDevframe(), { onReady({ origin }) { // devframe is headless by default — print our own ready banner so the // dev server doesn't look like it silently did nothing. diff --git a/plugins/inspect/package.json b/plugins/inspect/package.json index 84b7dcee..bc1b48ca 100644 --- a/plugins/inspect/package.json +++ b/plugins/inspect/package.json @@ -57,6 +57,7 @@ }, "dependencies": { "@valibot/to-json-schema": "catalog:deps", + "cac": "catalog:deps", "nostics": "catalog:deps" }, "devDependencies": { diff --git a/plugins/inspect/src/cli.ts b/plugins/inspect/src/cli.ts index 96b6acba..4718a781 100644 --- a/plugins/inspect/src/cli.ts +++ b/plugins/inspect/src/cli.ts @@ -1,5 +1,5 @@ -import type { CliHandle } from 'devframe/adapters/cli' -import { createCli } from 'devframe/adapters/cli' +import type { CacHandle } from 'devframe/adapters/cac' +import { createCac } from 'devframe/adapters/cac' import inspectDevframe from './index' /** @@ -8,6 +8,6 @@ import inspectDevframe from './index' * default {@link createInspectDevframe} definition with devframe's * `dev` / `build` / `spa` / `mcp` command shell. */ -export function createInspectCli(): CliHandle { - return createCli(inspectDevframe) +export function createInspectCli(): CacHandle { + return createCac(inspectDevframe) } diff --git a/plugins/messages/package.json b/plugins/messages/package.json index 1f3c8fb8..d2a1ab7d 100644 --- a/plugins/messages/package.json +++ b/plugins/messages/package.json @@ -61,6 +61,7 @@ } }, "dependencies": { + "cac": "catalog:deps", "nostics": "catalog:deps" }, "devDependencies": { diff --git a/plugins/messages/src/cli.ts b/plugins/messages/src/cli.ts index 40c5a525..1021023d 100644 --- a/plugins/messages/src/cli.ts +++ b/plugins/messages/src/cli.ts @@ -1,5 +1,5 @@ -import type { CliHandle } from 'devframe/adapters/cli' -import { createCli } from 'devframe/adapters/cli' +import type { CacHandle } from 'devframe/adapters/cac' +import { createCac } from 'devframe/adapters/cac' import messagesDevframe from './index' /** @@ -8,6 +8,6 @@ import messagesDevframe from './index' * default {@link createMessagesDevframe} definition with devframe's * `dev` / `build` / `spa` / `mcp` command shell. */ -export function createMessagesCli(): CliHandle { - return createCli(messagesDevframe) +export function createMessagesCli(): CacHandle { + return createCac(messagesDevframe) } diff --git a/plugins/terminals/package.json b/plugins/terminals/package.json index 80919395..8633a73f 100644 --- a/plugins/terminals/package.json +++ b/plugins/terminals/package.json @@ -61,6 +61,7 @@ "dependencies": { "@xterm/addon-fit": "catalog:frontend", "@xterm/xterm": "catalog:frontend", + "cac": "catalog:deps", "nostics": "catalog:deps", "pathe": "catalog:deps", "valibot": "catalog:deps", diff --git a/plugins/terminals/src/cli.ts b/plugins/terminals/src/cli.ts index 07b08fa7..eb8f4c75 100644 --- a/plugins/terminals/src/cli.ts +++ b/plugins/terminals/src/cli.ts @@ -1,6 +1,6 @@ -import type { CliHandle, CreateCliOptions } from 'devframe/adapters/cli' +import type { CacHandle, CreateCacOptions } from 'devframe/adapters/cac' import type { TerminalsOptions } from './types' -import { createCli } from 'devframe/adapters/cli' +import { createCac } from 'devframe/adapters/cac' import { createTerminalsDevframe } from './index' /** @@ -10,7 +10,7 @@ import { createTerminalsDevframe } from './index' */ export function createTerminalsCli( options: TerminalsOptions = {}, - cliOptions: CreateCliOptions = {}, -): CliHandle { - return createCli(createTerminalsDevframe(options), cliOptions) + cliOptions: CreateCacOptions = {}, +): CacHandle { + return createCac(createTerminalsDevframe(options), cliOptions) } diff --git a/plugins/terminals/src/index.ts b/plugins/terminals/src/index.ts index 191d682c..ed318d17 100644 --- a/plugins/terminals/src/index.ts +++ b/plugins/terminals/src/index.ts @@ -22,7 +22,7 @@ export { /** * Build a {@link DevframeDefinition} for the terminals panel. The same - * definition runs standalone (`createCli`), mounts into a Vite host + * definition runs standalone (`createCac`), mounts into a Vite host * (`/vite`), or docks inside a hub — its `setup` only relies on the core * devframe RPC surface. * diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 92ee607d..85c1f6c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -391,6 +391,9 @@ importers: '@antfu/design': specifier: catalog:frontend version: 0.2.1(@antfu/utils@9.3.0)(@iconify-json/catppuccin@1.2.17)(@tanstack/vue-virtual@3.13.30(vue@3.5.39(typescript@6.0.3)))(@unocss/core@66.7.5)(colorjs.io@0.6.1)(floating-vue@5.2.2(vue@3.5.39(typescript@6.0.3)))(playwright@1.61.1)(reka-ui@2.10.1(vue@3.5.39(typescript@6.0.3)))(unocss@66.7.5(@unocss/postcss@66.7.5(postcss@8.5.16))(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.23.0)(yaml@2.9.0)))(vue@3.5.39(typescript@6.0.3)) + cac: + specifier: catalog:deps + version: 7.0.0 colorjs.io: specifier: catalog:frontend version: 0.6.1 @@ -550,6 +553,9 @@ importers: '@antfu/design': specifier: catalog:frontend version: 0.2.1(@antfu/utils@9.3.0)(@iconify-json/catppuccin@1.2.17)(@tanstack/vue-virtual@3.13.30(vue@3.5.39(typescript@6.0.3)))(@unocss/core@66.7.5)(colorjs.io@0.6.1)(floating-vue@5.2.2(vue@3.5.39(typescript@6.0.3)))(playwright@1.61.1)(reka-ui@2.10.1(vue@3.5.39(typescript@6.0.3)))(unocss@66.7.5(@unocss/postcss@66.7.5(postcss@8.5.16))(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.23.0)(yaml@2.9.0)))(vue@3.5.39(typescript@6.0.3)) + cac: + specifier: catalog:deps + version: 7.0.0 colorjs.io: specifier: catalog:frontend version: 0.6.1 @@ -636,6 +642,9 @@ importers: '@antfu/design': specifier: catalog:frontend version: 0.2.1(@antfu/utils@9.3.0)(@iconify-json/catppuccin@1.2.17)(@tanstack/vue-virtual@3.13.30(vue@3.5.39(typescript@6.0.3)))(@unocss/core@66.7.5)(colorjs.io@0.6.1)(floating-vue@5.2.2(vue@3.5.39(typescript@6.0.3)))(playwright@1.61.1)(reka-ui@2.10.1(vue@3.5.39(typescript@6.0.3)))(unocss@66.7.5(@unocss/postcss@66.7.5(postcss@8.5.16))(vite@8.1.3(@types/node@26.1.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.47.1)(tsx@4.23.0)(yaml@2.9.0)))(vue@3.5.39(typescript@6.0.3)) + cac: + specifier: catalog:deps + version: 7.0.0 colorjs.io: specifier: catalog:frontend version: 0.6.1 @@ -676,9 +685,6 @@ importers: birpc: specifier: catalog:deps version: 4.0.0 - cac: - specifier: catalog:deps - version: 7.0.0 crossws: specifier: ^0.4.9 version: 0.4.9(srvx@0.11.15) @@ -707,6 +713,9 @@ importers: '@modelcontextprotocol/sdk': specifier: catalog:deps version: 1.29.0(zod@4.4.3) + cac: + specifier: catalog:deps + version: 7.0.0 get-port-please: specifier: catalog:deps version: 3.2.0 @@ -813,6 +822,9 @@ importers: axe-core: specifier: catalog:frontend version: 4.12.1 + cac: + specifier: catalog:deps + version: 7.0.0 solid-js: specifier: catalog:frontend version: 1.9.14 @@ -859,6 +871,9 @@ importers: plugins/code-server: dependencies: + cac: + specifier: catalog:deps + version: 7.0.0 get-port-please: specifier: catalog:deps version: 3.2.0 @@ -911,6 +926,9 @@ importers: plugins/git: dependencies: + cac: + specifier: catalog:deps + version: 7.0.0 devframe: specifier: workspace:* version: link:../../packages/devframe @@ -1011,6 +1029,9 @@ importers: '@valibot/to-json-schema': specifier: catalog:deps version: 1.7.1(valibot@1.4.2(typescript@5.9.3)) + cac: + specifier: catalog:deps + version: 7.0.0 nostics: specifier: catalog:deps version: 1.1.4 @@ -1075,6 +1096,9 @@ importers: plugins/messages: dependencies: + cac: + specifier: catalog:deps + version: 7.0.0 nostics: specifier: catalog:deps version: 1.1.4 @@ -1148,6 +1172,9 @@ importers: '@xterm/xterm': specifier: catalog:frontend version: 6.0.0 + cac: + specifier: catalog:deps + version: 7.0.0 nostics: specifier: catalog:deps version: 1.1.4 @@ -1986,18 +2013,12 @@ packages: resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@floating-ui/core@1.7.5': - resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} - '@floating-ui/core@1.8.0': resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==} '@floating-ui/dom@1.1.1': resolution: {integrity: sha512-TpIO93+DIujg3g7SykEAGZMDtbJRrmnYRCNYSjJlvIbGhBjRSNTLVbNeDQBrzy9qDgUbiWdc7KA0uZHZ2tJmiw==} - '@floating-ui/dom@1.7.6': - resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} - '@floating-ui/dom@1.8.0': resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==} @@ -2013,9 +2034,6 @@ packages: react: '>=17.0.0' react-dom: '>=17.0.0' - '@floating-ui/utils@0.2.11': - resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} - '@floating-ui/utils@0.2.12': resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==} @@ -9843,22 +9861,13 @@ snapshots: '@eslint/core': 1.2.1 levn: 0.4.1 - '@floating-ui/core@1.7.5': - dependencies: - '@floating-ui/utils': 0.2.11 - '@floating-ui/core@1.8.0': dependencies: '@floating-ui/utils': 0.2.12 '@floating-ui/dom@1.1.1': dependencies: - '@floating-ui/core': 1.7.5 - - '@floating-ui/dom@1.7.6': - dependencies: - '@floating-ui/core': 1.7.5 - '@floating-ui/utils': 0.2.11 + '@floating-ui/core': 1.8.0 '@floating-ui/dom@1.8.0': dependencies: @@ -9879,14 +9888,12 @@ snapshots: react-dom: 19.2.7(react@19.2.7) tabbable: 6.5.0 - '@floating-ui/utils@0.2.11': {} - '@floating-ui/utils@0.2.12': {} '@floating-ui/vue@1.1.11(vue@3.5.39(typescript@5.9.3))': dependencies: - '@floating-ui/dom': 1.7.6 - '@floating-ui/utils': 0.2.11 + '@floating-ui/dom': 1.8.0 + '@floating-ui/utils': 0.2.12 vue-demi: 0.14.10(vue@3.5.39(typescript@5.9.3)) transitivePeerDependencies: - '@vue/composition-api' @@ -9894,8 +9901,8 @@ snapshots: '@floating-ui/vue@1.1.11(vue@3.5.39(typescript@6.0.3))': dependencies: - '@floating-ui/dom': 1.7.6 - '@floating-ui/utils': 0.2.11 + '@floating-ui/dom': 1.8.0 + '@floating-ui/utils': 0.2.12 vue-demi: 0.14.10(vue@3.5.39(typescript@6.0.3)) transitivePeerDependencies: - '@vue/composition-api' @@ -16221,7 +16228,7 @@ snapshots: reka-ui@2.10.1(vue@3.5.39(typescript@5.9.3)): dependencies: - '@floating-ui/dom': 1.7.6 + '@floating-ui/dom': 1.8.0 '@floating-ui/vue': 1.1.11(vue@3.5.39(typescript@5.9.3)) '@internationalized/date': 3.12.2 '@internationalized/number': 3.6.7 @@ -16237,7 +16244,7 @@ snapshots: reka-ui@2.10.1(vue@3.5.39(typescript@6.0.3)): dependencies: - '@floating-ui/dom': 1.7.6 + '@floating-ui/dom': 1.8.0 '@floating-ui/vue': 1.1.11(vue@3.5.39(typescript@6.0.3)) '@internationalized/date': 3.12.2 '@internationalized/number': 3.6.7 diff --git a/skills/devframe/SKILL.md b/skills/devframe/SKILL.md index 14a67381..1dfccebc 100644 --- a/skills/devframe/SKILL.md +++ b/skills/devframe/SKILL.md @@ -11,7 +11,7 @@ description: > terminals, palette, etc.), the devframe can be mounted into a host that provides them — Vite DevTools is one supported target, reached via the `vite` adapter. Triggers on `devframe` imports, - `defineDevframe`, `createCli`, `createMcpServer`, + `defineDevframe`, `createCac`, `createMcpServer`, `connectDevframe`, and on migrations of existing inspectors (eslint-config-inspector, unocss-inspector, node-modules-inspector-style tools) to devframe. @@ -31,7 +31,7 @@ All adapter factories share the shape `createXxx(devframeDef, options?)`. | Author goal | Factory | Entry | |-------------|---------|-------| -| Standalone CLI for local use | `createCli(def, options?)` | `devframe/adapters/cli` | +| Standalone CLI for local use | `createCac(def, options?)` | `devframe/adapters/cac` | | Run the dev server programmatically (any CLI framework) | `createDevServer(def, options?)` | `devframe/adapters/dev` | | Self-contained static deploy with baked data | `createBuild(def, options?)` | `devframe/adapters/build` | | Mount into a host (Vite DevTools or any compatible host) | `createPluginFromDevframe(def, options?)` | `@vitejs/devtools-kit/node` | @@ -530,7 +530,7 @@ At runtime, static clients look up the argument hash in the dump; misses resolve ## CLI adapter subcommands -`createCli(devframe).parse()` gives the tool four subcommands out of the box: +`createCac(devframe).parse()` gives the tool four subcommands out of the box: | Subcommand | Action | |------------|--------| @@ -539,7 +539,7 @@ At runtime, static clients look up the argument hash in the dump; misses resolve | `spa` | Deployable SPA → `./dist-spa/` | | `mcp` | stdio MCP server (experimental) | -**Bring your own CLI framework?** `createCli` 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 `createCli`'s baked-in command structure doesn't fit. `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/cli`) validate an arbitrary flag bag against a `CliFlagsSchema` — typed flags aren't tied to cac. +**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. (The legacy `devframe/adapters/cli` entry / `createCli` remains as a deprecated alias.) `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. ## Bundled utilities diff --git a/tests/__snapshots__/tsnapi/@devframes/plugin-a11y/cli.snapshot.d.ts b/tests/__snapshots__/tsnapi/@devframes/plugin-a11y/cli.snapshot.d.ts index 3fa0844e..3448f23d 100644 --- a/tests/__snapshots__/tsnapi/@devframes/plugin-a11y/cli.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/@devframes/plugin-a11y/cli.snapshot.d.ts @@ -2,5 +2,5 @@ * Generated by tsnapi — public API snapshot of `@devframes/plugin-a11y/cli` */ // #region Functions -export declare function createA11yCli(): CliHandle; +export declare function createA11yCli(): CacHandle; // #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/cli.snapshot.d.ts b/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/cli.snapshot.d.ts index bc2dbb6a..61c175c8 100644 --- a/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/cli.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/@devframes/plugin-code-server/cli.snapshot.d.ts @@ -2,5 +2,5 @@ * Generated by tsnapi — public API snapshot of `@devframes/plugin-code-server/cli` */ // #region Functions -export declare function createCodeServerCli(_?: CodeServerOptions, _?: CreateCliOptions): CliHandle; +export declare function createCodeServerCli(_?: CodeServerOptions, _?: CreateCacOptions): CacHandle; // #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/@devframes/plugin-inspect/cli.snapshot.d.ts b/tests/__snapshots__/tsnapi/@devframes/plugin-inspect/cli.snapshot.d.ts index fc2a3114..3e6746d7 100644 --- a/tests/__snapshots__/tsnapi/@devframes/plugin-inspect/cli.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/@devframes/plugin-inspect/cli.snapshot.d.ts @@ -2,5 +2,5 @@ * Generated by tsnapi — public API snapshot of `@devframes/plugin-inspect/cli` */ // #region Functions -export declare function createInspectCli(): CliHandle; +export declare function createInspectCli(): CacHandle; // #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/@devframes/plugin-messages/cli.snapshot.d.ts b/tests/__snapshots__/tsnapi/@devframes/plugin-messages/cli.snapshot.d.ts index 1a42e16d..8a36d534 100644 --- a/tests/__snapshots__/tsnapi/@devframes/plugin-messages/cli.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/@devframes/plugin-messages/cli.snapshot.d.ts @@ -2,5 +2,5 @@ * Generated by tsnapi — public API snapshot of `@devframes/plugin-messages/cli` */ // #region Functions -export declare function createMessagesCli(): CliHandle; +export declare function createMessagesCli(): CacHandle; // #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/@devframes/plugin-terminals/cli.snapshot.d.ts b/tests/__snapshots__/tsnapi/@devframes/plugin-terminals/cli.snapshot.d.ts index 4715a40a..3a3659ff 100644 --- a/tests/__snapshots__/tsnapi/@devframes/plugin-terminals/cli.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/@devframes/plugin-terminals/cli.snapshot.d.ts @@ -2,5 +2,5 @@ * Generated by tsnapi — public API snapshot of `@devframes/plugin-terminals/cli` */ // #region Functions -export declare function createTerminalsCli(_?: TerminalsOptions, _?: CreateCliOptions): CliHandle; +export declare function createTerminalsCli(_?: TerminalsOptions, _?: CreateCacOptions): CacHandle; // #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/devframe/adapters/cac.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/adapters/cac.snapshot.d.ts new file mode 100644 index 00000000..3ab6ac66 --- /dev/null +++ b/tests/__snapshots__/tsnapi/devframe/adapters/cac.snapshot.d.ts @@ -0,0 +1,29 @@ +/** + * Generated by tsnapi — public API snapshot of `devframe/adapters/cac` + */ +// #region Interfaces +export interface CacHandle { + cli: CAC; + parse: (_?: string[]) => Promise; +} +export interface CreateCacOptions { + defaultPort?: number; + configureCli?: (_: CAC) => void; + onReady?: (_: { + origin: string; + port: number; + app: H3; + }) => void | Promise; +} +// #endregion + +// #region Functions +export declare function createCac(_: DevframeDefinition, _?: CreateCacOptions): CacHandle; +// #endregion + +// #region Other +export { CliFlagsSchema } +export { defineCliFlags } +export { InferCliFlags } +export { parseCliFlags } +// #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/devframe/adapters/cac.snapshot.js b/tests/__snapshots__/tsnapi/devframe/adapters/cac.snapshot.js new file mode 100644 index 00000000..4d1f42c5 --- /dev/null +++ b/tests/__snapshots__/tsnapi/devframe/adapters/cac.snapshot.js @@ -0,0 +1,8 @@ +/** + * Generated by tsnapi — public API snapshot of `devframe/adapters/cac` + */ +// #region Other +export { createCac } +export { defineCliFlags } +export { parseCliFlags } +// #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.d.ts index e941e7ad..a521e6c4 100644 --- a/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.d.ts @@ -1,24 +1,16 @@ /** * Generated by tsnapi — public API snapshot of `devframe/adapters/cli` */ -// #region Interfaces -export interface CliHandle { - cli: CAC; - parse: (_?: string[]) => Promise; -} -export interface CreateCliOptions { - defaultPort?: number; - configureCli?: (_: CAC) => void; - onReady?: (_: { - origin: string; - port: number; - app: H3; - }) => void | Promise; -} +// #region Types +/** @deprecated */ +export type CliHandle = CacHandle; +/** @deprecated */ +export type CreateCliOptions = CreateCacOptions; // #endregion -// #region Functions -export declare function createCli(_: DevframeDefinition, _?: CreateCliOptions): CliHandle; +// #region Variables +/** @deprecated */ +export declare const createCli: typeof createCac; // #endregion // #region Other diff --git a/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.js b/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.js index e2e54c74..7b59f0ee 100644 --- a/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.js +++ b/tests/__snapshots__/tsnapi/devframe/adapters/cli.snapshot.js @@ -1,8 +1,12 @@ /** * Generated by tsnapi — public API snapshot of `devframe/adapters/cli` */ -// #region Functions -export function createCli(_, _) {} -export function defineCliFlags(_) {} -export function parseCliFlags(_, _) {} +// #region Variables +/** @deprecated */ +export var createCli /* const */ +// #endregion + +// #region Other +export { defineCliFlags } +export { parseCliFlags } // #endregion \ No newline at end of file diff --git a/tsconfig.base.json b/tsconfig.base.json index b59a44f4..18f4506e 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -82,6 +82,9 @@ "devframe/utils/when": [ "./packages/devframe/src/utils/when.ts" ], + "devframe/adapters/cac": [ + "./packages/devframe/src/adapters/cac.ts" + ], "devframe/adapters/cli": [ "./packages/devframe/src/adapters/cli.ts" ],