mevebu 0.2.2 → 0.3.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.
package/README.md CHANGED
@@ -22,13 +22,16 @@ The tools open in your default browser. Press `Ctrl+C` in the terminal to stop.
22
22
  ### Options
23
23
 
24
24
  ```
25
- -p, --port <number> Port to listen on. Defaults to a free port.
25
+ -p, --port <number> Try this port first (5555, 5678, 5432 otherwise).
26
26
  -d, --dir <path> Folder to serve. Defaults to the bundled tools.
27
27
  --no-open Do not open the browser.
28
28
  -v, --version Print the version and exit.
29
29
  -h, --help Print this help and exit.
30
30
  ```
31
31
 
32
+ The port is stable across restarts: mevebu tries **5555** first, then **5678**, then **5432**,
33
+ and falls back to any free port only when those are taken.
34
+
32
35
  ## Tools
33
36
 
34
37
  15 tools, each with its own page. Most update as you type, with no submit button.
package/bin/mevebu.js CHANGED
@@ -20,6 +20,9 @@ const DEFAULT_DIR = resolve(here, "..", "mevebu");
20
20
  const pkg = JSON.parse(await readFile(resolve(here, "..", "package.json"), "utf8"));
21
21
  const VERSION = pkg.version;
22
22
 
23
+ // Preferred ports, tried in order. Falls back to any free port when all are taken.
24
+ const PREFERRED_PORTS = [5555, 5678, 5432];
25
+
23
26
  const HELP = `mevebu ${VERSION}
24
27
 
25
28
  Serve the offline tools on localhost. No accounts, no uploads, no tracking.
@@ -28,7 +31,7 @@ Usage:
28
31
  mevebu [options]
29
32
 
30
33
  Options:
31
- -p, --port <number> Port to listen on. Defaults to a free port.
34
+ -p, --port <number> Try this port first (${PREFERRED_PORTS.join(", ")} otherwise).
32
35
  -d, --dir <path> Folder to serve. Defaults to the bundled tools.
33
36
  --no-open Do not open the browser.
34
37
  -v, --version Print the version and exit.
@@ -73,6 +76,46 @@ function openBrowser(url) {
73
76
  });
74
77
  }
75
78
 
79
+ /**
80
+ * Binds the server to the first port that is free. A `--port` value is tried
81
+ * first, then the preferred list (5555, 5678, 5432), then any free port. This
82
+ * keeps the address stable across restarts while never failing on a clash.
83
+ */
84
+ function listen(server, preferred, host) {
85
+ const queue = [];
86
+ if (preferred) queue.push(preferred);
87
+ for (const port of PREFERRED_PORTS) if (!queue.includes(port)) queue.push(port);
88
+ queue.push(0); // 0 lets the OS pick any free port as the last resort
89
+
90
+ return new Promise((resolve, reject) => {
91
+ let index = 0;
92
+ const attempt = () => {
93
+ if (index >= queue.length) {
94
+ reject(new Error("No free port found."));
95
+ return;
96
+ }
97
+ const port = queue[index++];
98
+ const onError = (error) => {
99
+ server.removeListener("listening", onListening);
100
+ if (error.code === "EADDRINUSE" || error.code === "EACCES") {
101
+ if (port) console.log(` port ${port} is taken, trying the next one...`);
102
+ attempt();
103
+ } else {
104
+ reject(error);
105
+ }
106
+ };
107
+ const onListening = () => {
108
+ server.removeListener("error", onError);
109
+ resolve(server.address().port);
110
+ };
111
+ server.once("error", onError);
112
+ server.once("listening", onListening);
113
+ server.listen(port, host);
114
+ };
115
+ attempt();
116
+ });
117
+ }
118
+
76
119
  const options = args(process.argv);
77
120
  const root = resolve(options.dir);
78
121
 
@@ -107,9 +150,13 @@ const server = createServer(async (req, res) => {
107
150
  }
108
151
  });
109
152
 
110
- server.listen(options.port || 0, "127.0.0.1", () => {
111
- const { port } = server.address();
112
- const url = `http://localhost:${port}/`;
113
- console.log(`\n mevebu is running at ${url}\n Press Ctrl+C to stop.\n`);
114
- if (options.open) openBrowser(url);
115
- });
153
+ listen(server, options.port, "127.0.0.1")
154
+ .then((port) => {
155
+ const url = `http://localhost:${port}/`;
156
+ console.log(`\n mevebu is running at ${url}\n Press Ctrl+C to stop.\n`);
157
+ if (options.open) openBrowser(url);
158
+ })
159
+ .catch((error) => {
160
+ console.error(`\n Could not start mevebu: ${error.message}\n`);
161
+ process.exit(1);
162
+ });
@@ -169,7 +169,7 @@ function openUpdate(latest) {
169
169
  updatable ? commandBox : null,
170
170
  ],
171
171
  actions: updatable
172
- ? [el("a", { class: "mvb-btn", href: `https://www.npmjs.com/package/${PACKAGE_NAME}/v/${latest}`, target: "_blank", rel: "noopener" }, "What changed")]
172
+ ? [el("a", { class: "mvb-btn", href: `${REPO_URL}/releases/tag/v${latest}`, target: "_blank", rel: "noopener" }, "What changed")]
173
173
  : [],
174
174
  veilClass: "mvb-veil--help",
175
175
  });
@@ -593,7 +593,7 @@ export function blank(iconName, text) {
593
593
  // ---------- version ----------
594
594
 
595
595
  // Kept in one place. The CLI reads the same value from package.json.
596
- export const VERSION = "0.2.2";
596
+ export const VERSION = "0.3.1";
597
597
  export const PACKAGE_NAME = "mevebu";
598
598
  export const REPO_SLUG = "mevebu/mevebu";
599
599
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mevebu",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "description": "Small tools that run in your browser. No accounts, no uploads, no tracking.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -15,7 +15,7 @@
15
15
  ],
16
16
  "scripts": {
17
17
  "icons": "node scripts/vendor-icons.mjs",
18
- "dev": "node bin/mevebu.js --port 5173",
18
+ "dev": "node bin/mevebu.js",
19
19
  "start": "node bin/mevebu.js",
20
20
  "ship": "node scripts/ship.js"
21
21
  },