git-watchtower 1.12.1 → 1.12.2
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 +31 -13
- package/package.json +1 -1
- package/src/cli/args.js +9 -1
package/bin/git-watchtower.js
CHANGED
|
@@ -419,6 +419,10 @@ let worker = null;
|
|
|
419
419
|
let projectId = null;
|
|
420
420
|
let webStateInterval = null;
|
|
421
421
|
|
|
422
|
+
// Periodic update check controller — hoisted to module scope so the exit
|
|
423
|
+
// handler can clean it up regardless of where in start() we are.
|
|
424
|
+
let periodicUpdateCheck = null;
|
|
425
|
+
|
|
422
426
|
function applyConfig(config) {
|
|
423
427
|
// Server settings
|
|
424
428
|
SERVER_MODE = config.server?.mode || 'static';
|
|
@@ -481,6 +485,17 @@ function openInBrowser(url) {
|
|
|
481
485
|
});
|
|
482
486
|
}
|
|
483
487
|
|
|
488
|
+
/**
|
|
489
|
+
* Build a localhost URL for the given port.
|
|
490
|
+
* Centralizes the `http://localhost:${port}` pattern so it's easy to adjust
|
|
491
|
+
* (e.g. switch protocol or host) in one place.
|
|
492
|
+
* @param {number} port
|
|
493
|
+
* @returns {string}
|
|
494
|
+
*/
|
|
495
|
+
function localhostUrl(port) {
|
|
496
|
+
return `http://localhost:${port}`;
|
|
497
|
+
}
|
|
498
|
+
|
|
484
499
|
// parseRemoteUrl, buildBranchUrl, detectPlatform, buildWebUrl, extractSessionUrl
|
|
485
500
|
// imported from src/git/remote.js
|
|
486
501
|
|
|
@@ -2123,7 +2138,7 @@ function createStaticServer() {
|
|
|
2123
2138
|
return;
|
|
2124
2139
|
}
|
|
2125
2140
|
|
|
2126
|
-
const url = new URL(req.url,
|
|
2141
|
+
const url = new URL(req.url, localhostUrl(PORT));
|
|
2127
2142
|
let pathname = url.pathname;
|
|
2128
2143
|
const logPath = pathname; // Keep original for logging
|
|
2129
2144
|
|
|
@@ -2773,7 +2788,7 @@ function setupKeyboardInput() {
|
|
|
2773
2788
|
|
|
2774
2789
|
case 'o': // Open live server in browser
|
|
2775
2790
|
if (!NO_SERVER) {
|
|
2776
|
-
const serverUrl =
|
|
2791
|
+
const serverUrl = localhostUrl(PORT);
|
|
2777
2792
|
addLog(`Opening ${serverUrl} in browser...`, 'info');
|
|
2778
2793
|
openInBrowser(serverUrl);
|
|
2779
2794
|
render();
|
|
@@ -3016,7 +3031,7 @@ async function handleWebAction(action, payload) {
|
|
|
3016
3031
|
break;
|
|
3017
3032
|
case 'openBrowser':
|
|
3018
3033
|
if (!NO_SERVER) {
|
|
3019
|
-
openInBrowser(
|
|
3034
|
+
openInBrowser(localhostUrl(PORT));
|
|
3020
3035
|
sendResult(true, 'Opened in browser');
|
|
3021
3036
|
}
|
|
3022
3037
|
break;
|
|
@@ -3103,7 +3118,7 @@ async function startWebDashboard(openBrowser) {
|
|
|
3103
3118
|
});
|
|
3104
3119
|
worker.onCommand = (action, payload) => handleWebAction(action, payload);
|
|
3105
3120
|
await worker.connect();
|
|
3106
|
-
addLog(`Joined web dashboard at
|
|
3121
|
+
addLog(`Joined web dashboard at ${localhostUrl(existing.port)} (tab)`, 'success');
|
|
3107
3122
|
|
|
3108
3123
|
// Push state periodically
|
|
3109
3124
|
webStateInterval = setInterval(() => {
|
|
@@ -3154,8 +3169,8 @@ async function startWebDashboard(openBrowser) {
|
|
|
3154
3169
|
WEB_PORT = port;
|
|
3155
3170
|
writeLock(process.pid, port, coordinator.socketPath);
|
|
3156
3171
|
|
|
3157
|
-
addLog(`Web dashboard:
|
|
3158
|
-
if (openBrowser) openInBrowser(
|
|
3172
|
+
addLog(`Web dashboard: ${localhostUrl(port)}`, 'success');
|
|
3173
|
+
if (openBrowser) openInBrowser(localhostUrl(port));
|
|
3159
3174
|
render();
|
|
3160
3175
|
} catch (err) {
|
|
3161
3176
|
addLog(`Web dashboard failed: ${err.message}`, 'error');
|
|
@@ -3285,6 +3300,11 @@ async function shutdown() {
|
|
|
3285
3300
|
|
|
3286
3301
|
process.on('SIGINT', shutdown);
|
|
3287
3302
|
process.on('SIGTERM', shutdown);
|
|
3303
|
+
// Clean up long-lived timers on exit, regardless of which code path got us
|
|
3304
|
+
// here (normal exit, uncaught exception, early failure in start()).
|
|
3305
|
+
process.on('exit', () => {
|
|
3306
|
+
if (periodicUpdateCheck) periodicUpdateCheck.stop();
|
|
3307
|
+
});
|
|
3288
3308
|
process.on('uncaughtException', async (err) => {
|
|
3289
3309
|
telemetry.captureError(err);
|
|
3290
3310
|
write(ansi.showCursor);
|
|
@@ -3413,11 +3433,11 @@ async function start() {
|
|
|
3413
3433
|
// Static mode
|
|
3414
3434
|
server = createStaticServer();
|
|
3415
3435
|
server.listen(PORT, '127.0.0.1', () => {
|
|
3416
|
-
addLog(`Server started on
|
|
3436
|
+
addLog(`Server started on ${localhostUrl(PORT)}`, 'success');
|
|
3417
3437
|
addLog(`Serving ${STATIC_DIR.replace(PROJECT_ROOT, '.')}`, 'info');
|
|
3418
3438
|
addLog(`Current branch: ${store.get('currentBranch')}`, 'info');
|
|
3419
3439
|
// Add server log entries for static server
|
|
3420
|
-
addServerLog(`Static server started on
|
|
3440
|
+
addServerLog(`Static server started on ${localhostUrl(PORT)}`);
|
|
3421
3441
|
addServerLog(`Serving files from: ${STATIC_DIR.replace(PROJECT_ROOT, '.')}`);
|
|
3422
3442
|
addServerLog(`Live reload enabled - waiting for browser connections...`);
|
|
3423
3443
|
render();
|
|
@@ -3468,8 +3488,9 @@ async function start() {
|
|
|
3468
3488
|
}
|
|
3469
3489
|
}).catch(() => {});
|
|
3470
3490
|
|
|
3471
|
-
// Re-check for updates periodically (every 4 hours) while running
|
|
3472
|
-
|
|
3491
|
+
// Re-check for updates periodically (every 4 hours) while running.
|
|
3492
|
+
// Assigned to module scope so the top-level exit handler can stop it.
|
|
3493
|
+
periodicUpdateCheck = startPeriodicUpdateCheck((latestVersion) => {
|
|
3473
3494
|
const alreadyKnown = store.get('updateAvailable');
|
|
3474
3495
|
store.setState({ updateAvailable: latestVersion });
|
|
3475
3496
|
if (!alreadyKnown) {
|
|
@@ -3479,9 +3500,6 @@ async function start() {
|
|
|
3479
3500
|
}
|
|
3480
3501
|
render();
|
|
3481
3502
|
});
|
|
3482
|
-
|
|
3483
|
-
// Clean up periodic check on exit
|
|
3484
|
-
process.on('exit', () => periodicCheck.stop());
|
|
3485
3503
|
}
|
|
3486
3504
|
|
|
3487
3505
|
start().catch(err => {
|
package/package.json
CHANGED
package/src/cli/args.js
CHANGED
|
@@ -175,7 +175,15 @@ function parseArgs(argv, options = {}) {
|
|
|
175
175
|
* @returns {object} Merged config
|
|
176
176
|
*/
|
|
177
177
|
function applyCliArgsToConfig(config, cliArgs) {
|
|
178
|
-
|
|
178
|
+
// Shallow clone with nested object spreading — the config is at most two
|
|
179
|
+
// levels deep and all values are primitives, so this is equivalent to a deep
|
|
180
|
+
// clone but avoids the JSON round-trip (which silently drops `undefined`,
|
|
181
|
+
// functions, and throws on circular refs).
|
|
182
|
+
const merged = {
|
|
183
|
+
...config,
|
|
184
|
+
server: { ...config.server },
|
|
185
|
+
web: { ...config.web },
|
|
186
|
+
};
|
|
179
187
|
|
|
180
188
|
// Server settings
|
|
181
189
|
if (cliArgs.mode !== null) {
|