/** * apply-desired-config-full.js * ------------------------------------------------------------ * この環境では updatesitesettings(部分更新)がHTTP 200を返しても実際には * 反映されないことを確認済みのため(README.md「注意事項」参照)、 * Scripts/Styles/ServerScripts/Processesの反映には常にこちらを使う。 * * build-desired-config.js が生成した desired_config.json の * Scripts/Styles/ServerScripts/Processes を、現在のサイト全体(getsite)に * 上書きマージし、updatesite(全体更新)で送信する。 * Columns/GridColumns/Permissions等、それ以外のSiteSettings・Title等は * 現状のまま一切変更しない。 * * 使い方: * node build-desired-config.js site-{SiteId}_{サイト名} … 先にこちらを実行 * node apply-desired-config-full.js … 差分表示のみ(送信なし) * node apply-desired-config-full.js --execute … 上記に加えて実際に送信する * ------------------------------------------------------------ */ const fs = require("fs"); const path = require("path"); const { findSiteDir, newModifyDir, latestModifyDir } = require("./site-paths"); const baseDir = path.join(__dirname, "..", ".."); const execute = process.argv.includes("--execute"); function loadJson(p) { return JSON.parse(fs.readFileSync(p, "utf-8")); } function maskApiKey(key) { if (!key) return key; return key.length > 8 ? key.slice(0, 4) + "****" + key.slice(-4) : "****"; } function timestamp() { return new Date().toISOString().replace(/[:.]/g, "-"); } function diffList(curList, desList, key) { (curList || []).forEach((c) => { const d = (desList || []).find((x) => x.Id === c.Id); const same = d && JSON.stringify(d) === JSON.stringify(c); console.log(` ${key} Id:${c.Id} (${c.Title || c.Name || ""}) -> 変更${!same}`); }); } const config = loadJson(path.join(baseDir, "config.json")); const desired = loadJson(path.join(baseDir, "desired_config.json")); const SITE_ID = desired.SiteId; const siteDir = findSiteDir(path.join(baseDir, "configs"), SITE_ID); (async () => { console.log("[INFO] 現在のサイト情報を取得しています..."); const getUrl = `${config.BaseUrl.replace(/\/+$/, "")}/api/items/${SITE_ID}/getsite`; const getRes = await fetch(getUrl, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ApiVersion: config.ApiVersion || "1.1", ApiKey: config.ApiKey }), }); const getJson = await getRes.json(); if (getJson.StatusCode !== 200) { console.error("[エラー] getsiteに失敗しました:", JSON.stringify(getJson).slice(0, 500)); process.exit(1); } const data = getJson.Response.Data; console.log(`[OK] 取得しました(現在のVer: ${data.Ver}, UpdatedTime: ${data.UpdatedTime})`); const siteSettings = JSON.parse(JSON.stringify(data.SiteSettings)); console.log("========================================"); console.log(` Scripts/Styles/ServerScripts/Processes 差し替え(updatesite全体更新)${execute ? "(実行)" : "(プレビューのみ)"}`); console.log("========================================"); console.log("--- Scripts ---"); diffList(siteSettings.Scripts, desired.SiteSettings.Scripts, "Script"); console.log("--- Styles ---"); diffList(siteSettings.Styles, desired.SiteSettings.Styles, "Style"); console.log("--- ServerScripts ---"); diffList(siteSettings.ServerScripts, desired.SiteSettings.ServerScripts, "ServerScript"); console.log("他のSiteSettings(Columns/GridColumns等)・Permissions・Title等は一切変更しません。"); siteSettings.Scripts = desired.SiteSettings.Scripts; siteSettings.Styles = desired.SiteSettings.Styles; siteSettings.ServerScripts = desired.SiteSettings.ServerScripts; siteSettings.Processes = desired.SiteSettings.Processes; const body = { ApiVersion: config.ApiVersion || "1.1", ApiKey: config.ApiKey, SiteId: SITE_ID, Title: data.Title, ReferenceType: data.ReferenceType, ParentId: data.ParentId, InheritPermission: data.InheritPermission, Permissions: data.Permissions, SiteSettings: siteSettings, }; const modifyDir = latestModifyDir(siteDir) || newModifyDir(siteDir, "desired-config-full-update"); const ts = timestamp(); const maskedBody = { ...body, ApiKey: maskApiKey(body.ApiKey) }; const previewPath = path.join(modifyDir, `site-${SITE_ID}_full_update_preview_${ts}.json`); fs.writeFileSync(previewPath, JSON.stringify(maskedBody, null, 2), "utf-8"); console.log(`\n[OK] 送信予定内容を保存しました: ${previewPath}`); if (!execute) { console.log("\n[注意] --execute が指定されていないため、送信は行っていません。"); console.log("内容を確認の上、問題なければ次を実行してください: node apply-desired-config-full.js --execute"); process.exit(0); } console.log("\n実際に送信します(updatesite)..."); const url = `${config.BaseUrl.replace(/\/+$/, "")}/api/items/${SITE_ID}/updatesite`; const res = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); const text = await res.text(); const resultOutPath = path.join(modifyDir, `site-${SITE_ID}_full_update_result_${ts}.json`); fs.writeFileSync(resultOutPath, text, "utf-8"); console.log(`HTTP ${res.status} ${res.statusText}`); console.log(`[OK] 応答を保存しました: ${resultOutPath}`); console.log(text); })();