Skip to content

fix(parser): handle UPPER_SNAKE_CASE in env key transformation#65

Merged
AgentEnder merged 21 commits intomainfrom
claude/merge-conflicts-sandpack-cwpeT
Apr 8, 2026
Merged

fix(parser): handle UPPER_SNAKE_CASE in env key transformation#65
AgentEnder merged 21 commits intomainfrom
claude/merge-conflicts-sandpack-cwpeT

Conversation

@AgentEnder
Copy link
Copy Markdown
Owner

  • Treat _ as a word separator in fromCamelOrDashedCaseToConstCase,
    alongside the existing - handling
  • Pre-formed UPPER_SNAKE_CASE strings like GREET_NAME now pass through
    unchanged instead of being mangled to GREE_T__NAME
  • Adds regression tests for UPPER_SNAKE_CASE, lower_snake_case, and
    mixed cases

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

AgentEnder and others added 21 commits April 7, 2026 14:29
- Treat `_` as a word separator in `fromCamelOrDashedCaseToConstCase`,
  alongside the existing `-` handling
- Pre-formed UPPER_SNAKE_CASE strings like `GREET_NAME` now pass through
  unchanged instead of being mangled to `GREE_T__NAME`
- Adds regression tests for UPPER_SNAKE_CASE, lower_snake_case, and
  mixed cases

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…tion env demo

Replaces the single-file env.ts example with a multi-file example that
has two runnable entry points:

- per-option-env.ts: shows setting `env: 'KEY'` on individual options
  without any `.env()` call — only annotated options read from the
  environment, giving precise opt-in control
- with-global-env.ts: shows the `.env()` approach where all options get
  env support with an auto-derived prefix (CLI name → UPPER_SNAKE_CASE)

Adds content.md with narrative prose and a table showing auto-derived
variable names, and three test assertions covering both entry points.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Add readDtsFiles helper that recursively reads .d.mts and .d.cts files
from package dist dirs, add TypeDeclarationFile interface, and populate
typeDeclarations in the data() function for Monaco IntelliSense support.
…xample

The env prefix derived from a CLI named "greet-app" is GREET_APP, not
GREET_APP_ — the underscore separator is added by getEnvKey when joining
prefix and option name, not stored as part of the prefix itself.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The extractor name badge felt out of place on the example detail page.
Remaining badges (file count and tags) are unaffected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add aria-pressed to file explorer sidebar buttons so screen readers
  can indicate the currently active file
- Fix command preset button tooltip to show the command name instead of
  the raw args string

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Auto-generated docs now include the --moduleType (--module-type) option
added to the init command, covering type, default, and valid values.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Documents the design decisions and task breakdown used to implement
the Monaco-based IDE playground replacement.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…iSense

Monaco's TypeScript service cannot resolve bare module specifiers like
`import { cli } from 'cli-forge'` without a package.json at the virtual
node_modules path — it needs the exports/typings fields to locate the
declaration entry point.

- +data.ts: read and ship package.json content for cli-forge and parser
- +Page.tsx: register both as addExtraLib before the declaration files so
  TypeScript can resolve the full import chain

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…ound

Two bugs:
- Hydration mismatch: modKey was computed inline with navigator.userAgent,
  causing SSR to render 'Ctrl' while the client rendered '⌘'. Moved to
  useState('Ctrl') + useEffect so SSR and initial client output match.
- 'Could not find source file: inmemory://model/1': Monaco was creating
  models at the default inmemory URI instead of file:/// paths, so the
  TypeScript worker couldn't correlate them with the registered type libs.
  Fixed by passing path={`file:///${activeFile}`} to the Editor component.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…nner

Many examples use `if (require.main === module) { ... }` to guard their
forge() call. Stripping the `if (...)` condition leaves the block as a
standalone block statement, which is valid JS and still executes — so
the forge() call inside is preserved and gets the argv injection applied.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
…yground

Prepend `var module = {}; var require = { main: module };` to all
executed code so that `if (require.main === module)` guards evaluate to
true — the same object reference makes the strict equality hold.

Cleaner than stripping the guard pattern, which would look wrong in the
editor and break alternative idioms.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace configureRehypeTypedoc(options: RehypeTypedocOptions) with
  configureRehypeTypedoc(plugins: Plugin[]) — the context no longer
  exposes raw options, only pre-configured plugins via getRehypePlugins()
- Pass the whole plugin list as a single use() call (PluggableList path)
  so unified unpacks [plugin, options] tuples correctly
- Update call site to use typedoc.getRehypePlugins() instead of the
  removed typedoc.rehypeOptions property

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace placeholder `echo test` command (which never invoked the
  example) with four real tsx invocations
- Cover hello with default name, hello with custom name, goodbye, and
  goodbye --excited to exercise all commands and options

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Replace two-column textarea layout with a full IDE-style interface:
  file explorer sidebar, Monaco editor, bottom terminal panel
- Add virtual .env file for environment variable editing with an
  explanatory comment (cli-forge does not auto-load .env files)
- Smart import stripping: captures import aliases before stripping so
  var declarations are injected matching what the user wrote — fixes
  'already declared' collision when users assign `const cli = cliForge()`
- Strip export statements (default, named, re-exports, type/interface)
  so AsyncFunction does not throw 'Unexpected token export'
- Shim require/module so `if (require.main === module)` guards work
- SSR-safe Monaco load: useState<EditorComponent | null> + useEffect
  import replaces React.lazy/Suspense (fixes CJS/ESM interop crash)
- Register virtual package.json files and .d.mts declarations for
  cli-forge and @cli-forge/parser so Monaco IntelliSense resolves types
- Add playground-globals.d.ts extra lib declaring require/module so
  TypeScript in the editor does not flag the shimmed globals
- Hydration-safe modKey: useState('Ctrl') + useEffect for Mac detection
- Fix model URI: path={`file:///${activeFile}`} so Monaco declarations
  resolve against file:/// virtual paths
- Bake root CLI name into terminal prompt prefix, detected by parsing
  import aliases for cli/CLI from cli-forge across ESM and CJS styles
- Responsive: IDE hidden on <lg, replaced with a graceful degradation
  message and link to example docs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Resolve pnpm-lock.yaml conflict by regenerating lockfile after merge.
Incorporates main's changes: fluent .handler() method, env key
documentation, vite/vike alignment, and vike-plugin-typedoc patch.

https://claude.ai/code/session_01H6NzCDWZnPHpXCEMe74UCX
@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud bot commented Apr 8, 2026

View your CI Pipeline Execution ↗ for commit 1df082e

Command Status Duration Result
nx run-many -t build test e2e lint ✅ Succeeded 4m 17s View ↗
nx build docs-site ✅ Succeeded 40s View ↗

☁️ Nx Cloud last updated this comment at 2026-04-08 01:24:47 UTC

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

Docs Preview: https://craigory.dev/cli-forge/pr/65/

github-actions bot added a commit that referenced this pull request Apr 8, 2026
@AgentEnder AgentEnder merged commit 56ba5f0 into main Apr 8, 2026
4 checks passed
@AgentEnder AgentEnder deleted the claude/merge-conflicts-sandpack-cwpeT branch April 8, 2026 01:33
github-actions bot added a commit that referenced this pull request Apr 8, 2026
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.

2 participants