Skip to content

feat: custom global options#98

Open
franklad wants to merge 14 commits intowevm:mainfrom
franklad:feat/global-options
Open

feat: custom global options#98
franklad wants to merge 14 commits intowevm:mainfrom
franklad:feat/global-options

Conversation

@franklad
Copy link
Copy Markdown
Contributor

@franklad franklad commented Mar 27, 2026

Summary

  • Adds globals and globalAlias options to Cli.create() for defining CLI-wide flags (e.g. --rpc-url, --chain, --profile)
  • Global options are parsed after builtin flags and before command resolution via new Parser.parseGlobals()
  • Available in middleware via c.globals with full type inference
  • Integrated into --help, --llms, --schema, and shell completions
  • Conflict detection at create() time (vs builtins and reserved aliases) and command() time (vs command options and aliases)

API

const cli = Cli.create('forge', {
  globals: z.object({
    rpcUrl: z.string().optional(),
    chain: z.enum(['mainnet', 'sepolia']).default('mainnet'),
  }),
  globalAlias: { rpcUrl: 'r', chain: 'c' },
}).use(async (c, next) => {
  // c.globals.rpcUrl — fully typed
  await next()
})
forge --rpc-url https://rpc.example.com deploy <contract>
forge -r https://rpc.example.com status
forge deploy --chain sepolia

Test plan

  • 15 integration tests (middleware flow, aliases, defaults, routing, help, --llms, --schema, conflicts, negation, position flexibility, error envelopes)
  • 2 type-level tests (generic flow, alias constraint)
  • 22 parser unit tests for parseGlobals
  • 5 completions tests (global flags, aliases, dedup, enum values, booleans)
  • 2 help tests (deprecated globals, defaults rendering)
  • tsc -b clean

franklad added 11 commits March 27, 2026 09:47
Permissive argv scanner that extracts known global flags and passes
unknown flags + positionals through to rest. Reuses all existing
Parser internals (createOptionNames, normalizeOptionName, coerce, etc).
Adds globals as a third generic on Handler, Context, and middleware()
factory following the existing InferVars/InferEnv pattern. Wires
globals into execute.Options and mwCtx construction.
Extends globalOptionsLines, formatRoot, and formatCommand to accept an
optional globals schema. Custom globals render as a separate block
above the built-in global options using the existing optionEntries helper.
Extends complete() to accept an optional globals descriptor. Global
flags are suggested alongside command-specific options with dedup.
Value resolution falls through from command options to globals.
Adds globals as 4th generic on Cli type, all create() overloads, and
create.Options. Stores globals config in WeakMap. Validates against
builtin flag collisions at create() and command option collisions at
command(). Extracts globals via Parser.parseGlobals after builtin
extraction in serveImpl. Passes globals to middleware context,
Help output, Completions, --llms manifests, and --schema output.
13 integration tests (middleware flow, aliases, defaults, routing,
help, --llms, --schema, conflicts, negation, position flexibility),
2 type-level tests (generic flow, alias constraint), and 8 parser
unit tests for parseGlobals.
- Stop unknown flags from greedily eating the next token as a value
- Add -- separator handling in parseGlobals
- Wrap parseGlobals in try/catch for clean error envelopes
- Validate globalAlias values against reserved short flags (-h)
- Check command alias collisions with global aliases
- Include --no-{config} negation in builtin collision list
- Add globals to fetch gateway middleware context
- Delete redundant "stripped from argv" and "work with subcommands" tests
- Update validation error test to match new try/catch behavior
- Use toKebab import instead of inline regex in Completions.ts
Define GlobalsDescriptor once in Cli.ts, replace 6 inline repetitions
across Cli.ts, Help.ts, and Completions.ts.
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 27, 2026

Open in StackBlitz

npm i https://pkg.pr.new/incur@98

commit: 68c502d

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 27, 2026

Codecov Report

❌ Patch coverage is 96.84211% with 6 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@14e4d64). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/Parser.ts 94.04% 4 Missing and 1 partial ⚠️
src/Cli.ts 98.11% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main      #98   +/-   ##
=======================================
  Coverage        ?   92.68%           
=======================================
  Files           ?       23           
  Lines           ?     2899           
  Branches        ?     1153           
=======================================
  Hits            ?     2687           
  Misses          ?      176           
  Partials        ?       36           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

- Add undefined to GlobalsDescriptor.alias for exactOptionalPropertyTypes
- Restructure globalAlias type test to avoid tsc -b @ts-expect-error quirk
- 5 completions tests (global flags, aliases, dedup, enum values, booleans)
- 7 parser tests (-- separator, stacked shorts, count, array, unknown --no-*,
  unknown --flag=value, missing value error)
- 3 cli tests (parseGlobals error envelope, -h alias conflict, command alias conflict)
- 2 help tests (deprecated globals rendering, globals with defaults in formatRoot)
- 6 parser tests (stacked short count/non-boolean/value-taking, short
  missing value, known --no- negation, known --flag=value with array)
- 1 cli test (agent-mode error formatting for globals validation)
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