feat: Integrate Relay Hub for centralized Nostr connection management

- Introduce a new composable, useRelayHub, to manage all Nostr WebSocket connections, enhancing connection stability and performance.
- Update existing components and composables to utilize the Relay Hub for connecting, publishing events, and subscribing to updates, streamlining the overall architecture.
- Add a RelayHubStatus component to display connection status and health metrics, improving user feedback on the connection state.
- Implement a RelayHubDemo page to showcase the functionality of the Relay Hub, including connection tests and subscription management.
- Ensure proper error handling and logging throughout the integration process to facilitate debugging and user experience.
This commit is contained in:
padreug 2025-08-10 11:48:33 +02:00
parent df7e461c91
commit 7d7bee8e77
14 changed files with 1982 additions and 955 deletions

View file

@ -1,6 +1,6 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { NostrClient } from '@/lib/nostr/client'
import { relayHub } from '@/lib/nostr/relayHub'
import { config } from '@/lib/config'
import { pushService, type PushSubscriptionData } from '@/lib/notifications/push'
@ -23,17 +23,6 @@ export const useNostrStore = defineStore('nostr', () => {
// Push notifications
const pushSubscription = ref<PushSubscriptionData | null>(null)
const notificationsEnabled = ref(false)
// Singleton client instance
let client: NostrClient | null = null
// Get or create client instance
function getClient(): NostrClient {
if (!client) {
client = new NostrClient({ relays: relayUrls.value })
}
return client
}
// Connection management
async function connect(): Promise<void> {
@ -41,10 +30,11 @@ export const useNostrStore = defineStore('nostr', () => {
error.value = null
isConnecting.value = true
const nostrClient = getClient()
await nostrClient.connect()
// Initialize and connect using the centralized relay hub
await relayHub.initialize(relayUrls.value)
await relayHub.connect()
isConnected.value = nostrClient.isConnected
isConnected.value = relayHub.isConnected
} catch (err) {
error.value = err instanceof Error ? err : new Error('Failed to connect')
isConnected.value = false
@ -55,10 +45,8 @@ export const useNostrStore = defineStore('nostr', () => {
}
function disconnect(): void {
if (client) {
client.disconnect()
client = null
}
// Don't disconnect the relay hub as it's managed centrally
// Just update our local state
isConnected.value = false
isConnecting.value = false
error.value = null
@ -71,11 +59,7 @@ export const useNostrStore = defineStore('nostr', () => {
function setRelayUrls(urls: string[]) {
relayUrls.value = urls
// Recreate client with new relays
if (client) {
client.disconnect()
client = null
}
// The relay hub will handle reconnection with new relays if needed
}
function setAccount(nostrAccount: NostrAccount | null) {
@ -111,7 +95,6 @@ export const useNostrStore = defineStore('nostr', () => {
localStorage.removeItem('notifications-enabled')
} catch (error) {
console.error('Failed to disable push notifications:', error)
throw error
}
}
@ -154,6 +137,33 @@ export const useNostrStore = defineStore('nostr', () => {
})
}
// Setup relay hub event listeners to keep store state in sync
function setupRelayHubListeners(): void {
relayHub.on('connected', () => {
isConnected.value = true
isConnecting.value = false
error.value = null
})
relayHub.on('disconnected', () => {
isConnected.value = false
isConnecting.value = false
})
relayHub.on('error', (err: Error) => {
error.value = err
isConnected.value = false
isConnecting.value = false
})
relayHub.on('connecting', () => {
isConnecting.value = true
})
}
// Initialize relay hub listeners
setupRelayHubListeners()
return {
// State
isConnected,
@ -167,7 +177,6 @@ export const useNostrStore = defineStore('nostr', () => {
// Actions
connect,
disconnect,
getClient,
setConnected,
setRelayUrls,
setAccount,