Files
volar-docs/docs/cli-integration.md
2025-11-09 22:22:52 -06:00

154 lines
5.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CLI Integration & Headless Workflows
> [Docs Index](README.md) • [Repo README](../README.md) • [Workspace Diagnostics](workspace-diagnostics.md) • [Testing & CI](testing-and-ci.md) • [LSP Benchmarking](lsp-benchmarking.md)
Language intelligence isnt limited to editors—teams often run Volar-powered checks in CI, pre-commit hooks, or bespoke tooling. This guide shows how to build CLI utilities (à la `vue-tsc`) that reuse your Volar language service for headless diagnostics, formatting, or codegen tasks.
## Approaches
| Approach | Pros | Cons |
| --- | --- | --- |
| Reuse `vue-tsc` | Fast to adopt, maintained by Vue team | Limited to diagnostics; less customizable |
| Custom CLI (Node) | Full control, integrate custom plugins/services | Must manage FS, config, output formatting |
| LSP client CLI | Reuse existing LSP server, speak JSON-RPC | More setup (start server, send requests) |
## Building a Custom CLI
### 1. Shared Language Service Factory
Factor your language service creation into a reusable module (used by LSP + CLI):
```ts
export function createVolarService(tsconfigPath: string, config: MyConfig) {
const tsProject = createTypeScriptProject(tsconfigPath);
const core = createLanguageCore({ plugins: [...], ts: tsProject.typescript });
return createLanguageService(core, [volarServiceCss(), customService(config)], env, project);
}
```
### 2. CLI Entrypoint
```ts
#!/usr/bin/env node
import { URI } from 'vscode-uri';
import glob from 'fast-glob';
import chalk from 'chalk';
import { createVolarService } from './service';
async function main() {
const service = createVolarService(process.argv[2] ?? 'tsconfig.json', loadConfig());
const files = await glob(['src/**/*.vue', 'src/**/*.ts']);
let hasErrors = false;
for (const file of files) {
const uri = URI.file(file).toString();
const diagnostics = await service.getDiagnostics(uri);
diagnostics.forEach((diag) => {
hasErrors = hasErrors || diag.severity === 1;
console.log(formatDiagnostic(file, diag));
});
}
process.exit(hasErrors ? 1 : 0);
}
```
### 3. Formatting Output
Use a standard format (VS Code-style) so editors/CI parse easily:
```ts
function formatDiagnostic(file: string, diag: Diagnostic) {
const range = `${diag.range.start.line + 1}:${diag.range.start.character + 1}`;
const severity = ['Error', 'Warning', 'Information', 'Hint'][diag.severity ?? 0];
return `${chalk.gray(file)}:${range} - ${severity} ${diag.message} (${diag.source})`;
}
```
### 4. JSON Output (Optional)
Provide `--json` flag to emit machine-readable diagnostics:
```ts
if (argv.json) {
console.log(JSON.stringify({ uri, diagnostics }, null, 2));
}
```
## Leveraging `workspace/diagnostic`
Instead of looping per file, reuse the workspace diagnostics pipeline:
```ts
const report = await service.context.project.context.languageService.getWorkspaceDiagnostics();
report.forEach((docReport) => {
docReport.items.forEach((diag) => {
console.log(formatDiagnostic(URI.parse(docReport.uri).fsPath, diag));
});
});
```
This ensures CLI output matches editor diagnostics exactly.
## Integrating with CI
1. Add a script (`volar-check`) that runs your CLI.
2. Wire it into CI workflows:
```yaml
- run: npm run volar-check -- --json > artifacts/volar.json
- uses: actions/upload-artifact@v4
with:
name: volar-diagnostics
path: artifacts/volar.json
```
3. Fail the pipeline when exit code ≠ 0.
## Pre-commit Hooks
Use `lint-staged` or `husky` to run targeted diagnostics:
```json
{
"lint-staged": {
"*.{vue,ts,js}": "volar-check --files"
}
}
```
Implement `--files` flag to accept a comma-separated list and restrict diagnostics.
## Formatting & Code Actions
You can expose formatting or quick fixes via CLI:
```ts
const edits = await service.getDocumentFormattingEdits(uri, { tabSize: 2, insertSpaces: true }, undefined);
applyEditsToFile(fsPath, edits);
```
For code actions, use `service.getCodeActions` and apply `WorkspaceEdit`.
## Logging & Telemetry
- Print progress (“Analyzing 123 files…”) with timestamps.
- Collect metrics (time per file, total diagnostics) to feed into benchmarking dashboards.
## Packaging & Distribution
- Bundle with `pkg`/`nexe` if users lack Node.
- Provide `npx` entry for quick runs (`npx volar-check`).
- Document environment variables (`VOLAR_TRACE`, `VOLAR_CONFIG_PATH`) to customize behavior.
## Best Practices Checklist
- [ ] Shared service factory reused by both LSP and CLI.
- [ ] Configurable input (`tsconfig`, glob patterns, file list).
- [ ] Structured output (text + optional JSON).
- [ ] Proper exit codes (0 = success, 1 = errors, 2 = config failure).
- [ ] Support for ignoring warnings (e.g., `--max-warnings`).
- [ ] Telemetry/logging toggles for verbose debugging.
By bringing Volars language service into CLI form, you align editor diagnostics with automated checks, prevent regressions before they hit production, and empower teams to build custom workflows (codemods, linting, documentation pipelines) on top of the same intelligence.