windscout 0.2.1 → 0.3.0

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
@@ -18,6 +18,8 @@ WindScout drives the official `windscribe-cli`: it connects to each country × p
18
18
  npm install -g windscout # or run once with: npx windscout
19
19
  ```
20
20
 
21
+ On startup, WindScout checks npm for a newer version. If there is one, it shows the command to update, both in the picker and after the final report.
22
+
21
23
  ## Usage
22
24
 
23
25
  Run `windscout` with no arguments to open the interactive picker:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windscout",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Find which Windscribe locations and protocols work from your network, ranked by speed (unofficial)",
5
5
  "type": "module",
6
6
  "bin": {
package/windscout.js CHANGED
@@ -151,6 +151,26 @@ async function probe(query, protocol, timeout, onStep = () => {}) {
151
151
  }
152
152
  }
153
153
 
154
+ // ---------- update check ----------
155
+
156
+ const VERSION = JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8")).version;
157
+ let update = null; // newer version on npm, once known
158
+ let updateCheck = Promise.resolve();
159
+ // numeric x.y.z compare; parseInt drops a prerelease suffix ("0-beta" → 0)
160
+ const newer = (a, b) => {
161
+ const x = a.split(".").map((n) => parseInt(n)), y = b.split(".").map((n) => parseInt(n));
162
+ for (let i = 0; i < 3; i++) if (x[i] !== y[i]) return x[i] > y[i];
163
+ return false;
164
+ };
165
+ // best effort: offline or registry down just means no notice
166
+ const checkUpdate = () =>
167
+ fetch("https://registry.npmjs.org/windscout/latest", { signal: AbortSignal.timeout(3000) })
168
+ .then((r) => r.json())
169
+ .then(({ version }) => { if (version && newer(version, VERSION)) update = version; })
170
+ .catch(() => {});
171
+ const updateNotice = () => `update available: ${VERSION} → ${update} · run: ${
172
+ process.env.npm_command === "exec" ? "npx windscout@latest" : "npm install -g windscout@latest"}`;
173
+
154
174
  // ---------- formatting ----------
155
175
 
156
176
  const color = (code, s) => (process.env.NO_COLOR || !process.stdout.isTTY ? s : `\x1b[${code}m${s}\x1b[0m`);
@@ -382,7 +402,7 @@ function pick(saved, timeout) {
382
402
  const render = () => {
383
403
  const rows = out.rows || 24;
384
404
  const list = visible();
385
- const height = Math.max(3, rows - 19);
405
+ const height = Math.max(3, rows - 19 - (update ? 1 : 0));
386
406
  cursor = Math.max(0, Math.min(cursor, list.length - 1));
387
407
  if (cursor < top) top = cursor;
388
408
  if (cursor >= top + height) top = cursor - height + 1;
@@ -432,6 +452,7 @@ function pick(saved, timeout) {
432
452
  lines.splice(head.length + table.length + 1, 0, centerIn(buttonLine, width), "");
433
453
  if (message) lines.push(centerIn(yellow(message), width));
434
454
  lines.push("", centerIn(dim(repoLink), width));
455
+ if (update) lines.push(centerIn(yellow(updateNotice()), width));
435
456
  const at = draw(lines);
436
457
 
437
458
  // click map, in screen coordinates
@@ -458,7 +479,10 @@ function pick(saved, timeout) {
458
479
  };
459
480
  };
460
481
 
482
+ let closed = false;
483
+ updateCheck.then(() => update && !closed && render()); // the check usually lands after the first draw
461
484
  const finish = (value) => {
485
+ closed = true;
462
486
  out.off("resize", render);
463
487
  input.removeAllListeners("keypress");
464
488
  input.removeAllListeners("mouse");
@@ -747,6 +771,7 @@ async function main() {
747
771
  },
748
772
  });
749
773
  if (a.help) return console.log(HELP);
774
+ updateCheck = checkUpdate(); // runs while the app starts and the user picks, before the VPN starts switching
750
775
  const timeout = Number(a.timeout);
751
776
  if (!(timeout > 0)) throw new Error("--timeout must be a positive number");
752
777
 
@@ -776,6 +801,8 @@ async function main() {
776
801
  const results = await scan(countries, protocols, timeout, tty);
777
802
  if (stop) console.log(yellow("interrupted, showing partial results"));
778
803
  report(results, protocols, a.all);
804
+ await updateCheck;
805
+ if (update) console.error("\n" + yellow(updateNotice()));
779
806
  }
780
807
 
781
808
  main().catch((e) => {