213 lines
5.7 KiB
TypeScript
213 lines
5.7 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { getConvexClient, getAuthenticatedConvexClient, api, isConvexConfigured } from '@/lib/convex/client';
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
/**
|
|
* GET /api/workflows - List all workflows
|
|
* Uses Convex for storage
|
|
*/
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
if (!isConvexConfigured()) {
|
|
return NextResponse.json({
|
|
workflows: [],
|
|
total: 0,
|
|
source: 'none',
|
|
message: 'Convex not configured. Add NEXT_PUBLIC_CONVEX_URL to .env.local',
|
|
});
|
|
}
|
|
|
|
const convex = await getAuthenticatedConvexClient();
|
|
const workflows = await convex.query(api.workflows.listWorkflows, {});
|
|
|
|
return NextResponse.json({
|
|
workflows: workflows.map((w: any) => ({
|
|
id: w.customId || w._id, // Use customId if exists, otherwise Convex ID
|
|
name: w.name,
|
|
description: w.description,
|
|
category: w.category,
|
|
tags: w.tags,
|
|
difficulty: w.difficulty,
|
|
estimatedTime: w.estimatedTime,
|
|
nodes: w.nodes,
|
|
edges: w.edges,
|
|
createdAt: w.createdAt,
|
|
updatedAt: w.updatedAt,
|
|
nodeCount: w.nodes?.length || 0,
|
|
edgeCount: w.edges?.length || 0,
|
|
})),
|
|
total: workflows.length,
|
|
source: 'convex',
|
|
});
|
|
} catch (error) {
|
|
console.error('Error fetching workflows:', error);
|
|
return NextResponse.json(
|
|
{
|
|
error: 'Failed to fetch workflows',
|
|
message: error instanceof Error ? error.message : 'Unknown error',
|
|
},
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* POST /api/workflows - Save a workflow to Convex
|
|
*/
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
let workflow;
|
|
try {
|
|
const body = await request.text();
|
|
if (!body || body.trim() === '') {
|
|
return NextResponse.json(
|
|
{ error: 'Request body is empty' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
workflow = JSON.parse(body);
|
|
} catch (parseError) {
|
|
console.error('JSON parse error:', parseError);
|
|
return NextResponse.json(
|
|
{ error: 'Invalid JSON in request body' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
if (!workflow.id && !workflow.name) {
|
|
return NextResponse.json(
|
|
{ error: 'Workflow must have either id or name' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
if (!isConvexConfigured()) {
|
|
return NextResponse.json({
|
|
success: false,
|
|
message: 'Convex not configured. Add NEXT_PUBLIC_CONVEX_URL to .env.local',
|
|
}, { status: 500 });
|
|
}
|
|
|
|
// Validate workflow has required fields
|
|
if (!workflow.nodes || !Array.isArray(workflow.nodes)) {
|
|
return NextResponse.json(
|
|
{ error: 'Workflow must have a nodes array' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
if (!workflow.edges || !Array.isArray(workflow.edges)) {
|
|
return NextResponse.json(
|
|
{ error: 'Workflow must have an edges array' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
const convex = await getAuthenticatedConvexClient();
|
|
|
|
// Use workflow.id as customId for Convex
|
|
const customId = workflow.id || `workflow_${Date.now()}`;
|
|
|
|
const savedId = await convex.mutation(api.workflows.saveWorkflow, {
|
|
customId,
|
|
name: workflow.name || 'Untitled Workflow',
|
|
description: workflow.description,
|
|
category: workflow.category,
|
|
tags: workflow.tags,
|
|
difficulty: workflow.difficulty,
|
|
estimatedTime: workflow.estimatedTime,
|
|
nodes: workflow.nodes,
|
|
edges: workflow.edges,
|
|
version: workflow.version,
|
|
isTemplate: workflow.isTemplate,
|
|
});
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
workflowId: savedId,
|
|
source: 'convex',
|
|
message: 'Workflow saved successfully',
|
|
});
|
|
} catch (error) {
|
|
console.error('Error saving workflow:', error);
|
|
return NextResponse.json(
|
|
{
|
|
error: 'Failed to save workflow',
|
|
message: error instanceof Error ? error.message : 'Unknown error',
|
|
},
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* DELETE /api/workflows?id=xxx - Delete a workflow from Convex
|
|
*/
|
|
export async function DELETE(request: NextRequest) {
|
|
try {
|
|
const { searchParams } = new URL(request.url);
|
|
const workflowId = searchParams.get('id');
|
|
|
|
if (!workflowId) {
|
|
return NextResponse.json(
|
|
{ error: 'Workflow ID is required' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
if (!isConvexConfigured()) {
|
|
return NextResponse.json({
|
|
success: false,
|
|
message: 'Convex not configured',
|
|
}, { status: 500 });
|
|
}
|
|
|
|
const convex = await getAuthenticatedConvexClient();
|
|
|
|
// Look up workflow by customId first, then try Convex ID
|
|
let workflow = await convex.query(api.workflows.getWorkflowByCustomId, {
|
|
customId: workflowId,
|
|
});
|
|
|
|
// If not found and looks like Convex ID, try direct lookup
|
|
if (!workflow && workflowId.startsWith('j')) {
|
|
try {
|
|
workflow = await convex.query(api.workflows.getWorkflow, {
|
|
id: workflowId as any,
|
|
});
|
|
} catch (e) {
|
|
// Not a valid Convex ID
|
|
}
|
|
}
|
|
|
|
if (!workflow) {
|
|
return NextResponse.json(
|
|
{ error: `Workflow ${workflowId} not found` },
|
|
{ status: 404 }
|
|
);
|
|
}
|
|
|
|
// Delete using Convex ID
|
|
await convex.mutation(api.workflows.deleteWorkflow, {
|
|
id: workflow._id,
|
|
});
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
source: 'convex',
|
|
message: 'Workflow deleted successfully',
|
|
});
|
|
} catch (error) {
|
|
console.error('Error deleting workflow:', error);
|
|
return NextResponse.json(
|
|
{
|
|
error: 'Failed to delete workflow',
|
|
message: error instanceof Error ? error.message : 'Unknown error',
|
|
},
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|
|
|