Files
cruciverba_1/webapp/app/api/crosswords/generate/route.ts

66 lines
1.8 KiB
TypeScript

import { mkdir, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { spawn } from "node:child_process";
import { NextResponse } from "next/server";
const PYTHON = process.env.PYTHON_EXECUTABLE || "python";
const PROJECT_ROOT = join(process.cwd(), "..");
const RUNTIME_DIR = join(process.cwd(), ".runtime-crosswords");
function runPython(requestPayload: unknown): Promise<string> {
return new Promise((resolve, reject) => {
const child = spawn(PYTHON, ["crossword_service.py"], {
cwd: PROJECT_ROOT,
stdio: ["pipe", "pipe", "pipe"],
});
let stdout = "";
let stderr = "";
child.stdout.on("data", (chunk) => {
stdout += chunk.toString();
});
child.stderr.on("data", (chunk) => {
stderr += chunk.toString();
});
child.on("error", (error) => {
reject(error);
});
child.on("close", (code) => {
if (code !== 0) {
reject(new Error(stderr || `Python process exited with code ${code}`));
return;
}
resolve(stdout);
});
child.stdin.write(JSON.stringify(requestPayload));
child.stdin.end();
});
}
export async function POST(request: Request) {
try {
const payload = await request.json();
const stdout = await runPython(payload);
const responsePayload = JSON.parse(stdout);
await mkdir(RUNTIME_DIR, { recursive: true });
const targetPath = join(RUNTIME_DIR, `${responsePayload.crossword_id}.json`);
await writeFile(targetPath, JSON.stringify(responsePayload, null, 2), "utf-8");
return NextResponse.json(responsePayload);
} catch (error) {
return NextResponse.json(
{
status: "error",
message: error instanceof Error ? error.message : "Unknown error",
},
{ status: 500 },
);
}
}