Skip to content

One helper builds the body a command sends - #38

Merged
curquiza merged 1 commit into
mainfrom
body-fields-helper
Nov 1, 2026
Merged

curquiza merged 1 commit into
mainfrom
body-fields-helper

Conversation

@curquiza

@curquiza curquiza commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

What

Four commands spelled out the same body merge, comment included. readBodyWithFields says it once, in src/lib/input.ts. No behaviour changes.

Follow-up to the simplify passes of #36 and #37, where two reviewers independently named this as pre-existing debt rather than a finding against those diffs.

Contract

  • The command name and flags derive from its routes by the naming rules of docs/contract/commands.md, and each route is reachable by a distinct set of flags, or the exception is recorded with its reason (or this pull request changes the contract and nothing else)
  • Output goes through src/lib/output.ts, errors through src/lib/errors.ts
  • The command never waits for a human: no prompt, no question, no $EDITOR; a delete command spreads BaseCommand.confirmFlags and its examples carry --yes
  • The command never speaks HTTP itself: the SDK or the generated client only, no fetch outside src/lib/clients/

No command name, flag, variable, error code or output shape changes. search, similar, facet-search and update settings send exactly the body they sent before, which is why no snapshot moves.

Tests

  • --help snapshot added or updated on purpose
  • JSON output snapshot for one success case per route and one error case
  • Integration test added (Meilisearch API commands only)
  • pnpm lint, pnpm typecheck, pnpm test pass locally

No snapshot was touched: a refactor that changed one would be a bug, and that is the point of the box. The rule the deleted comment carried is now a unit test of its own in test/lib/input.test.ts: a field overrides the body, an undefined field does not erase it, and null stays a value.

Simplicity

  • Nothing in the diff exists for a case the API cannot produce, a caller that does not exist, or a generality nobody asked for (rule 16)
  • Anything shared lives in src/lib/, is used by this command, and is named below

readBodyWithFields in src/lib/input.ts, called by the four commands above. It lives there rather than in src/lib/values.ts, which the reviewers suggested: it calls readJsonObjectBody and takes BodyInputFlagValues, both of which input.ts already owns, while values.ts converts one flag value at a time and imports nothing. Net effect on the four command files: −33 lines.

Docs

  • docs/contract/ updated for every name, flag, variable or code this change adds or renames, or nothing to update
  • The ADRs that touch this change were read; what they decide still holds, or a new ADR says what changed
  • No accepted ADR was edited. A new ADR was added if a decision changed.

Nothing to update: rule 8 of commands.md already describes the behaviour, and the helper is named after it.

Housekeeping

  • oclif.manifest.json regenerated
  • Changeset added, or the change is invisible to users of the package (docs of this repository, tests, CI)
  • New dependency justified below, or none added

No changeset: no command, flag or output changes, so there is nothing for a user of the package to read in a changelog. Say the word if you would rather have one anyway.

Notes for the reviewer

One question for you. Three commands build their body the other way, with if (flag !== undefined) body.field = flag: multi-search (two fields), add indexes (one) and update indexes (two). They would read slightly shorter through the same helper, and the codebase would have one way to do this instead of two. I left them alone because converting them was not what this change was asked for, and because the if form is arguably clearer at one field. Tell me which you prefer and I will finish it either way.

Merge order. This branch starts from main at 2241077. #37 adds two more call sites of the old form, in add keys and update keys. Whichever of the two merges second, I convert them in the same pass — no conflict either way, they touch different files.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Search, similar-search, facet-search, and settings commands now combine JSON body data with command options consistently.
    • Explicit command options override matching values in the body, while omitted options preserve body values. Explicit null values are retained.

Four commands spelled out the same merge, comment included: the JSON of
`--file` or `--data` first, then the fields their flags define, the
undefined ones dropped so that an absent flag does not erase what the body
carries. `readBodyWithFields` says it once, in `src/lib/input.ts`, next to
the `readJsonObjectBody` it calls and to the rest of the body input. No
behaviour changes: no snapshot moves, and the rule the comment carried is
now a unit test of its own.

`multi-search`, `add indexes` and `update indexes` keep their `if (flag !==
undefined)` form: one or two fields each, and whether they should go the
same way is a question for the reviewer, not a silent change here.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 5c3e7d4a-acce-4a2e-a575-5c023edd76fe
Commits

Reviewing files that changed from the base of the PR and between 2241077 and fd4a114.

Files selected for processing: 6
  • src/commands/facet-search.ts
  • src/commands/search.ts
  • src/commands/similar.ts
  • src/commands/update/settings.ts
  • src/lib/input.ts
  • test/lib/input.test.ts

Included review availability: This review used your included allowance. 4 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.

Walkthrough

A shared helper now merges JSON body values with command fields. Facet search, search, similar, and update settings use it. Tests cover field precedence, undefined values, and null values.

Changes: Body and field merging

Layer / File(s) Summary
Shared merge helper
src/lib/input.ts, test/lib/input.test.ts
Added and tested readBodyWithFields. Defined fields override body values; undefined fields leave body values unchanged; null fields remain present.
Command adoption
src/commands/facet-search.ts, src/commands/search.ts, src/commands/similar.ts, src/commands/update/settings.ts
These commands now use readBodyWithFields to construct parameters from body data and command fields.

Priority: Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Refactor

Possibly related PRs

  • meilisearch/cli#21: Introduces the shared body-input flow that this change uses.
  • meilisearch/cli#24: Adds readJsonObjectBody and related body-and-field merging that this change centralizes.
  • meilisearch/cli#33: Adds facet-search with the body-field precedence behavior now handled by the shared helper.
Merge Risk: Minimal · up to fd4a1

The change consolidates body merging without an identified behavior regression. It is ready to merge after normal checks.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the main change: one shared helper now builds request bodies for multiple commands.
Docstring Coverage Passed No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 0 functions across 6 files.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@curquiza
curquiza merged commit fc5694d into main Nov 1, 2026
3 checks passed
curquiza added a commit that referenced this pull request Nov 1, 2026
`readBodyWithFields` landed in #38 while this branch was open, so
`add keys` and `update keys` were the last two copies of the merge it
replaces. No behaviour changes and no snapshot moves.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
curquiza added a commit that referenced this pull request Nov 1, 2026
* Add the four `keys` commands, the five routes of /keys

`get keys` covers the list and the unit route, `add keys` creates one with
`--actions`, `--indexes` and `--expires-at`, where `null` means no expiry,
`update keys` changes the two fields the route takes, and `delete keys`
answers nothing: the route returns 204.

The `key` field reaches stdout as the API answers it. `output.md` already
said that a secret an API returns is data the agent needs, while the Secrets
section of `config.md` still read "API keys and tokens never appear on
stdout". The two contradicted each other on exactly these routes, and the
rule now distinguishes the credentials the CLI holds to reach an API, still
redacted everywhere, from a credential an API returns, which passes through.
Rule 8 of CLAUDE.md follows.

`GET /keys` goes through `fetchKeys` in `src/lib/clients/`: `getKeys` of
meilisearch-js rewrites `createdAt` and `updatedAt` into `Date` objects,
which JSON writes back with milliseconds where Meilisearch answered
nanoseconds. ADR 0003 allows `client.httpRequest` for exactly that, as
`fetchStats` does. The four other routes return the body untouched, so they
call the SDK.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Say what redaction does not cover

A key named with `get keys --id <key value>` travels in the request path,
where the `--debug` trace prints it: redaction covers the headers and the
body fields the bullet below lists, and the Secrets section said more than
that. It now says exactly what it covers, and names this case, which is as
visible as any other value of the command line.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Build the body of the keys commands with the shared helper

`readBodyWithFields` landed in #38 while this branch was open, so
`add keys` and `update keys` were the last two copies of the merge it
replaces. No behaviour changes and no snapshot moves.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant