import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { ROLES_REPOSITORY, type CreateRoleInput, type RolesRepository, type UpdateRoleInput } from './roles.repository.js'; interface CreateRoleDto { name?: unknown; description?: unknown; permissionIds?: unknown; } interface UpdateRoleDto { name?: unknown; description?: unknown; status?: unknown; permissionIds?: unknown; } @Injectable() export class RolesService { constructor(@Inject(ROLES_REPOSITORY) private readonly roles: RolesRepository) {} listRoles() { return this.roles.listRoles(); } listPermissions() { return this.roles.listPermissions(); } createRole(body: CreateRoleDto, actorId?: string) { const input: CreateRoleInput = { name: this.requiredString(body.name, 'name').trim(), description: this.optionalString(body.description), permissionIds: this.permissionIds(body.permissionIds), actorId }; return this.roles.createRole(input); } updateRole(roleId: string, body: UpdateRoleDto, actorId?: string) { const input: UpdateRoleInput = { name: body.name === undefined ? undefined : this.requiredString(body.name, 'name').trim(), description: body.description === undefined ? undefined : this.nullableString(body.description), status: body.status === undefined ? undefined : this.status(body.status), permissionIds: body.permissionIds === undefined ? undefined : this.permissionIds(body.permissionIds), actorId }; return this.roles.updateRole(roleId, input); } removeRole(roleId: string, actorId?: string) { return this.roles.softDeleteRole(roleId, actorId); } private requiredString(value: unknown, field: string): string { if (typeof value !== 'string' || value.trim().length === 0) { throw new BadRequestException({ code: 'VALIDATION_ERROR', message: `${field} is required.` }); } return value; } private optionalString(value: unknown): string | undefined { if (value === undefined) { return undefined; } return this.requiredString(value, 'description').trim(); } private nullableString(value: unknown): string | null { if (value === null) { return null; } return this.requiredString(value, 'description').trim(); } private permissionIds(value: unknown): string[] { if (!Array.isArray(value) || !value.every((permissionId) => typeof permissionId === 'string' && permissionId.length > 0)) { throw new BadRequestException({ code: 'PERMISSION_IDS_INVALID', message: 'Permission ids are invalid.' }); } return [...new Set(value as string[])]; } private status(value: unknown): 'ENABLED' | 'DISABLED' { if (value !== 'ENABLED' && value !== 'DISABLED') { throw new BadRequestException({ code: 'STATUS_INVALID', message: 'Status is invalid.' }); } return value; } }