Skip to content

Type command values from declared option presets#4

Merged
cnluzhang merged 4 commits into
mainfrom
claude/cli-security-hardening-tctybe
Jun 30, 2026
Merged

Type command values from declared option presets#4
cnluzhang merged 4 commits into
mainfrom
claude/cli-security-hardening-tctybe

Conversation

@cnluzhang

Copy link
Copy Markdown
Contributor

What

Adds a PresetFlags<P> typedef to lib/command.js and uses it across the command handlers so each command's values type derives the preset-contributed flags from a single source instead of restating them per command.

Why

Every command's run body typed its values shape by hand, re-listing the flags its option presets ("ns", "control", "json", ...) expand to. That duplicated CLI_OPTION_PRESETS in common.js and could silently drift from it — a preset gaining or dropping a flag (e.g. --control picking up --no-token-store) would not surface in any handler's type.

How

  • PresetValueMap records the values each preset contributes, kept beside the preset-name doc it mirrors.
  • PresetFlags<"ns" | "control" | "json"> intersects the chosen presets via a UnionToIntersection helper.
  • Commands name their presets and intersect only their own defineCliOption flags inline, e.g. PresetFlags<"ns" | "control" | "json"> & { worker?: string, yes?: boolean }.

Type-only change: no runtime behavior change, zero any. Converted config, d1, delete, deploy, doctor, r2, secret, tail, token, whoami, workflows. workers reads context.values (no typed binding) and init uses its own parse shell, so both are untouched.

Checks

  • npm run typecheck — clean
  • npm run lint — clean
  • npm test — 379/379 pass

🤖 Generated with Claude Code


Generated by Claude Code

Each command's run body typed its `values` shape by hand, re-listing the flags
its option presets ("ns", "control", "json", ...) expand to. That duplicated
CLI_OPTION_PRESETS in common.js and could silently drift from it -- a preset
gaining or dropping a flag would not surface in the handler's type.

Add a `PresetFlags<P>` typedef to lib/command.js: `PresetValueMap` records the
`values` each preset contributes (kept beside the preset list it mirrors), and
`PresetFlags<"ns" | "control" | "json">` intersects a chosen set via a
`UnionToIntersection` helper. Commands now name their presets and intersect
only their own defineCliOption flags inline, e.g.
`PresetFlags<"ns" | "control" | "json"> & { worker?: string, yes?: boolean }`.

This is type-only: no runtime change, zero `any`, and the preset-contributed
portion of every handler's `values` is now derived from one source instead of
restated per command. Converted config, d1, delete, deploy, doctor, r2, secret,
tail, token, whoami, and workflows; workers reads `context.values` (no typed
binding) and init uses its own parse shell, so both are untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Lu Zhang <lu@wdl.dev>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR centralizes the JSDoc typing for command values by deriving preset-contributed flag shapes from a single map, reducing per-command duplication and preventing preset/type drift as shared option presets evolve.

Changes:

  • Add PresetValueMap, UnionToIntersection, and PresetFlags<P> typedefs in lib/command.js to model the parsed values each option preset contributes.
  • Update command handlers’ values parameter types to use PresetFlags<...> intersected with command-specific flags.
  • Align preset typing with the current preset set (including "control" carrying --no-token-store and the "endpoint" preset).

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.

Show a summary per file
File Description
lib/command.js Introduces PresetValueMap + PresetFlags<P> to type preset-expanded values from one source.
commands/config.js Switches values typing to PresetFlags<"ns" | "control" | "json">.
commands/d1.js Replaces the hand-written flags typedef with PresetFlags<...> + D1-specific flags.
commands/delete.js Uses PresetFlags<"ns" | "control" | "json"> for shared flags and keeps delete-specific flags inline.
commands/deploy.js Uses PresetFlags<"ns" | "control"> to include shared auth/namespace flags alongside deploy flags.
commands/doctor.js Switches values typing to the relevant preset-derived shape.
commands/r2.js Uses PresetFlags<"ns" | "control" | "json"> plus R2-specific flags.
commands/secret.js Uses PresetFlags<"ns" | "control" | "json"> plus secret-specific flags.
commands/tail.js Uses PresetFlags<"ns" | "control"> plus tail-specific flags.
commands/token.js Uses PresetFlags<"endpoint"> to type --control-url while keeping token subcommand flags explicit.
commands/whoami.js Switches values typing to PresetFlags<"ns" | "control" | "json">.
commands/workflows.js Uses PresetFlags<"ns" | "control" | "json"> plus workflows-specific flags.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

`runWorkers` was the last defineCommand handler still reading the json flag off
the untyped `context.values` (Record<string, unknown>), leaving its
["ns", "control", "json"] schema uncovered by the typed preset composition.

Bind a typed `values: PresetFlags<"ns" | "control" | "json">` in the run body
and thread the json boolean into printWorkersList as a parameter, so the read
goes through the derived type instead of the loose context bag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Lu Zhang <lu@wdl.dev>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comment thread lib/command.js Outdated
Reword the parenthetical so it no longer says "--control preset" (the preset is
the string "control"; there is no --control flag) and separates preset names
from the parsed `values` keys they map to.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Lu Zhang <lu@wdl.dev>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

The clarification repeated "keyed by preset name"; collapse it to one line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Lu Zhang <lu@wdl.dev>
@cnluzhang cnluzhang merged commit a0150e4 into main Jun 30, 2026
6 checks passed
@cnluzhang cnluzhang deleted the claude/cli-security-hardening-tctybe branch June 30, 2026 04:32
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.

3 participants