windscout 0.2.1 → 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
@@ -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:
@@ -72,6 +74,7 @@ windscout -t 40 -a # longer connect timeout, also list
72
74
  | `-t, --timeout` | seconds to wait for each connection | 20 |
73
75
  | `-a, --all` | include failed attempts in the final table | off |
74
76
  | `-n, --no-speed` | connect-only mode: skip the download test, rank by latency | saved, or off |
77
+ | `-v, --version` | print the installed version, and the update command if a newer one is on npm | |
75
78
 
76
79
  ## Connect-only mode
77
80
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windscout",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
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");
@@ -730,6 +754,7 @@ Options:
730
754
  -t, --timeout SEC seconds to wait for each connection (default: 20)
731
755
  -a, --all also show failed attempts in the final table
732
756
  -n, --no-speed connect-only: skip the download test, rank by latency (faster scan)
757
+ -v, --version show the installed version (and whether a newer one is out)
733
758
  -h, --help show this help
734
759
 
735
760
  Selection is stored in ${CONFIG}
@@ -743,10 +768,17 @@ async function main() {
743
768
  timeout: { type: "string", short: "t", default: "20" },
744
769
  all: { type: "boolean", short: "a", default: false },
745
770
  help: { type: "boolean", short: "h", default: false },
771
+ version: { type: "boolean", short: "v", default: false },
746
772
  "no-speed": { type: "boolean", short: "n", default: false },
747
773
  },
748
774
  });
749
775
  if (a.help) return console.log(HELP);
776
+ updateCheck = checkUpdate(); // runs while the app starts and the user picks, before the VPN starts switching
777
+ if (a.version) {
778
+ console.log(`windscout ${VERSION}`);
779
+ await updateCheck;
780
+ return update && console.error(yellow(updateNotice()));
781
+ }
750
782
  const timeout = Number(a.timeout);
751
783
  if (!(timeout > 0)) throw new Error("--timeout must be a positive number");
752
784
 
@@ -776,6 +808,8 @@ async function main() {
776
808
  const results = await scan(countries, protocols, timeout, tty);
777
809
  if (stop) console.log(yellow("interrupted, showing partial results"));
778
810
  report(results, protocols, a.all);
811
+ await updateCheck;
812
+ if (update) console.error("\n" + yellow(updateNotice()));
779
813
  }
780
814
 
781
815
  main().catch((e) => {