git-watchtower 1.9.5 → 1.9.7
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/bin/git-watchtower.js +14 -6
- package/package.json +8 -8
- package/src/telemetry/analytics.js +41 -25
- package/src/telemetry/index.js +1 -0
package/bin/git-watchtower.js
CHANGED
|
@@ -1691,11 +1691,17 @@ async function pollGitChanges() {
|
|
|
1691
1691
|
for (const knownName of knownBranchNames) {
|
|
1692
1692
|
if (!fetchedBranchNames.has(knownName)) {
|
|
1693
1693
|
// This branch was deleted from remote
|
|
1694
|
+
// Check if already present in allBranches (avoid duplicates)
|
|
1695
|
+
const alreadyInList = allBranches.some(b => b.name === knownName);
|
|
1696
|
+
if (alreadyInList) continue;
|
|
1697
|
+
|
|
1694
1698
|
const existingInList = currentBranches.find(b => b.name === knownName);
|
|
1695
|
-
if (existingInList
|
|
1696
|
-
existingInList.isDeleted
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
+
if (existingInList) {
|
|
1700
|
+
if (!existingInList.isDeleted) {
|
|
1701
|
+
existingInList.isDeleted = true;
|
|
1702
|
+
existingInList.deletedAt = now;
|
|
1703
|
+
addLog(`Branch deleted: ${knownName}`, 'warning');
|
|
1704
|
+
}
|
|
1699
1705
|
// Keep it in the list temporarily
|
|
1700
1706
|
allBranches.push(existingInList);
|
|
1701
1707
|
}
|
|
@@ -2839,13 +2845,14 @@ async function shutdown() {
|
|
|
2839
2845
|
|
|
2840
2846
|
process.on('SIGINT', shutdown);
|
|
2841
2847
|
process.on('SIGTERM', shutdown);
|
|
2842
|
-
process.on('uncaughtException', (err) => {
|
|
2848
|
+
process.on('uncaughtException', async (err) => {
|
|
2843
2849
|
telemetry.captureError(err);
|
|
2844
2850
|
write(ansi.showCursor);
|
|
2845
2851
|
write(ansi.restoreScreen);
|
|
2846
2852
|
restoreTerminalTitle();
|
|
2847
2853
|
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
2848
2854
|
console.error('Uncaught exception:', err);
|
|
2855
|
+
await telemetry.shutdown();
|
|
2849
2856
|
process.exit(1);
|
|
2850
2857
|
});
|
|
2851
2858
|
|
|
@@ -2867,7 +2874,8 @@ async function start() {
|
|
|
2867
2874
|
const config = await ensureConfig(cliArgs);
|
|
2868
2875
|
applyConfig(config);
|
|
2869
2876
|
|
|
2870
|
-
// Telemetry:
|
|
2877
|
+
// Telemetry: set version early so consent events include $lib_version
|
|
2878
|
+
telemetry.setVersion(PACKAGE_VERSION);
|
|
2871
2879
|
await telemetry.promptIfNeeded(promptYesNo);
|
|
2872
2880
|
telemetry.init({ version: PACKAGE_VERSION });
|
|
2873
2881
|
sessionStartTime = Date.now();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-watchtower",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.7",
|
|
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": {
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node bin/git-watchtower.js",
|
|
11
|
-
"test": "node --test tests/unit/**/*.test.js tests/integration/**/*.test.js",
|
|
12
|
-
"test:unit": "node --test tests/unit/**/*.test.js",
|
|
13
|
-
"test:integration": "node --test tests/integration/**/*.test.js",
|
|
14
|
-
"test:watch": "node --test --watch tests/unit/**/*.test.js",
|
|
15
|
-
"test:coverage": "c8 --reporter=text --reporter=html --reporter=lcov node --test tests/unit/**/*.test.js tests/integration/**/*.test.js",
|
|
16
|
-
"test:coverage:text": "c8 --reporter=text node --test tests/unit/**/*.test.js tests/integration/**/*.test.js",
|
|
17
|
-
"test:coverage:html": "c8 --reporter=html node --test tests/unit/**/*.test.js tests/integration/**/*.test.js && echo 'Coverage report: coverage/index.html'",
|
|
11
|
+
"test": "node --require ./tests/setup.js --test tests/unit/**/*.test.js tests/integration/**/*.test.js",
|
|
12
|
+
"test:unit": "node --require ./tests/setup.js --test tests/unit/**/*.test.js",
|
|
13
|
+
"test:integration": "node --require ./tests/setup.js --test tests/integration/**/*.test.js",
|
|
14
|
+
"test:watch": "node --require ./tests/setup.js --test --watch tests/unit/**/*.test.js",
|
|
15
|
+
"test:coverage": "c8 --reporter=text --reporter=html --reporter=lcov node --require ./tests/setup.js --test tests/unit/**/*.test.js tests/integration/**/*.test.js",
|
|
16
|
+
"test:coverage:text": "c8 --reporter=text node --require ./tests/setup.js --test tests/unit/**/*.test.js tests/integration/**/*.test.js",
|
|
17
|
+
"test:coverage:html": "c8 --reporter=html node --require ./tests/setup.js --test tests/unit/**/*.test.js tests/integration/**/*.test.js && echo 'Coverage report: coverage/index.html'",
|
|
18
18
|
"typecheck": "tsc --noEmit"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
@@ -22,40 +22,46 @@ const FLUSH_INTERVAL = 30000; // 30 seconds
|
|
|
22
22
|
const FLUSH_AT = 10; // flush when 10 events accumulated
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* Send a batch of events to PostHog via HTTPS POST
|
|
25
|
+
* Send a batch of events to PostHog via HTTPS POST.
|
|
26
|
+
* Returns a promise that resolves when the request completes (or fails).
|
|
27
|
+
* Callers that don't need to wait can ignore the return value.
|
|
26
28
|
* @param {Array<Record<string, any>>} events
|
|
29
|
+
* @returns {Promise<void>}
|
|
27
30
|
*/
|
|
28
31
|
function sendBatch(events) {
|
|
29
|
-
if (events.length === 0) return;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
if (events.length === 0) return Promise.resolve();
|
|
33
|
+
|
|
34
|
+
return new Promise((resolve) => {
|
|
35
|
+
const payload = JSON.stringify({ api_key: POSTHOG_API_KEY, batch: events });
|
|
36
|
+
|
|
37
|
+
const req = https.request({
|
|
38
|
+
hostname: POSTHOG_HOST,
|
|
39
|
+
port: 443,
|
|
40
|
+
path: '/batch',
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: {
|
|
43
|
+
'Content-Type': 'application/json',
|
|
44
|
+
'Content-Length': Buffer.byteLength(payload),
|
|
45
|
+
},
|
|
46
|
+
timeout: 5000,
|
|
47
|
+
});
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
req.on('error', () => resolve());
|
|
50
|
+
req.on('timeout', () => { req.destroy(); resolve(); });
|
|
51
|
+
req.on('response', () => resolve());
|
|
52
|
+
req.end(payload);
|
|
53
|
+
});
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
/**
|
|
52
|
-
* Flush pending events
|
|
57
|
+
* Flush pending events.
|
|
58
|
+
* @returns {Promise<void>} Resolves when the batch has been sent (or fails).
|
|
53
59
|
*/
|
|
54
60
|
function flush() {
|
|
55
|
-
if (eventQueue.length === 0) return;
|
|
61
|
+
if (eventQueue.length === 0) return Promise.resolve();
|
|
56
62
|
const batch = eventQueue;
|
|
57
63
|
eventQueue = [];
|
|
58
|
-
sendBatch(batch);
|
|
64
|
+
return sendBatch(batch);
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
/**
|
|
@@ -81,6 +87,15 @@ function queueEvent(event, properties, overrideDistinctId) {
|
|
|
81
87
|
}
|
|
82
88
|
}
|
|
83
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Set the app version so that even pre-init events include $lib_version.
|
|
92
|
+
* Call this before promptIfNeeded() so consent events carry the version.
|
|
93
|
+
* @param {string} version
|
|
94
|
+
*/
|
|
95
|
+
function setVersion(version) {
|
|
96
|
+
appVersion = version;
|
|
97
|
+
}
|
|
98
|
+
|
|
84
99
|
/**
|
|
85
100
|
* Initialize the analytics client if telemetry is enabled
|
|
86
101
|
* @param {{ version: string }} options
|
|
@@ -190,7 +205,7 @@ function captureAlways(event, userDistinctId, properties = {}) {
|
|
|
190
205
|
}
|
|
191
206
|
|
|
192
207
|
/**
|
|
193
|
-
* Flush pending events and shutdown
|
|
208
|
+
* Flush pending events and shutdown.
|
|
194
209
|
* Call this before process exit to ensure events are sent.
|
|
195
210
|
* @returns {Promise<void>}
|
|
196
211
|
*/
|
|
@@ -203,7 +218,7 @@ async function shutdown() {
|
|
|
203
218
|
if (!enabled) return;
|
|
204
219
|
|
|
205
220
|
try {
|
|
206
|
-
flush();
|
|
221
|
+
await flush();
|
|
207
222
|
} catch {
|
|
208
223
|
// Best-effort flush
|
|
209
224
|
} finally {
|
|
@@ -220,6 +235,7 @@ function isEnabled() {
|
|
|
220
235
|
}
|
|
221
236
|
|
|
222
237
|
module.exports = {
|
|
238
|
+
setVersion,
|
|
223
239
|
init,
|
|
224
240
|
capture,
|
|
225
241
|
captureError,
|