ken_nogi/ClaudePleasanter/助っ人クラウド/get-site-config.js
Kenichiro NOGI 67cc3da6c8 up
2026-07-13 19:02:04 +09:00

167 lines
6.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* get-site-config.js
* ------------------------------------------------------------
* プリザンターの指定サイトの構成情報SiteSettings等を取得し、
* ./configs/ 配下にタイムスタンプ付き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, "configs");
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();