import { ILocalDataSource } from '../source/local/ILocalDataSource'; import { IRemoteDataSource } from '../source/remote/IRemoteDataSource'; import { DialogEntity } from '../../Domain/entity/DialogEntity'; import RepositoryException, { DIALOG_ENTITY_REPOSITORY_EXCEPTION_CODE, DIALOG_ENTITY_REPOSITORY_EXCEPTION_MESSAGE, UNEXPECTED_REPOSITORY_EXCEPTION_CODE, UNEXPECTED_REPOSITORY_EXCEPTION_MESSAGE, } from '../source/exception/RepositoryException'; import { IDialogsRepository } from '../../Domain/repository/IDialogsRepository'; import { LocalDataSourceException, NOT_FOUND_LOCAL_DATASOURCE_EXCEPTION_CODE, NOT_FOUND_LOCAL_DATASOURCE_EXCEPTION_MESSAGE, UNEXPECTED_LOCAL_DATASOURCE_EXCEPTION_CODE, } from '../source/exception/LocalDataSourceException'; import { IMapper } from '../mapper/IMapper'; import { DialogRemoteDTOMapper } from '../mapper/DialogRemoteDTOMapper'; import { RemoteDialogDTO } from '../dto/dialog/RemoteDialogDTO'; import { RemoteDialogsDTO } from '../dto/dialog/RemoteDialogsDTO'; import { DialogLocalDTOMapper } from '../mapper/DialogLocalDTOMapper'; import { LocalDialogDTO } from '../dto/dialog/LocalDialogDTO'; import { LocalDialogsDTO } from '../dto/dialog/LocalDialogsDTO'; import { FunctionTypeVoidToVoid } from '../../CommonTypes/BaseViewModel'; import { MapperDTOException } from '../source/exception/MapperDTOException'; import { PaginatedResult, Pagination, } from '../../Domain/repository/Pagination'; import { GroupDialogEntity } from '../../Domain/entity/GroupDialogEntity'; import { stringifyError } from '../../utils/parse'; import { RemoteUserDTO } from '../dto/user/RemoteUserDTO'; import { QBUIKitConfig } from '../../CommonTypes/CommonTypes'; export default class DialogsRepository implements IDialogsRepository { private localDataStorage: ILocalDataSource; private remoteDataSource: IRemoteDataSource; private dialogRemoteDTOMapper: IMapper; private dialogLocalDTOMapper: IMapper; // eslint-disable-next-line no-useless-constructor constructor( localDataStorage: ILocalDataSource, remoteDataSource: IRemoteDataSource, ) { this.localDataStorage = localDataStorage; this.remoteDataSource = remoteDataSource; this.dialogRemoteDTOMapper = new DialogRemoteDTOMapper(); this.dialogLocalDTOMapper = new DialogLocalDTOMapper(); } release() { this.localDataStorage.clearAll(); } subscribeLocalSync(subscriber: FunctionTypeVoidToVoid): void { this.localDataStorage.subscribe(subscriber); } unsubscribeLocalSync(): void { this.localDataStorage.release(); } isLocalSynced(): Promise { return this.localDataStorage.isLocalSynced(); } setLocalSynced(synced: boolean): void { this.localDataStorage.setLocalSynced(synced); } async saveDialogToLocal(entity: DialogEntity): Promise { try { const dto: LocalDialogDTO = await this.dialogLocalDTOMapper.fromEntity( entity, ); await this.localDataStorage.saveDialog(dto); return Promise.resolve(true); } catch (e) { let exceptionMessage: string; if (e instanceof MapperDTOException) { exceptionMessage = `have exception: ${e.message}, description: ${e._description} `; console.log(exceptionMessage); } else if (e instanceof LocalDataSourceException) { exceptionMessage = `have exception: ${e.message}`; console.log(exceptionMessage); } else { exceptionMessage = `have exception: ${ (e as RepositoryException).message }`; console.log(exceptionMessage); } console.log('for entity: ', JSON.stringify(entity)); // eslint-disable-next-line prefer-promise-reject-errors return Promise.reject(exceptionMessage); } } async createDialogInRemote(entity: DialogEntity): Promise { console.log( 'call createDialogInRemote in Repository with param: ', JSON.stringify(entity), ); const remoteDialogDTO: RemoteDialogDTO = await this.dialogRemoteDTOMapper.fromEntity(entity); console.log('have remoteDialogDTO: ', JSON.stringify(remoteDialogDTO)); try { const resultDTO: RemoteDialogDTO = await this.remoteDataSource.createDialog(remoteDialogDTO); const resultEntity: DialogEntity = await this.dialogRemoteDTOMapper.toEntity(resultDTO); console.log( 'have result entity in createDialogInRemote:', JSON.stringify(resultEntity), ); return Promise.resolve(resultEntity); } catch (e) { return Promise.reject(e); } } async updateDialogInLocal(entity: DialogEntity): Promise { try { const dto: LocalDialogDTO = await this.dialogLocalDTOMapper.fromEntity( entity, ); await this.localDataStorage.updateDialog(dto); const newEntity: DialogEntity = await this.dialogLocalDTOMapper.toEntity( dto, ); return Promise.resolve(newEntity); } catch (e) { return Promise.reject(e); } } async updateCurrentDialogInLocalDataSource( entity: DialogEntity, qbConfig: QBUIKitConfig, ): Promise { try { const dto: RemoteDialogDTO = await this.dialogRemoteDTOMapper.fromEntity( entity, ); this.remoteDataSource.updateCurrentDialog(dto, qbConfig); return Promise.resolve(entity); } catch (e) { return Promise.reject(e); } } // eslint-disable-next-line class-methods-use-this,@typescript-eslint/no-unused-vars async updateDialogInRemote(entity: DialogEntity): Promise { const remoteDialogDTO: RemoteDialogDTO = await this.dialogRemoteDTOMapper.fromEntity< GroupDialogEntity, RemoteDialogDTO >(entity as GroupDialogEntity); try { const resultDTO: RemoteDialogDTO = await this.remoteDataSource.updateDialog(remoteDialogDTO); const resultEntity: DialogEntity = await this.dialogRemoteDTOMapper.toEntity(resultDTO); return Promise.resolve(resultEntity); } catch (e) { return Promise.reject(e); } } async getDialogFromLocal(dialogId: string): Promise { const dto: LocalDialogDTO = new LocalDialogDTO(); dto.id = dialogId; let checkResult = true; let dialog: DialogEntity = DialogRemoteDTOMapper.createDefaultDialogEntity('0'); if (checkResult) { try { const dtoResult: LocalDialogDTO = await this.localDataStorage.getDialog( dto, ); dialog = await this.dialogLocalDTOMapper.toEntity(dtoResult); } catch (e) { if (e instanceof LocalDataSourceException) { if (e.code !== UNEXPECTED_LOCAL_DATASOURCE_EXCEPTION_CODE) { // return Promise.reject(new RepositoryException(e.message, e.code)); return Promise.reject( new RepositoryException( NOT_FOUND_LOCAL_DATASOURCE_EXCEPTION_MESSAGE, NOT_FOUND_LOCAL_DATASOURCE_EXCEPTION_CODE, ), ); // } return Promise.reject( new RepositoryException( UNEXPECTED_REPOSITORY_EXCEPTION_MESSAGE, UNEXPECTED_REPOSITORY_EXCEPTION_CODE, ), ); } checkResult = false; } } const prom = new Promise((resolve, reject) => { if (checkResult === true) { resolve(dialog); } else { reject( new RepositoryException( DIALOG_ENTITY_REPOSITORY_EXCEPTION_MESSAGE, DIALOG_ENTITY_REPOSITORY_EXCEPTION_CODE, ), ); } }); return prom; } async getDialogFromRemote(dialogId: string): Promise { const dto: RemoteDialogDTO = new RemoteDialogDTO(); dto.id = dialogId; try { const resultDTO: RemoteDialogDTO = await this.remoteDataSource.getDialog( dto, ); const resultEntity: DialogEntity = await this.dialogRemoteDTOMapper.toEntity(resultDTO); return Promise.resolve(resultEntity); } catch (e) { return Promise.reject(e); } } async getDialogsFromLocal( pagination?: Pagination, ): Promise> { try { const resultDTO: LocalDialogsDTO = await this.localDataStorage.getDialogs( pagination, ); const entyties: Array = []; // eslint-disable-next-line no-restricted-syntax for (const item of resultDTO.dialogs) { // eslint-disable-next-line no-await-in-loop const entity: DialogEntity = await this.dialogLocalDTOMapper.toEntity( item, ); entyties.push(entity); } return Promise.resolve(entyties); } catch (e) { return Promise.reject(e); } } // eslint-disable-next-line class-methods-use-this async getDialogsFromRemote( pagination?: Pagination, ): Promise> { try { const resultDTO: RemoteDialogsDTO = await this.remoteDataSource.getDialogs(pagination); const entyties: Array = []; // eslint-disable-next-line no-restricted-syntax for (const item of resultDTO.dialogs) { // eslint-disable-next-line no-await-in-loop const entity: DialogEntity = await this.dialogRemoteDTOMapper.toEntity( item, ); entyties.push(entity); } const result: PaginatedResult = { // PaginatedList: DialogsDictionary, ResultData: entyties, CurrentPagination: resultDTO.pagination, }; return Promise.resolve(result); } catch (e) { return Promise.reject(e); } } async deleteDialogFromLocal(dialogId: string): Promise { const dto: LocalDialogDTO = new LocalDialogDTO(); dto.id = dialogId; try { await this.localDataStorage.deleteDialog(dto); return Promise.resolve(true); } catch (e) { console.log('exception in deleteDialogFromLocal: ', stringifyError(e)); return Promise.reject(e); } } // eslint-disable-next-line class-methods-use-this,@typescript-eslint/no-unused-vars async deleteDialogFromRemote(dialogId: string): Promise { const dto: RemoteDialogDTO = new RemoteDialogDTO(); dto.id = dialogId; try { await this.remoteDataSource.deleteDialog(dto); return Promise.resolve(true); } catch (e) { return Promise.reject(e); } } async deleteUsersFromDialogFromRemote( dialogId: string, usersIds: Array, ): Promise { const dialogDTO: RemoteDialogDTO = new RemoteDialogDTO(); dialogDTO.id = dialogId; const arrayUsersDTO: Array = new Array(); try { for (let i = 0; i < usersIds.length; i += 1) { const dto: RemoteUserDTO = new RemoteUserDTO(); dto.id = usersIds[i].toString(); arrayUsersDTO.push(dto); } await this.remoteDataSource.deleteUsersFromDialog( dialogDTO, arrayUsersDTO, ); return Promise.resolve(true); } catch (e) { return Promise.reject(e); } } }