// 公園データの簡易エディタ(ローカル専用)。 // // 使い方: // node scripts/park-editor.mjs // → 表示された URL(既定 http://localhost:8787/)をブラウザで開く // → 表のセルを直接編集し、「保存」を押すと src/data/kodaira-parks.json を更新 // → 反映確認後、git にコミットする // // 注意: ローカル(127.0.0.1)にのみ公開します。追加パッケージは不要です。 import { createServer } from "node:http"; import { readFile, writeFile } from "node:fs/promises"; import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; const root = join(dirname(fileURLToPath(import.meta.url)), ".."); const DATA = join(root, "src/data/kodaira-parks.json"); const HTML = join(root, "scripts/park-editor.html"); const PORT = Number(process.env.PORT || 8787); function send(res, code, type, body) { res.writeHead(code, { "content-type": type }); res.end(body); } const server = createServer(async (req, res) => { try { const url = (req.url || "").split("?")[0]; if (req.method === "GET" && (url === "/" || url === "/index.html")) { send(res, 200, "text/html; charset=utf-8", await readFile(HTML, "utf-8")); } else if (req.method === "GET" && url === "/api/parks") { send(res, 200, "application/json; charset=utf-8", await readFile(DATA, "utf-8")); } else if (req.method === "POST" && url === "/api/parks") { let body = ""; for await (const chunk of req) body += chunk; const parks = JSON.parse(body); if (!Array.isArray(parks) || parks.length === 0) { throw new Error("データが配列ではありません"); } // 元ファイルと同じコンパクトな1行JSONで保存する(日本語はそのまま)。 await writeFile(DATA, JSON.stringify(parks), "utf-8"); console.log(`保存しました: ${parks.length} 件 → ${DATA}`); send(res, 200, "application/json; charset=utf-8", JSON.stringify({ ok: true, count: parks.length })); } else { send(res, 404, "text/plain; charset=utf-8", "not found"); } } catch (e) { console.error(e); send(res, 500, "text/plain; charset=utf-8", String(e)); } }); server.listen(PORT, "127.0.0.1", () => { console.log(`公園データ編集: http://localhost:${PORT}/ (Ctrl+C で終了)`); });