mirror of
https://github.com/simstudioai/sim.git
synced 2026-02-12 07:24:55 -05:00
improvement(routes): type all untyped routes (#1848)
* improvement(routes): type all untyped routes * fix routes, remove unused workspace members route * fix obfuscation of errors behind zod errors * remove extraneous comments
This commit is contained in:
@@ -2,11 +2,32 @@ import { db } from '@sim/db'
|
||||
import { memory } from '@sim/db/schema'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { createLogger } from '@/lib/logs/console/logger'
|
||||
import { generateRequestId } from '@/lib/utils'
|
||||
|
||||
const logger = createLogger('MemoryByIdAPI')
|
||||
|
||||
const memoryQuerySchema = z.object({
|
||||
workflowId: z.string().uuid('Invalid workflow ID format'),
|
||||
})
|
||||
|
||||
const agentMemoryDataSchema = z.object({
|
||||
role: z.enum(['user', 'assistant', 'system'], {
|
||||
errorMap: () => ({ message: 'Role must be user, assistant, or system' }),
|
||||
}),
|
||||
content: z.string().min(1, 'Content is required'),
|
||||
})
|
||||
|
||||
const genericMemoryDataSchema = z.record(z.unknown())
|
||||
|
||||
const memoryPutBodySchema = z.object({
|
||||
data: z.union([agentMemoryDataSchema, genericMemoryDataSchema], {
|
||||
errorMap: () => ({ message: 'Invalid memory data structure' }),
|
||||
}),
|
||||
workflowId: z.string().uuid('Invalid workflow ID format'),
|
||||
})
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
export const runtime = 'nodejs'
|
||||
|
||||
@@ -24,29 +45,36 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
||||
const url = new URL(request.url)
|
||||
const workflowId = url.searchParams.get('workflowId')
|
||||
|
||||
if (!workflowId) {
|
||||
logger.warn(`[${requestId}] Missing required parameter: workflowId`)
|
||||
const validation = memoryQuerySchema.safeParse({ workflowId })
|
||||
|
||||
if (!validation.success) {
|
||||
const errorMessage = validation.error.errors
|
||||
.map((err) => `${err.path.join('.')}: ${err.message}`)
|
||||
.join(', ')
|
||||
logger.warn(`[${requestId}] Validation error: ${errorMessage}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: {
|
||||
message: 'workflowId parameter is required',
|
||||
message: errorMessage,
|
||||
},
|
||||
},
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const { workflowId: validatedWorkflowId } = validation.data
|
||||
|
||||
// Query the database for the memory
|
||||
const memories = await db
|
||||
.select()
|
||||
.from(memory)
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, workflowId)))
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, validatedWorkflowId)))
|
||||
.orderBy(memory.createdAt)
|
||||
.limit(1)
|
||||
|
||||
if (memories.length === 0) {
|
||||
logger.warn(`[${requestId}] Memory not found: ${id} for workflow: ${workflowId}`)
|
||||
logger.warn(`[${requestId}] Memory not found: ${id} for workflow: ${validatedWorkflowId}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
@@ -58,7 +86,9 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
||||
)
|
||||
}
|
||||
|
||||
logger.info(`[${requestId}] Memory retrieved successfully: ${id} for workflow: ${workflowId}`)
|
||||
logger.info(
|
||||
`[${requestId}] Memory retrieved successfully: ${id} for workflow: ${validatedWorkflowId}`
|
||||
)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
@@ -96,28 +126,35 @@ export async function DELETE(
|
||||
const url = new URL(request.url)
|
||||
const workflowId = url.searchParams.get('workflowId')
|
||||
|
||||
if (!workflowId) {
|
||||
logger.warn(`[${requestId}] Missing required parameter: workflowId`)
|
||||
const validation = memoryQuerySchema.safeParse({ workflowId })
|
||||
|
||||
if (!validation.success) {
|
||||
const errorMessage = validation.error.errors
|
||||
.map((err) => `${err.path.join('.')}: ${err.message}`)
|
||||
.join(', ')
|
||||
logger.warn(`[${requestId}] Validation error: ${errorMessage}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: {
|
||||
message: 'workflowId parameter is required',
|
||||
message: errorMessage,
|
||||
},
|
||||
},
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
const { workflowId: validatedWorkflowId } = validation.data
|
||||
|
||||
// Verify memory exists before attempting to delete
|
||||
const existingMemory = await db
|
||||
.select({ id: memory.id })
|
||||
.from(memory)
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, workflowId)))
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, validatedWorkflowId)))
|
||||
.limit(1)
|
||||
|
||||
if (existingMemory.length === 0) {
|
||||
logger.warn(`[${requestId}] Memory not found: ${id} for workflow: ${workflowId}`)
|
||||
logger.warn(`[${requestId}] Memory not found: ${id} for workflow: ${validatedWorkflowId}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
@@ -130,9 +167,13 @@ export async function DELETE(
|
||||
}
|
||||
|
||||
// Hard delete the memory
|
||||
await db.delete(memory).where(and(eq(memory.key, id), eq(memory.workflowId, workflowId)))
|
||||
await db
|
||||
.delete(memory)
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, validatedWorkflowId)))
|
||||
|
||||
logger.info(`[${requestId}] Memory deleted successfully: ${id} for workflow: ${workflowId}`)
|
||||
logger.info(
|
||||
`[${requestId}] Memory deleted successfully: ${id} for workflow: ${validatedWorkflowId}`
|
||||
)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
@@ -163,30 +204,37 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
|
||||
try {
|
||||
logger.info(`[${requestId}] Processing memory update request for ID: ${id}`)
|
||||
|
||||
// Parse request body
|
||||
const body = await request.json()
|
||||
const { data, workflowId } = body
|
||||
let validatedData
|
||||
let validatedWorkflowId
|
||||
try {
|
||||
const body = await request.json()
|
||||
const validation = memoryPutBodySchema.safeParse(body)
|
||||
|
||||
if (!data) {
|
||||
logger.warn(`[${requestId}] Missing required field: data`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: {
|
||||
message: 'Memory data is required',
|
||||
if (!validation.success) {
|
||||
const errorMessage = validation.error.errors
|
||||
.map((err) => `${err.path.join('.')}: ${err.message}`)
|
||||
.join(', ')
|
||||
logger.warn(`[${requestId}] Validation error: ${errorMessage}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: {
|
||||
message: `Invalid request body: ${errorMessage}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
if (!workflowId) {
|
||||
logger.warn(`[${requestId}] Missing required field: workflowId`)
|
||||
validatedData = validation.data.data
|
||||
validatedWorkflowId = validation.data.workflowId
|
||||
} catch (error: any) {
|
||||
logger.warn(`[${requestId}] Failed to parse request body: ${error.message}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: {
|
||||
message: 'workflowId is required',
|
||||
message: 'Invalid JSON in request body',
|
||||
},
|
||||
},
|
||||
{ status: 400 }
|
||||
@@ -197,11 +245,11 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
|
||||
const existingMemories = await db
|
||||
.select()
|
||||
.from(memory)
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, workflowId)))
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, validatedWorkflowId)))
|
||||
.limit(1)
|
||||
|
||||
if (existingMemories.length === 0) {
|
||||
logger.warn(`[${requestId}] Memory not found: ${id} for workflow: ${workflowId}`)
|
||||
logger.warn(`[${requestId}] Memory not found: ${id} for workflow: ${validatedWorkflowId}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
@@ -215,28 +263,19 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
|
||||
|
||||
const existingMemory = existingMemories[0]
|
||||
|
||||
// Validate memory data based on the existing memory type
|
||||
// Additional validation for agent memory type
|
||||
if (existingMemory.type === 'agent') {
|
||||
if (!data.role || !data.content) {
|
||||
logger.warn(`[${requestId}] Missing agent memory fields`)
|
||||
const agentValidation = agentMemoryDataSchema.safeParse(validatedData)
|
||||
if (!agentValidation.success) {
|
||||
const errorMessage = agentValidation.error.errors
|
||||
.map((err) => `${err.path.join('.')}: ${err.message}`)
|
||||
.join(', ')
|
||||
logger.warn(`[${requestId}] Agent memory validation error: ${errorMessage}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: {
|
||||
message: 'Agent memory requires role and content',
|
||||
},
|
||||
},
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
if (!['user', 'assistant', 'system'].includes(data.role)) {
|
||||
logger.warn(`[${requestId}] Invalid agent role: ${data.role}`)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: {
|
||||
message: 'Agent role must be user, assistant, or system',
|
||||
message: `Invalid agent memory data: ${errorMessage}`,
|
||||
},
|
||||
},
|
||||
{ status: 400 }
|
||||
@@ -245,16 +284,20 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
|
||||
}
|
||||
|
||||
// Update the memory with new data
|
||||
await db.delete(memory).where(and(eq(memory.key, id), eq(memory.workflowId, workflowId)))
|
||||
await db
|
||||
.delete(memory)
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, validatedWorkflowId)))
|
||||
|
||||
// Fetch the updated memory
|
||||
const updatedMemories = await db
|
||||
.select()
|
||||
.from(memory)
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, workflowId)))
|
||||
.where(and(eq(memory.key, id), eq(memory.workflowId, validatedWorkflowId)))
|
||||
.limit(1)
|
||||
|
||||
logger.info(`[${requestId}] Memory updated successfully: ${id} for workflow: ${workflowId}`)
|
||||
logger.info(
|
||||
`[${requestId}] Memory updated successfully: ${id} for workflow: ${validatedWorkflowId}`
|
||||
)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
|
||||
Reference in New Issue
Block a user