fix: resolve three critical bugs from GitHub issue tracker

Fix #684: Prevent Windows reserved filename creation
- Add sanitizeFilename() utility to detect and prefix Windows reserved names
  (NUL, CON, PRN, AUX, COM1-9, LPT1-9)
- Apply sanitization to save-image route to prevent "nul" file creation
- Add 23 comprehensive tests for filename sanitization edge cases

Fix #576: Detect actual dev server port from output
- Parse stdout/stderr for real server URLs (Vite, Next.js, generic formats)
- Update server URL when detected instead of using allocated PORT
- Emit dev-server:url-detected event for frontend updates
- Add 6 tests for URL detection patterns

Fix #193: Commit only feature-specific changes
- Change from 'git add -A' to branch-aware file staging
- Use git diff to find files changed on feature branch only
- Prevent committing unrelated changes from other features
- Maintain backward compatibility with main branch workflow

All fixes include comprehensive tests and maintain backward compatibility.
Test results: 1,968 tests passed (547 package + 1,421 server tests)
This commit is contained in:
DhanushSantosh
2026-02-05 10:42:56 +05:30
parent 63cae19aec
commit 84570842d3
7 changed files with 461 additions and 5 deletions

View File

@@ -37,6 +37,8 @@ export interface DevServerInfo {
flushTimeout: NodeJS.Timeout | null;
// Flag to indicate server is stopping (prevents output after stop)
stopping: boolean;
// Flag to indicate if URL has been detected from output
urlDetected: boolean;
}
// Port allocation starts at 3001 to avoid conflicts with common dev ports
@@ -103,6 +105,54 @@ class DevServerService {
}
}
/**
* Detect actual server URL from output
* Parses stdout/stderr for common URL patterns from dev servers
*/
private detectUrlFromOutput(server: DevServerInfo, content: string): void {
// Skip if URL already detected
if (server.urlDetected) {
return;
}
// Common URL patterns from various dev servers:
// - Vite: "Local: http://localhost:5173/"
// - Next.js: "ready - started server on 0.0.0.0:3000, url: http://localhost:3000"
// - CRA/Webpack: "On Your Network: http://192.168.1.1:3000"
// - Generic: Any http:// or https:// URL
const urlPatterns = [
/(?:Local|Network):\s+(https?:\/\/[^\s]+)/i, // Vite format
/(?:ready|started server).*?(?:url:\s*)?(https?:\/\/[^\s,]+)/i, // Next.js format
/(https?:\/\/(?:localhost|127\.0\.0\.1|\[::\]):\d+)/i, // Generic localhost URL
/(https?:\/\/[^\s<>"{}|\\^`\[\]]+)/i, // Any HTTP(S) URL
];
for (const pattern of urlPatterns) {
const match = content.match(pattern);
if (match && match[1]) {
const detectedUrl = match[1].trim();
// Validate it looks like a reasonable URL
if (detectedUrl.startsWith('http://') || detectedUrl.startsWith('https://')) {
server.url = detectedUrl;
server.urlDetected = true;
logger.info(
`Detected actual server URL: ${detectedUrl} (allocated port was ${server.port})`
);
// Emit URL update event
if (this.emitter) {
this.emitter.emit('dev-server:url-detected', {
worktreePath: server.worktreePath,
url: detectedUrl,
timestamp: new Date().toISOString(),
});
}
break;
}
}
}
}
/**
* Handle incoming stdout/stderr data from dev server process
* Buffers data for scrollback replay and schedules throttled emission
@@ -115,6 +165,9 @@ class DevServerService {
const content = data.toString();
// Try to detect actual server URL from output
this.detectUrlFromOutput(server, content);
// Append to scrollback buffer for replay on reconnect
this.appendToScrollback(server, content);
@@ -446,13 +499,14 @@ class DevServerService {
const serverInfo: DevServerInfo = {
worktreePath,
port,
url: `http://${hostname}:${port}`,
url: `http://${hostname}:${port}`, // Initial URL, may be updated by detectUrlFromOutput
process: devProcess,
startedAt: new Date(),
scrollbackBuffer: '',
outputBuffer: '',
flushTimeout: null,
stopping: false,
urlDetected: false, // Will be set to true when actual URL is detected from output
};
// Capture stdout with buffer management and event emission