mirror of
https://github.com/immich-app/immich.git
synced 2024-11-15 18:08:48 -07:00
refactor(server): client events (#13062)
This commit is contained in:
parent
47821cda35
commit
dfc2d5002b
@ -62,36 +62,20 @@ export type EmitHandler<T extends EmitEvent> = (...args: ArgsOf<T>) => Promise<v
|
|||||||
export type ArgOf<T extends EmitEvent> = EventMap[T][0];
|
export type ArgOf<T extends EmitEvent> = EventMap[T][0];
|
||||||
export type ArgsOf<T extends EmitEvent> = EventMap[T];
|
export type ArgsOf<T extends EmitEvent> = EventMap[T];
|
||||||
|
|
||||||
export enum ClientEvent {
|
|
||||||
UPLOAD_SUCCESS = 'on_upload_success',
|
|
||||||
USER_DELETE = 'on_user_delete',
|
|
||||||
ASSET_DELETE = 'on_asset_delete',
|
|
||||||
ASSET_TRASH = 'on_asset_trash',
|
|
||||||
ASSET_UPDATE = 'on_asset_update',
|
|
||||||
ASSET_HIDDEN = 'on_asset_hidden',
|
|
||||||
ASSET_RESTORE = 'on_asset_restore',
|
|
||||||
ASSET_STACK_UPDATE = 'on_asset_stack_update',
|
|
||||||
PERSON_THUMBNAIL = 'on_person_thumbnail',
|
|
||||||
SERVER_VERSION = 'on_server_version',
|
|
||||||
CONFIG_UPDATE = 'on_config_update',
|
|
||||||
NEW_RELEASE = 'on_new_release',
|
|
||||||
SESSION_DELETE = 'on_session_delete',
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ClientEventMap {
|
export interface ClientEventMap {
|
||||||
[ClientEvent.UPLOAD_SUCCESS]: AssetResponseDto;
|
on_upload_success: [AssetResponseDto];
|
||||||
[ClientEvent.USER_DELETE]: string;
|
on_user_delete: [string];
|
||||||
[ClientEvent.ASSET_DELETE]: string;
|
on_asset_delete: [string];
|
||||||
[ClientEvent.ASSET_TRASH]: string[];
|
on_asset_trash: [string[]];
|
||||||
[ClientEvent.ASSET_UPDATE]: AssetResponseDto;
|
on_asset_update: [AssetResponseDto];
|
||||||
[ClientEvent.ASSET_HIDDEN]: string;
|
on_asset_hidden: [string];
|
||||||
[ClientEvent.ASSET_RESTORE]: string[];
|
on_asset_restore: [string[]];
|
||||||
[ClientEvent.ASSET_STACK_UPDATE]: string[];
|
on_asset_stack_update: string[];
|
||||||
[ClientEvent.PERSON_THUMBNAIL]: string;
|
on_person_thumbnail: [string];
|
||||||
[ClientEvent.SERVER_VERSION]: ServerVersionResponseDto;
|
on_server_version: [ServerVersionResponseDto];
|
||||||
[ClientEvent.CONFIG_UPDATE]: Record<string, never>;
|
on_config_update: [];
|
||||||
[ClientEvent.NEW_RELEASE]: ReleaseNotification;
|
on_new_release: [ReleaseNotification];
|
||||||
[ClientEvent.SESSION_DELETE]: string;
|
on_session_delete: [string];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type EventItem<T extends EmitEvent> = {
|
export type EventItem<T extends EmitEvent> = {
|
||||||
@ -107,11 +91,11 @@ export interface IEventRepository {
|
|||||||
/**
|
/**
|
||||||
* Send to connected clients for a specific user
|
* Send to connected clients for a specific user
|
||||||
*/
|
*/
|
||||||
clientSend<E extends keyof ClientEventMap>(event: E, room: string, data: ClientEventMap[E]): void;
|
clientSend<E extends keyof ClientEventMap>(event: E, room: string, ...data: ClientEventMap[E]): void;
|
||||||
/**
|
/**
|
||||||
* Send to all connected clients
|
* Send to all connected clients
|
||||||
*/
|
*/
|
||||||
clientBroadcast<E extends keyof ClientEventMap>(event: E, data: ClientEventMap[E]): void;
|
clientBroadcast<E extends keyof ClientEventMap>(event: E, ...data: ClientEventMap[E]): void;
|
||||||
/**
|
/**
|
||||||
* Send to all connected servers
|
* Send to all connected servers
|
||||||
*/
|
*/
|
||||||
|
@ -106,12 +106,12 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clientSend<E extends keyof ClientEventMap>(event: E, room: string, data: ClientEventMap[E]) {
|
clientSend<T extends keyof ClientEventMap>(event: T, room: string, ...data: ClientEventMap[T]) {
|
||||||
this.server?.to(room).emit(event, data);
|
this.server?.to(room).emit(event, ...data);
|
||||||
}
|
}
|
||||||
|
|
||||||
clientBroadcast<E extends keyof ClientEventMap>(event: E, data: ClientEventMap[E]) {
|
clientBroadcast<T extends keyof ClientEventMap>(event: T, ...data: ClientEventMap[T]) {
|
||||||
this.server?.emit(event, data);
|
this.server?.emit(event, ...data);
|
||||||
}
|
}
|
||||||
|
|
||||||
serverSend<T extends ServerEvents>(event: T, ...args: ArgsOf<T>): void {
|
serverSend<T extends ServerEvents>(event: T, ...args: ArgsOf<T>): void {
|
||||||
|
@ -6,7 +6,7 @@ import { mapAsset } from 'src/dtos/asset-response.dto';
|
|||||||
import { AllJobStatusResponseDto, JobCommandDto, JobCreateDto, JobStatusDto } from 'src/dtos/job.dto';
|
import { AllJobStatusResponseDto, JobCommandDto, JobCreateDto, JobStatusDto } from 'src/dtos/job.dto';
|
||||||
import { AssetType, ManualJobName } from 'src/enum';
|
import { AssetType, ManualJobName } from 'src/enum';
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
import { ArgOf, ClientEvent, IEventRepository } from 'src/interfaces/event.interface';
|
import { ArgOf, IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import {
|
import {
|
||||||
ConcurrentQueueName,
|
ConcurrentQueueName,
|
||||||
IJobRepository,
|
IJobRepository,
|
||||||
@ -279,7 +279,7 @@ export class JobService {
|
|||||||
if (item.data.source === 'sidecar-write') {
|
if (item.data.source === 'sidecar-write') {
|
||||||
const [asset] = await this.assetRepository.getByIdsWithAllRelations([item.data.id]);
|
const [asset] = await this.assetRepository.getByIdsWithAllRelations([item.data.id]);
|
||||||
if (asset) {
|
if (asset) {
|
||||||
this.eventRepository.clientSend(ClientEvent.ASSET_UPDATE, asset.ownerId, mapAsset(asset));
|
this.eventRepository.clientSend('on_asset_update', asset.ownerId, mapAsset(asset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await this.jobRepository.queue({ name: JobName.LINK_LIVE_PHOTOS, data: item.data });
|
await this.jobRepository.queue({ name: JobName.LINK_LIVE_PHOTOS, data: item.data });
|
||||||
@ -302,7 +302,7 @@ export class JobService {
|
|||||||
const { id } = item.data;
|
const { id } = item.data;
|
||||||
const person = await this.personRepository.getById(id);
|
const person = await this.personRepository.getById(id);
|
||||||
if (person) {
|
if (person) {
|
||||||
this.eventRepository.clientSend(ClientEvent.PERSON_THUMBNAIL, person.ownerId, person.id);
|
this.eventRepository.clientSend('on_person_thumbnail', person.ownerId, person.id);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -331,7 +331,7 @@ export class JobService {
|
|||||||
|
|
||||||
await this.jobRepository.queueAll(jobs);
|
await this.jobRepository.queueAll(jobs);
|
||||||
if (asset.isVisible) {
|
if (asset.isVisible) {
|
||||||
this.eventRepository.clientSend(ClientEvent.UPLOAD_SUCCESS, asset.ownerId, mapAsset(asset));
|
this.eventRepository.clientSend('on_upload_success', asset.ownerId, mapAsset(asset));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -345,7 +345,7 @@ export class JobService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case JobName.USER_DELETION: {
|
case JobName.USER_DELETION: {
|
||||||
this.eventRepository.clientBroadcast(ClientEvent.USER_DELETE, item.data.id);
|
this.eventRepository.clientBroadcast('on_user_delete', item.data.id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import { AssetFileEntity } from 'src/entities/asset-files.entity';
|
|||||||
import { AssetFileType, UserMetadataKey } from 'src/enum';
|
import { AssetFileType, UserMetadataKey } from 'src/enum';
|
||||||
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
import { ClientEvent, IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
||||||
import { EmailTemplate, INotificationRepository } from 'src/interfaces/notification.interface';
|
import { EmailTemplate, INotificationRepository } from 'src/interfaces/notification.interface';
|
||||||
@ -104,7 +104,7 @@ describe(NotificationService.name, () => {
|
|||||||
it('should emit client and server events', () => {
|
it('should emit client and server events', () => {
|
||||||
const update = { newConfig: defaults };
|
const update = { newConfig: defaults };
|
||||||
expect(sut.onConfigUpdate(update)).toBeUndefined();
|
expect(sut.onConfigUpdate(update)).toBeUndefined();
|
||||||
expect(eventMock.clientBroadcast).toHaveBeenCalledWith(ClientEvent.CONFIG_UPDATE, {});
|
expect(eventMock.clientBroadcast).toHaveBeenCalledWith('on_config_update');
|
||||||
expect(eventMock.serverSend).toHaveBeenCalledWith('config.update', update);
|
expect(eventMock.serverSend).toHaveBeenCalledWith('config.update', update);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -236,28 +236,28 @@ describe(NotificationService.name, () => {
|
|||||||
describe('onStackCreate', () => {
|
describe('onStackCreate', () => {
|
||||||
it('should send connected clients an event', () => {
|
it('should send connected clients an event', () => {
|
||||||
sut.onStackCreate({ stackId: 'stack-id', userId: 'user-id' });
|
sut.onStackCreate({ stackId: 'stack-id', userId: 'user-id' });
|
||||||
expect(eventMock.clientSend).toHaveBeenCalledWith('on_asset_stack_update', 'user-id', []);
|
expect(eventMock.clientSend).toHaveBeenCalledWith('on_asset_stack_update', 'user-id');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('onStackUpdate', () => {
|
describe('onStackUpdate', () => {
|
||||||
it('should send connected clients an event', () => {
|
it('should send connected clients an event', () => {
|
||||||
sut.onStackUpdate({ stackId: 'stack-id', userId: 'user-id' });
|
sut.onStackUpdate({ stackId: 'stack-id', userId: 'user-id' });
|
||||||
expect(eventMock.clientSend).toHaveBeenCalledWith('on_asset_stack_update', 'user-id', []);
|
expect(eventMock.clientSend).toHaveBeenCalledWith('on_asset_stack_update', 'user-id');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('onStackDelete', () => {
|
describe('onStackDelete', () => {
|
||||||
it('should send connected clients an event', () => {
|
it('should send connected clients an event', () => {
|
||||||
sut.onStackDelete({ stackId: 'stack-id', userId: 'user-id' });
|
sut.onStackDelete({ stackId: 'stack-id', userId: 'user-id' });
|
||||||
expect(eventMock.clientSend).toHaveBeenCalledWith('on_asset_stack_update', 'user-id', []);
|
expect(eventMock.clientSend).toHaveBeenCalledWith('on_asset_stack_update', 'user-id');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('onStacksDelete', () => {
|
describe('onStacksDelete', () => {
|
||||||
it('should send connected clients an event', () => {
|
it('should send connected clients an event', () => {
|
||||||
sut.onStacksDelete({ stackIds: ['stack-id'], userId: 'user-id' });
|
sut.onStacksDelete({ stackIds: ['stack-id'], userId: 'user-id' });
|
||||||
expect(eventMock.clientSend).toHaveBeenCalledWith('on_asset_stack_update', 'user-id', []);
|
expect(eventMock.clientSend).toHaveBeenCalledWith('on_asset_stack_update', 'user-id');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto';
|
|||||||
import { AlbumEntity } from 'src/entities/album.entity';
|
import { AlbumEntity } from 'src/entities/album.entity';
|
||||||
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
import { ArgOf, ClientEvent, IEventRepository } from 'src/interfaces/event.interface';
|
import { ArgOf, IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import {
|
import {
|
||||||
IEmailJob,
|
IEmailJob,
|
||||||
IJobRepository,
|
IJobRepository,
|
||||||
@ -45,7 +45,7 @@ export class NotificationService {
|
|||||||
|
|
||||||
@OnEvent({ name: 'config.update' })
|
@OnEvent({ name: 'config.update' })
|
||||||
onConfigUpdate({ oldConfig, newConfig }: ArgOf<'config.update'>) {
|
onConfigUpdate({ oldConfig, newConfig }: ArgOf<'config.update'>) {
|
||||||
this.eventRepository.clientBroadcast(ClientEvent.CONFIG_UPDATE, {});
|
this.eventRepository.clientBroadcast('on_config_update');
|
||||||
this.eventRepository.serverSend('config.update', { oldConfig, newConfig });
|
this.eventRepository.serverSend('config.update', { oldConfig, newConfig });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ export class NotificationService {
|
|||||||
|
|
||||||
@OnEvent({ name: 'asset.hide' })
|
@OnEvent({ name: 'asset.hide' })
|
||||||
onAssetHide({ assetId, userId }: ArgOf<'asset.hide'>) {
|
onAssetHide({ assetId, userId }: ArgOf<'asset.hide'>) {
|
||||||
this.eventRepository.clientSend(ClientEvent.ASSET_HIDDEN, userId, assetId);
|
this.eventRepository.clientSend('on_asset_hidden', userId, assetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'asset.show' })
|
@OnEvent({ name: 'asset.show' })
|
||||||
@ -76,42 +76,42 @@ export class NotificationService {
|
|||||||
|
|
||||||
@OnEvent({ name: 'asset.trash' })
|
@OnEvent({ name: 'asset.trash' })
|
||||||
onAssetTrash({ assetId, userId }: ArgOf<'asset.trash'>) {
|
onAssetTrash({ assetId, userId }: ArgOf<'asset.trash'>) {
|
||||||
this.eventRepository.clientSend(ClientEvent.ASSET_TRASH, userId, [assetId]);
|
this.eventRepository.clientSend('on_asset_trash', userId, [assetId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'asset.delete' })
|
@OnEvent({ name: 'asset.delete' })
|
||||||
onAssetDelete({ assetId, userId }: ArgOf<'asset.delete'>) {
|
onAssetDelete({ assetId, userId }: ArgOf<'asset.delete'>) {
|
||||||
this.eventRepository.clientSend(ClientEvent.ASSET_DELETE, userId, assetId);
|
this.eventRepository.clientSend('on_asset_delete', userId, assetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'assets.trash' })
|
@OnEvent({ name: 'assets.trash' })
|
||||||
onAssetsTrash({ assetIds, userId }: ArgOf<'assets.trash'>) {
|
onAssetsTrash({ assetIds, userId }: ArgOf<'assets.trash'>) {
|
||||||
this.eventRepository.clientSend(ClientEvent.ASSET_TRASH, userId, assetIds);
|
this.eventRepository.clientSend('on_asset_trash', userId, assetIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'assets.restore' })
|
@OnEvent({ name: 'assets.restore' })
|
||||||
onAssetsRestore({ assetIds, userId }: ArgOf<'assets.restore'>) {
|
onAssetsRestore({ assetIds, userId }: ArgOf<'assets.restore'>) {
|
||||||
this.eventRepository.clientSend(ClientEvent.ASSET_RESTORE, userId, assetIds);
|
this.eventRepository.clientSend('on_asset_restore', userId, assetIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'stack.create' })
|
@OnEvent({ name: 'stack.create' })
|
||||||
onStackCreate({ userId }: ArgOf<'stack.create'>) {
|
onStackCreate({ userId }: ArgOf<'stack.create'>) {
|
||||||
this.eventRepository.clientSend(ClientEvent.ASSET_STACK_UPDATE, userId, []);
|
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'stack.update' })
|
@OnEvent({ name: 'stack.update' })
|
||||||
onStackUpdate({ userId }: ArgOf<'stack.update'>) {
|
onStackUpdate({ userId }: ArgOf<'stack.update'>) {
|
||||||
this.eventRepository.clientSend(ClientEvent.ASSET_STACK_UPDATE, userId, []);
|
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'stack.delete' })
|
@OnEvent({ name: 'stack.delete' })
|
||||||
onStackDelete({ userId }: ArgOf<'stack.delete'>) {
|
onStackDelete({ userId }: ArgOf<'stack.delete'>) {
|
||||||
this.eventRepository.clientSend(ClientEvent.ASSET_STACK_UPDATE, userId, []);
|
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'stacks.delete' })
|
@OnEvent({ name: 'stacks.delete' })
|
||||||
onStacksDelete({ userId }: ArgOf<'stacks.delete'>) {
|
onStacksDelete({ userId }: ArgOf<'stacks.delete'>) {
|
||||||
this.eventRepository.clientSend(ClientEvent.ASSET_STACK_UPDATE, userId, []);
|
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'user.signup' })
|
@OnEvent({ name: 'user.signup' })
|
||||||
@ -134,7 +134,7 @@ export class NotificationService {
|
|||||||
@OnEvent({ name: 'session.delete' })
|
@OnEvent({ name: 'session.delete' })
|
||||||
onSessionDelete({ sessionId }: ArgOf<'session.delete'>) {
|
onSessionDelete({ sessionId }: ArgOf<'session.delete'>) {
|
||||||
// after the response is sent
|
// after the response is sent
|
||||||
setTimeout(() => this.eventRepository.clientSend(ClientEvent.SESSION_DELETE, sessionId, sessionId), 500);
|
setTimeout(() => this.eventRepository.clientSend('on_session_delete', sessionId, sessionId), 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendTestEmail(id: string, dto: SystemConfigSmtpDto) {
|
async sendTestEmail(id: string, dto: SystemConfigSmtpDto) {
|
||||||
|
@ -7,7 +7,7 @@ import { OnEvent } from 'src/decorators';
|
|||||||
import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto';
|
import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server.dto';
|
||||||
import { VersionCheckMetadata } from 'src/entities/system-metadata.entity';
|
import { VersionCheckMetadata } from 'src/entities/system-metadata.entity';
|
||||||
import { SystemMetadataKey } from 'src/enum';
|
import { SystemMetadataKey } from 'src/enum';
|
||||||
import { ArgOf, ClientEvent, IEventRepository } from 'src/interfaces/event.interface';
|
import { ArgOf, IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
||||||
import { IServerInfoRepository } from 'src/interfaces/server-info.interface';
|
import { IServerInfoRepository } from 'src/interfaces/server-info.interface';
|
||||||
@ -80,7 +80,7 @@ export class VersionService {
|
|||||||
|
|
||||||
if (semver.gt(releaseVersion, serverVersion)) {
|
if (semver.gt(releaseVersion, serverVersion)) {
|
||||||
this.logger.log(`Found ${releaseVersion}, released at ${new Date(publishedAt).toLocaleString()}`);
|
this.logger.log(`Found ${releaseVersion}, released at ${new Date(publishedAt).toLocaleString()}`);
|
||||||
this.eventRepository.clientBroadcast(ClientEvent.NEW_RELEASE, asNotification(metadata));
|
this.eventRepository.clientBroadcast('on_new_release', asNotification(metadata));
|
||||||
}
|
}
|
||||||
} catch (error: Error | any) {
|
} catch (error: Error | any) {
|
||||||
this.logger.warn(`Unable to run version check: ${error}`, error?.stack);
|
this.logger.warn(`Unable to run version check: ${error}`, error?.stack);
|
||||||
@ -92,10 +92,10 @@ export class VersionService {
|
|||||||
|
|
||||||
@OnEvent({ name: 'websocket.connect' })
|
@OnEvent({ name: 'websocket.connect' })
|
||||||
async onWebsocketConnection({ userId }: ArgOf<'websocket.connect'>) {
|
async onWebsocketConnection({ userId }: ArgOf<'websocket.connect'>) {
|
||||||
this.eventRepository.clientSend(ClientEvent.SERVER_VERSION, userId, serverVersion);
|
this.eventRepository.clientSend('on_server_version', userId, serverVersion);
|
||||||
const metadata = await this.systemMetadataRepository.get(SystemMetadataKey.VERSION_CHECK_STATE);
|
const metadata = await this.systemMetadataRepository.get(SystemMetadataKey.VERSION_CHECK_STATE);
|
||||||
if (metadata) {
|
if (metadata) {
|
||||||
this.eventRepository.clientSend(ClientEvent.NEW_RELEASE, userId, asNotification(metadata));
|
this.eventRepository.clientSend('on_new_release', userId, asNotification(metadata));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ export const newEventRepositoryMock = (): Mocked<IEventRepository> => {
|
|||||||
return {
|
return {
|
||||||
on: vitest.fn() as any,
|
on: vitest.fn() as any,
|
||||||
emit: vitest.fn() as any,
|
emit: vitest.fn() as any,
|
||||||
clientSend: vitest.fn(),
|
clientSend: vitest.fn() as any,
|
||||||
clientBroadcast: vitest.fn(),
|
clientBroadcast: vitest.fn() as any,
|
||||||
serverSend: vitest.fn(),
|
serverSend: vitest.fn(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user