feat(cli): add --json output flag to list and env commands - #195
feat(cli): add --json output flag to list and env commands#195aosmcleod wants to merge 3 commits into
Conversation
Apply eslint --fix for sort-keys / sort-destructure-keys / prettier errors in list-action and env-action, and replace direct console.log calls with Logger.log so they no longer trip the no-console rule (--max-warnings=0).
|
@wingkwong fixed the lint. The failing job was ESLint (under the `lint` workflow) with
Local `pnpm lint` now exits clean. Ready for re-review. |
| if (json) { | ||
| Logger.log(JSON.stringify({packages: []}, null, 2)); | ||
| } else { | ||
| Logger.warn( | ||
| 'No HeroUI packages found. Run `heroui install` to install @heroui/react and @heroui/styles.' | ||
| ); | ||
| } |
There was a problem hiding this comment.
The key message "No HeroUI packages found. Run heroui install to install @heroui/react and @heroui/styles." should be shown even in --json mode.
{
"packages": []
}
|
|
||
| export async function envAction(options: EnvOptions) { | ||
| const {packagePath = resolver('package.json')} = options; | ||
| const {json, packagePath = resolver('package.json')} = options as EnvOptions & {json?: boolean}; |
There was a problem hiding this comment.
avoid as ... & { json?: boolean }. just add it in EnvOptions
|
|
||
| export async function listAction(options: CommandOptions) { | ||
| const {packagePath = resolver('package.json')} = options; | ||
| const {json, packagePath = resolver('package.json')} = options as CommandOptions & { |
There was a problem hiding this comment.
avoid as ... & { json?: boolean }. just add it in CommandOptions
| } catch (error) { | ||
| Logger.prefix('error', `An error occurred while listing packages: ${error}`); | ||
| if (json) { | ||
| Logger.log(JSON.stringify({error: String(error)}, null, 2)); |
There was a problem hiding this comment.
if it is an error, it shouldn't use Logger.log
- Add `json?: boolean` to CommandOptions and EnvOptions, drop the
`as ... & { json?: boolean }` casts in both action files.
- Restructure JSON package objects to match the requested CI-friendly
shape: split the previous `"current -> latest"` string into discrete
`version`, `latestVersion`, `upgradeAvailable`, `versionMode` fields.
Helper lives in @helpers/package as mapPackageComponentForJson.
- list --json with no installed packages now ALSO emits the human
hint (via Logger.warn → stderr) so the message isn't silently
dropped, while the `{ "packages": [] }` JSON still goes to stdout.
- list --json error path uses Logger.error (stderr) instead of
Logger.log so errors don't masquerade as regular output.
- Suppress the gradient "HeroUI CLI v<version>" branding banner when
`--json` is on the command line so the JSON payload on stdout
remains clean for `... --json | jq` pipelines.
|
@wingkwong addressed all four inline comments plus the JSON shape suggestion: Type definitions — added JSON output shape — restructured to match your suggestion. The previous string-with-arrow ```json (Keys are alphabetized to satisfy
Bonus — found a separate stdout-pollution issue while testing: the gradient "HeroUI CLI v<version>" banner was emitting to stdout on every command, contaminating Ready for re-review. |

Closes #192
📝 Description
Adds a
--jsonflag to thelistandenvcommands that outputs structured JSON instead of the human-readable box-drawing tables.heroui list --json{ "packages": [ { "package": "@heroui/react", "version": "3.0.0 -> 3.0.4", "status": "stable", "docs": "https://heroui.com" }, { "package": "@heroui/styles", "version": "3.0.0 -> 3.0.4", "status": "stable", "docs": "https://heroui.com" } ] }heroui env --json{ "packages": [...], "environment": { "os": "darwin", "arch": "arm64", "nodeVersion": "v22.0.0" } }Why
--json)Implementation
The data was already structured internally as
PackageComponent[]objects. This PR adds an alternative output path:--jsonoption tolistandenvcommand registrationJSON.stringifys the data instead of callingoutputComponents()--jsonis set, outputs clean JSON to stdout (no banners, no colors)💣 Is this a breaking change (Yes/No):
No — the flag is opt-in. Default behavior is unchanged.
✅ Type of change