Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@salesforce/core": "^8.25.0",
"@salesforce/kit": "^3.2.4",
"@salesforce/sf-plugins-core": "^12.2.6",
"@salesforce/webapp-experimental": "^0.2.0",
"@salesforce/webapp-experimental": "^1.23.0",
"chokidar": "^3.6.0",
"http-proxy": "^1.18.1",
"micromatch": "^4.0.8",
Expand Down Expand Up @@ -78,7 +78,6 @@
"format": "wireit",
"link-check": "wireit",
"lint": "wireit",
"postbuild": "node scripts/copy-templates.cjs",
"postpack": "sf-clean --ignore-signing-artifacts",
"prepack": "sf-prepack",
"prepare": "sf-install",
Expand Down
31 changes: 0 additions & 31 deletions scripts/copy-templates.cjs

This file was deleted.

7 changes: 5 additions & 2 deletions src/proxy/ProxyServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ export class ProxyServer extends EventEmitter {

this.server.on('connection', (socket) => {
this.activeConnections.add(socket);
socket.on('error', (err) => {
// Handle ECONNRESET and other socket errors gracefully
// These can happen when the dev server crashes or a client disconnects abruptly
this.logger.debug(`Socket error (${err.message}), cleaning up connection`);
});
socket.once('close', () => {
this.activeConnections.delete(socket);
});
Expand Down Expand Up @@ -407,8 +412,6 @@ export class ProxyServer extends EventEmitter {
private initializeProxyHandler(): void {
const manifest: WebAppManifest = this.config.manifest ?? {
name: 'webapp',
label: 'WebApp',
version: '1.0.0',
outputDir: 'dist',
};

Expand Down
9 changes: 4 additions & 5 deletions src/server/DevServerManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,11 +429,10 @@ export class DevServerManager extends EventEmitter {
this.logger.error(`Dev server error: ${parsedError.title}`);
this.logger.debug(`Error type: ${parsedError.type}`);

// Convert to SfError for proper error handling
// Use just the message (not title) since title will be shown separately
const sfError = new SfError(parsedError.message, 'DevServerError', parsedError.suggestions);

this.emit('error', sfError);
// Emit the parsed DevServerError directly so the receiver (dev.ts)
// can access stderrLines, title, and type for the error page.
// Previously this was wrapped in SfError which lost those properties.
this.emit('error', parsedError);
}

// Reset state
Expand Down
54 changes: 2 additions & 52 deletions src/templates/ErrorPageRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
* limitations under the License.
*/

import { readFileSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { getErrorPageTemplate } from '@salesforce/webapp-experimental/proxy';
import type { DevServerError } from '../config/types.js';

export type ErrorPageData = {
Expand All @@ -37,55 +35,7 @@ export class ErrorPageRenderer {
private template: string;

public constructor() {
// Load the HTML template
const currentDir = dirname(fileURLToPath(import.meta.url));
const templatePath = join(currentDir, 'error-page.html');

try {
this.template = readFileSync(templatePath, 'utf-8');
} catch (error) {
// Log warning but don't crash - use minimal fallback template
// eslint-disable-next-line no-console
console.error(`[ErrorPageRenderer] Failed to load template from ${templatePath}:`, error);
this.template = ErrorPageRenderer.getMinimalFallbackTemplate();
}
}

/**
* Minimal fallback template used when the main template file cannot be loaded.
* This ensures the proxy can still display error pages even if the template is missing.
*/
private static getMinimalFallbackTemplate(): string {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{PAGE_TITLE}}</title>
{{META_REFRESH}}
<style>
body { font-family: system-ui, sans-serif; background: #1a1a2e; color: #eee; padding: 40px; }
.container { max-width: 800px; margin: 0 auto; }
h1 { color: #ff6b6b; }
.status { color: #ffd93d; margin-bottom: 20px; }
.info { background: #16213e; padding: 20px; border-radius: 8px; margin: 20px 0; }
.info p { margin: 8px 0; }
code { background: #0f3460; padding: 2px 6px; border-radius: 4px; }
</style>
</head>
<body>
<div class="container">
<h1>{{ERROR_TITLE}}</h1>
<p class="status">{{ERROR_STATUS}}</p>
<div class="info">
{{MESSAGE_CONTENT}}
<p><strong>Dev Server:</strong> <code>{{DEV_SERVER_URL}}</code></p>
<p><strong>Proxy:</strong> <code>{{PROXY_URL}}</code></p>
<p><strong>Last Check:</strong> {{LAST_CHECK_TIME}}</p>
</div>
<p style="color:#888;font-size:14px;">{{AUTO_REFRESH_TEXT}}</p>
</div>
</body>
</html>`;
this.template = getErrorPageTemplate();
}

/**
Expand Down
Loading