Skip to content

fix(cli): set output mode before loadLocalEnv, normalise URLs - #8

Closed
DuncanAForbes wants to merge 1 commit into
mainfrom
develop
Closed

fix(cli): set output mode before loadLocalEnv, normalise URLs#8
DuncanAForbes wants to merge 1 commit into
mainfrom
develop

Conversation

@DuncanAForbes

@DuncanAForbes DuncanAForbes commented Apr 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Addresses CodeRabbit feedback from PR #7:

  • Output mode ordering: setOutputMode now runs before loadLocalEnv() in the preAction hook, so --json / --quiet flags are active before any loader messages print
  • URL normalization: Adds normalizeUrl() helper that strips surrounding quotes, removes trailing slashes, and validates http(s):// scheme on .env.local URL values

Test plan

  • bagdock login --ngrok --json produces no text before JSON output
  • .env.local with BAGDOCK_API_URL="https://foo.ngrok.app/" resolves to https://foo.ngrok.app (no quotes, no trailing slash)
  • .env.local with BAGDOCK_API_URL=not-a-url exits with a clear error

Summary by CodeRabbit

  • New Features

    • Added --ngrok global CLI flag to load API and dashboard URLs from .env.local file at runtime.
  • Improvements

    • API and dashboard base URLs now resolve dynamically at runtime instead of compile time, allowing flexible configuration.
    • Enhanced URL validation with automatic normalisation and error handling for invalid URLs.
  • Version

    • Bumped version to 0.6.0.

@coderabbitai

coderabbitai Bot commented Apr 6, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@DuncanAForbes has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 21 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 10 minutes and 21 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9f4833e3-cba9-45bc-8a1e-5d0a5d478891

📥 Commits

Reviewing files that changed from the base of the PR and between 153fdd7 and fbd4632.

📒 Files selected for processing (2)
  • bin/bagdock.ts
  • src/config.ts

Walkthrough

The changes implement runtime-configurable API and dashboard base URLs, replacing compile-time constants with dynamic getters. A new --ngrok CLI flag triggers loading environment variables from .env.local, enabling flexible API endpoint configuration. Version incremented to 0.6.0 across package metadata.

Changes

Cohort / File(s) Summary
CLI & Version Updates
bin/bagdock.ts, package.json
Added global --ngrok flag to CLI that triggers loadLocalEnv() on execution; version bumped to 0.6.0 and @types/bun dependency pinned to ^1.3.10.
Config Infrastructure
src/config.ts
Replaced static API_BASE/DASHBOARD_BASE constants with mutable internal variables backed by getter functions getApiBase() and getDashboardBase(). Added loadLocalEnv() to parse .env.local from working directory, and normalizeUrl() to validate and normalise URLs; missing .env.local or required variables trigger process termination.
API & Auth Endpoints
src/api.ts, src/auth.ts, src/deploy.ts, src/submit.ts
Updated all HTTP requests (device auth, token polling, user info, deploy, submit) to call getApiBase() at runtime instead of importing static API_BASE constant.
Dashboard URL
src/open.ts
Changed dashboard URL construction to use getDashboardBase() function at runtime instead of static DASHBOARD_BASE constant.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI as CLI (bin/bagdock.ts)
    participant Config as Config Module
    participant Env as .env.local
    participant API as API Endpoint

    User->>CLI: Execute command with --ngrok flag
    CLI->>CLI: Check opts.ngrok in preAction hook
    alt ngrok flag set
        CLI->>Config: Call loadLocalEnv()
        Config->>Env: Read .env.local from cwd
        Env-->>Config: BAGDOCK_API_URL, BAGDOCK_DASHBOARD_URL
        Config->>Config: normalizeUrl() validation & normalisation
        Config->>Config: Update _apiBase, _dashboardBase variables
        Config-->>CLI: Configuration loaded (print message)
    end
    
    CLI->>CLI: Apply per-invocation overrides (--api-key, --profile, --env)
    CLI->>API: Make API request
    API->>Config: getApiBase() called at request time
    Config-->>API: Return current _apiBase value
    API-->>CLI: Response
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

Poem

🐰 Constants? Nay! Let URLs flow free,
From .env.local files, just let them be,
The --ngrok flag hops with glee,
Runtime configs—dynamic as can be! 🚀✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the two main fixes: output mode ordering before loadLocalEnv and URL normalisation in .env.local handling.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/config.ts`:
- Around line 38-69: Change loadLocalEnv to accept an optional options object
(e.g., loadLocalEnv({ silent?: boolean } = {})) and use that silent flag to
suppress the final informational console.log; leave error console.error calls
intact so failures still surface. Update the call site (where loadLocalEnv is
invoked, e.g., in bin/bagdock.ts) to pass { silent: Boolean(opts.json ||
opts.quiet) } when running in JSON/quiet mode so the dim "Using local env → ..."
line does not emit during --json/--quiet.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9bcca0c5-81f1-4351-9f26-9a2eff73d41e

📥 Commits

Reviewing files that changed from the base of the PR and between 47873a0 and 153fdd7.

📒 Files selected for processing (8)
  • bin/bagdock.ts
  • package.json
  • src/api.ts
  • src/auth.ts
  • src/config.ts
  • src/deploy.ts
  • src/open.ts
  • src/submit.ts

Comment thread src/config.ts
Comment on lines +38 to +69
export function loadLocalEnv() {
const envPath = join(process.cwd(), '.env.local')
if (!existsSync(envPath)) {
console.error(chalk.red('No .env.local found in'), chalk.bold(process.cwd()))
console.error(chalk.dim('Create one with BAGDOCK_API_URL=https://your-ngrok-url'))
process.exit(1)
}

const vars: Record<string, string> = {}
const lines = readFileSync(envPath, 'utf-8').split('\n')
for (const line of lines) {
const trimmed = line.trim()
if (!trimmed || trimmed.startsWith('#')) continue
const eq = trimmed.indexOf('=')
if (eq === -1) continue
vars[trimmed.slice(0, eq).trim()] = trimmed.slice(eq + 1).trim()
}

const apiUrl = vars['BAGDOCK_API_URL']
if (!apiUrl) {
console.error(chalk.red('BAGDOCK_API_URL not found in .env.local'))
console.error(chalk.dim('Add BAGDOCK_API_URL=https://your-ngrok-url to .env.local'))
process.exit(1)
}

_apiBase = normalizeUrl(apiUrl)
if (vars['BAGDOCK_DASHBOARD_URL']) {
_dashboardBase = normalizeUrl(vars['BAGDOCK_DASHBOARD_URL'])
}

console.log(chalk.dim(`Using local env → ${_apiBase}`))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

loadLocalEnv() still emits stdout in JSON/quiet mode.

Line 68 prints unconditionally, so commands using --ngrok --json can still emit non-JSON text before structured output.

Proposed fix
-export function loadLocalEnv() {
+export function loadLocalEnv(opts: { silent?: boolean } = {}) {
   const envPath = join(process.cwd(), '.env.local')
@@
-  console.log(chalk.dim(`Using local env → ${_apiBase}`))
+  if (!opts.silent) {
+    console.log(chalk.dim(`Using local env → ${_apiBase}`))
+  }
 }
// bin/bagdock.ts (call site)
if (opts.ngrok) loadLocalEnv({ silent: Boolean(opts.json || opts.quiet) })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/config.ts` around lines 38 - 69, Change loadLocalEnv to accept an
optional options object (e.g., loadLocalEnv({ silent?: boolean } = {})) and use
that silent flag to suppress the final informational console.log; leave error
console.error calls intact so failures still surface. Update the call site
(where loadLocalEnv is invoked, e.g., in bin/bagdock.ts) to pass { silent:
Boolean(opts.json || opts.quiet) } when running in JSON/quiet mode so the dim
"Using local env → ..." line does not emit during --json/--quiet.

- Reorder preAction hook so --json/--quiet flags are active before
  loadLocalEnv prints any messages
- Add normalizeUrl() to strip surrounding quotes, trailing slashes, and
  validate http(s) scheme on .env.local URL values
@DuncanAForbes

Copy link
Copy Markdown
Contributor Author

Replaced with a fresh PR after rebasing develop onto main to fix SHA divergence from squash merge.

@DuncanAForbes
DuncanAForbes deleted the develop branch April 6, 2026 20:19
@DuncanAForbes
DuncanAForbes restored the develop branch April 6, 2026 20:21
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