modular_cli_sdk 0.3.4
modular_cli_sdk: ^0.3.4 copied to clipboard
Command-centric SDK for building modular CLIs with Dart — Command/Input/Output contract, structured errors, output formatting, and automatic TTY detection. Built on cli_router.
Changelog #
All notable changes to this project will be documented in this file.
The format loosely follows Keep a Changelog and the project adheres to Semantic Versioning.
0.3.4 #
Fixed #
-
An incomplete invocation is no longer reported as an unknown command. Typing the beginning of a registered route without reaching its end —
mathwheremath addexists — answeredunknown command 'math'followed by the whole catalog. The name was real; what was missing was the end of it, and the user was sent looking for a typo they had not made. The error path now asks the catalog whether what was typed continues into any route, says so, and lists only those continuationsThe rule is stated over routes rather than modules on purpose.
api graphqlis not a module — it is the first segment of the routeapi graphql compile— so a module-only check would have left it reported as unknown. Prefix-of-a-route covers the module without an action and the half-typed route as the one case they are, and is the simpler rule of the twoA name that begins no registered route keeps exactly the behaviour it had: it is named, and the full catalog follows. The exit code is unchanged for both, and is now pinned by a test rather than inherited
No public API was added. The completions are rendered by narrowing what
HelpRendereris given rather than teaching it a new shape, which keeps it the only place help text is produced
Notes #
- This does not give the surface position help of its own.
api graphql --helpstill renders nothing; what changes is that the error stops calling it unknown. Whether a CLI should have three levels at all is a question for the CLIs built on this SDK, not for the SDK
0.3.3 #
Fixed #
- A command with positionals can be asked for its contract. The router cannot match
show <id>until the id is supplied, soshow --helpfell to the error path — the user had to provide the very argument he was asking about. A command is now named by its route without positional placeholders, so bothshow --helpandhelp showrender its contract.show 1 --helpkeeps working
Added #
CommandContract.name— the route without its positional placeholders, i.e. the tokens a user types to name the commandCommandCatalog.forName— lookup by that name
0.3.2 #
Fixed #
- A command can now declare that it accepts no options, and be enforced.
paramsdefaulted toconst [], so declaring an empty contract was the same value as declaring none: a zero-argument command was indistinguishable from an undeclared one and its arguments went unchecked —init --host fooran, silently doing nothing the flag implied.paramsis now nullable (null= declares nothing, unenforced, as before;[]= declares no options, and any option is rejected)
Changed #
ModularCli.command/ModuleBuilder.commandtakeList<CliParam>? params(wasList<CliParam> params = const []). Source-compatible: omittingparamsbehaves exactly as beforeCommandContract.paramsisList<CliParam>?, withisDeclaredanddeclaredParamsfor the two readings
0.3.1 #
Fixed #
- A registered root route owns the empty invocation.
ModularClirewrote bare<cli>intohelpunconditionally, on the assumption that no route can serve the empty invocation. A CLI that registers one — a dashboard, a status screen, a banner — had that command silently replaced by the help. The rewrite now applies only when nothing claims the empty route; a CLI without a root route is unaffected - The help listing names the root route. Having no token to type, it rendered as a description hanging off a blank column. It is now listed as
(no arguments)— the only way it can be invoked
Added #
- The example registers a root command, so the bare invocation is exercised. Its absence is why no test could see either defect above
0.3.0 #
Added #
- Command contract —
CliParamdeclares a command's parameters (kind, type, short alias, required, default, allowed values) on itsInput, andcommand(...)accepts them viaparams:(#7) - Native help —
help, no arguments,--helpand-hprint the command list to stdout with exit 0. Unknown or invalid usage stays on stderr with exit 64. Ahelpcommand registered by the developer overrides the built-in one - Focused help —
<command> --helprenders that command's contract;<module> --helprenders every command in the module help --json— the full contract catalog as JSON (help.json), the machine twin of the text help, through the existingJsonCliOutput- Enforcement — the declaration governs parsing: aliases resolved, declared defaults applied, values coerced to their declared type, undeclared options and values outside
allowedrejected with exit 7. A rejected invocation is answered with the contract it failed to honour
Changed #
Input.schemaFieldsis now typedList<CliParam>?(wasList<dynamic>?, documented as reserved)- Requires
cli_router: ^0.1.0, which adds theonNotFoundhook the SDK uses to render its own catalog on the error path, and route metadata for positionals
Notes #
- Commands that declare no
paramsbehave exactly as before: not described in help, not enforced
0.2.1 #
0.2.0 #
Added #
ModularCli.command<I, O>()— register root-level commands without a module prefix- Root commands reuse the full
Command<I, O>lifecycle (validate → execute → format) - Root commands honor
--json,--quiet,CommandException, and semantic exit codes - Example
versionroot command inexample/commands/version.dart - 4 new integration tests for root commands
0.1.0 #
Added #
ModularCli— entry point that orchestrates modules, global flags, and TTY detectionModuleBuilder— per-module command registration viacommand()Command<I, O>— abstract unit of work withvalidate()andexecute()lifecycleInput— abstract inbound DTO (deserialize fromCliRequestflags/params)Output— abstract outbound DTO withtoJson()andexitCodeCommandException— structured error withcode,message,details,isRetryableExitCode— semantic exit code constants (0, 1, 2, 4, 5, 6, 7, 64)CliOutput/JsonCliOutput/TextCliOutput— output formatting abstraction--jsonglobal flag — machine-readable JSON output--quiet/-qglobal flag — suppress informational messages- Working example with two modules (greetings + math)
- Full test suite (unit + integration)