Enhance README and RPC for package management

- Added instructions to README.md for building an ISO from source and flashing it to USB.
- Introduced a new RPC method for package installation, including security checks and container management.
- Updated Docker and Podman integration in build scripts to support both container runtimes.
- Enhanced Nginx configuration for improved timeout settings and WebSocket support.
- Added new app metadata for additional applications in the Docker package scanner.
This commit is contained in:
Dorian
2026-02-01 18:46:35 +00:00
parent 22024bde84
commit 0f40cb88b5
59 changed files with 3473 additions and 360 deletions

View File

@@ -18,6 +18,9 @@ export class WebSocketClient {
private reconnectTimer: ReturnType<typeof setTimeout> | null = null
private visibilityChangeHandler: (() => void) | null = null
private onlineHandler: (() => void) | null = null
private heartbeatTimer: ReturnType<typeof setTimeout> | null = null
private lastMessageTime: number = Date.now()
private heartbeatInterval = 10000 // Check connection every 10 seconds
constructor(url: string = '/ws/db') {
this.url = url
@@ -132,8 +135,10 @@ export class WebSocketClient {
this.ws.onopen = () => {
clearTimeout(connectionTimeout)
this.reconnectAttempts = 0
this.lastMessageTime = Date.now()
console.log('[WebSocket] Connected successfully')
this.notifyConnectionState(true)
this.startHeartbeat()
resolve()
}
@@ -145,6 +150,7 @@ export class WebSocketClient {
}
this.ws.onmessage = (event) => {
this.lastMessageTime = Date.now()
try {
const update: Update = JSON.parse(event.data)
this.callbacks.forEach((callback) => callback(update))
@@ -155,6 +161,7 @@ export class WebSocketClient {
this.ws.onclose = (event) => {
clearTimeout(connectionTimeout)
this.stopHeartbeat()
console.log('[WebSocket] Closed', { code: event.code, reason: event.reason, wasClean: event.wasClean })
// Notify connection state changed
@@ -243,9 +250,39 @@ export class WebSocketClient {
this.connectionStateCallbacks.forEach((callback) => callback(connected))
}
private startHeartbeat(): void {
this.stopHeartbeat()
this.heartbeatTimer = setInterval(() => {
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
console.warn('[WebSocket] Heartbeat detected closed connection')
this.stopHeartbeat()
return
}
// Check if we've received a message recently
const timeSinceLastMessage = Date.now() - this.lastMessageTime
// If no message for more than 60 seconds, assume connection is stale
if (timeSinceLastMessage > 60000) {
console.warn('[WebSocket] No messages for 60s, reconnecting...')
this.ws.close()
return
}
}, this.heartbeatInterval)
}
private stopHeartbeat(): void {
if (this.heartbeatTimer) {
clearInterval(this.heartbeatTimer)
this.heartbeatTimer = null
}
}
disconnect(): void {
this.shouldReconnect = false
this.reconnectAttempts = 0
this.stopHeartbeat()
// Clear reconnect timer
if (this.reconnectTimer) {