Browse Source
Scans subdirectories of a given parent path for valid workflow JSON files, returning name, path, node count, and last modified time. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>handoff-20260429-1057
1 changed files with 82 additions and 0 deletions
@ -0,0 +1,82 @@ |
|||
import { NextRequest, NextResponse } from "next/server"; |
|||
import * as fs from "fs/promises"; |
|||
import * as path from "path"; |
|||
import { validateWorkflowPath } from "@/utils/pathValidation"; |
|||
|
|||
interface WorkflowListEntry { |
|||
name: string; |
|||
directoryPath: string; |
|||
nodeCount: number; |
|||
lastModified: number; |
|||
} |
|||
|
|||
export async function GET(request: NextRequest) { |
|||
const parentPath = request.nextUrl.searchParams.get("path"); |
|||
|
|||
if (!parentPath) { |
|||
return NextResponse.json( |
|||
{ success: false, error: "Path parameter required" }, |
|||
{ status: 400 } |
|||
); |
|||
} |
|||
|
|||
const pathValidation = validateWorkflowPath(parentPath); |
|||
if (!pathValidation.valid) { |
|||
return NextResponse.json( |
|||
{ success: false, error: pathValidation.error }, |
|||
{ status: 400 } |
|||
); |
|||
} |
|||
|
|||
try { |
|||
const entries = await fs.readdir(parentPath, { withFileTypes: true }); |
|||
const directories = entries.filter((e) => e.isDirectory()); |
|||
|
|||
const workflows: WorkflowListEntry[] = []; |
|||
|
|||
for (const dir of directories) { |
|||
const dirPath = path.join(parentPath, dir.name); |
|||
try { |
|||
const files = await fs.readdir(dirPath); |
|||
const jsonFiles = files.filter((f) => f.endsWith(".json")); |
|||
|
|||
for (const jsonFile of jsonFiles) { |
|||
try { |
|||
const filePath = path.join(dirPath, jsonFile); |
|||
const content = await fs.readFile(filePath, "utf-8"); |
|||
const parsed = JSON.parse(content); |
|||
|
|||
if (parsed.version && parsed.nodes && parsed.edges) { |
|||
const stat = await fs.stat(filePath); |
|||
workflows.push({ |
|||
name: parsed.name || dir.name, |
|||
directoryPath: dirPath, |
|||
nodeCount: parsed.nodes.length, |
|||
lastModified: stat.mtimeMs, |
|||
}); |
|||
break; // Use first valid workflow file per directory
|
|||
} |
|||
} catch { |
|||
continue; |
|||
} |
|||
} |
|||
} catch { |
|||
// Skip directories we can't read
|
|||
continue; |
|||
} |
|||
} |
|||
|
|||
// Sort by most recently modified first
|
|||
workflows.sort((a, b) => b.lastModified - a.lastModified); |
|||
|
|||
return NextResponse.json({ success: true, workflows }); |
|||
} catch (error) { |
|||
return NextResponse.json( |
|||
{ |
|||
success: false, |
|||
error: error instanceof Error ? error.message : "Failed to list workflows", |
|||
}, |
|||
{ status: 500 } |
|||
); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue