1
import { useEnv } from '@directus/env';
2
import { ServiceUnavailableError } from '@directus/errors';
3
import type { ActionHandler } from '@directus/types';
4
import { toBoolean } from '@directus/utils';
5
import emitter from '../emitter.js';
6
import { getWebSocketController } from '../websocket/controllers/index.js';
7
import type { WebSocketController } from '../websocket/controllers/rest.js';
8
import type { WebSocketMessage } from '../websocket/messages.js';
9
import type { WebSocketClient } from '../websocket/types.js';
13
export class WebSocketService {
14
private controller: WebSocketController;
17
if (!toBoolean(env['WEBSOCKETS_ENABLED']) || !toBoolean(env['WEBSOCKETS_REST_ENABLED'])) {
18
throw new ServiceUnavailableError({ service: 'ws', reason: 'WebSocket server is disabled' });
21
const controller = getWebSocketController();
24
throw new ServiceUnavailableError({ service: 'ws', reason: 'WebSocket server is not initialized' });
27
this.controller = controller;
30
on(event: 'connect' | 'message' | 'error' | 'close', callback: ActionHandler) {
31
emitter.onAction('websocket.' + event, callback);
34
off(event: 'connect' | 'message' | 'error' | 'close', callback: ActionHandler) {
35
emitter.offAction('websocket.' + event, callback);
38
broadcast(message: string | WebSocketMessage, filter?: { user?: string; role?: string }) {
39
this.controller.clients.forEach((client: WebSocketClient) => {
40
if (filter && filter.user && filter.user !== client.accountability?.user) return;
41
if (filter && filter.role && filter.role !== client.accountability?.role) return;
42
client.send(typeof message === 'string' ? message : JSON.stringify(message));
46
clients(): Set<WebSocketClient> {
47
return this.controller.clients;