/** * build-desired-config.js * ------------------------------------------------------------ * extract-site-config.js で分割した configs/site-{SiteId}/ 配下のファイル * (scripts/*.js, styles/*.css, serverscripts/*.js, processes.json)を * manifest.json を手がかりに再構成し、apply-site-config.js が読み込む * desired_config.json を生成します。 * * ★★★ このスクリプトもAPIへは一切送信しません(ファイル生成のみ)。★★★ * 反映は既存の運用どおり、 * 1. node apply-site-config.js でドライラン確認(差分・送信Body・curl表示) * 2. 内容を確認し、問題なければ表示されたcurlコマンドを手動実行 * の流れに乗せてください。 * * 使い方: * node build-desired-config.js site-214812 * (フォルダ名は "site-{SiteId}_{サイト名}" 形式だが、"site-{SiteId}" だけの * 前方一致指定でも configs/ 配下から自動的に該当フォルダを探して解決する) * node build-desired-config.js ./configs/site-214812_物件基本情報 * * 出力: desired_config.json(このスクリプトと同じ階層。既存ファイルは上書き) * * 対応範囲: * Scripts / Styles / ServerScripts / Processes * → Mode:"partial"(updatesitesettings)で反映可能なため、そのまま組み込みます。 * Html(GridGuide等のガイド) * → SiteSettingsではなくサイトデータ直下の項目のため、 * 部分更新(updatesitesettings)には含められません。 * 反映したい場合は Mode:"full"(updatesite)用の別JSONを用意し、 * Title/ReferenceType等の必須項目とあわせて指定してください。 * このスクリプトはhtml/配下に抽出物がある場合、警告のみ表示します。 * ------------------------------------------------------------ */ const fs = require("fs"); const path = require("path"); function readJson(p) { return JSON.parse(fs.readFileSync(p, "utf-8")); } // フォルダ名は "site-{SiteId}_{サイト名}" 形式。"site-{SiteId}" のみの指定でも // configs/ 配下から前方一致で該当フォルダを探して解決する。 // 新形式(サイト名付き)を優先し、裸の "site-{SiteId}" 完全一致(リネーム前の古い抽出結果の可能性)は // 他に候補が無い場合のみ後方互換フォールバックとして使う。 function resolveSiteDir(baseDir, arg) { const configsDir = path.join(baseDir, "configs"); const direct = path.isAbsolute(arg) ? arg : path.join(configsDir, path.basename(arg)); const baseName = path.basename(arg); const candidates = fs.existsSync(configsDir) ? fs.readdirSync(configsDir).filter((name) => { const full = path.join(configsDir, name); return ( fs.statSync(full).isDirectory() && (name === baseName || name.startsWith(`${baseName}_`)) ); }) : []; const suffixed = candidates.filter((name) => name !== baseName); if (suffixed.length === 1) return path.join(configsDir, suffixed[0]); if (suffixed.length > 1) { console.error(`[エラー] "${baseName}" に一致するフォルダが複数見つかりました: ${suffixed.join(", ")}`); console.error("フォルダ名をフルで指定してください。"); process.exit(1); } if (candidates.includes(baseName)) return path.join(configsDir, baseName); if (fs.existsSync(direct) && fs.statSync(direct).isDirectory()) return direct; console.error(`[エラー] フォルダが見つかりません: ${direct}`); console.error("先に node extract-site-config.js(またはnode get-site-config.js)を実行してください。"); process.exit(1); } function rebuildList(manifestEntries, dir, bodyKey = "Body") { return (manifestEntries || []).map((entry) => { const { File, ...meta } = entry; const filePath = path.join(dir, File); if (!fs.existsSync(filePath)) { console.error(`[エラー] manifest.jsonに記載のファイルが見つかりません: ${filePath}`); process.exit(1); } const body = fs.readFileSync(filePath, "utf-8"); return { ...meta, [bodyKey]: body }; }); } function main() { const baseDir = path.join(__dirname, "..", ".."); const arg = process.argv[2]; if (!arg) { console.error("[エラー] 対象フォルダを指定してください(例: node build-desired-config.js site-214812)"); process.exit(1); } const siteDir = resolveSiteDir(baseDir, arg); const manifestPath = path.join(siteDir, "manifest.json"); if (!fs.existsSync(manifestPath)) { console.error(`[エラー] manifest.jsonが見つかりません: ${manifestPath}`); console.error("先に node extract-site-config.js を実行してください。"); process.exit(1); } const manifest = readJson(manifestPath); const siteSettings = {}; siteSettings.Scripts = rebuildList(manifest.Scripts, path.join(siteDir, "scripts")); siteSettings.Styles = rebuildList(manifest.Styles, path.join(siteDir, "styles")); siteSettings.ServerScripts = rebuildList(manifest.ServerScripts, path.join(siteDir, "serverscripts")); const processesPath = path.join(siteDir, manifest.ProcessesFile || "processes.json"); siteSettings.Processes = fs.existsSync(processesPath) ? readJson(processesPath) : []; const desired = { Mode: "partial", SiteId: manifest.SiteId, SiteSettings: siteSettings, }; const outPath = path.join(baseDir, "desired_config.json"); fs.writeFileSync(outPath, JSON.stringify(desired, null, 2), "utf-8"); console.log(`[OK] 生成しました: ${outPath}`); console.log(` Scripts : ${siteSettings.Scripts.length}件`); console.log(` Styles : ${siteSettings.Styles.length}件`); console.log(` ServerScripts : ${siteSettings.ServerScripts.length}件`); console.log(` Processes : ${siteSettings.Processes.length}件`); if (manifest.Html && manifest.Html.length > 0) { console.log("\n[注意] html/ 配下のガイドHTMLは、この desired_config.json には含まれていません。"); console.log(" GridGuide等はSiteSettingsではなくサイト直下の項目のため、部分更新(updatesitesettings)では送れません。"); console.log(' 反映するには Mode:"full"(updatesite)用の別JSONを用意し、Title等の必須項目とあわせて指定してください。'); } console.log("\n次のステップ: node apply-site-config.js でドライラン確認 → 内容確認の上、表示されたcurlコマンドを手動実行してください。"); } main();