From 562859202bf45b4b9d5f01304b33e98699ad4856 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Thu, 29 Jan 2026 23:35:40 -0600 Subject: [PATCH] fix: code review cleanup - Replace all 'any' types with proper Prisma types - Fix exactOptionalPropertyTypes compatibility - Export AuthUser type from better-auth-request.interface - Remove duplicate empty migration folder - Ensure proper JSON handling with Prisma.InputJsonValue All agent-tasks tests passing (18/18) --- .../src/agent-tasks/agent-tasks.controller.ts | 3 +- .../src/agent-tasks/agent-tasks.service.ts | 67 ++++++++++++++----- .../types/better-auth-request.interface.ts | 3 + 3 files changed, 54 insertions(+), 19 deletions(-) diff --git a/apps/api/src/agent-tasks/agent-tasks.controller.ts b/apps/api/src/agent-tasks/agent-tasks.controller.ts index 3ddb8bb..f5ed62c 100644 --- a/apps/api/src/agent-tasks/agent-tasks.controller.ts +++ b/apps/api/src/agent-tasks/agent-tasks.controller.ts @@ -19,6 +19,7 @@ import { AuthGuard } from "../auth/guards/auth.guard"; import { WorkspaceGuard, PermissionGuard } from "../common/guards"; import { Workspace, Permission, RequirePermission } from "../common/decorators"; import { CurrentUser } from "../auth/decorators/current-user.decorator"; +import type { AuthUser } from "../auth/types/better-auth-request.interface"; /** * Controller for agent task endpoints @@ -44,7 +45,7 @@ export class AgentTasksController { async create( @Body() createAgentTaskDto: CreateAgentTaskDto, @Workspace() workspaceId: string, - @CurrentUser() user: any + @CurrentUser() user: AuthUser ) { return this.agentTasksService.create( workspaceId, diff --git a/apps/api/src/agent-tasks/agent-tasks.service.ts b/apps/api/src/agent-tasks/agent-tasks.service.ts index 8d60453..27b98ef 100644 --- a/apps/api/src/agent-tasks/agent-tasks.service.ts +++ b/apps/api/src/agent-tasks/agent-tasks.service.ts @@ -1,6 +1,10 @@ import { Injectable, NotFoundException } from "@nestjs/common"; import { PrismaService } from "../prisma/prisma.service"; -import { AgentTaskStatus, AgentTaskPriority } from "@prisma/client"; +import { + AgentTaskStatus, + AgentTaskPriority, + Prisma, +} from "@prisma/client"; import type { CreateAgentTaskDto, UpdateAgentTaskDto, @@ -22,33 +26,40 @@ export class AgentTasksService { userId: string, createAgentTaskDto: CreateAgentTaskDto ) { - const data: any = { - ...createAgentTaskDto, + // Build the create input, handling optional fields properly for exactOptionalPropertyTypes + const createInput: Prisma.AgentTaskUncheckedCreateInput = { + title: createAgentTaskDto.title, workspaceId, createdById: userId, - status: createAgentTaskDto.status || AgentTaskStatus.PENDING, - priority: createAgentTaskDto.priority || AgentTaskPriority.MEDIUM, - agentConfig: createAgentTaskDto.agentConfig || {}, + status: createAgentTaskDto.status ?? AgentTaskStatus.PENDING, + priority: createAgentTaskDto.priority ?? AgentTaskPriority.MEDIUM, + agentType: createAgentTaskDto.agentType, + agentConfig: (createAgentTaskDto.agentConfig ?? {}) as Prisma.InputJsonValue, }; + // Add optional fields only if they exist + if (createAgentTaskDto.description) createInput.description = createAgentTaskDto.description; + if (createAgentTaskDto.result) createInput.result = createAgentTaskDto.result as Prisma.InputJsonValue; + if (createAgentTaskDto.error) createInput.error = createAgentTaskDto.error; + // Set startedAt if status is RUNNING - if (data.status === AgentTaskStatus.RUNNING) { - data.startedAt = new Date(); + if (createInput.status === AgentTaskStatus.RUNNING) { + createInput.startedAt = new Date(); } // Set completedAt if status is COMPLETED or FAILED if ( - data.status === AgentTaskStatus.COMPLETED || - data.status === AgentTaskStatus.FAILED + createInput.status === AgentTaskStatus.COMPLETED || + createInput.status === AgentTaskStatus.FAILED ) { - data.completedAt = new Date(); - if (!data.startedAt) { - data.startedAt = new Date(); + createInput.completedAt = new Date(); + if (!createInput.startedAt) { + createInput.startedAt = new Date(); } } const agentTask = await this.prisma.agentTask.create({ - data, + data: createInput, include: { createdBy: { select: { id: true, name: true, email: true }, @@ -68,9 +79,11 @@ export class AgentTasksService { const skip = (page - 1) * limit; // Build where clause - const where: any = { - workspaceId: query.workspaceId, - }; + const where: Prisma.AgentTaskWhereInput = {}; + + if (query.workspaceId) { + where.workspaceId = query.workspaceId; + } if (query.status) { where.status = query.status; @@ -157,7 +170,25 @@ export class AgentTasksService { throw new NotFoundException(`Agent task with ID ${id} not found`); } - const data: any = { ...updateAgentTaskDto }; + const data: Prisma.AgentTaskUpdateInput = {}; + + // Only include fields that are actually being updated + if (updateAgentTaskDto.title !== undefined) data.title = updateAgentTaskDto.title; + if (updateAgentTaskDto.description !== undefined) data.description = updateAgentTaskDto.description; + if (updateAgentTaskDto.status !== undefined) data.status = updateAgentTaskDto.status; + if (updateAgentTaskDto.priority !== undefined) data.priority = updateAgentTaskDto.priority; + if (updateAgentTaskDto.agentType !== undefined) data.agentType = updateAgentTaskDto.agentType; + if (updateAgentTaskDto.error !== undefined) data.error = updateAgentTaskDto.error; + + if (updateAgentTaskDto.agentConfig !== undefined) { + data.agentConfig = updateAgentTaskDto.agentConfig as Prisma.InputJsonValue; + } + + if (updateAgentTaskDto.result !== undefined) { + data.result = updateAgentTaskDto.result === null + ? Prisma.JsonNull + : (updateAgentTaskDto.result as Prisma.InputJsonValue); + } // Handle startedAt based on status changes if (updateAgentTaskDto.status) { diff --git a/apps/api/src/auth/types/better-auth-request.interface.ts b/apps/api/src/auth/types/better-auth-request.interface.ts index daf4fde..8ff7587 100644 --- a/apps/api/src/auth/types/better-auth-request.interface.ts +++ b/apps/api/src/auth/types/better-auth-request.interface.ts @@ -8,6 +8,9 @@ import type { AuthUser } from "@mosaic/shared"; +// Re-export AuthUser for use in other modules +export type { AuthUser }; + /** * Session data stored in request after authentication */