Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added public/wasm/tree-sitter-go.wasm
Binary file not shown.
Binary file added public/wasm/tree-sitter-typescript.wasm
Binary file not shown.
8 changes: 6 additions & 2 deletions src/app/[lang]/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { notFound } from "next/navigation";
import { getDictionary } from "@/i18n/dictionaries";
import { isLocale } from "@/i18n/config";
import Header from "@/components/layout/Header";
import CodeTool from "@/components/ui/CodeTool";
import CodeWorkspace from "@/components/ui/CodeWorkspace";

export const metadata: Metadata = {
title: "CodeViz — Editor",
Expand All @@ -21,13 +21,17 @@ export default async function AppPage({
return (
<>
<Header lang={lang} />
<CodeTool
<CodeWorkspace
languageLabel={t.languageLabel}
analyzeLabel={t.analyze}
analyzingLabel={t.analyzing}
inputPlaceholder={t.inputPlaceholder}
diagramPlaceholder={t.diagramPlaceholder}
noFunctions={t.noFunctions}
snippetTab={t.snippetTab}
projectTab={t.projectTab}
uploadFolder={t.uploadFolder}
projectHint={t.projectHint}
/>
</>
);
Expand Down
83 changes: 68 additions & 15 deletions src/app/api/analyze/route.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
import { NextResponse } from "next/server";
import { getAnalyzer, SUPPORTED_LANGUAGES } from "@/lib/analysis/registry";
import type { SourceFile } from "@/lib/analysis/types";

// Needs the Node runtime (reads .wasm from the filesystem), not Edge.
export const runtime = "nodejs";

const MAX_CODE_BYTES = 100_000;
const MAX_TOTAL_BYTES = 2_000_000;
const MAX_FILES = 400;

const EXT: Record<string, string> = {
python: "py",
javascript: "js",
typescript: "ts",
go: "go",
};

function normalizePath(p: string): string {
return p.replace(/\\/g, "/").replace(/^\.\//, "");
}

export async function POST(request: Request) {
let body: unknown;
Expand All @@ -14,23 +27,12 @@ export async function POST(request: Request) {
return NextResponse.json({ error: "JSON inválido" }, { status: 400 });
}

const { code, language } = (body ?? {}) as {
const { code, files, language } = (body ?? {}) as {
code?: unknown;
files?: unknown;
language?: unknown;
};

if (typeof code !== "string" || code.trim() === "") {
return NextResponse.json(
{ error: "El campo 'code' es obligatorio." },
{ status: 400 },
);
}
if (Buffer.byteLength(code, "utf8") > MAX_CODE_BYTES) {
return NextResponse.json(
{ error: `El código excede el límite de ${MAX_CODE_BYTES} bytes.` },
{ status: 413 },
);
}
if (typeof language !== "string") {
return NextResponse.json(
{ error: "El campo 'language' es obligatorio." },
Expand All @@ -48,8 +50,59 @@ export async function POST(request: Request) {
);
}

// Build the file set: either a project (files[]) or a single snippet (code).
let sources: SourceFile[];
if (Array.isArray(files)) {
if (files.length === 0) {
return NextResponse.json(
{ error: "No se encontraron archivos analizables." },
{ status: 400 },
);
}
if (files.length > MAX_FILES) {
return NextResponse.json(
{ error: `Demasiados archivos (máx. ${MAX_FILES}).` },
{ status: 413 },
);
}
const valid = files.every(
(f): f is SourceFile =>
!!f &&
typeof (f as SourceFile).path === "string" &&
typeof (f as SourceFile).content === "string",
);
if (!valid) {
return NextResponse.json(
{ error: "Formato de archivos inválido." },
{ status: 400 },
);
}
sources = (files as SourceFile[]).map((f) => ({
path: normalizePath(f.path),
content: f.content,
}));
} else if (typeof code === "string" && code.trim() !== "") {
sources = [{ path: `snippet.${EXT[language] ?? "txt"}`, content: code }];
} else {
return NextResponse.json(
{ error: "Envía 'code' o 'files'." },
{ status: 400 },
);
}

const totalBytes = sources.reduce(
(sum, f) => sum + Buffer.byteLength(f.content, "utf8"),
0,
);
if (totalBytes > MAX_TOTAL_BYTES) {
return NextResponse.json(
{ error: `El código excede el límite de ${MAX_TOTAL_BYTES} bytes.` },
{ status: 413 },
);
}

try {
const graph = await analyzer.analyze(code);
const graph = await analyzer.analyzeProject(sources);
return NextResponse.json(graph);
} catch (err) {
console.error("Error analyzing code:", err);
Expand Down
128 changes: 0 additions & 128 deletions src/components/ui/CodeTool.tsx

This file was deleted.

Loading
Loading