Skip to content

refactor(config): enhance config with @clevercloud/reglage - #1081

Open
pdesoyres-cc wants to merge 8 commits into
masterfrom
enhance-config
Open

refactor(config): enhance config with @clevercloud/reglage#1081
pdesoyres-cc wants to merge 8 commits into
masterfrom
enhance-config

Conversation

@pdesoyres-cc

@pdesoyres-cc pdesoyres-cc commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Context

The config module was hand-rolled around a Zod schema plus safeParse, with a few sharp edges that
made it awkward to extend:

  • Reload mutated the singleton in place (delete every key, then Object.assign) so consumers that
    imported config saw fresh values. Fragile, and incompatible with any immutable config object.
  • Profiles flowed through the same Zod schema as configuration values, even though they are
    auth-related runtime state, not user-facing config.
  • We had no first-class notion of named sources, derived keys, or secret marking — features we kept
    reaching for ad hoc.

@clevercloud/reglage is a purpose-built config builder that gives us all of the above out of the
box. Adopting it lets us delete the bespoke validation/merge code and gain better diagnostics
(per-source error attribution, structured toString, secret redaction) for free.

Changes

  • Wrap config in a Config class exposing a typed get(key) accessor. reload() now swaps the
    inner config reference instead of mutating fields in place.
  • Migrate every call site from config.API_HOST / config.TOKEN / etc. to config.get('API_HOST'),
    config.activeProfile?.token, and so on.
  • Split BaseConfig (validated config values) from Config (adds profiles and activeProfile as
    dedicated properties). The $env virtual profile derived from CLEVER_TOKEN / CLEVER_SECRET
    lives here too.
  • Replace the Zod safeParse pipeline with createConfigBuilder from @clevercloud/reglage.
    CONSOLE_TOKEN_URL and GOTO_URL become refine-based derived keys off CONSOLE_URL; OAuth
    consumer key/secret are marked secret: true.
  • Add 23 unit tests covering defaults, env overrides, derived keys, profile overrides, source
    priority, and reload semantics. Wire npm test into the validate script and the
    code-quality CI workflow.

Implementation notes

The Config wrapper is the linchpin: reglage produces immutable config instances, so we cannot
keep mutating a shared object on reload. The wrapper lets every consumer hold a stable reference
to config while the inner immutable object gets swapped on reloadConfig(). That is also why
the call-site migration to get() is mandatory rather than cosmetic — direct property access on
the inner instance would skip the swap.

How to review

  1. Start with src/config/config.js — the BaseConfig / Config split, loadConfig(), and
    buildConfig() are the load-bearing pieces.
  2. Skim src/config/config.test.js to see the contract that's now pinned down (defaults, env
    overrides, derived keys, profile overrides, priority, reload).
  3. Run npm test locally to exercise the suite; CI now runs it via the new step in
    .github/workflows/code-quality.yml.
  4. Spot-check a few migrated call sites (e.g. src/models/send-to-api.js,
    src/commands/curl/curl.command.js, src/commands/login/login.command.js) to confirm the
    config.get(...) / config.activeProfile pattern reads cleanly.

@pdesoyres-cc
pdesoyres-cc requested a review from a team as a code owner April 10, 2026 14:29
@pdesoyres-cc pdesoyres-cc self-assigned this Apr 10, 2026
@pdesoyres-cc
pdesoyres-cc force-pushed the enhance-config branch 2 times, most recently from 13ca0ae to 763778f Compare April 10, 2026 14:34
@github-actions

github-actions Bot commented Apr 10, 2026

Copy link
Copy Markdown

🔎 A preview has been automatically published!

If you created the alias to the preview script, you can run this command to download and install this preview:

clever-preview update enhance-config

You can also run it from your local repository:

./scripts/preview.js update enhance-config
OS SHA256 checksum
🐧 linux c3ea9c5f6f54d7cd3cbd137469aa29e2217a1e51a35c52f92d6c1e4516c9f451
🍏 macos 244b0fb324cf11c6aa62411dfc77d2be1b8cd2121cefd850a87e439cbc94e2e9

This preview will be deleted once this PR is closed.

Pierre DE SOYRES added 8 commits May 6, 2026 11:03
Introduce a Config class that holds the config data and exposes a
typed `get()` method with proper Zod type inference. This replaces the
previous mutate-in-place reload strategy (delete all keys + Object.assign)
with a clean `reload()` that swaps the inner reference.

This is needed for the integration of @clevercloud/reglage, which
provides immutable config instances that cannot be mutated in place.
The Config wrapper lets us swap the immutable inner object on reload
while keeping the same singleton reference for all consumers.
Replace all direct property accesses (config.API_HOST, baseConfig.TOKEN, etc.)
with config.get('API_HOST'), baseConfig.get('TOKEN'), etc. across the codebase.

This ensures all consumers go through the Config class accessor, which is
required for the reglage integration where the underlying config object
is immutable and gets swapped on reload.
Split Config into BaseConfig (Zod-validated config values) and Config
(extends BaseConfig with profiles/activeProfile as dedicated properties).

Profiles are auth-related runtime state, not configuration values —
they no longer pass through the Zod schema. loadConfig() now returns
{ data, profiles } separately, and reloadConfig() updates each independently.
Update all consumers to use the new Config properties instead of
config.get('profiles'), config.get('token'), config.get('secret').
Profiles and auth credentials are now accessed through config.profiles,
config.activeProfile, and config.activeProfile?.token/secret.
Replace the hand-rolled Zod schema + safeParse approach with
@clevercloud/reglage's createConfigBuilder, gaining named sources,
refine-based derived keys, secret marking, and structured toString
output. Remove now-unnecessary test helpers and add coverage for
explicit CONSOLE_TOKEN_URL / GOTO_URL overrides
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