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

196 lines
7.4 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.

/**
* extract-site-config.js
* ------------------------------------------------------------
* 取得済みのサイト構成 (configs/site-{SiteId}_latest.json) から、
* Scripts / Styles / ServerScripts / Processes / ガイドHTML を
* 個別ファイルとして configs/site-{SiteId}/ 配下に書き出します。
*
* 使い方:
* node extract-site-config.js
* node extract-site-config.js ./configs/site-214812_latest.json
*
* 出力:
* configs/site-{SiteId}/
* manifest.json ← 抽出内容の一覧build-desired-config.jsでの再構成に使用
* scripts/{Id}_{Title}.js
* styles/{Id}_{Title}.css
* serverscripts/{Id}_{Title}.js
* html/{GuideName}.html ← GridGuide等、ガイドHTML値が空でないもののみ
* processes.json ← プロセス設定SiteSettings.Processes をそのまま保存)
*
* 注意:
* ガイドHTMLGridGuide等はSiteSettingsではなく、サイトデータ直下の項目です。
* そのため反映時はサイト設定の部分更新updatesitesettingsではなく、
* サイト全体更新updatesite / Mode:"full")が必要になります。
* Scripts/Styles/ServerScripts/Processesは部分更新Mode:"partial")で反映できます。
* 詳しくは build-desired-config.js の実行結果メッセージを参照してください。
* ------------------------------------------------------------
*/
const fs = require("fs");
const path = require("path");
function sanitize(name) {
return (
String(name || "untitled")
.replace(/[\\/:*?"<>|]/g, "_")
.trim()
.slice(0, 60) || "untitled"
);
}
function ensureDir(dir) {
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
}
function extractList(items, outDir, ext, bodyKey = "Body") {
const manifestEntries = [];
if (!items || items.length === 0) return manifestEntries;
ensureDir(outDir);
for (const item of items) {
const fileName = `${item.Id}_${sanitize(item.Title || item.Name)}${ext}`;
fs.writeFileSync(path.join(outDir, fileName), item[bodyKey] || "", "utf-8");
const { [bodyKey]: _omit, ...meta } = item;
manifestEntries.push({ ...meta, File: fileName });
}
return manifestEntries;
}
// config.json の SiteId数値 / カンマ区切り文字列 / 配列)を
// 個々のSiteId文字列の配列に正規化するget-site-config.jsと同仕様
function parseSiteIds(rawSiteId) {
const list = Array.isArray(rawSiteId) ? rawSiteId : String(rawSiteId).split(",");
return list
.map((id) => String(id).trim())
.filter((id) => id.length > 0);
}
const GUIDE_FIELDS = [
"GridGuide",
"EditorGuide",
"CalendarGuide",
"CrosstabGuide",
"GanttGuide",
"BurnDownGuide",
"TimeSeriesGuide",
"AnalyGuide",
"KambanGuide",
"ImageLibGuide",
];
// get-site-config.js からも呼び出せるよう関数化。
// CLI実行時直接 `node extract-site-config.js`)は末尾のブロックが引数解決を行う。
function extractSiteConfig(latestPath) {
const baseDir = __dirname;
if (!fs.existsSync(latestPath)) {
console.error(`[エラー] ファイルが見つかりません: ${latestPath}`);
console.error("先に node get-site-config.js を実行してください。");
process.exit(1);
}
const json = JSON.parse(fs.readFileSync(latestPath, "utf-8"));
const data = json?.Response?.Data;
if (!data) {
console.error("[エラー] Response.Data が見つかりません。getsiteのレスポンス形式を確認してください。");
process.exit(1);
}
const siteId = data.SiteId;
const settings = data.SiteSettings || {};
const dirName = `site-${siteId}_${sanitize(data.Title)}`;
const outRoot = path.join(baseDir, "configs", dirName);
ensureDir(outRoot);
const manifest = {
SiteId: siteId,
Title: data.Title,
ExtractedAt: new Date().toISOString(),
SourceFile: path.relative(baseDir, latestPath).replace(/\\/g, "/"),
};
manifest.Scripts = extractList(settings.Scripts, path.join(outRoot, "scripts"), ".js");
manifest.Styles = extractList(settings.Styles, path.join(outRoot, "styles"), ".css");
manifest.ServerScripts = extractList(settings.ServerScripts, path.join(outRoot, "serverscripts"), ".js");
// ガイドHTMLサイトデータ直下。SiteSettingsではない点に注意
const htmlDir = path.join(outRoot, "html");
const htmlEntries = [];
for (const field of GUIDE_FIELDS) {
const value = data[field];
if (value) {
ensureDir(htmlDir);
const fileName = `${field}.html`;
fs.writeFileSync(path.join(htmlDir, fileName), value, "utf-8");
htmlEntries.push({ Field: field, File: fileName, TopLevel: true });
}
}
manifest.Html = htmlEntries;
// プロセス設定 … 個別分割せず1つの定義ファイルとして保存
fs.writeFileSync(
path.join(outRoot, "processes.json"),
JSON.stringify(settings.Processes || [], null, 2),
"utf-8"
);
manifest.ProcessesFile = "processes.json";
manifest.ProcessesCount = (settings.Processes || []).length;
fs.writeFileSync(path.join(outRoot, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
console.log(`[OK] 抽出完了: ${outRoot}`);
console.log(` Scripts : ${manifest.Scripts.length}`);
console.log(` Styles : ${manifest.Styles.length}`);
console.log(` ServerScripts : ${manifest.ServerScripts.length}`);
console.log(` Html(ガイド) : ${manifest.Html.length}`);
console.log(` Processes : ${manifest.ProcessesCount}件 → processes.json`);
console.log("\n次のステップ: 各ファイルを直接編集するか、Claudeに修正内容を指示してください。");
console.log(`修正後は次のコマンドで反映用JSONを作成できます: node build-desired-config.js ${dirName}`);
return manifest;
}
// CLIとして直接実行された場合のみ、引数からlatestPathを解決して実行する
if (require.main === module) {
const baseDir = __dirname;
const latestPathArg = process.argv[2];
if (latestPathArg) {
extractSiteConfig(latestPathArg);
} else {
const configPath = path.join(baseDir, "config.json");
if (!fs.existsSync(configPath)) {
console.error("[エラー] config.jsonが見つかりません。抽出対象のJSONパスを引数で指定してください。");
process.exit(1);
}
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
const siteIds = parseSiteIds(config.SiteId);
if (siteIds.length === 0) {
console.error("[エラー] config.json の SiteId から有効なサイトIDを取得できませんでした。");
process.exit(1);
}
const missing = [];
for (const siteId of siteIds) {
const latestPath = path.join(baseDir, "configs", `site-${siteId}_latest.json`);
if (!fs.existsSync(latestPath)) {
console.error(`[警告] ファイルが見つかりません(スキップ): ${latestPath}`);
missing.push(siteId);
continue;
}
if (siteIds.length > 1) {
console.log(`\n==== SiteId: ${siteId} ====`);
}
extractSiteConfig(latestPath);
}
if (missing.length > 0) {
console.error(`\n[エラー] 未取得のSiteIdがあります: ${missing.join(", ")}`);
console.error("先に node get-site-config.js を実行してください。");
process.exit(1);
}
}
}
module.exports = { extractSiteConfig };