@djangocfg/centrifugo 2.1.103 → 2.1.105
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/package.json +22 -27
- package/src/components/CentrifugoMonitor/CentrifugoMonitor.tsx +1 -1
- package/src/components/CentrifugoMonitor/CentrifugoMonitorDialog.tsx +2 -2
- package/src/components/CentrifugoMonitor/CentrifugoMonitorWidget.tsx +1 -1
- package/src/components/ConnectionStatus/ConnectionStatus.tsx +1 -1
- package/src/components/ConnectionStatus/ConnectionStatusCard.tsx +1 -1
- package/src/components/MessagesFeed/MessageFilters.tsx +1 -1
- package/src/components/MessagesFeed/MessagesFeed.tsx +1 -1
- package/src/components/SubscriptionsList/SubscriptionsList.tsx +1 -1
- package/src/components/index.ts +2 -0
- package/src/debug/ConnectionTab/ConnectionTab.tsx +1 -1
- package/src/debug/DebugPanel/DebugPanel.tsx +1 -1
- package/src/debug/LogsTab/LogsTab.tsx +1 -1
- package/src/debug/SubscriptionsTab/SubscriptionsTab.tsx +1 -1
- package/src/hooks/index.ts +2 -0
- package/src/index.ts +2 -0
- package/dist/components.cjs +0 -871
- package/dist/components.cjs.map +0 -1
- package/dist/components.d.mts +0 -129
- package/dist/components.d.ts +0 -129
- package/dist/components.mjs +0 -857
- package/dist/components.mjs.map +0 -1
- package/dist/hooks.cjs +0 -379
- package/dist/hooks.cjs.map +0 -1
- package/dist/hooks.d.mts +0 -128
- package/dist/hooks.d.ts +0 -128
- package/dist/hooks.mjs +0 -374
- package/dist/hooks.mjs.map +0 -1
- package/dist/index.cjs +0 -3007
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.mts +0 -838
- package/dist/index.d.ts +0 -838
- package/dist/index.mjs +0 -2948
- package/dist/index.mjs.map +0 -1
package/dist/index.d.mts
DELETED
|
@@ -1,838 +0,0 @@
|
|
|
1
|
-
import { Centrifuge } from 'centrifuge';
|
|
2
|
-
export * from 'centrifuge';
|
|
3
|
-
import * as consola from 'consola';
|
|
4
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
-
import { ReactNode } from 'react';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Core Types for Centrifugo Package
|
|
9
|
-
*
|
|
10
|
-
* Type-only exports, no runtime dependencies
|
|
11
|
-
*/
|
|
12
|
-
type LogLevel = 'debug' | 'info' | 'success' | 'warning' | 'error';
|
|
13
|
-
interface LogEntry {
|
|
14
|
-
id: string;
|
|
15
|
-
timestamp: Date;
|
|
16
|
-
level: LogLevel;
|
|
17
|
-
source: 'client' | 'provider' | 'subscription' | 'system';
|
|
18
|
-
message: string;
|
|
19
|
-
data?: unknown;
|
|
20
|
-
}
|
|
21
|
-
type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'error';
|
|
22
|
-
interface CentrifugoToken {
|
|
23
|
-
token: string;
|
|
24
|
-
centrifugo_url?: string;
|
|
25
|
-
channels: string[];
|
|
26
|
-
expires_at: string;
|
|
27
|
-
}
|
|
28
|
-
interface User {
|
|
29
|
-
id: number;
|
|
30
|
-
centrifugo?: CentrifugoToken;
|
|
31
|
-
}
|
|
32
|
-
interface ActiveSubscription {
|
|
33
|
-
channel: string;
|
|
34
|
-
type: 'client' | 'server';
|
|
35
|
-
subscribedAt: number;
|
|
36
|
-
data?: unknown;
|
|
37
|
-
}
|
|
38
|
-
interface CentrifugoClientConfig {
|
|
39
|
-
url: string;
|
|
40
|
-
token: string;
|
|
41
|
-
userId: string;
|
|
42
|
-
timeout?: number;
|
|
43
|
-
onLog?: (entry: Omit<LogEntry, 'id' | 'timestamp'>) => void;
|
|
44
|
-
}
|
|
45
|
-
interface CentrifugoClientState {
|
|
46
|
-
isConnected: boolean;
|
|
47
|
-
isConnecting: boolean;
|
|
48
|
-
error: Error | null;
|
|
49
|
-
connectionState: ConnectionState;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Create Logger
|
|
54
|
-
*
|
|
55
|
-
* Creates logger that writes to both console (consola) and LogsStore.
|
|
56
|
-
* Dual output: developer console + UI logs viewer.
|
|
57
|
-
*/
|
|
58
|
-
|
|
59
|
-
interface Logger {
|
|
60
|
-
debug: (message: string, data?: unknown) => void;
|
|
61
|
-
info: (message: string, data?: unknown) => void;
|
|
62
|
-
success: (message: string, data?: unknown) => void;
|
|
63
|
-
warning: (message: string, data?: unknown) => void;
|
|
64
|
-
error: (message: string, error?: Error | unknown) => void;
|
|
65
|
-
}
|
|
66
|
-
interface LoggerConfig {
|
|
67
|
-
source: LogEntry['source'];
|
|
68
|
-
isDevelopment?: boolean;
|
|
69
|
-
tag?: string;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Create a logger instance
|
|
73
|
-
*
|
|
74
|
-
* @param configOrPrefix - Either a full LoggerConfig object or a simple string prefix
|
|
75
|
-
* @returns Logger instance
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* // Simple usage with prefix
|
|
79
|
-
* const logger = createLogger('MyComponent');
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
|
-
* // Advanced usage with full config
|
|
83
|
-
* const logger = createLogger({
|
|
84
|
-
* source: 'client',
|
|
85
|
-
* tag: 'MyComponent',
|
|
86
|
-
* isDevelopment: true
|
|
87
|
-
* });
|
|
88
|
-
*/
|
|
89
|
-
declare function createLogger(configOrPrefix: LoggerConfig | string): Logger;
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Logs Store
|
|
93
|
-
*
|
|
94
|
-
* In-memory store for accumulated logs with circular buffer.
|
|
95
|
-
* Thread-safe, max capacity, auto-cleanup.
|
|
96
|
-
*/
|
|
97
|
-
|
|
98
|
-
declare class LogsStore {
|
|
99
|
-
private logs;
|
|
100
|
-
private listeners;
|
|
101
|
-
private maxLogs;
|
|
102
|
-
constructor(maxLogs?: number);
|
|
103
|
-
/**
|
|
104
|
-
* Add log entry
|
|
105
|
-
*/
|
|
106
|
-
add(entry: Omit<LogEntry, 'id' | 'timestamp'>): void;
|
|
107
|
-
/**
|
|
108
|
-
* Get all logs
|
|
109
|
-
*/
|
|
110
|
-
getAll(): LogEntry[];
|
|
111
|
-
/**
|
|
112
|
-
* Get logs by level
|
|
113
|
-
*/
|
|
114
|
-
getByLevel(level: LogLevel): LogEntry[];
|
|
115
|
-
/**
|
|
116
|
-
* Get logs by source
|
|
117
|
-
*/
|
|
118
|
-
getBySource(source: LogEntry['source']): LogEntry[];
|
|
119
|
-
/**
|
|
120
|
-
* Clear all logs
|
|
121
|
-
*/
|
|
122
|
-
clear(): void;
|
|
123
|
-
/**
|
|
124
|
-
* Subscribe to log changes
|
|
125
|
-
*/
|
|
126
|
-
subscribe(listener: (logs: LogEntry[]) => void): () => void;
|
|
127
|
-
/**
|
|
128
|
-
* Notify all listeners
|
|
129
|
-
*/
|
|
130
|
-
private notify;
|
|
131
|
-
/**
|
|
132
|
-
* Get logs count
|
|
133
|
-
*/
|
|
134
|
-
get count(): number;
|
|
135
|
-
}
|
|
136
|
-
declare function getGlobalLogsStore(): LogsStore;
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Centrifugo Client Types
|
|
140
|
-
*/
|
|
141
|
-
|
|
142
|
-
interface CentrifugoClientOptions {
|
|
143
|
-
url: string;
|
|
144
|
-
token: string;
|
|
145
|
-
userId: string;
|
|
146
|
-
timeout?: number;
|
|
147
|
-
logger?: Logger;
|
|
148
|
-
/**
|
|
149
|
-
* Callback to get fresh token when current token expires.
|
|
150
|
-
* Centrifuge-js calls this automatically on token expiration.
|
|
151
|
-
*/
|
|
152
|
-
getToken?: () => Promise<string>;
|
|
153
|
-
}
|
|
154
|
-
interface RPCOptions {
|
|
155
|
-
timeout?: number;
|
|
156
|
-
replyChannel?: string;
|
|
157
|
-
}
|
|
158
|
-
interface RetryOptions {
|
|
159
|
-
/** Max retry attempts (default: 3) */
|
|
160
|
-
maxRetries?: number;
|
|
161
|
-
/** Base delay in ms for exponential backoff (default: 100) */
|
|
162
|
-
baseDelayMs?: number;
|
|
163
|
-
/** Max delay cap in ms (default: 2000) */
|
|
164
|
-
maxDelayMs?: number;
|
|
165
|
-
}
|
|
166
|
-
interface VersionCheckResult {
|
|
167
|
-
compatible: boolean;
|
|
168
|
-
clientVersion: string;
|
|
169
|
-
serverVersion: string;
|
|
170
|
-
message: string;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* RPC Error with classification for retry logic.
|
|
175
|
-
*
|
|
176
|
-
* Mirrors Swift's RPCError implementation with:
|
|
177
|
-
* - isRetryable: Whether the error should trigger a retry
|
|
178
|
-
* - suggestedRetryDelay: Recommended delay before retry
|
|
179
|
-
* - userMessage: User-friendly error message
|
|
180
|
-
*/
|
|
181
|
-
type RPCErrorCode = 'not_connected' | 'timeout' | 'server_error' | 'encoding_error' | 'decoding_error' | 'websocket_error' | 'connection_failed' | 'cancelled' | 'network_error' | 'unknown';
|
|
182
|
-
declare class RPCError extends Error {
|
|
183
|
-
readonly code: RPCErrorCode;
|
|
184
|
-
readonly serverCode?: number;
|
|
185
|
-
readonly method?: string;
|
|
186
|
-
readonly isRetryable: boolean;
|
|
187
|
-
readonly suggestedRetryDelay: number;
|
|
188
|
-
readonly userMessage: string;
|
|
189
|
-
constructor(code: RPCErrorCode, message: string, options?: {
|
|
190
|
-
serverCode?: number;
|
|
191
|
-
method?: string;
|
|
192
|
-
cause?: unknown;
|
|
193
|
-
});
|
|
194
|
-
/**
|
|
195
|
-
* Determine if this error should trigger a retry.
|
|
196
|
-
* Transient errors (timeout, network) are retryable.
|
|
197
|
-
* Permanent errors (encoding, 4xx) are not.
|
|
198
|
-
*/
|
|
199
|
-
private determineRetryable;
|
|
200
|
-
/**
|
|
201
|
-
* Suggested delay before retry based on error type.
|
|
202
|
-
*/
|
|
203
|
-
private determineSuggestedDelay;
|
|
204
|
-
/**
|
|
205
|
-
* User-friendly message for UI display.
|
|
206
|
-
*/
|
|
207
|
-
private determineUserMessage;
|
|
208
|
-
/**
|
|
209
|
-
* Create RPCError from Centrifugo/unknown error.
|
|
210
|
-
*/
|
|
211
|
-
static fromError(error: unknown, method?: string): RPCError;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* RPC Module
|
|
216
|
-
*
|
|
217
|
-
* Handles Centrifugo RPC patterns (request-response and fire-and-forget).
|
|
218
|
-
*/
|
|
219
|
-
|
|
220
|
-
interface NamedRPCWithRetryOptions {
|
|
221
|
-
timeout?: number;
|
|
222
|
-
maxRetries?: number;
|
|
223
|
-
baseDelayMs?: number;
|
|
224
|
-
maxDelayMs?: number;
|
|
225
|
-
onRetry?: (attempt: number, error: RPCError, delayMs: number) => void;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Centrifugo RPC Client
|
|
230
|
-
*
|
|
231
|
-
* Facade for WebSocket connection and RPC call handling.
|
|
232
|
-
* Provides both RPC (request/response) and Subscription (pub/sub) patterns.
|
|
233
|
-
*
|
|
234
|
-
* Architecture:
|
|
235
|
-
* - connection.ts - Connection lifecycle management
|
|
236
|
-
* - subscriptions.ts - Channel subscription management
|
|
237
|
-
* - rpc.ts - RPC methods (namedRPC, namedRPCNoWait)
|
|
238
|
-
* - version.ts - API version checking
|
|
239
|
-
* - types.ts - Type definitions
|
|
240
|
-
*/
|
|
241
|
-
|
|
242
|
-
declare class CentrifugoRPCClient {
|
|
243
|
-
private state;
|
|
244
|
-
constructor(options: CentrifugoClientOptions);
|
|
245
|
-
/** @deprecated Use options object instead */
|
|
246
|
-
constructor(url: string, token: string, userId: string, timeout?: number, logger?: Logger);
|
|
247
|
-
connect(): Promise<void>;
|
|
248
|
-
disconnect(): Promise<void>;
|
|
249
|
-
getCentrifuge(): Centrifuge;
|
|
250
|
-
subscribe(channel: string, callback: (data: any) => void): () => void;
|
|
251
|
-
unsubscribe(channel: string): void;
|
|
252
|
-
unsubscribeAll(): void;
|
|
253
|
-
getActiveSubscriptions(): string[];
|
|
254
|
-
getServerSideSubscriptions(): string[];
|
|
255
|
-
getAllSubscriptions(): string[];
|
|
256
|
-
call<T = any>(method: string, params: any): Promise<T>;
|
|
257
|
-
rpc<TRequest = any, TResponse = any>(method: string, params: TRequest, options?: RPCOptions): Promise<TResponse>;
|
|
258
|
-
namedRPC<TRequest = any, TResponse = any>(method: string, data: TRequest, options?: {
|
|
259
|
-
timeout?: number;
|
|
260
|
-
}): Promise<TResponse>;
|
|
261
|
-
namedRPCNoWait<TRequest = any>(method: string, data: TRequest, options?: RetryOptions): void;
|
|
262
|
-
namedRPCWithRetry<TRequest = any, TResponse = any>(method: string, data: TRequest, options?: NamedRPCWithRetryOptions): Promise<TResponse>;
|
|
263
|
-
checkApiVersion(clientVersion: string): Promise<VersionCheckResult>;
|
|
264
|
-
private handleResponse;
|
|
265
|
-
private get subscriptionManager();
|
|
266
|
-
private get rpcManager();
|
|
267
|
-
/** @internal */
|
|
268
|
-
get logger(): Logger;
|
|
269
|
-
/** @internal */
|
|
270
|
-
get userId(): string;
|
|
271
|
-
/** @internal */
|
|
272
|
-
get replyChannel(): string;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Shared consola logger for Centrifugo package
|
|
277
|
-
*/
|
|
278
|
-
declare const consolaLogger: consola.ConsolaInstance;
|
|
279
|
-
/**
|
|
280
|
-
* Get a consola logger with custom tag wrapped to match Logger interface
|
|
281
|
-
*/
|
|
282
|
-
declare function getConsolaLogger(tag: string): Logger;
|
|
283
|
-
|
|
284
|
-
interface CentrifugoContextValue {
|
|
285
|
-
client: CentrifugoRPCClient | null;
|
|
286
|
-
isConnected: boolean;
|
|
287
|
-
isConnecting: boolean;
|
|
288
|
-
error: Error | null;
|
|
289
|
-
connectionState: ConnectionState;
|
|
290
|
-
uptime: number;
|
|
291
|
-
subscriptions: string[];
|
|
292
|
-
activeSubscriptions: ActiveSubscription[];
|
|
293
|
-
connect: () => Promise<void>;
|
|
294
|
-
disconnect: () => void;
|
|
295
|
-
reconnect: () => Promise<void>;
|
|
296
|
-
unsubscribe: (channel: string) => void;
|
|
297
|
-
enabled: boolean;
|
|
298
|
-
}
|
|
299
|
-
interface CentrifugoProviderProps {
|
|
300
|
-
children: ReactNode;
|
|
301
|
-
enabled?: boolean;
|
|
302
|
-
url?: string;
|
|
303
|
-
autoConnect?: boolean;
|
|
304
|
-
/**
|
|
305
|
-
* Callback to refresh the Centrifugo token when it expires.
|
|
306
|
-
* If provided, centrifuge-js will automatically call this when token expires.
|
|
307
|
-
* Should return a fresh JWT token string.
|
|
308
|
-
*
|
|
309
|
-
* @example
|
|
310
|
-
* onTokenRefresh={async () => {
|
|
311
|
-
* const response = await getCentrifugoAuthTokenRetrieve();
|
|
312
|
-
* return response.token;
|
|
313
|
-
* }}
|
|
314
|
-
*/
|
|
315
|
-
onTokenRefresh?: () => Promise<string>;
|
|
316
|
-
}
|
|
317
|
-
declare function CentrifugoProvider(props: CentrifugoProviderProps): react_jsx_runtime.JSX.Element;
|
|
318
|
-
declare function useCentrifugo(): CentrifugoContextValue;
|
|
319
|
-
|
|
320
|
-
interface LogsContextValue {
|
|
321
|
-
logs: LogEntry[];
|
|
322
|
-
filteredLogs: LogEntry[];
|
|
323
|
-
filter: LogsFilter;
|
|
324
|
-
setFilter: (filter: Partial<LogsFilter>) => void;
|
|
325
|
-
clearLogs: () => void;
|
|
326
|
-
count: number;
|
|
327
|
-
}
|
|
328
|
-
interface LogsFilter {
|
|
329
|
-
level?: LogLevel;
|
|
330
|
-
source?: LogEntry['source'];
|
|
331
|
-
search?: string;
|
|
332
|
-
}
|
|
333
|
-
interface LogsProviderProps {
|
|
334
|
-
children: ReactNode;
|
|
335
|
-
}
|
|
336
|
-
declare function LogsProvider({ children }: LogsProviderProps): react_jsx_runtime.JSX.Element;
|
|
337
|
-
declare function useLogs(): LogsContextValue;
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* useSubscription Hook
|
|
341
|
-
*
|
|
342
|
-
* Subscribe to Centrifugo channel with auto-cleanup.
|
|
343
|
-
*
|
|
344
|
-
* Best practices:
|
|
345
|
-
* - Callbacks are stored in refs to avoid re-subscriptions
|
|
346
|
-
* - Proper error handling in callbacks (as recommended by centrifuge-js)
|
|
347
|
-
* - Cleanup on unmount
|
|
348
|
-
* - Stable unsubscribe function
|
|
349
|
-
*/
|
|
350
|
-
interface UseSubscriptionOptions<T = any> {
|
|
351
|
-
channel: string;
|
|
352
|
-
enabled?: boolean;
|
|
353
|
-
onPublication?: (data: T) => void;
|
|
354
|
-
onError?: (error: Error) => void;
|
|
355
|
-
}
|
|
356
|
-
interface UseSubscriptionResult<T = any> {
|
|
357
|
-
data: T | null;
|
|
358
|
-
error: Error | null;
|
|
359
|
-
isSubscribed: boolean;
|
|
360
|
-
unsubscribe: () => void;
|
|
361
|
-
}
|
|
362
|
-
declare function useSubscription<T = any>(options: UseSubscriptionOptions<T>): UseSubscriptionResult<T>;
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* useRPC Hook
|
|
366
|
-
*
|
|
367
|
-
* React hook for making RPC calls via Centrifugo using correlation ID pattern.
|
|
368
|
-
* Provides type-safe request-response communication over WebSocket.
|
|
369
|
-
*
|
|
370
|
-
* Pattern:
|
|
371
|
-
* 1. Client sends request with correlation_id to rpc#{method}
|
|
372
|
-
* 2. Backend processes and sends response to user#{userId} with same correlation_id
|
|
373
|
-
* 3. Client matches response by correlation_id and resolves Promise
|
|
374
|
-
*
|
|
375
|
-
* @example
|
|
376
|
-
* const { call, isLoading, error } = useRPC();
|
|
377
|
-
*
|
|
378
|
-
* const handleGetStats = async () => {
|
|
379
|
-
* const result = await call('tasks.get_stats', { bot_id: '123' });
|
|
380
|
-
* console.log('Stats:', result);
|
|
381
|
-
* };
|
|
382
|
-
*/
|
|
383
|
-
interface UseRPCOptions {
|
|
384
|
-
timeout?: number;
|
|
385
|
-
replyChannel?: string;
|
|
386
|
-
onError?: (error: Error) => void;
|
|
387
|
-
}
|
|
388
|
-
interface UseRPCResult {
|
|
389
|
-
call: <TRequest = any, TResponse = any>(method: string, params: TRequest, options?: UseRPCOptions) => Promise<TResponse>;
|
|
390
|
-
isLoading: boolean;
|
|
391
|
-
error: Error | null;
|
|
392
|
-
reset: () => void;
|
|
393
|
-
}
|
|
394
|
-
declare function useRPC(defaultOptions?: UseRPCOptions): UseRPCResult;
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* useNamedRPC Hook
|
|
398
|
-
*
|
|
399
|
-
* React hook for making native Centrifugo RPC calls via RPC proxy.
|
|
400
|
-
* Uses Centrifugo's built-in RPC mechanism which proxies to Django.
|
|
401
|
-
*
|
|
402
|
-
* Flow:
|
|
403
|
-
* 1. Client calls namedRPC('terminal.input', data)
|
|
404
|
-
* 2. Centrifuge.js sends RPC over WebSocket
|
|
405
|
-
* 3. Centrifugo proxies to Django: POST /centrifugo/rpc/
|
|
406
|
-
* 4. Django routes to @websocket_rpc handler
|
|
407
|
-
* 5. Response returned to client
|
|
408
|
-
*
|
|
409
|
-
* @example
|
|
410
|
-
* const { call, isLoading, error } = useNamedRPC();
|
|
411
|
-
*
|
|
412
|
-
* const handleSendInput = async () => {
|
|
413
|
-
* const result = await call('terminal.input', {
|
|
414
|
-
* session_id: 'abc-123',
|
|
415
|
-
* data: btoa('ls -la')
|
|
416
|
-
* });
|
|
417
|
-
* console.log('Result:', result);
|
|
418
|
-
* };
|
|
419
|
-
*/
|
|
420
|
-
interface UseNamedRPCOptions {
|
|
421
|
-
onError?: (error: Error) => void;
|
|
422
|
-
}
|
|
423
|
-
interface UseNamedRPCResult {
|
|
424
|
-
call: <TRequest = any, TResponse = any>(method: string, data: TRequest) => Promise<TResponse>;
|
|
425
|
-
isLoading: boolean;
|
|
426
|
-
error: Error | null;
|
|
427
|
-
reset: () => void;
|
|
428
|
-
}
|
|
429
|
-
declare function useNamedRPC(defaultOptions?: UseNamedRPCOptions): UseNamedRPCResult;
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* usePageVisibility Hook
|
|
433
|
-
*
|
|
434
|
-
* Tracks browser tab visibility state using the Page Visibility API.
|
|
435
|
-
* Returns true when the page is visible, false when hidden.
|
|
436
|
-
*
|
|
437
|
-
* Use cases:
|
|
438
|
-
* - Pause/resume WebSocket connections
|
|
439
|
-
* - Pause expensive operations when tab is inactive
|
|
440
|
-
* - Trigger data sync when tab becomes visible
|
|
441
|
-
*/
|
|
442
|
-
interface PageVisibilityState {
|
|
443
|
-
/** Whether the page is currently visible */
|
|
444
|
-
isVisible: boolean;
|
|
445
|
-
/** Whether the page was ever hidden during this session */
|
|
446
|
-
wasHidden: boolean;
|
|
447
|
-
/** Timestamp when page became visible (for uptime tracking) */
|
|
448
|
-
visibleSince: number | null;
|
|
449
|
-
/** How long the page was hidden (ms), reset when visible */
|
|
450
|
-
hiddenDuration: number;
|
|
451
|
-
}
|
|
452
|
-
interface UsePageVisibilityOptions {
|
|
453
|
-
/** Callback when page becomes visible */
|
|
454
|
-
onVisible?: () => void;
|
|
455
|
-
/** Callback when page becomes hidden */
|
|
456
|
-
onHidden?: () => void;
|
|
457
|
-
/** Callback with visibility state change */
|
|
458
|
-
onChange?: (isVisible: boolean) => void;
|
|
459
|
-
}
|
|
460
|
-
interface UsePageVisibilityResult extends PageVisibilityState {
|
|
461
|
-
/** Force check visibility state */
|
|
462
|
-
checkVisibility: () => boolean;
|
|
463
|
-
}
|
|
464
|
-
declare function usePageVisibility(options?: UsePageVisibilityOptions): UsePageVisibilityResult;
|
|
465
|
-
|
|
466
|
-
/**
|
|
467
|
-
* useCodegenTip Hook
|
|
468
|
-
*
|
|
469
|
-
* Shows development tip about client generation once per session.
|
|
470
|
-
*/
|
|
471
|
-
/**
|
|
472
|
-
* Show dev tip about generating type-safe clients from @websocket_rpc handlers
|
|
473
|
-
*
|
|
474
|
-
* @example
|
|
475
|
-
* function MyComponent() {
|
|
476
|
-
* useCodegenTip();
|
|
477
|
-
* // ... rest of component
|
|
478
|
-
* }
|
|
479
|
-
*/
|
|
480
|
-
declare function useCodegenTip(): void;
|
|
481
|
-
|
|
482
|
-
/**
|
|
483
|
-
* Centrifugo Package Configuration
|
|
484
|
-
*/
|
|
485
|
-
declare const isDevelopment: boolean;
|
|
486
|
-
declare const isProduction: boolean;
|
|
487
|
-
declare const isStaticBuild: boolean;
|
|
488
|
-
declare const centrifugoConfig: {
|
|
489
|
-
readonly showDebugPanel: boolean;
|
|
490
|
-
readonly reconnect: {
|
|
491
|
-
readonly initialDelay: 1000 | 2000;
|
|
492
|
-
readonly maxDelay: 30000 | 60000;
|
|
493
|
-
readonly multiplier: 1.5;
|
|
494
|
-
readonly maxAttempts: 3 | 10;
|
|
495
|
-
readonly jitter: 0.1;
|
|
496
|
-
};
|
|
497
|
-
};
|
|
498
|
-
type CentrifugoConfig = typeof centrifugoConfig;
|
|
499
|
-
|
|
500
|
-
/**
|
|
501
|
-
* RPC Retry Handler with exponential backoff.
|
|
502
|
-
*
|
|
503
|
-
* Mirrors Swift's RPCRetryHandler implementation with:
|
|
504
|
-
* - Configurable max retries and delays
|
|
505
|
-
* - Exponential backoff with jitter
|
|
506
|
-
* - Retry decision based on RPCError.isRetryable
|
|
507
|
-
*/
|
|
508
|
-
|
|
509
|
-
interface RetryConfig {
|
|
510
|
-
maxRetries: number;
|
|
511
|
-
baseDelayMs: number;
|
|
512
|
-
maxDelayMs: number;
|
|
513
|
-
jitterFactor: number;
|
|
514
|
-
}
|
|
515
|
-
declare const DEFAULT_RETRY_CONFIG: RetryConfig;
|
|
516
|
-
interface RetryState {
|
|
517
|
-
attempt: number;
|
|
518
|
-
lastError: RPCError | null;
|
|
519
|
-
totalDelayMs: number;
|
|
520
|
-
}
|
|
521
|
-
/**
|
|
522
|
-
* Calculate delay with exponential backoff and jitter.
|
|
523
|
-
*/
|
|
524
|
-
declare function calculateDelay(attempt: number, config: RetryConfig, error?: RPCError): number;
|
|
525
|
-
/**
|
|
526
|
-
* Sleep for specified milliseconds.
|
|
527
|
-
*/
|
|
528
|
-
declare function sleep(ms: number): Promise<void>;
|
|
529
|
-
/**
|
|
530
|
-
* Execute operation with retry logic.
|
|
531
|
-
*
|
|
532
|
-
* @param operation - Async function to execute
|
|
533
|
-
* @param config - Retry configuration
|
|
534
|
-
* @param onRetry - Optional callback before each retry
|
|
535
|
-
* @returns Promise with operation result
|
|
536
|
-
* @throws RPCError after all retries exhausted
|
|
537
|
-
*/
|
|
538
|
-
declare function withRetry<T>(operation: () => Promise<T>, config?: Partial<RetryConfig>, onRetry?: (state: RetryState, delayMs: number) => void): Promise<T>;
|
|
539
|
-
/**
|
|
540
|
-
* Create a retry wrapper for RPC calls.
|
|
541
|
-
*/
|
|
542
|
-
declare function createRetryHandler(config?: Partial<RetryConfig>): {
|
|
543
|
-
config: RetryConfig;
|
|
544
|
-
/**
|
|
545
|
-
* Execute with retry.
|
|
546
|
-
*/
|
|
547
|
-
execute: <T>(operation: () => Promise<T>, onRetry?: (state: RetryState, delayMs: number) => void) => Promise<T>;
|
|
548
|
-
/**
|
|
549
|
-
* Check if error should be retried.
|
|
550
|
-
*/
|
|
551
|
-
shouldRetry: (error: unknown, attempt: number) => boolean;
|
|
552
|
-
/**
|
|
553
|
-
* Get delay for next retry.
|
|
554
|
-
*/
|
|
555
|
-
getDelay: (attempt: number, error?: unknown) => number;
|
|
556
|
-
};
|
|
557
|
-
|
|
558
|
-
/**
|
|
559
|
-
* Centrifugo Package Events
|
|
560
|
-
*
|
|
561
|
-
* Unified event system for Centrifugo client.
|
|
562
|
-
* All events use single 'centrifugo' CustomEvent with type discriminator.
|
|
563
|
-
*/
|
|
564
|
-
/**
|
|
565
|
-
* Single event name for all Centrifugo events.
|
|
566
|
-
* Use `type` field in payload to distinguish event types.
|
|
567
|
-
*/
|
|
568
|
-
declare const CENTRIFUGO_EVENT: "centrifugo";
|
|
569
|
-
/**
|
|
570
|
-
* Internal events for UI components (via events.publish)
|
|
571
|
-
*/
|
|
572
|
-
declare const CENTRIFUGO_MONITOR_EVENTS: {
|
|
573
|
-
readonly OPEN_MONITOR_DIALOG: "CENTRIFUGO_OPEN_MONITOR_DIALOG";
|
|
574
|
-
readonly CLOSE_MONITOR_DIALOG: "CENTRIFUGO_CLOSE_MONITOR_DIALOG";
|
|
575
|
-
};
|
|
576
|
-
declare const CENTRIFUGO_ERROR_EVENT: "centrifugo";
|
|
577
|
-
declare const CENTRIFUGO_VERSION_MISMATCH_EVENT: "centrifugo";
|
|
578
|
-
type CentrifugoEventType = 'error' | 'version_mismatch' | 'connected' | 'disconnected' | 'reconnecting';
|
|
579
|
-
interface CentrifugoErrorData {
|
|
580
|
-
/** RPC method that failed */
|
|
581
|
-
method: string;
|
|
582
|
-
/** Error message */
|
|
583
|
-
error: string;
|
|
584
|
-
/** Error code from Centrifugo */
|
|
585
|
-
code?: number;
|
|
586
|
-
/** Additional data sent with the request */
|
|
587
|
-
data?: any;
|
|
588
|
-
}
|
|
589
|
-
interface CentrifugoVersionMismatchData {
|
|
590
|
-
/** Client API version hash */
|
|
591
|
-
clientVersion: string;
|
|
592
|
-
/** Server API version hash */
|
|
593
|
-
serverVersion: string;
|
|
594
|
-
/** Human-readable message */
|
|
595
|
-
message: string;
|
|
596
|
-
}
|
|
597
|
-
interface CentrifugoConnectionData {
|
|
598
|
-
/** User ID */
|
|
599
|
-
userId?: string;
|
|
600
|
-
/** Reconnect attempt number (for reconnecting) */
|
|
601
|
-
attempt?: number;
|
|
602
|
-
/** Reason for disconnect */
|
|
603
|
-
reason?: string;
|
|
604
|
-
}
|
|
605
|
-
/**
|
|
606
|
-
* Unified Centrifugo event payload
|
|
607
|
-
*/
|
|
608
|
-
type CentrifugoEventPayload = {
|
|
609
|
-
type: 'error';
|
|
610
|
-
data: CentrifugoErrorData;
|
|
611
|
-
} | {
|
|
612
|
-
type: 'version_mismatch';
|
|
613
|
-
data: CentrifugoVersionMismatchData;
|
|
614
|
-
} | {
|
|
615
|
-
type: 'connected';
|
|
616
|
-
data: CentrifugoConnectionData;
|
|
617
|
-
} | {
|
|
618
|
-
type: 'disconnected';
|
|
619
|
-
data: CentrifugoConnectionData;
|
|
620
|
-
} | {
|
|
621
|
-
type: 'reconnecting';
|
|
622
|
-
data: CentrifugoConnectionData;
|
|
623
|
-
};
|
|
624
|
-
/**
|
|
625
|
-
* Full event detail (includes timestamp)
|
|
626
|
-
*/
|
|
627
|
-
type CentrifugoEventDetail = CentrifugoEventPayload & {
|
|
628
|
-
timestamp: Date;
|
|
629
|
-
};
|
|
630
|
-
interface OpenMonitorDialogPayload {
|
|
631
|
-
variant?: 'compact' | 'full' | 'minimal';
|
|
632
|
-
defaultTab?: 'connection' | 'messages' | 'subscriptions';
|
|
633
|
-
}
|
|
634
|
-
/** @deprecated Use CentrifugoErrorData */
|
|
635
|
-
type CentrifugoErrorPayload = CentrifugoErrorData;
|
|
636
|
-
/** @deprecated Use CentrifugoVersionMismatchData */
|
|
637
|
-
type VersionMismatchPayload = CentrifugoVersionMismatchData;
|
|
638
|
-
/**
|
|
639
|
-
* Dispatch unified Centrifugo event
|
|
640
|
-
*
|
|
641
|
-
* @example
|
|
642
|
-
* ```ts
|
|
643
|
-
* // Dispatch error
|
|
644
|
-
* dispatchCentrifugoEvent({
|
|
645
|
-
* type: 'error',
|
|
646
|
-
* data: { method: 'terminal.input', error: 'timeout' }
|
|
647
|
-
* });
|
|
648
|
-
*
|
|
649
|
-
* // Listen to all Centrifugo events
|
|
650
|
-
* window.addEventListener('centrifugo', (e) => {
|
|
651
|
-
* const { type, data, timestamp } = e.detail;
|
|
652
|
-
* switch (type) {
|
|
653
|
-
* case 'error':
|
|
654
|
-
* console.error('RPC error:', data.method, data.error);
|
|
655
|
-
* break;
|
|
656
|
-
* case 'version_mismatch':
|
|
657
|
-
* toast.warning('Please refresh the page');
|
|
658
|
-
* break;
|
|
659
|
-
* }
|
|
660
|
-
* });
|
|
661
|
-
* ```
|
|
662
|
-
*/
|
|
663
|
-
declare const dispatchCentrifugoEvent: (payload: CentrifugoEventPayload) => void;
|
|
664
|
-
/**
|
|
665
|
-
* Dispatch error event
|
|
666
|
-
*/
|
|
667
|
-
declare const dispatchCentrifugoError: (data: CentrifugoErrorData) => void;
|
|
668
|
-
/**
|
|
669
|
-
* Dispatch version mismatch event
|
|
670
|
-
*/
|
|
671
|
-
declare const dispatchVersionMismatch: (data: CentrifugoVersionMismatchData) => void;
|
|
672
|
-
/**
|
|
673
|
-
* Dispatch connected event
|
|
674
|
-
*/
|
|
675
|
-
declare const dispatchConnected: (data?: CentrifugoConnectionData) => void;
|
|
676
|
-
/**
|
|
677
|
-
* Dispatch disconnected event
|
|
678
|
-
*/
|
|
679
|
-
declare const dispatchDisconnected: (data?: CentrifugoConnectionData) => void;
|
|
680
|
-
/**
|
|
681
|
-
* Dispatch reconnecting event
|
|
682
|
-
*/
|
|
683
|
-
declare const dispatchReconnecting: (data?: CentrifugoConnectionData) => void;
|
|
684
|
-
declare const emitOpenMonitorDialog: (payload?: OpenMonitorDialogPayload) => void;
|
|
685
|
-
declare const emitCloseMonitorDialog: () => void;
|
|
686
|
-
|
|
687
|
-
/**
|
|
688
|
-
* Connection Status Component
|
|
689
|
-
*
|
|
690
|
-
* Universal component for displaying Centrifugo connection status
|
|
691
|
-
* Supports multiple variants: badge, inline, card, detailed
|
|
692
|
-
*/
|
|
693
|
-
interface ConnectionStatusProps {
|
|
694
|
-
variant?: 'badge' | 'inline' | 'detailed';
|
|
695
|
-
showUptime?: boolean;
|
|
696
|
-
showSubscriptions?: boolean;
|
|
697
|
-
className?: string;
|
|
698
|
-
}
|
|
699
|
-
declare function ConnectionStatus({ variant, showUptime, showSubscriptions, className, }: ConnectionStatusProps): react_jsx_runtime.JSX.Element;
|
|
700
|
-
|
|
701
|
-
/**
|
|
702
|
-
* Connection Status Card Component
|
|
703
|
-
*
|
|
704
|
-
* Card wrapper for ConnectionStatus - ready for dashboard widgets
|
|
705
|
-
* Clickable - opens CentrifugoMonitorDialog on click via events
|
|
706
|
-
*/
|
|
707
|
-
interface ConnectionStatusCardProps {
|
|
708
|
-
showUptime?: boolean;
|
|
709
|
-
showSubscriptions?: boolean;
|
|
710
|
-
className?: string;
|
|
711
|
-
}
|
|
712
|
-
declare function ConnectionStatusCard({ showUptime, showSubscriptions, className, }: ConnectionStatusCardProps): react_jsx_runtime.JSX.Element;
|
|
713
|
-
|
|
714
|
-
/**
|
|
715
|
-
* Messages Feed Types
|
|
716
|
-
*/
|
|
717
|
-
interface CentrifugoMessage {
|
|
718
|
-
id: string;
|
|
719
|
-
timestamp: number;
|
|
720
|
-
type: 'connection' | 'subscription' | 'publication' | 'error' | 'system' | 'unsubscription';
|
|
721
|
-
channel?: string;
|
|
722
|
-
data?: any;
|
|
723
|
-
level: 'info' | 'success' | 'warning' | 'error';
|
|
724
|
-
message?: string;
|
|
725
|
-
}
|
|
726
|
-
interface MessageFilters$1 {
|
|
727
|
-
channels?: string[];
|
|
728
|
-
types?: CentrifugoMessage['type'][];
|
|
729
|
-
levels?: CentrifugoMessage['level'][];
|
|
730
|
-
searchQuery?: string;
|
|
731
|
-
}
|
|
732
|
-
interface MessagesFeedProps {
|
|
733
|
-
maxMessages?: number;
|
|
734
|
-
showFilters?: boolean;
|
|
735
|
-
showControls?: boolean;
|
|
736
|
-
channels?: string[];
|
|
737
|
-
autoScroll?: boolean;
|
|
738
|
-
onMessageClick?: (message: CentrifugoMessage) => void;
|
|
739
|
-
className?: string;
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
declare function MessagesFeed({ maxMessages, showFilters, showControls, channels, autoScroll: initialAutoScroll, onMessageClick, className, }: MessagesFeedProps): react_jsx_runtime.JSX.Element;
|
|
743
|
-
|
|
744
|
-
interface MessageFiltersProps {
|
|
745
|
-
filters: MessageFilters$1;
|
|
746
|
-
onFiltersChange: (filters: MessageFilters$1) => void;
|
|
747
|
-
autoScroll?: boolean;
|
|
748
|
-
onAutoScrollChange?: (enabled: boolean) => void;
|
|
749
|
-
}
|
|
750
|
-
declare function MessageFilters({ filters, onFiltersChange, autoScroll, onAutoScrollChange, }: MessageFiltersProps): react_jsx_runtime.JSX.Element;
|
|
751
|
-
|
|
752
|
-
/**
|
|
753
|
-
* Subscriptions List Component
|
|
754
|
-
*
|
|
755
|
-
* Displays active Centrifugo subscriptions with status and controls
|
|
756
|
-
*/
|
|
757
|
-
interface SubscriptionsListProps {
|
|
758
|
-
showControls?: boolean;
|
|
759
|
-
onSubscriptionClick?: (channel: string) => void;
|
|
760
|
-
className?: string;
|
|
761
|
-
}
|
|
762
|
-
declare function SubscriptionsList({ showControls, onSubscriptionClick, className, }: SubscriptionsListProps): react_jsx_runtime.JSX.Element;
|
|
763
|
-
|
|
764
|
-
interface CentrifugoMonitorProps {
|
|
765
|
-
variant?: 'compact' | 'full' | 'minimal';
|
|
766
|
-
showConnectionStatus?: boolean;
|
|
767
|
-
showMessagesFeed?: boolean;
|
|
768
|
-
showSubscriptions?: boolean;
|
|
769
|
-
showFilters?: boolean;
|
|
770
|
-
showControls?: boolean;
|
|
771
|
-
maxMessages?: number;
|
|
772
|
-
channels?: string[];
|
|
773
|
-
autoScroll?: boolean;
|
|
774
|
-
onMessageClick?: (message: CentrifugoMessage) => void;
|
|
775
|
-
onSubscriptionClick?: (channel: string) => void;
|
|
776
|
-
className?: string;
|
|
777
|
-
}
|
|
778
|
-
declare function CentrifugoMonitor({ variant, showConnectionStatus, showMessagesFeed, showSubscriptions, showFilters, showControls, maxMessages, channels, autoScroll, onMessageClick, onSubscriptionClick, className, }: CentrifugoMonitorProps): react_jsx_runtime.JSX.Element;
|
|
779
|
-
|
|
780
|
-
/**
|
|
781
|
-
* Centrifugo Monitor Dialog Component
|
|
782
|
-
*
|
|
783
|
-
* Sheet/Dialog wrapper for CentrifugoMonitor
|
|
784
|
-
* Uses event-driven approach - listens to OPEN_MONITOR_DIALOG event
|
|
785
|
-
*/
|
|
786
|
-
declare function CentrifugoMonitorDialog(): react_jsx_runtime.JSX.Element;
|
|
787
|
-
|
|
788
|
-
interface CentrifugoMonitorFABProps {
|
|
789
|
-
position?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
|
|
790
|
-
size?: 'sm' | 'md' | 'lg';
|
|
791
|
-
variant?: OpenMonitorDialogPayload['variant'];
|
|
792
|
-
}
|
|
793
|
-
declare function CentrifugoMonitorFAB({ position, size, variant, }: CentrifugoMonitorFABProps): react_jsx_runtime.JSX.Element;
|
|
794
|
-
|
|
795
|
-
/**
|
|
796
|
-
* Centrifugo Monitor Widget Component
|
|
797
|
-
*
|
|
798
|
-
* Card-based widget for dashboards
|
|
799
|
-
* Opens monitor dialog via events
|
|
800
|
-
*/
|
|
801
|
-
interface CentrifugoMonitorWidgetProps {
|
|
802
|
-
title?: string;
|
|
803
|
-
showExpandButton?: boolean;
|
|
804
|
-
className?: string;
|
|
805
|
-
}
|
|
806
|
-
declare function CentrifugoMonitorWidget({ title, showExpandButton, className, }: CentrifugoMonitorWidgetProps): react_jsx_runtime.JSX.Element;
|
|
807
|
-
|
|
808
|
-
/**
|
|
809
|
-
* Debug Panel
|
|
810
|
-
*
|
|
811
|
-
* Main debug UI with FAB button + Sheet modal + Tabs.
|
|
812
|
-
* Visibility controlled by CentrifugoProvider (dev mode OR admin users).
|
|
813
|
-
*/
|
|
814
|
-
declare function DebugPanel(): react_jsx_runtime.JSX.Element;
|
|
815
|
-
|
|
816
|
-
/**
|
|
817
|
-
* Connection Tab
|
|
818
|
-
*
|
|
819
|
-
* Shows WebSocket connection status, uptime, and controls.
|
|
820
|
-
*/
|
|
821
|
-
declare function ConnectionTab(): react_jsx_runtime.JSX.Element;
|
|
822
|
-
|
|
823
|
-
/**
|
|
824
|
-
* Logs Tab
|
|
825
|
-
*
|
|
826
|
-
* Bash-like logs viewer with filters, search, and auto-scroll.
|
|
827
|
-
* Uses PrettyCode for syntax highlighting.
|
|
828
|
-
*/
|
|
829
|
-
declare function LogsTab(): react_jsx_runtime.JSX.Element;
|
|
830
|
-
|
|
831
|
-
/**
|
|
832
|
-
* Subscriptions Tab
|
|
833
|
-
*
|
|
834
|
-
* Shows active channel subscriptions with controls.
|
|
835
|
-
*/
|
|
836
|
-
declare function SubscriptionsTab(): react_jsx_runtime.JSX.Element;
|
|
837
|
-
|
|
838
|
-
export { type ActiveSubscription, CENTRIFUGO_ERROR_EVENT, CENTRIFUGO_EVENT, CENTRIFUGO_MONITOR_EVENTS, CENTRIFUGO_VERSION_MISMATCH_EVENT, type CentrifugoClientConfig, type CentrifugoClientState, type CentrifugoConfig, type CentrifugoConnectionData, type CentrifugoContextValue, type CentrifugoErrorData, type CentrifugoErrorPayload, type CentrifugoEventDetail, type CentrifugoEventPayload, type CentrifugoEventType, type CentrifugoMessage, CentrifugoMonitor, CentrifugoMonitorDialog, CentrifugoMonitorFAB, type CentrifugoMonitorFABProps, type CentrifugoMonitorProps, CentrifugoMonitorWidget, type CentrifugoMonitorWidgetProps, CentrifugoProvider, type CentrifugoProviderProps, CentrifugoRPCClient, type CentrifugoToken, type CentrifugoVersionMismatchData, type ConnectionState, ConnectionStatus, ConnectionStatusCard, type ConnectionStatusCardProps, type ConnectionStatusProps, ConnectionTab, DEFAULT_RETRY_CONFIG, DebugPanel, type LogEntry, type LogLevel, LogsProvider, LogsTab, MessageFilters, type MessageFiltersProps, type MessageFilters$1 as MessageFiltersType, MessagesFeed, type MessagesFeedProps, type OpenMonitorDialogPayload, type PageVisibilityState, RPCError, type RPCErrorCode, type RetryConfig, type RetryState, SubscriptionsList, type SubscriptionsListProps, SubscriptionsTab, type UseNamedRPCOptions, type UseNamedRPCResult, type UsePageVisibilityOptions, type UsePageVisibilityResult, type UseRPCOptions, type UseRPCResult, type UseSubscriptionOptions, type UseSubscriptionResult, type User, type VersionMismatchPayload, calculateDelay, centrifugoConfig, consolaLogger, createLogger, createRetryHandler, dispatchCentrifugoError, dispatchCentrifugoEvent, dispatchConnected, dispatchDisconnected, dispatchReconnecting, dispatchVersionMismatch, emitCloseMonitorDialog, emitOpenMonitorDialog, getConsolaLogger, getGlobalLogsStore, isDevelopment, isProduction, isStaticBuild, sleep, useCentrifugo, useCodegenTip, useLogs, useNamedRPC, usePageVisibility, useRPC, useSubscription, withRetry };
|