@accorudo/cli
v0.0.2
Published
Import, export, and sync Accorudo contracts and OpenAPI specs.
Maintainers
Readme
@accorudo/cli
The accorudo command line: scaffold, import, export, and sync Accorudo contract bundles against OpenAPI specs. It's a thin wrapper over [@accorudo/openapi](../openapi) — import/export call straight through to parseOpenApi/generateContracts and extractBundle/emitOpenApi; this package only adds argument parsing, config loading, and filesystem dry-run diffing.
Install
pnpm add -D @accorudo/cliRun via pnpm exec or add scripts to your package.json:
{
"scripts": {
"accorudo:import": "accorudo import openapi/main.yaml --out contracts/main",
"accorudo:export": "accorudo export contracts/main --out openapi/main.yaml"
}
}Requires Node 22.18+ or 23.6+ (24+ recommended) — see Config loading for why.
Commands
accorudo init
Scaffolds accorudo.config.ts, an empty contracts/main/, and a placeholder openapi/main.yaml. Won't overwrite an existing accorudo.config.ts.
accorudo import <spec> --out <dir>
Generates a full contract bundle from an OpenAPI 3.x file — api.ts, routes/<tag>.ts per tag, models/<tag or common>.ts.
| Flag | Description |
| ------------------- | --------------------------------------------------------------------------------------- |
| -o, --out <dir> | Output directory (required) |
| -n, --name <name> | Bundle name for the registry/Api type names (default: derived from spec info.title) |
| --only <tags> | Limit to comma-separated OpenAPI tags |
| --dry-run | Print the planned create/update/skip summary without writing |
A file is skipped when the freshly generated content is byte-identical to what's already on disk, so hand-edited routes survive a re-import when the underlying OpenAPI operation hasn't changed. Generated code is a starting point, not a lock-in — see @accorudo/openapi's known limitations (mechanical naming, model-file grouping, allOf flattening, etc.) before committing it as-is.
accorudo export <contracts> [--out <file>]
Generates an OpenAPI 3.1 spec from a contract bundle. --out's extension (.yaml, .yml, or .json) picks the output format.
| Flag | Description |
| ------------------ | ------------------------------------------------------------------------------ |
| -o, --out <file> | Output path — required unless --dry-run |
| --title <title> | Override info.title in the generated spec |
| --dry-run | Print the spec to stdout (yaml by default) instead of writing — pipe to diff |
accorudo sync [bundle] [--reverse] [--dry-run]
Runs import (default) or export (--reverse) for one or all bundles listed in accorudo.config.ts.
accorudo sync # import every bundle (openapi -> contracts)
accorudo sync main # import just "main"
accorudo sync main --reverse # export "main" (contracts -> openapi)Configuration
defineConfig is both a small runtime identity function and the type your accorudo.config.ts is checked against:
import { defineConfig } from "@accorudo/cli";
export default defineConfig({
bundles: {
main: {
contracts: "./contracts/main",
openapi: "./openapi/main.yaml",
},
},
});Config loading
accorudo.config.ts is loaded with Node's built-in TypeScript support — no bundler, no typescript dependency at runtime. Two consequences worth knowing:
- It needs Node 22.18+ or 23.6+ (stable/default-on there); older Node builds don't strip types without an explicit flag and will fail to load the config.
- The file is only ever read for its erasable syntax (imports, type annotations, a function call) — enums, namespaces, and other constructs that need real transformation aren't supported inside it.
Development
pnpm --filter @accorudo/cli test # vitest
pnpm --filter @accorudo/cli build # tsc -> dist/, then chmod +x dist/bin.jsCommand logic lives in src/commands/*.ts as plain functions (runInit, runImport, runExport, runSync) taking resolved option objects — src/bin.ts is only commander wiring on top, so tests call the command functions directly rather than spawning a subprocess.
