Files
rspade_system/app/RSpade/resource/vscode_extension/out/debug_client.js
root 9ebcc359ae Fix code quality violations and enhance ROUTE-EXISTS-01 rule
Implement JQHTML function cache ID system and fix bundle compilation
Implement underscore prefix for system tables
Fix JS syntax linter to support decorators and grant exception to Task system
SPA: Update planning docs and wishlists with remaining features
SPA: Document Navigation API abandonment and future enhancements
Implement SPA browser integration with History API (Phase 1)
Convert contacts view page to SPA action
Convert clients pages to SPA actions and document conversion procedure
SPA: Merge GET parameters and update documentation
Implement SPA route URL generation in JavaScript and PHP
Implement SPA bootstrap controller architecture
Add SPA routing manual page (rsx:man spa)
Add SPA routing documentation to CLAUDE.md
Phase 4 Complete: Client-side SPA routing implementation
Update get_routes() consumers for unified route structure
Complete SPA Phase 3: PHP-side route type detection and is_spa flag
Restore unified routes structure and Manifest_Query class
Refactor route indexing and add SPA infrastructure
Phase 3 Complete: SPA route registration in manifest
Implement SPA Phase 2: Extract router code and test decorators
Rename Jqhtml_Component to Component and complete SPA foundation setup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 17:48:15 +00:00

211 lines
7.4 KiB
JavaScript
Executable File

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DebugClient = void 0;
const vscode = __importStar(require("vscode"));
const crypto = __importStar(require("crypto"));
class DebugClient {
constructor(formattingProvider) {
this.ws = null; // WebSocket instance
this.isConnecting = false;
this.reconnectTimer = null;
this.pingTimer = null;
this.sessionId = null;
this.serverKey = null;
this.formattingProvider = formattingProvider;
this.outputChannel = vscode.window.createOutputChannel('RSPade Debug Proxy');
this.outputChannel.show();
this.log('Debug client initialized');
}
async start() {
this.log('Starting debug client...');
await this.connect();
}
async connect() {
if (this.isConnecting || this.ws?.readyState === WebSocket.OPEN) {
return;
}
this.isConnecting = true;
try {
// Get authentication from formatting provider
await this.ensureAuthenticated();
const serverUrl = await this.formattingProvider.get_server_url();
if (!serverUrl) {
throw new Error('No server URL configured');
}
// Parse URL and construct WebSocket URL
const url = new URL(serverUrl);
const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = `${wsProtocol}//${url.host}/_ide/debug/ws`;
this.log(`Connecting to WebSocket: ${wsUrl}`);
// Create WebSocket (standard API doesn't support headers in constructor)
// We'll send auth after connection
this.ws = new WebSocket(wsUrl);
this.setupEventHandlers();
}
catch (error) {
this.log(`Connection failed: ${error.message}`);
this.isConnecting = false;
this.scheduleReconnect();
}
}
setupEventHandlers() {
if (!this.ws)
return;
this.ws.onopen = () => {
this.isConnecting = false;
this.log('WebSocket connected, sending authentication...');
// Send authentication as first message
const signature = crypto
.createHmac('sha256', this.serverKey)
.update(this.sessionId)
.digest('hex');
this.sendMessage({
type: 'auth',
data: {
sessionId: this.sessionId,
signature: signature
}
});
// Send initial hello message after auth
setTimeout(() => {
this.sendMessage({
type: 'hello',
data: { name: 'VS Code Debug Client' }
});
// Start ping timer
this.startPingTimer();
}, 100);
};
this.ws.onmessage = (event) => {
try {
const message = JSON.parse(event.data);
this.handleMessage(message);
}
catch (error) {
this.log(`Failed to parse message: ${error}`);
}
};
this.ws.onclose = () => {
this.log('WebSocket disconnected');
this.ws = null;
this.stopPingTimer();
this.scheduleReconnect();
};
this.ws.onerror = (error) => {
this.log(`WebSocket error: ${error}`);
};
}
handleMessage(message) {
this.log(`Received: ${message.type}`, message.data);
switch (message.type) {
case 'welcome':
this.log('✅ Authentication successful! Connected to debug proxy');
this.log(`Session ID: ${message.data?.sessionId}`);
break;
case 'pong':
this.log(`PONG received! Server responded to ping`);
break;
case 'hello_response':
this.log(`Server says: ${message.data?.message}`);
break;
case 'error':
this.log(`❌ Error: ${message.data?.message}`);
break;
default:
this.log(`Unknown message type: ${message.type}`);
}
}
sendMessage(message) {
if (this.ws?.readyState === 1) { // 1 = OPEN in standard WebSocket API
this.ws.send(JSON.stringify(message));
this.log(`Sent: ${message.type}`, message.data);
}
}
startPingTimer() {
this.stopPingTimer();
// Send ping every 5 seconds
this.pingTimer = setInterval(() => {
this.sendMessage({
type: 'ping',
data: { timestamp: Date.now() }
});
this.log('PING sent to server');
}, 5000);
}
stopPingTimer() {
if (this.pingTimer) {
clearInterval(this.pingTimer);
this.pingTimer = null;
}
}
scheduleReconnect() {
if (this.reconnectTimer) {
return;
}
this.log('Scheduling reconnection in 5 seconds...');
this.reconnectTimer = setTimeout(() => {
this.reconnectTimer = null;
this.connect();
}, 5000);
}
async ensureAuthenticated() {
// Get auth data from formatting provider
const authData = await this.formattingProvider.ensure_auth();
if (!authData) {
throw new Error('Failed to authenticate');
}
// Extract session ID and server key
this.sessionId = authData.session_id;
this.serverKey = authData.server_key;
if (!this.sessionId || !this.serverKey) {
throw new Error('Invalid auth data');
}
}
log(message, data) {
const timestamp = new Date().toISOString();
const logMessage = `[${timestamp}] ${message}`;
if (data) {
this.outputChannel.appendLine(`${logMessage}\n${JSON.stringify(data, null, 2)}`);
}
else {
this.outputChannel.appendLine(logMessage);
}
}
dispose() {
this.stopPingTimer();
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
this.reconnectTimer = null;
}
if (this.ws) {
this.ws.close();
this.ws = null;
}
this.outputChannel.dispose();
}
}
exports.DebugClient = DebugClient;
//# sourceMappingURL=debug_client.js.map