feat: support extraURLs and detect portless by env by default#228
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds declarative Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #228 +/- ##
==========================================
+ Coverage 49.42% 49.64% +0.22%
==========================================
Files 17 9 -8
Lines 1819 568 -1251
Branches 147 198 +51
==========================================
- Hits 899 282 -617
+ Misses 915 231 -684
- Partials 5 55 +50 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
I think it should be displayed additionally vs overring public url. #227 (comment) |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
test/index.test.ts (1)
15-21:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRestore the original
PORTLESS_URLvalue instead of always deleting it.Line 20 unconditionally deletes the env var; if it was set before this suite, that state is lost for later tests. Snapshot and restore the original value for safer test isolation.
Suggested patch
describe("listhen", () => { let listener: Listener | undefined; + const originalPortlessURL = process.env.PORTLESS_URL; afterEach(async () => { if (listener) { await listener.close(); listener = undefined; } - delete process.env.PORTLESS_URL; + if (originalPortlessURL === undefined) { + delete process.env.PORTLESS_URL; + } else { + process.env.PORTLESS_URL = originalPortlessURL; + } });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/index.test.ts` around lines 15 - 21, The afterEach currently deletes process.env.PORTLESS_URL unconditionally and should instead restore the pre-test value: add a top-level variable (e.g., originalPortlessUrl) and capture process.env.PORTLESS_URL in a beforeAll or beforeEach hook, then in the afterEach for the listener test restore that value by setting process.env.PORTLESS_URL = originalPortlessUrl when defined or deleting it when undefined; update the afterEach block that references listener to use this restore logic and clear originalPortlessUrl if desired.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@test/index.test.ts`:
- Around line 15-21: The afterEach currently deletes process.env.PORTLESS_URL
unconditionally and should instead restore the pre-test value: add a top-level
variable (e.g., originalPortlessUrl) and capture process.env.PORTLESS_URL in a
beforeAll or beforeEach hook, then in the afterEach for the listener test
restore that value by setting process.env.PORTLESS_URL = originalPortlessUrl
when defined or deleting it when undefined; update the afterEach block that
references listener to use this restore logic and clear originalPortlessUrl if
desired.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 61ea975a-ed92-4a01-92e7-7f5ddc5979c2
📒 Files selected for processing (2)
src/listen.tstest/index.test.ts
There was a problem hiding this comment.
🧹 Nitpick comments (2)
test/index.test.ts (1)
171-221: ⚡ Quick winAdd a dedicated test for
publicURLvsPORTLESS_URLprecedenceThese tests cover
additionalURLsprecedence well, but they don’t directly assert the PR’s stated contract that explicitpublicURLoverridesPORTLESS_URL. A focused test here would lock that behavior and prevent regressions.Suggested test addition
+ test("prefers explicit publicURL over PORTLESS_URL fallback", async () => { + process.env.PORTLESS_URL = "https://fallback.portless.dev"; + listener = await listen(handle, { + hostname: "localhost", + publicURL: "https://configured.example.com", + additionalURLs: [{ title: "Portless", env: "PORTLESS_URL" }], + }); + + const urls = await listener.getURLs(); + expect(urls).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + url: "https://configured.example.com", + }), + ]), + ); + });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/index.test.ts` around lines 171 - 221, Add a focused unit test that ensures an explicit publicURL passed to listen takes precedence over the PORTLESS_URL env var: set process.env.PORTLESS_URL to a fallback value, call listen(handle, { hostname: "localhost", publicURL: "https://explicit.example.com" }), then assert listener.getURLs() contains an object with type "public" and url "https://explicit.example.com" and does not contain the fallback PORTLESS_URL; use the same pattern as existing additionalURLs tests and reference listen, publicURL, process.env.PORTLESS_URL, handle, and listener.getURLs to locate where to add the test.src/types.ts (1)
188-203: ⚡ Quick winRequire at least one source field in
AdditionalURL
AdditionalURLcurrently allows entries with onlytitle, which makes invalid config type-check. Tightening this prevents no-op/undefined URL entries from reaching runtime.Proposed type tightening
-export interface AdditionalURL { - /** - * The label shown in the CLI output. - */ - title: string; - - /** - * Static URL to show. - */ - url?: string; - - /** - * Environment variable that contains the URL to show. - */ - env?: string; -} +export type AdditionalURL = + | { + /** + * The label shown in the CLI output. + */ + title: string; + /** + * Static URL to show. + */ + url: string; + /** + * Optional fallback env when url is absent in downstream overrides. + */ + env?: string; + } + | { + /** + * The label shown in the CLI output. + */ + title: string; + /** + * Environment variable that contains the URL to show. + */ + env: string; + /** + * Optional explicit URL; when provided, runtime can still prefer url. + */ + url?: string; + };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/types.ts` around lines 188 - 203, AdditionalURL currently allows only title and can be empty at runtime; update the type to require at least one source by replacing the interface with a union that combines title with either a required url or a required env (e.g., make AdditionalURL = { title: string } & ({ url: string; env?: string } | { env: string; url?: string })), and adjust any usages of AdditionalURL to satisfy the stronger type (functions or places creating AdditionalURL objects must provide url or env).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/types.ts`:
- Around line 188-203: AdditionalURL currently allows only title and can be
empty at runtime; update the type to require at least one source by replacing
the interface with a union that combines title with either a required url or a
required env (e.g., make AdditionalURL = { title: string } & ({ url: string;
env?: string } | { env: string; url?: string })), and adjust any usages of
AdditionalURL to satisfy the stronger type (functions or places creating
AdditionalURL objects must provide url or env).
In `@test/index.test.ts`:
- Around line 171-221: Add a focused unit test that ensures an explicit
publicURL passed to listen takes precedence over the PORTLESS_URL env var: set
process.env.PORTLESS_URL to a fallback value, call listen(handle, { hostname:
"localhost", publicURL: "https://explicit.example.com" }), then assert
listener.getURLs() contains an object with type "public" and url
"https://explicit.example.com" and does not contain the fallback PORTLESS_URL;
use the same pattern as existing additionalURLs tests and reference listen,
publicURL, process.env.PORTLESS_URL, handle, and listener.getURLs to locate
where to add the test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f5ecc14d-e9fd-4e43-85b7-fe68d18df3ee
📒 Files selected for processing (4)
README.mdsrc/listen.tssrc/types.tstest/index.test.ts
✅ Files skipped from review due to trivial changes (1)
- README.md
🚧 Files skipped from review as they are similar to previous changes (1)
- src/listen.ts
additionalURLs
|
Done! should i create another PR to move tunnel to |
Co-authored-by: Copilot <copilot@github.com>
additionalURLsadditionalURLs and detect portless by env
There was a problem hiding this comment.
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/listen.ts`:
- Around line 226-241: The current additionalURLs loop in listen.ts (using
listhenOptions.additionalURLs, additionalURLs, and pushing into urls) can add
duplicates that other URL-type code avoids; modify the loop to apply the same
de-dup logic used elsewhere before pushing: compute the resolved url (from
additionalURL.url or process.env[additionalURL.env]) and only push an object
into urls if that exact url string is not already present in urls (or call the
existing dedupe helper used for other types if one exists), preserving
type/title/url fields.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
additionalURLs and detect portless by envextraURLs and detect portless by env
extraURLs and detect portless by envextraURLs and detect portless by env by default
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
test/index.test.ts (1)
15-21:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPreserve pre-existing
PORTLESS_URLinstead of always deleting it.Line 20 always deletes the variable, which can unintentionally alter global test-process state outside this suite.
Suggested fix
describe("listhen", () => { let listener: Listener | undefined; + const originalPortlessURL = process.env.PORTLESS_URL; afterEach(async () => { if (listener) { await listener.close(); listener = undefined; } - delete process.env.PORTLESS_URL; + if (originalPortlessURL === undefined) { + delete process.env.PORTLESS_URL; + } else { + process.env.PORTLESS_URL = originalPortlessURL; + } });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/index.test.ts` around lines 15 - 21, afterEach currently always deletes process.env.PORTLESS_URL which can leak state; change the teardown to restore the original value captured before tests instead: add a top-level variable (e.g., originalPortlessUrl) and capture its value in beforeEach (or at module init) and then in afterEach, if originalPortlessUrl is undefined delete PORTLESS_URL, otherwise set process.env.PORTLESS_URL = originalPortlessUrl; keep the existing listener.close() logic intact (refer to afterEach and listener).
🧹 Nitpick comments (1)
test/index.test.ts (1)
171-235: ⚡ Quick winAdd coverage for the implicit default Portless path (
extraURLsomitted).The suite validates explicit
extraURLs, but not the new default fallback behavior wired insrc/listen.ts(defaulting toPORTLESS_URLwhenextraURLsis absent).Suggested test
describe("extra urls", () => { + test("includes default Portless url when extraURLs is omitted", async () => { + process.env.PORTLESS_URL = "https://default.portless.dev"; + listener = await listen(handle, { + hostname: "localhost", + }); + + expect(await listener.getURLs()).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + type: "extra", + title: "Portless", + url: "https://default.portless.dev", + }), + ]), + ); + }); + test("includes env-backed urls (resolved at getURLs time)", async () => {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/index.test.ts` around lines 171 - 235, Add a test to cover the implicit default Portless extra URL when extraURLs is omitted: call listen(handle, { hostname: "localhost" }) (no extraURLs), set process.env.PORTLESS_URL (either before or after listen to assert lazy resolution), then call listener.getURLs() and assert the returned array contains an object with type: "extra", title: "Portless", and url equal to process.env.PORTLESS_URL; ensure you use the existing listener variable and clean up/reset process.env.PORTLESS_URL after the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@test/index.test.ts`:
- Around line 15-21: afterEach currently always deletes process.env.PORTLESS_URL
which can leak state; change the teardown to restore the original value captured
before tests instead: add a top-level variable (e.g., originalPortlessUrl) and
capture its value in beforeEach (or at module init) and then in afterEach, if
originalPortlessUrl is undefined delete PORTLESS_URL, otherwise set
process.env.PORTLESS_URL = originalPortlessUrl; keep the existing
listener.close() logic intact (refer to afterEach and listener).
---
Nitpick comments:
In `@test/index.test.ts`:
- Around line 171-235: Add a test to cover the implicit default Portless extra
URL when extraURLs is omitted: call listen(handle, { hostname: "localhost" })
(no extraURLs), set process.env.PORTLESS_URL (either before or after listen to
assert lazy resolution), then call listener.getURLs() and assert the returned
array contains an object with type: "extra", title: "Portless", and url equal to
process.env.PORTLESS_URL; ensure you use the existing listener variable and
clean up/reset process.env.PORTLESS_URL after the test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 31e7392d-2e87-4d2a-bdf4-76fdd3b9f1f9
📒 Files selected for processing (4)
README.mdsrc/listen.tssrc/types.tstest/index.test.ts
✅ Files skipped from review due to trivial changes (2)
- README.md
- src/types.ts
There was a problem hiding this comment.
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/listen.ts`:
- Around line 224-225: The current assignment for extraURLs uses logical OR
which treats an explicit empty array as falsy and overrides it with the default;
change the fallback chain to use nullish coalescing so only null/undefined fall
back — update the expression that sets extraURLs (referencing
getURLOptions.extraURLs, listhenOptions.extraURLs, and the default Portless
entry) to use ?? between operands instead of ||.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: d102288e-b5ea-48df-8ec5-eb5bd877c893
📒 Files selected for processing (2)
src/listen.tssrc/types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/types.ts

Adds a generic
extraURLsoption for showing integration-managed URLs in listhen output, including env-backed values for cases where the URL is only known at runtime.resolves #227.
Summary by CodeRabbit
New Features
Behavior Changes
Documentation
Tests