/** * get-site-config.js * ------------------------------------------------------------ * プリザンターの指定サイトの構成情報(SiteSettings等)を取得し、 * ./siteSettingJsons/ 配下にタイムスタンプ付きJSONとして保存します。 * * 使い方: * node get-site-config.js * node get-site-config.js ./config.json ← 設定ファイルを明示指定する場合 * * 事前準備: * 1. config.example.json を config.json にコピーし、 * BaseUrl / SiteId / ApiKey を実環境の値に書き換えてください。 * SiteId はカンマ区切りで複数指定可能です(例: "480111,438166,96235")。 * 1件のみの場合は従来通り数値(例: 480111)でも構いません。 * 2. Node.js 18以降(組み込みfetchを使用) * * 参照した公式マニュアル: * - 開発者向け機能:API:サイト操作:サイト更新 * https://pleasanter.org/manual/api-site-update * - 開発者向け機能:API:サイト操作:サイト設定の更新(部分追加/更新/削除) * https://pleasanter.org/ja/manual/api-update-sitesettings * * 注意: * プリザンターのバージョンにより get のレスポンス構造 * (SiteSettingsが Response.Site 配下にあるか等)が異なる場合があります。 * 初回実行時はコンソールに出力されるレスポンスのトップレベルキーを確認し、 * 想定通りの構造か確認してください。 * ------------------------------------------------------------ */ const fs = require("fs"); const path = require("path"); const { extractSiteConfig } = require("./extract-site-config"); // config.json の SiteId(数値 / カンマ区切り文字列 / 配列)を // 個々のSiteId文字列の配列に正規化する。 function parseSiteIds(rawSiteId) { const list = Array.isArray(rawSiteId) ? rawSiteId : String(rawSiteId).split(","); return list .map((id) => String(id).trim()) .filter((id) => id.length > 0); } // 1サイト分の取得・保存・抽出処理 async function fetchAndSaveSite(siteId, { BaseUrl, ApiKey, ApiVersion }) { const url = `${BaseUrl.replace(/\/+$/, "")}/api/items/${siteId}/getsite`; const body = { ApiVersion: ApiVersion || "1.1", ApiKey: ApiKey, }; console.log(`[INFO] 取得先: ${url}`); console.log(`[INFO] SiteId: ${siteId}`); let response; try { response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); } catch (err) { console.error("[エラー] リクエスト送信に失敗しました:", err.message); console.error("BaseUrlの疎通・ネットワーク設定を確認してください。"); return false; } const text = await response.text(); if (!response.ok) { console.error(`[エラー] HTTP ${response.status} ${response.statusText}`); console.error(text); return false; } let json; try { json = JSON.parse(text); } catch (err) { console.error("[エラー] レスポンスがJSONとして解析できませんでした。"); console.error(text); return false; } // レスポンス構造の確認用ログ(初回はここを見て構造を把握してください) console.log("[INFO] レスポンス トップレベルキー:", Object.keys(json)); if (json.Response) { console.log("[INFO] Response配下のキー:", Object.keys(json.Response)); } // 保存 const outDir = path.join(__dirname, "siteSettingJsons"); if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true }); const timestamp = new Date() .toISOString() .replace(/[:.]/g, "-"); const outFile = path.join(outDir, `site-${siteId}_${timestamp}.json`); fs.writeFileSync(outFile, JSON.stringify(json, null, 2), "utf-8"); // 常に「最新」ファイルも別名で保持(Claudeへのアップロード用に固定名があると便利) const latestFile = path.join(outDir, `site-${siteId}_latest.json`); fs.writeFileSync(latestFile, JSON.stringify(json, null, 2), "utf-8"); console.log(`[OK] 保存しました: ${outFile}`); console.log(`[OK] 最新版としても保存しました: ${latestFile}`); // 取得と同時に Scripts/Styles/ServerScripts/Processes/ガイドHTML も抽出する console.log("\n[INFO] 続けて設定の個別ファイル抽出を実行します..."); extractSiteConfig(latestFile); return true; } async function main() { const configPath = process.argv[2] || path.join(__dirname, "config.json"); if (!fs.existsSync(configPath)) { console.error(`[エラー] 設定ファイルが見つかりません: ${configPath}`); console.error("config.example.json をコピーして config.json を作成してください。"); process.exit(1); } const config = JSON.parse(fs.readFileSync(configPath, "utf-8")); const { BaseUrl, SiteId, ApiKey, ApiVersion } = config; if (!BaseUrl || !SiteId || !ApiKey) { console.error("[エラー] config.json に BaseUrl / SiteId / ApiKey を設定してください。"); process.exit(1); } const siteIds = parseSiteIds(SiteId); if (siteIds.length === 0) { console.error("[エラー] config.json の SiteId から有効なサイトIDを取得できませんでした。"); process.exit(1); } const multiple = siteIds.length > 1; const results = []; for (const [index, siteId] of siteIds.entries()) { if (multiple) { console.log(`\n==== [${index + 1}/${siteIds.length}] SiteId: ${siteId} ====`); } const ok = await fetchAndSaveSite(siteId, { BaseUrl, ApiKey, ApiVersion }); results.push({ siteId, ok }); } if (multiple) { console.log("\n==== 取得結果まとめ ===="); for (const { siteId, ok } of results) { console.log(` SiteId ${siteId}: ${ok ? "OK" : "失敗"}`); } } console.log("\n次のステップ: latest.jsonをClaudeのチャットにアップロードして仕様書化を依頼するか、"); console.log("configs/site-{SiteId}/ 配下のファイルを直接編集・指示して修正してください。"); if (results.some((r) => !r.ok)) { process.exit(1); } } main();