nostr-websocket-utils 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +151 -103
- package/dist/__mocks__/extendedWsMock.d.ts +35 -0
- package/dist/__mocks__/extendedWsMock.js +156 -0
- package/dist/__mocks__/logger.d.ts +9 -0
- package/dist/__mocks__/logger.js +6 -0
- package/dist/__mocks__/mockLogger.d.ts +41 -0
- package/dist/__mocks__/mockLogger.js +47 -0
- package/dist/__mocks__/mockserver.d.ts +31 -0
- package/dist/__mocks__/mockserver.js +39 -0
- package/dist/__mocks__/wsMock.d.ts +26 -0
- package/dist/__mocks__/wsMock.js +120 -0
- package/dist/client.d.ts +105 -0
- package/dist/client.js +105 -0
- package/dist/core/client.d.ts +94 -0
- package/dist/core/client.js +360 -0
- package/dist/core/nostr-server.d.ts +27 -0
- package/dist/core/nostr-server.js +95 -0
- package/dist/core/queue.d.ts +61 -0
- package/dist/core/queue.js +108 -0
- package/dist/core/server.d.ts +27 -0
- package/dist/core/server.js +114 -0
- package/dist/crypto/bech32.d.ts +26 -0
- package/dist/crypto/bech32.js +163 -0
- package/dist/crypto/handlers.d.ts +11 -0
- package/dist/crypto/handlers.js +36 -0
- package/dist/crypto/index.d.ts +5 -0
- package/dist/crypto/index.js +5 -0
- package/dist/crypto/schnorr.d.ts +16 -0
- package/dist/crypto/schnorr.js +51 -0
- package/dist/endpoints/metrics.d.ts +29 -0
- package/dist/endpoints/metrics.js +101 -0
- package/dist/index.d.ts +11 -6
- package/dist/index.js +16 -4
- package/dist/nips/index.d.ts +19 -0
- package/dist/nips/index.js +34 -0
- package/dist/nips/nip-01.d.ts +34 -0
- package/dist/nips/nip-01.js +145 -0
- package/dist/nips/nip-02.d.ts +83 -0
- package/dist/nips/nip-02.js +123 -0
- package/dist/nips/nip-04.d.ts +36 -0
- package/dist/nips/nip-04.js +105 -0
- package/dist/nips/nip-05.d.ts +86 -0
- package/dist/nips/nip-05.js +151 -0
- package/dist/nips/nip-09.d.ts +92 -0
- package/dist/nips/nip-09.js +190 -0
- package/dist/nips/nip-11.d.ts +64 -0
- package/dist/nips/nip-11.js +154 -0
- package/dist/nips/nip-13.d.ts +73 -0
- package/dist/nips/nip-13.js +128 -0
- package/dist/nips/nip-15.d.ts +83 -0
- package/dist/nips/nip-15.js +101 -0
- package/dist/nips/nip-16.d.ts +88 -0
- package/dist/nips/nip-16.js +150 -0
- package/dist/nips/nip-19.d.ts +28 -0
- package/dist/nips/nip-19.js +103 -0
- package/dist/nips/nip-20.d.ts +59 -0
- package/dist/nips/nip-20.js +95 -0
- package/dist/nips/nip-22.d.ts +89 -0
- package/dist/nips/nip-22.js +142 -0
- package/dist/nips/nip-26.d.ts +52 -0
- package/dist/nips/nip-26.js +139 -0
- package/dist/nips/nip-28.d.ts +103 -0
- package/dist/nips/nip-28.js +170 -0
- package/dist/nips/nip-33.d.ts +94 -0
- package/dist/nips/nip-33.js +133 -0
- package/dist/nostr-server.d.ts +23 -0
- package/dist/nostr-server.js +44 -0
- package/dist/server.d.ts +13 -3
- package/dist/server.js +60 -33
- package/dist/transport/base.d.ts +54 -0
- package/dist/transport/base.js +104 -0
- package/dist/transport/websocket.d.ts +22 -0
- package/dist/transport/websocket.js +122 -0
- package/dist/types/events.d.ts +63 -0
- package/dist/types/events.js +5 -0
- package/dist/types/filters.d.ts +19 -0
- package/dist/types/filters.js +5 -0
- package/dist/types/handlers.d.ts +80 -0
- package/dist/types/handlers.js +5 -0
- package/dist/types/index.d.ts +118 -39
- package/dist/types/index.js +21 -1
- package/dist/types/logger.d.ts +40 -0
- package/dist/types/logger.js +5 -0
- package/dist/types/messages.d.ts +135 -0
- package/dist/types/messages.js +40 -0
- package/dist/types/nostr.d.ts +120 -39
- package/dist/types/nostr.js +5 -10
- package/dist/types/options.d.ts +154 -0
- package/dist/types/options.js +5 -0
- package/dist/types/relays.d.ts +26 -0
- package/dist/types/relays.js +5 -0
- package/dist/types/scoring.d.ts +47 -0
- package/dist/types/scoring.js +29 -0
- package/dist/types/socket.d.ts +99 -0
- package/dist/types/socket.js +5 -0
- package/dist/types/transport.d.ts +97 -0
- package/dist/types/transport.js +5 -0
- package/dist/types/validation.d.ts +50 -0
- package/dist/types/validation.js +5 -0
- package/dist/types/websocket.d.ts +172 -0
- package/dist/types/websocket.js +5 -0
- package/dist/utils/http.d.ts +10 -0
- package/dist/utils/http.js +24 -0
- package/dist/utils/logger.d.ts +11 -2
- package/dist/utils/logger.js +18 -13
- package/dist/utils/metrics.d.ts +81 -0
- package/dist/utils/metrics.js +206 -0
- package/dist/utils/rate-limiter.d.ts +85 -0
- package/dist/utils/rate-limiter.js +175 -0
- package/package.json +18 -21
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file WebSocket client configuration options
|
|
3
|
+
* @module types/options
|
|
4
|
+
*/
|
|
5
|
+
import WebSocket from 'ws';
|
|
6
|
+
import { NostrWSMessage } from './messages';
|
|
7
|
+
/**
|
|
8
|
+
* Handler functions for WebSocket events
|
|
9
|
+
*/
|
|
10
|
+
export interface NostrWSHandlers {
|
|
11
|
+
/**
|
|
12
|
+
* Handler for incoming messages
|
|
13
|
+
*/
|
|
14
|
+
message: (message: NostrWSMessage) => Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Handler for WebSocket errors
|
|
17
|
+
*/
|
|
18
|
+
error: (error: Error) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Handler for connection close events
|
|
21
|
+
*/
|
|
22
|
+
close: () => void;
|
|
23
|
+
/**
|
|
24
|
+
* Handler for connection state changes
|
|
25
|
+
*/
|
|
26
|
+
stateChange?: (state: string) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Handler for heartbeat events
|
|
29
|
+
*/
|
|
30
|
+
heartbeat?: () => void;
|
|
31
|
+
/**
|
|
32
|
+
* Handler for connection events
|
|
33
|
+
*/
|
|
34
|
+
connect?: () => void;
|
|
35
|
+
/**
|
|
36
|
+
* Handler for disconnection events
|
|
37
|
+
*/
|
|
38
|
+
disconnect?: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Handler for reconnection events
|
|
41
|
+
*/
|
|
42
|
+
reconnect?: () => void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Connection retry configuration
|
|
46
|
+
*/
|
|
47
|
+
export interface RetryConfig {
|
|
48
|
+
/**
|
|
49
|
+
* Maximum number of retry attempts
|
|
50
|
+
* @default 10
|
|
51
|
+
*/
|
|
52
|
+
maxAttempts: number;
|
|
53
|
+
/**
|
|
54
|
+
* Initial delay between retries in milliseconds
|
|
55
|
+
* @default 1000
|
|
56
|
+
*/
|
|
57
|
+
initialDelay: number;
|
|
58
|
+
/**
|
|
59
|
+
* Maximum delay between retries in milliseconds
|
|
60
|
+
* @default 30000
|
|
61
|
+
*/
|
|
62
|
+
maxDelay: number;
|
|
63
|
+
/**
|
|
64
|
+
* Factor to multiply delay by after each attempt
|
|
65
|
+
* @default 1.5
|
|
66
|
+
*/
|
|
67
|
+
backoffFactor: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Queue configuration
|
|
71
|
+
*/
|
|
72
|
+
export interface QueueConfig {
|
|
73
|
+
/**
|
|
74
|
+
* Maximum size of the message queue
|
|
75
|
+
* @default 1000
|
|
76
|
+
*/
|
|
77
|
+
maxSize: number;
|
|
78
|
+
/**
|
|
79
|
+
* Maximum number of retry attempts per message
|
|
80
|
+
* @default 3
|
|
81
|
+
*/
|
|
82
|
+
maxRetries: number;
|
|
83
|
+
/**
|
|
84
|
+
* Base delay between retries in milliseconds
|
|
85
|
+
* @default 1000
|
|
86
|
+
*/
|
|
87
|
+
retryDelay: number;
|
|
88
|
+
/**
|
|
89
|
+
* Time in milliseconds after which messages are considered stale
|
|
90
|
+
* @default 300000 (5 minutes)
|
|
91
|
+
*/
|
|
92
|
+
staleTimeout: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Heartbeat configuration
|
|
96
|
+
*/
|
|
97
|
+
export interface HeartbeatConfig {
|
|
98
|
+
/**
|
|
99
|
+
* Interval between heartbeat pings in milliseconds
|
|
100
|
+
* @default 30000
|
|
101
|
+
*/
|
|
102
|
+
interval: number;
|
|
103
|
+
/**
|
|
104
|
+
* Timeout for heartbeat response in milliseconds
|
|
105
|
+
* @default 5000
|
|
106
|
+
*/
|
|
107
|
+
timeout: number;
|
|
108
|
+
/**
|
|
109
|
+
* Maximum missed heartbeats before connection is considered dead
|
|
110
|
+
* @default 3
|
|
111
|
+
*/
|
|
112
|
+
maxMissed: number;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* WebSocket client configuration options
|
|
116
|
+
*/
|
|
117
|
+
export interface NostrWSOptions {
|
|
118
|
+
/**
|
|
119
|
+
* WebSocket implementation to use
|
|
120
|
+
* @default ws
|
|
121
|
+
*/
|
|
122
|
+
WebSocketImpl: typeof WebSocket;
|
|
123
|
+
/**
|
|
124
|
+
* Event handlers
|
|
125
|
+
*/
|
|
126
|
+
handlers: NostrWSHandlers;
|
|
127
|
+
/**
|
|
128
|
+
* Retry configuration
|
|
129
|
+
*/
|
|
130
|
+
retry?: Partial<RetryConfig>;
|
|
131
|
+
/**
|
|
132
|
+
* Queue configuration
|
|
133
|
+
*/
|
|
134
|
+
queue?: Partial<QueueConfig>;
|
|
135
|
+
/**
|
|
136
|
+
* Heartbeat configuration
|
|
137
|
+
*/
|
|
138
|
+
heartbeat?: Partial<HeartbeatConfig>;
|
|
139
|
+
/**
|
|
140
|
+
* Whether to automatically reconnect on disconnection
|
|
141
|
+
* @default true
|
|
142
|
+
*/
|
|
143
|
+
autoReconnect?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Whether to buffer messages when disconnected
|
|
146
|
+
* @default true
|
|
147
|
+
*/
|
|
148
|
+
bufferMessages?: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Whether to automatically remove stale messages from the queue
|
|
151
|
+
* @default true
|
|
152
|
+
*/
|
|
153
|
+
cleanStaleMessages?: boolean;
|
|
154
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Relay type definitions
|
|
3
|
+
* @module types/relays
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Relay information interface
|
|
7
|
+
*/
|
|
8
|
+
export interface NostrRelayInfo {
|
|
9
|
+
name?: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
pubkey?: string;
|
|
12
|
+
contact?: string;
|
|
13
|
+
supported_nips?: number[];
|
|
14
|
+
software?: string;
|
|
15
|
+
version?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Relay metadata interface
|
|
19
|
+
*/
|
|
20
|
+
export interface NostrRelayMetadata extends NostrRelayInfo {
|
|
21
|
+
url: string;
|
|
22
|
+
status: 'connected' | 'disconnected' | 'error';
|
|
23
|
+
error?: string;
|
|
24
|
+
lastConnected?: number;
|
|
25
|
+
lastDisconnected?: number;
|
|
26
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Scoring interfaces for connection metrics
|
|
3
|
+
* @module types/scoring
|
|
4
|
+
*/
|
|
5
|
+
export interface BaseMetrics {
|
|
6
|
+
totalConnections: number;
|
|
7
|
+
activeConnections: number;
|
|
8
|
+
connectionErrors: number;
|
|
9
|
+
messagesReceived: number;
|
|
10
|
+
messagesSent: number;
|
|
11
|
+
bytesReceived: number;
|
|
12
|
+
bytesSent: number;
|
|
13
|
+
averageLatency: number;
|
|
14
|
+
lastSeen: number;
|
|
15
|
+
}
|
|
16
|
+
export interface ScoringStrategy {
|
|
17
|
+
calculateScore(metrics: BaseMetrics): number;
|
|
18
|
+
}
|
|
19
|
+
export interface MetricsProvider<T extends BaseMetrics = BaseMetrics> {
|
|
20
|
+
getMetrics(endpoint: string): T;
|
|
21
|
+
getAllMetrics(): Map<string, T>;
|
|
22
|
+
trackMetric(endpoint: string, metricType: string, value: any): void;
|
|
23
|
+
}
|
|
24
|
+
export declare const DEFAULT_WEIGHTS: {
|
|
25
|
+
readonly latency: 0.2;
|
|
26
|
+
readonly reliability: 0.3;
|
|
27
|
+
readonly uptime: 0.2;
|
|
28
|
+
readonly errors: 0.2;
|
|
29
|
+
readonly activity: 0.1;
|
|
30
|
+
};
|
|
31
|
+
export declare class DefaultScoringStrategy implements ScoringStrategy {
|
|
32
|
+
private weights;
|
|
33
|
+
constructor(weights?: {
|
|
34
|
+
readonly latency: 0.2;
|
|
35
|
+
readonly reliability: 0.3;
|
|
36
|
+
readonly uptime: 0.2;
|
|
37
|
+
readonly errors: 0.2;
|
|
38
|
+
readonly activity: 0.1;
|
|
39
|
+
});
|
|
40
|
+
calculateScore(metrics: BaseMetrics): number;
|
|
41
|
+
}
|
|
42
|
+
export type MetricUpdateEvent = {
|
|
43
|
+
endpoint: string;
|
|
44
|
+
metricType: string;
|
|
45
|
+
value: any;
|
|
46
|
+
timestamp: number;
|
|
47
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Scoring interfaces for connection metrics
|
|
3
|
+
* @module types/scoring
|
|
4
|
+
*/
|
|
5
|
+
// Default scoring weights
|
|
6
|
+
export const DEFAULT_WEIGHTS = {
|
|
7
|
+
latency: 0.2,
|
|
8
|
+
reliability: 0.3,
|
|
9
|
+
uptime: 0.2,
|
|
10
|
+
errors: 0.2,
|
|
11
|
+
activity: 0.1,
|
|
12
|
+
};
|
|
13
|
+
// Default scoring strategy
|
|
14
|
+
export class DefaultScoringStrategy {
|
|
15
|
+
constructor(weights = DEFAULT_WEIGHTS) {
|
|
16
|
+
this.weights = weights;
|
|
17
|
+
}
|
|
18
|
+
calculateScore(metrics) {
|
|
19
|
+
const now = Date.now();
|
|
20
|
+
// Basic scoring components that would work for any transport
|
|
21
|
+
const latencyScore = Math.max(0, 100 - (metrics.averageLatency / 10));
|
|
22
|
+
const activityScore = metrics.lastSeen ?
|
|
23
|
+
Math.max(0, 100 - ((now - metrics.lastSeen) / (60 * 1000))) : 0;
|
|
24
|
+
const errorScore = Math.max(0, 100 - (metrics.connectionErrors * 5));
|
|
25
|
+
return Math.round((latencyScore * this.weights.latency) +
|
|
26
|
+
(errorScore * this.weights.errors) +
|
|
27
|
+
(activityScore * this.weights.activity));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Socket type definitions
|
|
3
|
+
* @module types/socket
|
|
4
|
+
*/
|
|
5
|
+
/// <reference types="node" />
|
|
6
|
+
/// <reference types="node" />
|
|
7
|
+
import type { WebSocket } from 'ws';
|
|
8
|
+
import type { NostrWSMessage } from './messages';
|
|
9
|
+
/**
|
|
10
|
+
* Extended WebSocket interface with Nostr-specific properties
|
|
11
|
+
*/
|
|
12
|
+
export interface NostrWSSocket extends WebSocket {
|
|
13
|
+
/**
|
|
14
|
+
* Unique client ID
|
|
15
|
+
*/
|
|
16
|
+
clientId?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Set of subscribed channels
|
|
19
|
+
*/
|
|
20
|
+
subscriptions?: Set<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Whether the socket is alive (for heartbeat)
|
|
23
|
+
*/
|
|
24
|
+
isAlive?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Send a message through the WebSocket
|
|
27
|
+
*/
|
|
28
|
+
send(message: string | Buffer): void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* WebSocket client options
|
|
32
|
+
*/
|
|
33
|
+
export interface NostrWSClientOptions {
|
|
34
|
+
/**
|
|
35
|
+
* WebSocket implementation to use
|
|
36
|
+
*/
|
|
37
|
+
WebSocketImpl?: typeof WebSocket;
|
|
38
|
+
/**
|
|
39
|
+
* Heartbeat interval in milliseconds
|
|
40
|
+
*/
|
|
41
|
+
heartbeatInterval?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Reconnect interval in milliseconds
|
|
44
|
+
*/
|
|
45
|
+
reconnectInterval?: number;
|
|
46
|
+
/**
|
|
47
|
+
* Maximum number of reconnect attempts
|
|
48
|
+
*/
|
|
49
|
+
maxReconnectAttempts?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Message handlers
|
|
52
|
+
*/
|
|
53
|
+
handlers?: {
|
|
54
|
+
message?: (message: NostrWSMessage) => Promise<void>;
|
|
55
|
+
connect?: () => Promise<void>;
|
|
56
|
+
disconnect?: () => Promise<void>;
|
|
57
|
+
error?: (error: Error) => Promise<void>;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* WebSocket server options
|
|
62
|
+
*/
|
|
63
|
+
export interface NostrWSServerOptions {
|
|
64
|
+
/**
|
|
65
|
+
* WebSocket server implementation to use
|
|
66
|
+
*/
|
|
67
|
+
WebSocketImpl?: typeof WebSocket;
|
|
68
|
+
/**
|
|
69
|
+
* Heartbeat interval in milliseconds
|
|
70
|
+
*/
|
|
71
|
+
heartbeatInterval?: number;
|
|
72
|
+
/**
|
|
73
|
+
* Message handlers
|
|
74
|
+
*/
|
|
75
|
+
handlers?: {
|
|
76
|
+
message?: (ws: NostrWSSocket, message: NostrWSMessage) => Promise<void>;
|
|
77
|
+
connect?: (ws: NostrWSSocket) => Promise<void>;
|
|
78
|
+
disconnect?: (ws: NostrWSSocket) => Promise<void>;
|
|
79
|
+
error?: (ws: NostrWSSocket, error: Error) => Promise<void>;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Client event types
|
|
84
|
+
*/
|
|
85
|
+
export type NostrWSClientEvents = {
|
|
86
|
+
message: (message: NostrWSMessage) => void;
|
|
87
|
+
connect: () => void;
|
|
88
|
+
disconnect: () => void;
|
|
89
|
+
error: (error: Error) => void;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Server event types
|
|
93
|
+
*/
|
|
94
|
+
export type NostrWSServerEvents = {
|
|
95
|
+
message: (ws: NostrWSSocket, message: NostrWSMessage) => void;
|
|
96
|
+
connect: (ws: NostrWSSocket) => void;
|
|
97
|
+
disconnect: (ws: NostrWSSocket) => void;
|
|
98
|
+
error: (ws: NostrWSSocket, error: Error) => void;
|
|
99
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Transport type definitions
|
|
3
|
+
* @module types/transport
|
|
4
|
+
*/
|
|
5
|
+
import { NostrEvent } from './events';
|
|
6
|
+
import { NostrWSMessage } from './messages';
|
|
7
|
+
/**
|
|
8
|
+
* Base transport interface
|
|
9
|
+
*/
|
|
10
|
+
export interface Transport {
|
|
11
|
+
/**
|
|
12
|
+
* Connect to the transport
|
|
13
|
+
*/
|
|
14
|
+
connect(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Disconnect from the transport
|
|
17
|
+
*/
|
|
18
|
+
disconnect(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Send a message through the transport
|
|
21
|
+
*/
|
|
22
|
+
send(message: NostrWSMessage): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Subscribe to events
|
|
25
|
+
*/
|
|
26
|
+
subscribe(filter: NostrEvent): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Unsubscribe from events
|
|
29
|
+
*/
|
|
30
|
+
unsubscribe(subscriptionId: string): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Check if transport is connected
|
|
33
|
+
*/
|
|
34
|
+
isConnected(): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Get transport metrics
|
|
37
|
+
*/
|
|
38
|
+
getMetrics(): TransportMetrics;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Transport metrics
|
|
42
|
+
*/
|
|
43
|
+
export interface TransportMetrics {
|
|
44
|
+
/**
|
|
45
|
+
* Total number of messages sent
|
|
46
|
+
*/
|
|
47
|
+
messagesSent: number;
|
|
48
|
+
/**
|
|
49
|
+
* Total number of messages received
|
|
50
|
+
*/
|
|
51
|
+
messagesReceived: number;
|
|
52
|
+
/**
|
|
53
|
+
* Total number of bytes sent
|
|
54
|
+
*/
|
|
55
|
+
bytesSent: number;
|
|
56
|
+
/**
|
|
57
|
+
* Total number of bytes received
|
|
58
|
+
*/
|
|
59
|
+
bytesReceived: number;
|
|
60
|
+
/**
|
|
61
|
+
* Average message latency in milliseconds
|
|
62
|
+
*/
|
|
63
|
+
averageLatency: number;
|
|
64
|
+
/**
|
|
65
|
+
* Number of active subscriptions
|
|
66
|
+
*/
|
|
67
|
+
activeSubscriptions: number;
|
|
68
|
+
/**
|
|
69
|
+
* Connection uptime in milliseconds
|
|
70
|
+
*/
|
|
71
|
+
uptime: number;
|
|
72
|
+
/**
|
|
73
|
+
* Number of connection attempts
|
|
74
|
+
*/
|
|
75
|
+
connectionAttempts: number;
|
|
76
|
+
/**
|
|
77
|
+
* Number of successful connections
|
|
78
|
+
*/
|
|
79
|
+
successfulConnections: number;
|
|
80
|
+
/**
|
|
81
|
+
* Number of failed connections
|
|
82
|
+
*/
|
|
83
|
+
failedConnections: number;
|
|
84
|
+
/**
|
|
85
|
+
* Transport-specific metrics
|
|
86
|
+
*/
|
|
87
|
+
[key: string]: number | string | boolean | undefined;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Transport factory interface
|
|
91
|
+
*/
|
|
92
|
+
export interface TransportFactory {
|
|
93
|
+
/**
|
|
94
|
+
* Create a new transport instance
|
|
95
|
+
*/
|
|
96
|
+
create(options: unknown): Transport;
|
|
97
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Validation type definitions
|
|
3
|
+
* @module types/validation
|
|
4
|
+
*/
|
|
5
|
+
import { NostrEvent } from './events';
|
|
6
|
+
import { NostrWSMessage } from './messages';
|
|
7
|
+
/**
|
|
8
|
+
* Validation result interface
|
|
9
|
+
*/
|
|
10
|
+
export interface NostrWSValidationResult {
|
|
11
|
+
/**
|
|
12
|
+
* Whether the validation passed
|
|
13
|
+
*/
|
|
14
|
+
isValid: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Error message if validation failed
|
|
17
|
+
*/
|
|
18
|
+
error?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Event validator interface
|
|
22
|
+
*/
|
|
23
|
+
export interface NostrEventValidator {
|
|
24
|
+
/**
|
|
25
|
+
* Validate a Nostr event
|
|
26
|
+
*/
|
|
27
|
+
validateEvent(event: NostrEvent): NostrWSValidationResult;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Message validator interface
|
|
31
|
+
*/
|
|
32
|
+
export interface NostrMessageValidator {
|
|
33
|
+
/**
|
|
34
|
+
* Validate a WebSocket message
|
|
35
|
+
*/
|
|
36
|
+
validateMessage(message: NostrWSMessage): NostrWSValidationResult;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Validator factory interface
|
|
40
|
+
*/
|
|
41
|
+
export interface ValidatorFactory {
|
|
42
|
+
/**
|
|
43
|
+
* Create an event validator
|
|
44
|
+
*/
|
|
45
|
+
createEventValidator(): NostrEventValidator;
|
|
46
|
+
/**
|
|
47
|
+
* Create a message validator
|
|
48
|
+
*/
|
|
49
|
+
createMessageValidator(): NostrMessageValidator;
|
|
50
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file WebSocket type definitions and extensions
|
|
3
|
+
* @module types/websocket
|
|
4
|
+
*/
|
|
5
|
+
import type { WebSocket } from 'ws';
|
|
6
|
+
import type { NostrWSMessage } from './messages';
|
|
7
|
+
import { MessageType } from './messages';
|
|
8
|
+
import { RateLimitConfig } from '../utils/rate-limiter';
|
|
9
|
+
import type { Logger } from './logger';
|
|
10
|
+
/**
|
|
11
|
+
* Extended WebSocket interface with additional properties
|
|
12
|
+
* @interface ExtendedWebSocket
|
|
13
|
+
*/
|
|
14
|
+
export interface ExtendedWebSocket extends WebSocket {
|
|
15
|
+
/**
|
|
16
|
+
* Whether the WebSocket connection is alive
|
|
17
|
+
*/
|
|
18
|
+
isAlive?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Set of subscription channels
|
|
21
|
+
*/
|
|
22
|
+
subscriptions?: Set<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Unique client identifier
|
|
25
|
+
*/
|
|
26
|
+
clientId?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Queue of messages to be sent
|
|
29
|
+
*/
|
|
30
|
+
messageQueue?: NostrWSMessage[];
|
|
31
|
+
/**
|
|
32
|
+
* Timestamp of the last ping message
|
|
33
|
+
*/
|
|
34
|
+
lastPing?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Timestamp of the last pong message
|
|
37
|
+
*/
|
|
38
|
+
lastPong?: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Configuration options for the NostrWSClient
|
|
42
|
+
* @interface NostrWSOptions
|
|
43
|
+
*/
|
|
44
|
+
export interface NostrWSOptions {
|
|
45
|
+
/**
|
|
46
|
+
* Interval in milliseconds between heartbeat messages
|
|
47
|
+
* @default 30000
|
|
48
|
+
*/
|
|
49
|
+
heartbeatInterval?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Interval in milliseconds between reconnect attempts
|
|
52
|
+
* @default 5000
|
|
53
|
+
*/
|
|
54
|
+
reconnectInterval?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Maximum number of reconnect attempts
|
|
57
|
+
* @default 10
|
|
58
|
+
*/
|
|
59
|
+
maxReconnectAttempts?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Logger instance for handling log messages
|
|
62
|
+
*/
|
|
63
|
+
logger: Logger;
|
|
64
|
+
/**
|
|
65
|
+
* WebSocket implementation to use
|
|
66
|
+
*/
|
|
67
|
+
WebSocketImpl: typeof WebSocket;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* State of the NostrWSClient connection
|
|
71
|
+
* @interface NostrWSConnectionState
|
|
72
|
+
*/
|
|
73
|
+
export interface NostrWSConnectionState {
|
|
74
|
+
/**
|
|
75
|
+
* Whether the client is currently connected
|
|
76
|
+
*/
|
|
77
|
+
isConnected: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Number of reconnection attempts made
|
|
80
|
+
*/
|
|
81
|
+
reconnectAttempts: number;
|
|
82
|
+
/**
|
|
83
|
+
* Last error encountered
|
|
84
|
+
*/
|
|
85
|
+
lastError?: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Server configuration options
|
|
89
|
+
* @interface NostrWSServerOptions
|
|
90
|
+
*/
|
|
91
|
+
export interface NostrWSServerOptions {
|
|
92
|
+
/**
|
|
93
|
+
* Port to listen on
|
|
94
|
+
*/
|
|
95
|
+
port: number;
|
|
96
|
+
/**
|
|
97
|
+
* Host to bind to
|
|
98
|
+
*/
|
|
99
|
+
host?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Path for the WebSocket endpoint
|
|
102
|
+
*/
|
|
103
|
+
path?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Maximum payload size in bytes
|
|
106
|
+
*/
|
|
107
|
+
maxPayload?: number;
|
|
108
|
+
/**
|
|
109
|
+
* Maximum number of concurrent connections
|
|
110
|
+
*/
|
|
111
|
+
maxConnections?: number;
|
|
112
|
+
/**
|
|
113
|
+
* Ping interval in milliseconds
|
|
114
|
+
*/
|
|
115
|
+
pingInterval?: number;
|
|
116
|
+
/**
|
|
117
|
+
* Rate limiting configuration
|
|
118
|
+
*/
|
|
119
|
+
rateLimits?: RateLimitConfig;
|
|
120
|
+
/**
|
|
121
|
+
* Message handler
|
|
122
|
+
*/
|
|
123
|
+
onMessage?: (message: NostrWSMessage, socket: NostrWSServerSocket) => Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Error handler
|
|
126
|
+
*/
|
|
127
|
+
onError?: (error: Error, socket: NostrWSServerSocket) => void;
|
|
128
|
+
/**
|
|
129
|
+
* Close handler
|
|
130
|
+
*/
|
|
131
|
+
onClose?: (socket: NostrWSServerSocket) => void;
|
|
132
|
+
/**
|
|
133
|
+
* Connection handler
|
|
134
|
+
*/
|
|
135
|
+
onConnection?: (socket: NostrWSServerSocket) => Promise<void>;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Server message structure
|
|
139
|
+
* @interface NostrWSServerMessage
|
|
140
|
+
*/
|
|
141
|
+
export interface NostrWSServerMessage {
|
|
142
|
+
/**
|
|
143
|
+
* Message type
|
|
144
|
+
*/
|
|
145
|
+
type: MessageType;
|
|
146
|
+
/**
|
|
147
|
+
* Message data
|
|
148
|
+
*/
|
|
149
|
+
data?: unknown;
|
|
150
|
+
/**
|
|
151
|
+
* Error message if applicable
|
|
152
|
+
*/
|
|
153
|
+
error?: string;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Extended WebSocket interface for Nostr server
|
|
157
|
+
* @interface NostrWSServerSocket
|
|
158
|
+
*/
|
|
159
|
+
export interface NostrWSServerSocket extends WebSocket {
|
|
160
|
+
clientId: string;
|
|
161
|
+
subscriptions: Set<string>;
|
|
162
|
+
lastPing?: number;
|
|
163
|
+
isAlive: boolean;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Nostr WebSocket server message with client info
|
|
167
|
+
* @interface NostrWSServerClientMessage
|
|
168
|
+
*/
|
|
169
|
+
export interface NostrWSServerClientMessage extends NostrWSMessage {
|
|
170
|
+
clientId?: string;
|
|
171
|
+
timestamp?: number;
|
|
172
|
+
}
|