git-watchtower 1.7.0 → 1.8.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.
@@ -74,6 +74,7 @@ const { formatTimeAgo } = require('../src/utils/time');
74
74
  const { openInBrowser: openUrl } = require('../src/utils/browser');
75
75
  const { playSound: playSoundEffect } = require('../src/utils/sound');
76
76
  const { parseArgs: parseCliArgs, applyCliArgsToConfig: mergeCliArgs, getHelpText, PACKAGE_VERSION } = require('../src/cli/args');
77
+ const { checkForUpdate } = require('../src/utils/version-check');
77
78
  const { parseRemoteUrl, buildBranchUrl, detectPlatform, buildWebUrl, extractSessionUrl } = require('../src/git/remote');
78
79
  const { parseGitHubPr, parseGitLabMr, parseGitHubPrList, parseGitLabMrList, isBaseBranch } = require('../src/git/pr');
79
80
 
@@ -2953,6 +2954,15 @@ async function start() {
2953
2954
 
2954
2955
  // Initial render
2955
2956
  render();
2957
+
2958
+ // Check for newer version on npm (non-blocking, silent on failure)
2959
+ checkForUpdate().then((latestVersion) => {
2960
+ if (latestVersion) {
2961
+ store.setState({ updateAvailable: latestVersion });
2962
+ addLog(`New version available: ${latestVersion} \u2192 npm i -g git-watchtower`, 'update');
2963
+ render();
2964
+ }
2965
+ }).catch(() => {});
2956
2966
  }
2957
2967
 
2958
2968
  start().catch(err => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-watchtower",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Terminal-based Git branch monitor with activity sparklines and optional dev server with live reload",
5
5
  "main": "bin/git-watchtower.js",
6
6
  "bin": {
package/src/cli/args.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * @module cli/args
4
4
  */
5
5
 
6
- const PACKAGE_VERSION = '1.2.0';
6
+ const { version: PACKAGE_VERSION } = require('../../package.json');
7
7
 
8
8
  /**
9
9
  * @typedef {object} CliArgs
@@ -101,6 +101,7 @@
101
101
  * @property {number} maxLogEntries - Max activity log entries
102
102
  * @property {string} projectName - Project name
103
103
  * @property {number} clientCount - Connected SSE clients
104
+ * @property {string|null} updateAvailable - Latest version if update available, or null
104
105
  */
105
106
 
106
107
  /**
@@ -180,6 +181,9 @@ function getInitialState() {
180
181
  maxLogEntries: 10,
181
182
  projectName: '',
182
183
  clientCount: 0,
184
+
185
+ // Version check
186
+ updateAvailable: null,
183
187
  };
184
188
  }
185
189
 
@@ -23,6 +23,7 @@ const {
23
23
  } = require('../ui/ansi');
24
24
  const { formatTimeAgo } = require('../utils/time');
25
25
  const { isBaseBranch } = require('../git/pr');
26
+ const { version: PACKAGE_VERSION } = require('../../package.json');
26
27
 
27
28
  // ---------------------------------------------------------------------------
28
29
  // renderHeader
@@ -46,8 +47,9 @@ function renderHeader(state, write) {
46
47
  write(ansi.moveTo(headerRow, 1));
47
48
  write(ansi.bgBlue + ansi.white + ansi.bold);
48
49
 
49
- const leftContent = ` \uD83C\uDFF0 Git Watchtower ${ansi.dim}\u2502${ansi.bold} ${state.projectName}`;
50
- const leftVisibleLen = 21 + state.projectName.length;
50
+ const versionStr = `v${PACKAGE_VERSION}`;
51
+ const leftContent = ` \uD83C\uDFF0 Git Watchtower ${ansi.dim}${versionStr} \u2502${ansi.bold} ${state.projectName}`;
52
+ const leftVisibleLen = 21 + versionStr.length + 1 + state.projectName.length;
51
53
  write(leftContent);
52
54
 
53
55
  let badges = '';
@@ -73,6 +75,11 @@ function renderHeader(state, write) {
73
75
  badges += ' ' + ansi.bgRed + ansi.white + label + ansi.bgBlue + ansi.white;
74
76
  badgesVisibleLen += 1 + label.length;
75
77
  }
78
+ if (state.updateAvailable) {
79
+ const label = ` UPDATE v${state.updateAvailable} `;
80
+ badges += ' ' + ansi.bgMagenta + ansi.white + label + ansi.bgBlue + ansi.white;
81
+ badgesVisibleLen += 1 + label.length;
82
+ }
76
83
  write(badges);
77
84
 
78
85
  let modeLabel = '';
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Version check utility - queries npm registry for latest version
3
+ * Uses only Node.js built-in modules (zero dependencies)
4
+ */
5
+
6
+ const https = require('https');
7
+ const { version: currentVersion } = require('../../package.json');
8
+
9
+ /**
10
+ * Compare two semver version strings
11
+ * @param {string} a - First version (e.g. '1.8.0')
12
+ * @param {string} b - Second version (e.g. '1.7.0')
13
+ * @returns {number} 1 if a > b, -1 if a < b, 0 if equal
14
+ */
15
+ function compareVersions(a, b) {
16
+ const pa = a.split('.').map(Number);
17
+ const pb = b.split('.').map(Number);
18
+ for (let i = 0; i < 3; i++) {
19
+ if (pa[i] > pb[i]) return 1;
20
+ if (pa[i] < pb[i]) return -1;
21
+ }
22
+ return 0;
23
+ }
24
+
25
+ /**
26
+ * Check npm registry for a newer version of git-watchtower
27
+ * @returns {Promise<string|null>} Latest version string if newer, or null
28
+ */
29
+ function checkForUpdate() {
30
+ return new Promise((resolve) => {
31
+ const req = https.get(
32
+ 'https://registry.npmjs.org/git-watchtower/latest',
33
+ { timeout: 5000 },
34
+ (res) => {
35
+ if (res.statusCode !== 200) {
36
+ res.resume();
37
+ resolve(null);
38
+ return;
39
+ }
40
+ let data = '';
41
+ res.on('data', (chunk) => { data += chunk; });
42
+ res.on('end', () => {
43
+ try {
44
+ const { version } = JSON.parse(data);
45
+ resolve(compareVersions(version, currentVersion) > 0 ? version : null);
46
+ } catch {
47
+ resolve(null);
48
+ }
49
+ });
50
+ }
51
+ );
52
+ req.on('error', () => resolve(null));
53
+ req.on('timeout', () => { req.destroy(); resolve(null); });
54
+ });
55
+ }
56
+
57
+ module.exports = { checkForUpdate, compareVersions };