portless 0.7.1 → 0.7.2

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.
package/README.md CHANGED
@@ -29,7 +29,7 @@ portless myapp next dev
29
29
  # -> http://myapp.localhost:1355
30
30
  ```
31
31
 
32
- The proxy auto-starts when you run an app. A random port (4000--4999) is assigned via the `PORT` environment variable. Most frameworks (Next.js, Express, Nuxt, etc.) respect this automatically. For frameworks that ignore `PORT` (Vite, Astro, React Router, Angular), portless auto-injects `--port` and `--host` flags.
32
+ The proxy auto-starts when you run an app. A random port (4000--4999) is assigned via the `PORT` environment variable. Most frameworks (Next.js, Express, Nuxt, etc.) respect this automatically. For frameworks that ignore `PORT` (Vite, Astro, React Router, Angular, Expo, React Native), portless auto-injects `--port` and `--host` flags.
33
33
 
34
34
  ## Use in package.json
35
35
 
@@ -93,10 +93,10 @@ Recommended: `.test` (IANA-reserved, no collision risk). Avoid `.local` (conflic
93
93
 
94
94
  ```mermaid
95
95
  flowchart TD
96
- Browser["Browser\nmyapp.localhost:1355"]
97
- Proxy["portless proxy\n(port 1355)"]
98
- App1[":4123\nmyapp"]
99
- App2[":4567\napi"]
96
+ Browser["Browser<br>myapp.localhost:1355"]
97
+ Proxy["portless proxy<br>(port 1355)"]
98
+ App1[":4123<br>myapp"]
99
+ App2[":4567<br>api"]
100
100
 
101
101
  Browser -->|port 1355| Proxy
102
102
  Proxy --> App1
@@ -515,6 +515,9 @@ function createProxyServer(options) {
515
515
  const plainServer = http.createServer(handleRequest);
516
516
  plainServer.on("upgrade", handleUpgrade);
517
517
  const wrapper = net.createServer((socket) => {
518
+ socket.on("error", () => {
519
+ socket.destroy();
520
+ });
518
521
  socket.once("readable", () => {
519
522
  const buf = socket.read(1);
520
523
  if (!buf) {
@@ -894,9 +897,12 @@ function collectBinPaths(cwd) {
894
897
  return dirs;
895
898
  }
896
899
  function augmentedPath(env) {
897
- const base = (env ?? process.env).PATH ?? "";
900
+ const source = env ?? process.env;
901
+ const base = source.PATH ?? source.Path ?? "";
898
902
  const bins = collectBinPaths(process.cwd());
899
- return bins.length > 0 ? bins.join(path2.delimiter) + path2.delimiter + base : base;
903
+ const nodeBin = path2.dirname(process.execPath);
904
+ const allBins = [...bins, nodeBin];
905
+ return allBins.join(path2.delimiter) + path2.delimiter + base;
900
906
  }
901
907
  function spawnCommand(commandArgs, options) {
902
908
  const env = { ...options?.env ?? process.env, PATH: augmentedPath(options?.env) };
@@ -953,12 +959,38 @@ var FRAMEWORKS_NEEDING_PORT = {
953
959
  "react-native": { strictPort: false },
954
960
  expo: { strictPort: false }
955
961
  };
962
+ var PACKAGE_RUNNERS = {
963
+ npx: [],
964
+ bunx: [],
965
+ pnpx: [],
966
+ yarn: ["dlx", "exec"],
967
+ pnpm: ["dlx", "exec"]
968
+ };
969
+ function findFrameworkBasename(commandArgs) {
970
+ if (commandArgs.length === 0) return null;
971
+ const first = path2.basename(commandArgs[0]);
972
+ if (FRAMEWORKS_NEEDING_PORT[first]) return first;
973
+ const subcommands = PACKAGE_RUNNERS[first];
974
+ if (!subcommands) return null;
975
+ let i = 1;
976
+ if (subcommands.length > 0) {
977
+ while (i < commandArgs.length && commandArgs[i].startsWith("-")) i++;
978
+ if (i >= commandArgs.length) return null;
979
+ if (!subcommands.includes(commandArgs[i])) {
980
+ const name2 = path2.basename(commandArgs[i]);
981
+ return FRAMEWORKS_NEEDING_PORT[name2] ? name2 : null;
982
+ }
983
+ i++;
984
+ }
985
+ while (i < commandArgs.length && commandArgs[i].startsWith("-")) i++;
986
+ if (i >= commandArgs.length) return null;
987
+ const name = path2.basename(commandArgs[i]);
988
+ return FRAMEWORKS_NEEDING_PORT[name] ? name : null;
989
+ }
956
990
  function injectFrameworkFlags(commandArgs, port) {
957
- const cmd = commandArgs[0];
958
- if (!cmd) return;
959
- const basename2 = path2.basename(cmd);
991
+ const basename2 = findFrameworkBasename(commandArgs);
992
+ if (!basename2) return;
960
993
  const framework = FRAMEWORKS_NEEDING_PORT[basename2];
961
- if (!framework) return;
962
994
  if (!commandArgs.includes("--port")) {
963
995
  commandArgs.push("--port", port.toString());
964
996
  if (framework.strictPort) {
package/dist/cli.js CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  waitForProxy,
32
32
  writeTldFile,
33
33
  writeTlsMarker
34
- } from "./chunk-AXEPQFLY.js";
34
+ } from "./chunk-ROBZDJST.js";
35
35
 
36
36
  // src/cli.ts
37
37
  import chalk from "chalk";
@@ -332,6 +332,7 @@ var HOST_CERTS_DIR = "host-certs";
332
332
  function sanitizeHostForFilename(hostname) {
333
333
  return hostname.replace(/\./g, "_").replace(/[^a-z0-9_-]/gi, "");
334
334
  }
335
+ var MAX_CN_LENGTH = 64;
335
336
  async function generateHostCertAsync(stateDir, hostname) {
336
337
  const caKeyPath = path.join(stateDir, CA_KEY_FILE);
337
338
  const caCertPath = path.join(stateDir, CA_CERT_FILE);
@@ -346,7 +347,8 @@ async function generateHostCertAsync(stateDir, hostname) {
346
347
  const csrPath = path.join(hostDir, `${safeName}.csr`);
347
348
  const extPath = path.join(hostDir, `${safeName}-ext.cnf`);
348
349
  await opensslAsync(["ecparam", "-genkey", "-name", "prime256v1", "-noout", "-out", keyPath]);
349
- await opensslAsync(["req", "-new", "-key", keyPath, "-out", csrPath, "-subj", `/CN=${hostname}`]);
350
+ const cn = hostname.length > MAX_CN_LENGTH ? hostname.slice(0, MAX_CN_LENGTH) : hostname;
351
+ await opensslAsync(["req", "-new", "-key", keyPath, "-out", csrPath, "-subj", `/CN=${cn}`]);
350
352
  const sans = [`DNS:${hostname}`];
351
353
  const parts = hostname.split(".");
352
354
  if (parts.length >= 2) {
@@ -975,10 +977,12 @@ portless
975
977
  timeout: SUDO_SPAWN_TIMEOUT_MS
976
978
  });
977
979
  if (result.status !== 0) {
978
- console.error(chalk.red("Failed to start proxy."));
979
- console.error(chalk.blue("Try starting it manually:"));
980
- console.error(chalk.cyan(" sudo portless proxy start"));
981
- process.exit(1);
980
+ if (!await isProxyRunning(proxyPort)) {
981
+ console.error(chalk.red("Failed to start proxy."));
982
+ console.error(chalk.blue("Try starting it manually:"));
983
+ console.error(chalk.cyan(" sudo portless proxy start"));
984
+ process.exit(1);
985
+ }
982
986
  }
983
987
  } else {
984
988
  console.log(chalk.yellow("Starting proxy..."));
@@ -990,10 +994,12 @@ portless
990
994
  timeout: SUDO_SPAWN_TIMEOUT_MS
991
995
  });
992
996
  if (result.status !== 0) {
993
- console.error(chalk.red("Failed to start proxy."));
994
- console.error(chalk.blue("Try starting it manually:"));
995
- console.error(chalk.cyan(" portless proxy start"));
996
- process.exit(1);
997
+ if (!await isProxyRunning(proxyPort)) {
998
+ console.error(chalk.red("Failed to start proxy."));
999
+ console.error(chalk.blue("Try starting it manually:"));
1000
+ console.error(chalk.cyan(" portless proxy start"));
1001
+ process.exit(1);
1002
+ }
997
1003
  }
998
1004
  }
999
1005
  const autoTls = readTlsMarker(stateDir);
@@ -1287,7 +1293,7 @@ ${chalk.bold("Reserved names:")}
1287
1293
  process.exit(0);
1288
1294
  }
1289
1295
  function printVersion() {
1290
- console.log("0.7.1");
1296
+ console.log("0.7.2");
1291
1297
  process.exit(0);
1292
1298
  }
1293
1299
  async function handleTrust() {
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  parseHostname,
20
20
  removeBlock,
21
21
  syncHostsFile
22
- } from "./chunk-AXEPQFLY.js";
22
+ } from "./chunk-ROBZDJST.js";
23
23
  export {
24
24
  DIR_MODE,
25
25
  FILE_MODE,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "portless",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
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",