src/groups/GroupRepository.ts
import {Immutable} from 'immer';
import {Observable, concat, defer, map, scan, tap} from 'rxjs';
import Logs from '../Logs';
import {GroupService} from '../wac-proxy/wac-stack/groups/GroupService';
import {GroupDto} from '../wac-proxy/wac-stack/groups/types';
import {Group} from './Group';
const log = Logs.instance.getLogger('SippoJS/GroupRepository');
function fromGroupDto(data: GroupDto): Group {
return Group.of({
id: data.groupId,
name: data.name,
owner: data.owner.id,
participants: data.participants,
});
}
type Action = Immutable<{
type: 'DELETE';
body: {groupId: string};
} | {
type: 'INIT';
body: GroupDto[];
} | {
type: 'UPDATE';
body: GroupDto;
}>;
const reducer = (state: Group[], action: Action): Group[] => {
switch (action.type) {
case 'INIT':
return action.body.map(datum => fromGroupDto(datum));
case 'DELETE':
return state.filter(group => group.id !== action.body.groupId);
case 'UPDATE':
if (state.findIndex(group => group.id === action.body.groupId) >= 0) {
return state.map(group => group.id === action.body.groupId ? fromGroupDto(action.body) : group);
}
return [...state, fromGroupDto(action.body)];
}
};
/**
* This class allows manager the groups. To obtain an instance of the
* class @link {Session#getGroupRepository} method must be used.
*/
export class GroupRepository {
groups$: Observable<Group[]>;
constructor(
private groupService: GroupService,
) {
this.groups$ = defer(() => this.getActions()).pipe(
tap(x => log.debug('action', x)),
scan(reducer, []),
tap(x => log.debug('state', x)),
);
}
private getActions(): Observable<Action> {
return concat(
this.groupService.fetch().pipe(map((groupDtos): Action =>
({type: 'INIT', body: groupDtos}),
)),
this.groupService.event$.pipe(map((eventDto): Action => {
switch (eventDto.method) {
case 'PUT':
case 'POST':
return {type: 'UPDATE', body: eventDto.body};
case 'DELETE':
return {type: 'DELETE', body: eventDto.body};
}
})),
);
}
/**
* Creates a new group
*/
async createGroup(name: string, participants: string[]): Promise<void> {
await this.groupService.create(name, participants);
}
/**
* Saves a group
*/
async saveGroup(group: Group): Promise<void> {
await this.groupService.update(group.id, group.name, group.participants);
}
/**
* Deletes a group
*/
async deleteGroup(group: Group): Promise<void> {
await this.groupService.delete(group.id);
}
}