feat: full studio build -- light theme, canvas thumbnails, i18n (fa/en)
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Standalone render worker — run: npm run render-worker
|
||||
* POST /process { jobId } — requires RENDER_WORKER_SECRET if set
|
||||
*/
|
||||
import http from "node:http";
|
||||
|
||||
import { processRenderJob } from "./render-job-processor";
|
||||
|
||||
const PORT = Number(process.env.RENDER_WORKER_PORT ?? 3355);
|
||||
const SECRET = process.env.RENDER_WORKER_SECRET;
|
||||
|
||||
function isAuthorized(request: http.IncomingMessage): boolean {
|
||||
if (!SECRET) return true;
|
||||
const header = request.headers.authorization;
|
||||
return header === `Bearer ${SECRET}`;
|
||||
}
|
||||
|
||||
function readBody(request: http.IncomingMessage): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const chunks: Buffer[] = [];
|
||||
request.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
||||
request.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
||||
request.on("error", reject);
|
||||
});
|
||||
}
|
||||
|
||||
const server = http.createServer(async (request, response) => {
|
||||
const url = request.url ?? "/";
|
||||
|
||||
if (request.method === "GET" && url === "/health") {
|
||||
response.writeHead(200, { "Content-Type": "application/json" });
|
||||
response.end(JSON.stringify({ ok: true }));
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.method === "POST" && url === "/process") {
|
||||
if (!isAuthorized(request)) {
|
||||
response.writeHead(401, { "Content-Type": "application/json" });
|
||||
response.end(JSON.stringify({ error: "Unauthorized" }));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const body = JSON.parse(await readBody(request)) as { jobId?: string };
|
||||
if (!body.jobId) {
|
||||
response.writeHead(400, { "Content-Type": "application/json" });
|
||||
response.end(JSON.stringify({ error: "jobId required" }));
|
||||
return;
|
||||
}
|
||||
|
||||
response.writeHead(202, { "Content-Type": "application/json" });
|
||||
response.end(JSON.stringify({ accepted: true, jobId: body.jobId }));
|
||||
|
||||
void processRenderJob(body.jobId).catch((err) => {
|
||||
console.error(`Render job ${body.jobId} failed:`, err);
|
||||
});
|
||||
} catch {
|
||||
response.writeHead(400, { "Content-Type": "application/json" });
|
||||
response.end(JSON.stringify({ error: "Invalid JSON" }));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
response.writeHead(404, { "Content-Type": "application/json" });
|
||||
response.end(JSON.stringify({ error: "Not found" }));
|
||||
});
|
||||
|
||||
server.listen(PORT, () => {
|
||||
console.log(`Render worker listening on http://localhost:${PORT}`);
|
||||
console.log("Endpoints: GET /health, POST /process");
|
||||
});
|
||||
Reference in New Issue
Block a user