52 lines
1.5 KiB
TypeScript
52 lines
1.5 KiB
TypeScript
|
|
/**
|
||
|
|
* Multi-request CSV sink that listens on 0.0.0.0:8765 and accepts
|
||
|
|
* POST requests, writing each one to the configured path
|
||
|
|
* (overwriting on each call). Stays up across multiple requests.
|
||
|
|
*
|
||
|
|
* Usage:
|
||
|
|
* node scripts/_csv-sink.ts <out-path> [port]
|
||
|
|
*/
|
||
|
|
import { createServer } from "node:http";
|
||
|
|
import { writeFileSync } from "node:fs";
|
||
|
|
|
||
|
|
const OUT_PATH = process.argv[2];
|
||
|
|
const PORT = Number(process.argv[3] ?? 8765);
|
||
|
|
if (!OUT_PATH) {
|
||
|
|
console.error("Usage: tsx _csv-sink.ts <out-path> [port]");
|
||
|
|
process.exit(1);
|
||
|
|
}
|
||
|
|
|
||
|
|
let count = 0;
|
||
|
|
|
||
|
|
const server = createServer((req, res) => {
|
||
|
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
||
|
|
res.setHeader("Access-Control-Allow-Headers", "*");
|
||
|
|
res.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
|
||
|
|
if (req.method === "OPTIONS") {
|
||
|
|
res.writeHead(204);
|
||
|
|
res.end();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (req.method !== "POST") {
|
||
|
|
res.writeHead(405);
|
||
|
|
res.end("POST only");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
const chunks: Buffer[] = [];
|
||
|
|
req.on("data", (c: Buffer) => chunks.push(c));
|
||
|
|
req.on("end", () => {
|
||
|
|
const buf = Buffer.concat(chunks);
|
||
|
|
writeFileSync(OUT_PATH, buf);
|
||
|
|
count++;
|
||
|
|
console.log(`#${count} wrote ${buf.length} bytes to ${OUT_PATH}`);
|
||
|
|
res.writeHead(200, { "content-type": "text/plain" });
|
||
|
|
res.end("ok");
|
||
|
|
// Note: intentionally NOT closing the server — it stays up for
|
||
|
|
// multiple requests.
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
server.listen(PORT, "0.0.0.0", () => {
|
||
|
|
console.log(`csv-sink (persistent) listening on 0.0.0.0:${PORT} → ${OUT_PATH}`);
|
||
|
|
});
|