#457

Proposal: let portless.json pin the proxy settings, so one file configures the proxy for every checkout

OpenKnat-Devopened 1mo ago

The gap

Every proxy option has a flag and a PORTLESS_* variable, and that pairing is the right design: flags exist only on proxy start and service install, while the proxy is usually auto-started by portless run or the zero-arg portless, which take no proxy flags. So the variable is how an auto-start learns how the proxy should run.

The consequence is that a project cannot say how its proxy should run. A team that wants plain HTTP, wildcard routing or (after #455) unprivileged mode on every machine has each developer export the variables, and the README already warns that per-project installs leave contributors on different configurations. Scripted runs hit it too (#392): a runner with a clean environment gets the defaults, and in a Turborepo root the per-shell environment is what made registrations drift (#332). An agent on a fresh checkout has no shell profile at all.

Proposal: the proxy variables as portless.json keys

{ "https": false, "wildcard": true, "unprivileged": true }

Six keys, each the camelCase form of the variable it stands for:

KeyVariable
httpsPORTLESS_HTTPS
portPORTLESS_PORT
tldPORTLESS_TLD (string or array)
wildcardPORTLESS_WILDCARD
syncHostsPORTLESS_SYNC_HOSTS
unprivilegedPORTLESS_UNPRIVILEGED

At startup each key becomes the default for its variable when nothing has set it. That one rule gives the precedence the docs already describe for appPort: CLI flag, then env var, then config, then the last proxy run, then default. Nothing in the resolvers changes; every command, and every proxy it starts, sees the variable as if it had been exported. The package.json "portless" key works the same way.

Two details that follow from the proxy being one per machine:

  • A package directory inside a workspace with no proxy settings of its own uses the workspace root's. App keys keep the current-directory-only rule.
  • When a file disagrees with a proxy that is already running, the existing "stop it first" error names the file and the keys it supplied, so a developer is not told about a conflict they never typed.

A combination that can never work, unprivileged: true with syncHosts: true (writing the hosts file needs root), is rejected when the file is read, before any process starts. Types are strict JSON types: booleans, an integer port, a string or array for tld validated with the same rules as --tld.

What does not change

Without any of the six keys, nothing happens: no variable is set and every code path runs as today. Anyone who already had a top-level port or https in their config was getting an unknown-key warning and no effect; after this it takes effect, which is the one compatibility note.

Verified

Unit tests for each key's mapping, the "already set wins" rule, the workspace-root fallback and the in-file conflict; CLI tests that the proxy starts from the file alone, that an exported variable and a flag each beat it, that a package directory picks up the root file, that the mismatch error names the file, that the conflict is refused before any state is written, that --help still works with an invalid file, and that portless run auto-starts the proxy from the file. End to end on top of #456: a committed portless.json with unprivileged, wildcard and https: false, nothing exported and no TTY, brought up the proxy on *:80 as a normal user from a git worktree and served the app, Storybook beside it and a tenant-prefixed hostname.

PR follows.

Activity

0

No activity yet.