Remove LEGACY Nostr client services and related components to streamline the codebase
- Delete Nostr client hub and associated files, including the Nostr store, to eliminate unused functionality. - Update service tokens and dependency injections to reflect the removal of Nostr client services. - Adjust notification settings in NotificationSettings.vue to prepare for future implementation of notifications.
This commit is contained in:
parent
92c33aa0a3
commit
7e4b64b831
8 changed files with 7 additions and 661 deletions
|
|
@ -2,7 +2,6 @@ import type { App } from 'vue'
|
|||
import type { ModulePlugin } from '@/core/types'
|
||||
import { container, SERVICE_TOKENS } from '@/core/di-container'
|
||||
import { relayHub } from './nostr/relay-hub'
|
||||
import { nostrclientHub } from './nostr/nostrclient-hub'
|
||||
|
||||
// Import auth services
|
||||
import { auth } from './auth/auth-service'
|
||||
|
|
@ -27,7 +26,6 @@ export const baseModule: ModulePlugin = {
|
|||
|
||||
// Register core Nostr services
|
||||
container.provide(SERVICE_TOKENS.RELAY_HUB, relayHub)
|
||||
container.provide(SERVICE_TOKENS.NOSTR_CLIENT_HUB, nostrclientHub)
|
||||
|
||||
// Register auth service
|
||||
container.provide(SERVICE_TOKENS.AUTH_SERVICE, auth)
|
||||
|
|
@ -56,10 +54,6 @@ export const baseModule: ModulePlugin = {
|
|||
waitForDependencies: false, // VisibilityService has no dependencies
|
||||
maxRetries: 1
|
||||
})
|
||||
await nostrclientHub.initialize({
|
||||
waitForDependencies: true, // NostrClientHub depends on VisibilityService
|
||||
maxRetries: 3
|
||||
})
|
||||
|
||||
console.log('✅ Base module installed successfully')
|
||||
},
|
||||
|
|
@ -69,7 +63,6 @@ export const baseModule: ModulePlugin = {
|
|||
|
||||
// Cleanup services
|
||||
await relayHub.dispose()
|
||||
await nostrclientHub.dispose()
|
||||
await auth.dispose()
|
||||
await paymentService.dispose()
|
||||
await visibilityService.dispose()
|
||||
|
|
@ -79,7 +72,6 @@ export const baseModule: ModulePlugin = {
|
|||
|
||||
services: {
|
||||
relayHub,
|
||||
nostrclientHub,
|
||||
auth,
|
||||
paymentService,
|
||||
pwaService
|
||||
|
|
|
|||
|
|
@ -1,16 +1,10 @@
|
|||
// Re-export Nostr infrastructure from base module
|
||||
export { RelayHub } from './relay-hub'
|
||||
export { NostrclientHub } from './nostrclient-hub'
|
||||
export { relayHub } from './relay-hub'
|
||||
export { nostrclientHub } from './nostrclient-hub'
|
||||
|
||||
// Re-export types
|
||||
export type {
|
||||
RelayConfig,
|
||||
SubscriptionConfig,
|
||||
RelayStatus
|
||||
} from './relay-hub'
|
||||
|
||||
export type {
|
||||
NostrclientConfig
|
||||
} from './nostrclient-hub'
|
||||
} from './relay-hub'
|
||||
|
|
@ -1,442 +0,0 @@
|
|||
import type { Filter, Event } from 'nostr-tools'
|
||||
import { BaseService } from '@/core/base/BaseService'
|
||||
|
||||
|
||||
export interface NostrclientConfig {
|
||||
url: string
|
||||
privateKey?: string // For private WebSocket endpoint
|
||||
}
|
||||
|
||||
export interface SubscriptionConfig {
|
||||
id: string
|
||||
filters: Filter[]
|
||||
onEvent?: (event: Event) => void
|
||||
onEose?: () => void
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
export interface RelayStatus {
|
||||
url: string
|
||||
connected: boolean
|
||||
lastSeen: number
|
||||
error?: string
|
||||
}
|
||||
|
||||
export class NostrclientHub extends BaseService {
|
||||
// Service metadata
|
||||
protected readonly metadata = {
|
||||
name: 'NostrclientHub',
|
||||
version: '1.0.0',
|
||||
dependencies: ['VisibilityService']
|
||||
}
|
||||
|
||||
// EventEmitter functionality
|
||||
private events: { [key: string]: Function[] } = {}
|
||||
|
||||
// Service state
|
||||
private ws: WebSocket | null = null
|
||||
private config: NostrclientConfig
|
||||
private subscriptions: Map<string, SubscriptionConfig> = new Map()
|
||||
private reconnectInterval?: number
|
||||
private reconnectAttempts = 0
|
||||
private readonly maxReconnectAttempts = 5
|
||||
private readonly reconnectDelay = 5000
|
||||
private visibilityUnsubscribe?: () => void
|
||||
|
||||
// Connection state
|
||||
private _isConnected = false
|
||||
private _isConnecting = false
|
||||
|
||||
constructor(config: NostrclientConfig) {
|
||||
super()
|
||||
this.config = config
|
||||
}
|
||||
|
||||
// EventEmitter methods
|
||||
on(event: string, listener: Function) {
|
||||
if (!this.events[event]) {
|
||||
this.events[event] = []
|
||||
}
|
||||
this.events[event].push(listener)
|
||||
}
|
||||
|
||||
emit(event: string, ...args: any[]) {
|
||||
if (this.events[event]) {
|
||||
this.events[event].forEach(listener => listener(...args))
|
||||
}
|
||||
}
|
||||
|
||||
removeAllListeners(event?: string) {
|
||||
if (event) {
|
||||
delete this.events[event]
|
||||
} else {
|
||||
this.events = {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Service-specific initialization (called by BaseService)
|
||||
*/
|
||||
protected async onInitialize(): Promise<void> {
|
||||
// Connect to WebSocket
|
||||
console.log('🔧 NostrclientHub: Initializing connection to', this.config.url)
|
||||
await this.connect()
|
||||
|
||||
// Register with visibility service
|
||||
this.registerWithVisibilityService()
|
||||
|
||||
this.debug('NostrclientHub initialized')
|
||||
}
|
||||
|
||||
get isConnected(): boolean {
|
||||
return this._isConnected
|
||||
}
|
||||
|
||||
get isConnecting(): boolean {
|
||||
return this._isConnecting
|
||||
}
|
||||
|
||||
get totalSubscriptionCount(): number {
|
||||
return this.subscriptions.size
|
||||
}
|
||||
|
||||
get subscriptionDetails(): Array<{ id: string; filters: Filter[] }> {
|
||||
return Array.from(this.subscriptions.values()).map(sub => ({
|
||||
id: sub.id,
|
||||
filters: sub.filters
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Connect to the nostrclient WebSocket
|
||||
*/
|
||||
async connect(): Promise<void> {
|
||||
if (this._isConnecting || this._isConnected) {
|
||||
return
|
||||
}
|
||||
|
||||
this._isConnecting = true
|
||||
this.reconnectAttempts++
|
||||
|
||||
try {
|
||||
console.log('🔧 NostrclientHub: Connecting to nostrclient WebSocket')
|
||||
|
||||
// Determine WebSocket endpoint
|
||||
const wsUrl = this.config.privateKey
|
||||
? `${this.config.url}/${this.config.privateKey}` // Private endpoint
|
||||
: `${this.config.url}/relay` // Public endpoint
|
||||
|
||||
this.ws = new WebSocket(wsUrl)
|
||||
|
||||
this.ws.onopen = () => {
|
||||
console.log('🔧 NostrclientHub: WebSocket connected')
|
||||
this._isConnected = true
|
||||
this._isConnecting = false
|
||||
this.reconnectAttempts = 0
|
||||
this.emit('connected')
|
||||
|
||||
// Resubscribe to existing subscriptions
|
||||
this.resubscribeAll()
|
||||
}
|
||||
|
||||
this.ws.onmessage = (event) => {
|
||||
this.handleMessage(event.data)
|
||||
}
|
||||
|
||||
this.ws.onclose = (event) => {
|
||||
console.log('🔧 NostrclientHub: WebSocket closed:', event.code, event.reason)
|
||||
this._isConnected = false
|
||||
this._isConnecting = false
|
||||
this.emit('disconnected', event)
|
||||
|
||||
// Schedule reconnection
|
||||
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
||||
this.scheduleReconnect()
|
||||
} else {
|
||||
this.emit('maxReconnectionAttemptsReached')
|
||||
}
|
||||
}
|
||||
|
||||
this.ws.onerror = (error) => {
|
||||
console.error('🔧 NostrclientHub: WebSocket error:', error)
|
||||
this.emit('error', error)
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this._isConnecting = false
|
||||
console.error('🔧 NostrclientHub: Connection failed:', error)
|
||||
this.emit('connectionError', error)
|
||||
|
||||
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
||||
this.scheduleReconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the WebSocket
|
||||
*/
|
||||
disconnect(): void {
|
||||
if (this.reconnectInterval) {
|
||||
clearTimeout(this.reconnectInterval)
|
||||
this.reconnectInterval = undefined
|
||||
}
|
||||
|
||||
if (this.ws) {
|
||||
this.ws.close()
|
||||
this.ws = null
|
||||
}
|
||||
|
||||
this._isConnected = false
|
||||
this._isConnecting = false
|
||||
this.subscriptions.clear()
|
||||
this.emit('disconnected')
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to events
|
||||
*/
|
||||
subscribe(config: SubscriptionConfig): () => void {
|
||||
if (!this._isConnected) {
|
||||
throw new Error('Not connected to nostrclient')
|
||||
}
|
||||
|
||||
// Store subscription
|
||||
this.subscriptions.set(config.id, config)
|
||||
|
||||
// Send REQ message
|
||||
const reqMessage = JSON.stringify([
|
||||
'REQ',
|
||||
config.id,
|
||||
...config.filters
|
||||
])
|
||||
|
||||
this.ws?.send(reqMessage)
|
||||
console.log('🔧 NostrclientHub: Subscribed to', config.id)
|
||||
|
||||
// Return unsubscribe function
|
||||
return () => {
|
||||
this.unsubscribe(config.id)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from events
|
||||
*/
|
||||
unsubscribe(subscriptionId: string): void {
|
||||
if (!this._isConnected) {
|
||||
return
|
||||
}
|
||||
|
||||
// Send CLOSE message
|
||||
const closeMessage = JSON.stringify(['CLOSE', subscriptionId])
|
||||
this.ws?.send(closeMessage)
|
||||
|
||||
// Remove from subscriptions
|
||||
this.subscriptions.delete(subscriptionId)
|
||||
console.log('🔧 NostrclientHub: Unsubscribed from', subscriptionId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish an event
|
||||
*/
|
||||
async publishEvent(event: Event): Promise<void> {
|
||||
if (!this._isConnected) {
|
||||
throw new Error('Not connected to nostrclient')
|
||||
}
|
||||
|
||||
const eventMessage = JSON.stringify(['EVENT', event])
|
||||
this.ws?.send(eventMessage)
|
||||
|
||||
console.log('🔧 NostrclientHub: Published event', event.id)
|
||||
this.emit('eventPublished', { eventId: event.id })
|
||||
}
|
||||
|
||||
/**
|
||||
* Query events (one-time fetch)
|
||||
*/
|
||||
async queryEvents(filters: Filter[]): Promise<Event[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this._isConnected) {
|
||||
reject(new Error('Not connected to nostrclient'))
|
||||
return
|
||||
}
|
||||
|
||||
const queryId = `query-${Date.now()}`
|
||||
const events: Event[] = []
|
||||
let eoseReceived = false
|
||||
|
||||
// Create temporary subscription for query
|
||||
const tempSubscription = this.subscribe({
|
||||
id: queryId,
|
||||
filters,
|
||||
onEvent: (event) => {
|
||||
events.push(event)
|
||||
},
|
||||
onEose: () => {
|
||||
eoseReceived = true
|
||||
this.unsubscribe(queryId)
|
||||
resolve(events)
|
||||
},
|
||||
onClose: () => {
|
||||
if (!eoseReceived) {
|
||||
reject(new Error('Query subscription closed unexpectedly'))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Timeout after 30 seconds
|
||||
setTimeout(() => {
|
||||
if (!eoseReceived) {
|
||||
tempSubscription()
|
||||
reject(new Error('Query timeout'))
|
||||
}
|
||||
}, 30000)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incoming WebSocket messages
|
||||
*/
|
||||
private handleMessage(data: string): void {
|
||||
try {
|
||||
const message = JSON.parse(data)
|
||||
|
||||
if (Array.isArray(message) && message.length >= 2) {
|
||||
const [type, subscriptionId, ...rest] = message
|
||||
|
||||
switch (type) {
|
||||
case 'EVENT':
|
||||
const event = rest[0] as Event
|
||||
const subscription = this.subscriptions.get(subscriptionId)
|
||||
if (subscription?.onEvent) {
|
||||
subscription.onEvent(event)
|
||||
}
|
||||
this.emit('event', { subscriptionId, event })
|
||||
break
|
||||
|
||||
case 'EOSE':
|
||||
const eoseSubscription = this.subscriptions.get(subscriptionId)
|
||||
if (eoseSubscription?.onEose) {
|
||||
eoseSubscription.onEose()
|
||||
}
|
||||
this.emit('eose', { subscriptionId })
|
||||
break
|
||||
|
||||
case 'NOTICE':
|
||||
console.log('🔧 NostrclientHub: Notice from relay:', rest[0])
|
||||
this.emit('notice', { message: rest[0] })
|
||||
break
|
||||
|
||||
default:
|
||||
console.log('🔧 NostrclientHub: Unknown message type:', type)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('🔧 NostrclientHub: Failed to parse message:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resubscribe to all existing subscriptions after reconnection
|
||||
*/
|
||||
private resubscribeAll(): void {
|
||||
for (const [id, config] of this.subscriptions) {
|
||||
const reqMessage = JSON.stringify([
|
||||
'REQ',
|
||||
id,
|
||||
...config.filters
|
||||
])
|
||||
this.ws?.send(reqMessage)
|
||||
}
|
||||
console.log('🔧 NostrclientHub: Resubscribed to', this.subscriptions.size, 'subscriptions')
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule automatic reconnection
|
||||
*/
|
||||
private scheduleReconnect(): void {
|
||||
if (this.reconnectInterval) {
|
||||
clearTimeout(this.reconnectInterval)
|
||||
}
|
||||
|
||||
const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1)
|
||||
console.log(`🔧 NostrclientHub: Scheduling reconnection in ${delay}ms`)
|
||||
|
||||
this.reconnectInterval = setTimeout(async () => {
|
||||
await this.connect()
|
||||
}, delay) as unknown as number
|
||||
}
|
||||
|
||||
/**
|
||||
* Register with VisibilityService for connection management
|
||||
*/
|
||||
private registerWithVisibilityService(): void {
|
||||
if (!this.visibilityService) {
|
||||
this.debug('VisibilityService not available')
|
||||
return
|
||||
}
|
||||
|
||||
this.visibilityUnsubscribe = this.visibilityService.registerService(
|
||||
this.metadata.name,
|
||||
async () => this.handleAppResume(),
|
||||
async () => this.handleAppPause()
|
||||
)
|
||||
|
||||
this.debug('Registered with VisibilityService')
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle app resuming from visibility change
|
||||
*/
|
||||
private async handleAppResume(): Promise<void> {
|
||||
this.debug('App resumed - checking nostrclient WebSocket connection')
|
||||
|
||||
// Check if we need to reconnect
|
||||
if (!this.isConnected && !this._isConnecting) {
|
||||
this.debug('WebSocket disconnected, attempting to reconnect...')
|
||||
await this.connect()
|
||||
} else if (this.isConnected) {
|
||||
// Connection is alive, resubscribe to ensure all subscriptions are active
|
||||
this.resubscribeAll()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle app pausing from visibility change
|
||||
*/
|
||||
private async handleAppPause(): Promise<void> {
|
||||
this.debug('App paused - WebSocket connection will be maintained for quick resume')
|
||||
|
||||
// Don't immediately disconnect - WebSocket will be checked on resume
|
||||
// This allows for quick resume without full reconnection overhead
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup when service is disposed (overrides BaseService)
|
||||
*/
|
||||
protected async onDispose(): Promise<void> {
|
||||
// Unregister from visibility service
|
||||
if (this.visibilityUnsubscribe) {
|
||||
this.visibilityUnsubscribe()
|
||||
this.visibilityUnsubscribe = undefined
|
||||
}
|
||||
|
||||
// Disconnect WebSocket
|
||||
this.disconnect()
|
||||
|
||||
// Clear all event listeners
|
||||
this.removeAllListeners()
|
||||
|
||||
this.debug('NostrclientHub disposed')
|
||||
}
|
||||
}
|
||||
|
||||
// Export singleton instance
|
||||
export const nostrclientHub = new NostrclientHub({
|
||||
url: import.meta.env.VITE_NOSTRCLIENT_URL || 'wss://localhost:5000/nostrclient/api/v1'
|
||||
})
|
||||
|
||||
// Ensure global export
|
||||
;(globalThis as any).nostrclientHub = nostrclientHub
|
||||
Loading…
Add table
Add a link
Reference in a new issue