87 lines
2.3 KiB
TypeScript

import type { Low } from 'lowdb';
import { nanoid } from 'nanoid';
import { type New, type Updated } from '../../types';
import { type Group, type GroupError, GroupErrors } from '../../types/group';
import type { IGroupRepo } from '../groupRepo';
import type { LowStorage } from './_init';
export class LowGroupRepo implements IGroupRepo {
private readonly db;
constructor(db: Low<LowStorage.LowData>) {
this.db = db;
}
async getAll(): Promise<Group[]> {
return this.db.data.groups;
}
async getById(id: string): Promise<Group | undefined> {
return this.db.data.groups.find((g) => g.id === id);
}
async create(group: New<Group>): Promise<GroupError | undefined> {
if (this.db.data.groups.find((g) => g.name === group.name)) {
return GroupErrors.DUPLICATE_NAME;
}
for (const deviceId of group.devices) {
if (!this.db.data.devices.some((d) => d.id === deviceId)) {
return GroupErrors.UNKNOWN_DEVICE;
}
}
await this.db.update(({ groups }) => {
groups.push({ id: nanoid(), ...group });
});
return undefined;
}
async update(group: Updated<Group>): Promise<GroupError | undefined> {
if (this.db.data.groups.find((g) => g.name === group.name && g.id !== group.id)) {
return GroupErrors.DUPLICATE_NAME;
}
for (const deviceId of group.devices ?? []) {
if (!this.db.data.devices.some((d) => d.id === deviceId)) {
return GroupErrors.UNKNOWN_DEVICE;
}
}
let found = false;
await this.db.update(({ groups }) => {
const existingGroup = groups.find((g) => g.id === group.id);
if (!existingGroup) return;
Object.assign(existingGroup, group);
found = true;
});
return found ? undefined : GroupErrors.NOT_FOUND;
}
async delete(groupId: string): Promise<GroupError | undefined> {
let found = false;
this.db.data.groups = this.db.data.groups.filter((g) => {
if (g.id === groupId) {
found = true;
return false;
}
return true;
});
if (found) {
this.db.data.users.forEach((u) => (u.groups = u.groups.filter((gid) => gid != groupId)));
await this.db.write();
}
return found ? undefined : GroupErrors.NOT_FOUND;
}
async countUsers(groupId: string): Promise<number> {
return this.db.data.users.filter((u) => u.groups.includes(groupId)).length;
}
}