import * as repository from "@apihub24/repository"; import { Inject, Injectable } from "@nestjs/common"; import { IAccount } from "../contracts/models/account"; import { IGroup } from "../contracts/models/group"; @Injectable() export class AccountService { constructor( @Inject("@apihub24/account_repository") private readonly accountRepository: repository.IRepository, @Inject("@apihub24/group_repository") private readonly groupRepository: repository.IRepository ) {} /** * This asynchronous method retrieves accounts that match a given filter. * @param filter A function that takes an `IAccount` object and returns a boolean. It serves as the condition for selecting accounts. * @returns A Promise that resolves to an array of `IAccount` objects that satisfy the filter condition. */ async getBy(filter: (account: IAccount) => boolean): Promise { return await this.accountRepository.getBy(filter); } /** * This asynchronous method saves a single `IAccount` object. It uses the `accountRepository` to persist the account. If the save operation fails, it logs a warning and returns null. * @param account The `IAccount` object to be saved. * @returns A Promise that resolves to the saved `IAccount` object, or `null` if the save operation fails. */ async save(account: IAccount): Promise { try { const accounts = await this.accountRepository.save([account]); return accounts?.length ? accounts[0] : null; } catch (err) { console.warn(err); return null; } } /** * This asynchronous method deletes accounts based on a provided filter. * @param filter A function that takes an `IAccount` object and returns a boolean. It specifies which accounts to delete. * @returns A Promise that resolves to `true` if the deletion is successful, and `false` otherwise. */ async delete(filter: (account: IAccount) => boolean): Promise { return await this.accountRepository.deleteBy(filter); } /** * This asynchronous method adds a specific account to a group. It first finds both the account and the group using their IDs. If they are found, it adds the group to the account's groups array and saves the updated account. * @param accountId The unique identifier of the account. * @param groupId The unique identifier of the group to which the account should be added. * @returns A Promise that resolves to the updated `IAccount` object. * @throws An error if the account or the group cannot be found, or if the updated account cannot be saved. */ async addAccountToGroup( accountId: string, groupId: string ): Promise { const [account, group] = await this.getAccountAndGroup(accountId, groupId); account.groups = account.groups.filter((x) => x.id !== groupId); account.groups.push(group); const accountsSaved = await this.accountRepository.save([account]); if (!accountsSaved.length) { throw new Error(`account ${account.accountName} can not be saved`); } return accountsSaved[0]; } /** * This asynchronous method removes a specific account from a group. It first finds the account and group, then filters the group out of the account's groups array before saving the updated account. * @param accountId The unique identifier of the account. * @param groupId The unique identifier of the group to be removed. * @returns A Promise that resolves to the updated `IAccount` object. * @throws An error if the account or the group cannot be found, or if the updated account cannot be saved. */ async removeAccountFromGroup( accountId: string, groupId: string ): Promise { const [account] = await this.getAccountAndGroup(accountId, groupId); account.groups = account.groups.filter((x) => x.id !== groupId); const accountsSaved = await this.accountRepository.save([account]); if (!accountsSaved.length) { throw new Error(`account ${account.accountName} can not be saved`); } return accountsSaved[0]; } private async getAccountAndGroup( accountId: string, groupId: string ): Promise<[IAccount, IGroup]> { const accounts = await this.accountRepository.getBy( (x) => x.id === accountId ); if (!accounts.length) { throw new Error(`account with id ${accountId} not found`); } const groups = await this.groupRepository.getBy((x) => x.id === groupId); if (!groups.length) { throw new Error(`group with id ${groupId} not found`); } return [accounts[0], groups[0]]; } }