portless 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/cli.js +34 -3
  2. package/package.json +11 -30
  3. package/README.md +0 -160
package/dist/cli.js CHANGED
@@ -599,6 +599,28 @@ function spawnCommand(commandArgs, options) {
599
599
  process.exit(code ?? 1);
600
600
  });
601
601
  }
602
+ var FRAMEWORKS_NEEDING_PORT = {
603
+ vite: { strictPort: true },
604
+ "react-router": { strictPort: true },
605
+ astro: { strictPort: false },
606
+ ng: { strictPort: false }
607
+ };
608
+ function injectFrameworkFlags(commandArgs, port) {
609
+ const cmd = commandArgs[0];
610
+ if (!cmd) return;
611
+ const basename2 = path2.basename(cmd);
612
+ const framework = FRAMEWORKS_NEEDING_PORT[basename2];
613
+ if (!framework) return;
614
+ if (!commandArgs.includes("--port")) {
615
+ commandArgs.push("--port", port.toString());
616
+ if (framework.strictPort) {
617
+ commandArgs.push("--strictPort");
618
+ }
619
+ }
620
+ if (!commandArgs.includes("--host")) {
621
+ commandArgs.push("--host", "127.0.0.1");
622
+ }
623
+ }
602
624
  function prompt(question) {
603
625
  const rl = readline.createInterface({
604
626
  input: process.stdin,
@@ -891,10 +913,16 @@ portless
891
913
  console.log(chalk.cyan.bold(`
892
914
  -> ${finalUrl}
893
915
  `));
894
- console.log(chalk.gray(`Running: PORT=${port} ${commandArgs.join(" ")}
916
+ injectFrameworkFlags(commandArgs, port);
917
+ console.log(chalk.gray(`Running: PORT=${port} HOST=127.0.0.1 ${commandArgs.join(" ")}
895
918
  `));
896
919
  spawnCommand(commandArgs, {
897
- env: { ...process.env, PORT: port.toString() },
920
+ env: {
921
+ ...process.env,
922
+ PORT: port.toString(),
923
+ HOST: "127.0.0.1",
924
+ __VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS: ".localhost"
925
+ },
898
926
  onCleanup: () => {
899
927
  try {
900
928
  store.removeRoute(hostname);
@@ -942,6 +970,7 @@ ${chalk.bold("Examples:")}
942
970
  portless proxy start # Start proxy on port 1355
943
971
  portless proxy start --https # Start with HTTPS/2 (faster page loads)
944
972
  portless myapp next dev # -> http://myapp.localhost:1355
973
+ portless myapp vite dev # -> http://myapp.localhost:1355
945
974
  portless api.myapp pnpm start # -> http://api.myapp.localhost:1355
946
975
 
947
976
  ${chalk.bold("In package.json:")}
@@ -956,6 +985,8 @@ ${chalk.bold("How it works:")}
956
985
  2. Run your apps - they auto-start the proxy and register automatically
957
986
  3. Access via http://<name>.localhost:1355
958
987
  4. .localhost domains auto-resolve to 127.0.0.1
988
+ 5. Frameworks that ignore PORT (Vite, Astro, React Router, Angular) get
989
+ --port and --host flags injected automatically
959
990
 
960
991
  ${chalk.bold("HTTP/2 + HTTPS:")}
961
992
  Use --https for HTTP/2 multiplexing (faster dev server page loads).
@@ -984,7 +1015,7 @@ ${chalk.bold("Skip portless:")}
984
1015
  process.exit(0);
985
1016
  }
986
1017
  if (args[0] === "--version" || args[0] === "-v") {
987
- console.log("0.4.0");
1018
+ console.log("0.4.1");
988
1019
  process.exit(0);
989
1020
  }
990
1021
  if (args[0] === "trust") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "portless",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Replace port numbers with stable, named .localhost URLs. For humans and agents.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,7 +17,6 @@
17
17
  "files": [
18
18
  "dist"
19
19
  ],
20
- "packageManager": "pnpm@9.15.4",
21
20
  "engines": {
22
21
  "node": ">=20"
23
22
  },
@@ -25,21 +24,6 @@
25
24
  "darwin",
26
25
  "linux"
27
26
  ],
28
- "scripts": {
29
- "build": "tsup",
30
- "dev": "tsup --watch",
31
- "format": "prettier --write .",
32
- "format:check": "prettier --check .",
33
- "lint": "eslint src/",
34
- "lint:fix": "eslint src/ --fix",
35
- "prepublishOnly": "pnpm build",
36
- "pretest": "pnpm build",
37
- "test": "vitest run",
38
- "test:coverage": "vitest run --coverage",
39
- "test:watch": "vitest",
40
- "typecheck": "tsc --noEmit",
41
- "prepare": "husky"
42
- },
43
27
  "keywords": [
44
28
  "local",
45
29
  "development",
@@ -60,24 +44,21 @@
60
44
  "chalk": "^5.3.0"
61
45
  },
62
46
  "devDependencies": {
63
- "@eslint/js": "^9.39.2",
64
47
  "@types/node": "^20.11.0",
65
48
  "@vitest/coverage-v8": "^4.0.18",
66
49
  "eslint": "^9.39.2",
67
- "eslint-config-prettier": "^10.1.8",
68
- "husky": "^9.1.7",
69
- "lint-staged": "^16.2.7",
70
- "prettier": "^3.8.1",
71
50
  "tsup": "^8.0.1",
72
51
  "typescript": "^5.3.3",
73
- "typescript-eslint": "^8.55.0",
74
52
  "vitest": "^4.0.18"
75
53
  },
76
- "lint-staged": {
77
- "*.{ts,js}": [
78
- "eslint --fix",
79
- "prettier --write"
80
- ],
81
- "*.{json,md,yml,yaml}": "prettier --write"
54
+ "scripts": {
55
+ "build": "tsup",
56
+ "dev": "tsup --watch",
57
+ "lint": "eslint src/",
58
+ "lint:fix": "eslint src/ --fix",
59
+ "test": "vitest run",
60
+ "test:coverage": "vitest run --coverage",
61
+ "test:watch": "vitest",
62
+ "typecheck": "tsc --noEmit"
82
63
  }
83
- }
64
+ }
package/README.md DELETED
@@ -1,160 +0,0 @@
1
- # portless
2
-
3
- Replace port numbers with stable, named .localhost URLs. For humans and agents.
4
-
5
- ```diff
6
- - "dev": "next dev" # http://localhost:3000
7
- + "dev": "portless myapp next dev" # http://myapp.localhost:1355
8
- ```
9
-
10
- ## Quick Start
11
-
12
- ```bash
13
- # Install
14
- npm install -g portless
15
-
16
- # Start the proxy (once, no sudo needed)
17
- portless proxy start
18
-
19
- # Run your app (auto-starts the proxy if needed)
20
- portless myapp next dev
21
- # -> http://myapp.localhost:1355
22
- ```
23
-
24
- > The proxy auto-starts when you run an app. You can also start it explicitly with `portless proxy start`.
25
-
26
- ## Why
27
-
28
- Local dev with port numbers is fragile:
29
-
30
- - **Port conflicts** -- two projects default to the same port and you get `EADDRINUSE`
31
- - **Memorizing ports** -- was the API on 3001 or 8080?
32
- - **Refreshing shows the wrong app** -- stop one server, start another on the same port, and your open tab now shows something completely different
33
- - **Monorepo multiplier** -- every problem above scales with each service in the repo
34
- - **Agents test the wrong port** -- AI coding agents guess or hardcode the wrong port, especially in monorepos
35
- - **Cookie and storage clashes** -- cookies set on `localhost` bleed across apps on different ports; localStorage is lost when ports shift
36
- - **Hardcoded ports in config** -- CORS allowlists, OAuth redirect URIs, and `.env` files all break when ports change
37
- - **Sharing URLs with teammates** -- "what port is that on?" becomes a Slack question
38
- - **Browser history is useless** -- your history for `localhost:3000` is a jumble of unrelated projects
39
-
40
- Portless fixes all of this by giving each dev server a stable, named `.localhost` URL that both humans and agents can rely on.
41
-
42
- ## Usage
43
-
44
- ```bash
45
- # Basic
46
- portless myapp next dev
47
- # -> http://myapp.localhost:1355
48
-
49
- # Subdomains
50
- portless api.myapp pnpm start
51
- # -> http://api.myapp.localhost:1355
52
-
53
- portless docs.myapp next dev
54
- # -> http://docs.myapp.localhost:1355
55
- ```
56
-
57
- ### In package.json
58
-
59
- ```json
60
- {
61
- "scripts": {
62
- "dev": "portless myapp next dev"
63
- }
64
- }
65
- ```
66
-
67
- The proxy auto-starts when you run an app. Or start it explicitly: `portless proxy start`.
68
-
69
- ## How It Works
70
-
71
- ```mermaid
72
- flowchart TD
73
- Browser["Browser\nmyapp.localhost:1355"]
74
- Proxy["portless proxy\n(port 1355)"]
75
- App1[":4123\nmyapp"]
76
- App2[":4567\napi"]
77
-
78
- Browser -->|port 1355| Proxy
79
- Proxy --> App1
80
- Proxy --> App2
81
- ```
82
-
83
- 1. **Start the proxy** -- auto-starts when you run an app, or start explicitly with `portless proxy start`
84
- 2. **Run apps** -- `portless <name> <command>` assigns a free port and registers with the proxy
85
- 3. **Access via URL** -- `http://<name>.localhost:1355` routes through the proxy to your app
86
-
87
- Apps are assigned a random port (4000-4999) via the `PORT` environment variable. Most frameworks (Next.js, Vite, etc.) respect this automatically.
88
-
89
- ## HTTP/2 + HTTPS
90
-
91
- Enable HTTP/2 for faster dev server page loads. Browsers limit HTTP/1.1 to 6 connections per host, which bottlenecks dev servers that serve many unbundled files (Vite, Nuxt, etc.). HTTP/2 multiplexes all requests over a single connection.
92
-
93
- ```bash
94
- # Start with HTTPS/2 -- generates certs and trusts them automatically
95
- portless proxy start --https
96
-
97
- # First run prompts for sudo once to add the CA to your system trust store.
98
- # After that, no prompts. No browser warnings.
99
-
100
- # Make it permanent (add to .bashrc / .zshrc)
101
- export PORTLESS_HTTPS=1
102
- portless proxy start # HTTPS by default now
103
-
104
- # Use your own certs (e.g., from mkcert)
105
- portless proxy start --cert ./cert.pem --key ./key.pem
106
-
107
- # If you skipped sudo on first run, trust the CA later
108
- sudo portless trust
109
- ```
110
-
111
- ## Commands
112
-
113
- ```bash
114
- portless <name> <cmd> [args...] # Run app at http://<name>.localhost:1355
115
- portless list # Show active routes
116
- portless trust # Add local CA to system trust store
117
-
118
- # Disable portless (run command directly)
119
- PORTLESS=0 pnpm dev # Bypasses proxy, uses default port
120
- # Also accepts PORTLESS=skip
121
-
122
- # Proxy control
123
- portless proxy start # Start the proxy (port 1355, daemon)
124
- portless proxy start --https # Start with HTTP/2 + TLS
125
- portless proxy start -p 80 # Start on port 80 (requires sudo)
126
- portless proxy start --foreground # Start in foreground (for debugging)
127
- portless proxy stop # Stop the proxy
128
-
129
- # Options
130
- -p, --port <number> # Port for the proxy (default: 1355)
131
- # Ports < 1024 require sudo
132
- --https # Enable HTTP/2 + TLS with auto-generated certs
133
- --cert <path> # Use a custom TLS certificate (implies --https)
134
- --key <path> # Use a custom TLS private key (implies --https)
135
- --no-tls # Disable HTTPS (overrides PORTLESS_HTTPS)
136
- --foreground # Run proxy in foreground instead of daemon
137
-
138
- # Environment variables
139
- PORTLESS_PORT=<number> # Override the default proxy port
140
- PORTLESS_HTTPS=1 # Always enable HTTPS
141
- PORTLESS_STATE_DIR=<path> # Override the state directory
142
-
143
- # Info
144
- portless --help # Show help
145
- portless --version # Show version
146
- ```
147
-
148
- ## State Directory
149
-
150
- Portless stores its state (routes, PID file, port file) in a directory that depends on the proxy port:
151
-
152
- - **Port < 1024** (sudo required): `/tmp/portless` -- shared between root and user processes
153
- - **Port >= 1024** (no sudo): `~/.portless` -- user-scoped, no root involvement
154
-
155
- Override with the `PORTLESS_STATE_DIR` environment variable if needed.
156
-
157
- ## Requirements
158
-
159
- - Node.js 20+
160
- - macOS or Linux