diff --git a/electron-app/src/events/events.ts b/electron-app/src/events/events.ts index 6ff23da..f401e83 100644 --- a/electron-app/src/events/events.ts +++ b/electron-app/src/events/events.ts @@ -1,6 +1,9 @@ export enum EVENTS { START_LISTENING = 'start-listening', STOP_LISTENING = 'stop-listening', + SYNC_CREATED = 'sync-created', + SYNC_UPDATED = 'sync-updated', + SYNC_DELETED = 'sync-deleted', } export type EVENTS_TYPE = (typeof EVENTS)[keyof typeof EVENTS]; diff --git a/electron-app/src/index.ts b/electron-app/src/index.ts index 9fd18f7..4ad5e63 100644 --- a/electron-app/src/index.ts +++ b/electron-app/src/index.ts @@ -3,14 +3,17 @@ import os from 'os'; import path from 'path'; import { EVENTS } from './events/events'; import { beforeStartServer } from './fileSystemServerFn'; + import { AppFileSystemRoutes } from './presentation/routes'; import { Server, eventEmitter } from './server'; +import { initFileSystemSubscribers } from './subscribers'; let contextMenu: Electron.Menu; let tray = null; const basePath = `${os.homedir()}/.nuclia`; const appRoutes = new AppFileSystemRoutes(basePath); const server = new Server({ port: 8000, routes: appRoutes.getRoutes() }); +initFileSystemSubscribers(basePath); // Handle creating/removing shortcuts on Windows when installing/uninstalling. if (require('electron-squirrel-startup')) { diff --git a/electron-app/src/logic/logs/domain/log.entity.ts b/electron-app/src/logic/logs/domain/log.entity.ts index 82e35ff..9c434e3 100644 --- a/electron-app/src/logic/logs/domain/log.entity.ts +++ b/electron-app/src/logic/logs/domain/log.entity.ts @@ -12,7 +12,7 @@ export interface LogEntityOptions { } export class LogEntity { - public level: LogSeverityLevel; // Enum + public level: LogSeverityLevel; public message: string; public createdAt: Date; public origin: string; diff --git a/electron-app/src/logic/logs/infrastructure/file-system.log.datasource.ts b/electron-app/src/logic/logs/infrastructure/file-system.log.datasource.ts index d8e10c9..9a89f5b 100644 --- a/electron-app/src/logic/logs/infrastructure/file-system.log.datasource.ts +++ b/electron-app/src/logic/logs/infrastructure/file-system.log.datasource.ts @@ -40,7 +40,7 @@ export class FileSystemLogDatasource implements ILogDatasource { const content = await readFile(path); if (content === '') return []; - const logs = content.split('\n').map(LogEntity.fromJson); + const logs = content.split('\n').filter(Boolean).map(LogEntity.fromJson); return logs; }; diff --git a/electron-app/src/logic/sync/domain/use-cases/create-sync.use-case.ts b/electron-app/src/logic/sync/domain/use-cases/create-sync.use-case.ts index 5f439d2..aebab39 100644 --- a/electron-app/src/logic/sync/domain/use-cases/create-sync.use-case.ts +++ b/electron-app/src/logic/sync/domain/use-cases/create-sync.use-case.ts @@ -1,3 +1,5 @@ +import { EVENTS } from '../../../../events/events'; +import { eventEmitter } from '../../../../server'; import { CreateSyncDto } from '../dto/create-sync.dto'; import { ISyncRepository } from '../sync.repository'; @@ -10,5 +12,6 @@ export class CreateSync implements CreateSyncUseCase { async execute(dto: CreateSyncDto): Promise { await this.repository.createSync(dto); + eventEmitter.emit(EVENTS.SYNC_CREATED); } } diff --git a/electron-app/src/logic/sync/domain/use-cases/delete-sync.use-case.ts b/electron-app/src/logic/sync/domain/use-cases/delete-sync.use-case.ts index 4f8df85..c368c27 100644 --- a/electron-app/src/logic/sync/domain/use-cases/delete-sync.use-case.ts +++ b/electron-app/src/logic/sync/domain/use-cases/delete-sync.use-case.ts @@ -1,4 +1,5 @@ -import { CustomError } from '../../../errors'; +import { EVENTS } from '../../../../events/events'; +import { eventEmitter } from '../../../../server'; import { ISyncRepository } from '../sync.repository'; export interface DeleteSyncUseCase { @@ -9,10 +10,7 @@ export class DeleteSync implements DeleteSyncUseCase { constructor(private readonly repository: ISyncRepository) {} async execute(id: string) { - const data = await this.repository.getSync(id); - if (data === null) { - throw new CustomError(`Sync with id ${id} not found`, 404); - } await this.repository.deleteSync(id); + eventEmitter.emit(EVENTS.SYNC_DELETED); } } diff --git a/electron-app/src/logic/sync/domain/use-cases/update-sync.use-case.ts b/electron-app/src/logic/sync/domain/use-cases/update-sync.use-case.ts index f1fe6ab..14cb28b 100644 --- a/electron-app/src/logic/sync/domain/use-cases/update-sync.use-case.ts +++ b/electron-app/src/logic/sync/domain/use-cases/update-sync.use-case.ts @@ -1,3 +1,5 @@ +import { EVENTS } from '../../../../events/events'; +import { eventEmitter } from '../../../../server'; import { UpdateSyncDto } from '../dto/update-sync.dto'; import { ISyncRepository } from '../sync.repository'; @@ -10,5 +12,6 @@ export class UpdateSync implements UpdateSyncUseCase { async execute(dto: UpdateSyncDto) { await this.repository.updateSync(dto); + eventEmitter.emit(EVENTS.SYNC_UPDATED); } } diff --git a/electron-app/src/logic/sync/infrastructure/file-system.sync.datasource.ts b/electron-app/src/logic/sync/infrastructure/file-system.sync.datasource.ts index 128fa74..7b80d08 100644 --- a/electron-app/src/logic/sync/infrastructure/file-system.sync.datasource.ts +++ b/electron-app/src/logic/sync/infrastructure/file-system.sync.datasource.ts @@ -50,6 +50,10 @@ export class FileSystemSyncDatasource implements ISyncDatasource { } async deleteSync(id: string): Promise { + const data = await this.getSync(id); + if (data === null) { + throw new CustomError(`Sync with id ${id} not found`, 404); + } await this.loadSyncData(); delete this.allSyncData[id]; await writeFile(this.basePath, JSON.stringify(this.allSyncData, null, 2)); diff --git a/electron-app/src/subscribers.ts b/electron-app/src/subscribers.ts new file mode 100644 index 0000000..a84fcbd --- /dev/null +++ b/electron-app/src/subscribers.ts @@ -0,0 +1,41 @@ +import { EVENTS } from './events/events'; +import { LogEntity, LogSeverityLevel } from './logic/logs/domain/log.entity'; +import { SaveLogs } from './logic/logs/domain/use-cases/save-logs.use-case'; +import { FileSystemLogDatasource } from './logic/logs/infrastructure/file-system.log.datasource'; +import { LogRepository } from './logic/logs/infrastructure/log.repository'; +import { eventEmitter } from './server'; + +export function initFileSystemSubscribers(basePath: string) { + eventEmitter.subscribe(EVENTS.SYNC_CREATED, () => { + const saveLog = new SaveLogs(new LogRepository(new FileSystemLogDatasource(basePath))); + saveLog.execute( + new LogEntity({ + message: 'Sync created', + level: LogSeverityLevel.low, + origin: 'electron-app', + }), + ); + }); + + eventEmitter.subscribe(EVENTS.SYNC_UPDATED, () => { + const saveLog = new SaveLogs(new LogRepository(new FileSystemLogDatasource(basePath))); + saveLog.execute( + new LogEntity({ + message: 'Sync updated', + level: LogSeverityLevel.low, + origin: 'electron-app', + }), + ); + }); + + eventEmitter.subscribe(EVENTS.SYNC_DELETED, () => { + const saveLog = new SaveLogs(new LogRepository(new FileSystemLogDatasource(basePath))); + saveLog.execute( + new LogEntity({ + message: 'Sync deleted', + level: LogSeverityLevel.low, + origin: 'electron-app', + }), + ); + }); +} diff --git a/electron-app/tests/sever.spec.js b/electron-app/tests/sever.spec.js index 3b7a5b6..ce3ca3b 100644 --- a/electron-app/tests/sever.spec.js +++ b/electron-app/tests/sever.spec.js @@ -4,9 +4,11 @@ import { deleteDirectory } from '../src/fileSystemFn'; import { beforeStartServer } from '../src/fileSystemServerFn'; import { AppFileSystemRoutes } from '../src/presentation/routes'; import { Server } from '../src/server'; +import { initFileSystemSubscribers } from '../src/subscribers'; const appRoutes = new AppFileSystemRoutes('.nuclia'); const testServer = new Server({ port: 8000, routes: appRoutes.getRoutes() }); +initFileSystemSubscribers('.nuclia'); describe('Server without folder', () => { beforeAll(async () => { @@ -53,6 +55,12 @@ describe('Server width folder', () => { expect(Object.keys(response.body).length).toEqual(0); }); + test('Get empty logs', async () => { + const response = await request(testServer.app).get('/logs'); + expect(response.status).toBe(200); + expect(Object.keys(response.body).length).toEqual(0); + }); + test('Add new sync', async () => { const response = await request(testServer.app).post('/sync').send({}); expect(response.status).toBe(201); @@ -64,6 +72,12 @@ describe('Server width folder', () => { expect(Object.keys(response.body).length).toEqual(1); }); + test('Get logs with sync created', async () => { + const response = await request(testServer.app).get('/logs'); + expect(response.status).toBe(200); + expect(Object.keys(response.body).length).toEqual(1); + }); + test('Update a sync', async () => { const response = await request(testServer.app).get('/sync'); expect(response.status).toBe(200); @@ -106,25 +120,19 @@ describe('Server width folder', () => { expect(response.status).toBe(200); expect(Object.keys(response.body).length).toEqual(0); }); -}); -describe('Server Logs', () => { - beforeAll(async () => { - await beforeStartServer('.nuclia'); - await testServer.start(); - }); - afterAll(async () => { - await deleteDirectory('.nuclia'); - await testServer.close(); + test('Get all logs', async () => { + const response = await request(testServer.app).get('/logs'); + expect(response.status).toBe(200); + expect(Object.keys(response.body).length).toEqual(3); }); - test('Init server', async () => { - const response = await request(testServer.app).get('/'); + test('Delete logs', async () => { + let response = await request(testServer.app).delete('/logs'); expect(response.status).toBe(200); - }); - test('Get logs', async () => { - const response = await request(testServer.app).get('/logs'); + response = await request(testServer.app).get('/logs'); expect(response.status).toBe(200); + expect(Object.keys(response.body).length).toEqual(0); }); });