ken_nogi/Pleasanter/.claude/js/build-desired-config.js
Kenichiro NOGI ce58cb4be4 初回コミット: dev配下(NodeSrv/Pleasanter等)をGitea管理下に統合
GitHub(nextgroup2706/ken_nogi)は今後使わず自社Gitea運用に切替え。
NodeSrvは旧リポジトリの履歴を破棄しファイルのみ統合(Dokploy用サービスアカウントは
別途mygit-admin/NodeSrv.gitに履歴あり)。notepmエクスポート(12GB)とPleasanter
インストーラzip(208MB)はサイズが大きいため.gitignoreで除外。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-04 15:37:06 +09:00

143 lines
6.9 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.

/**
* 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 を生成します。
* ClaudePleasanter直下に置く共通実装。全プロジェクトの薄いラッパーから require される。
* 抽出先の構成はlayoutによらず共通のため、このスクリプト自体はlayout非依存。
*
* ★★★ このスクリプトも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で反映可能なため、そのまま組み込みます。
* HtmlGridGuide等のガイド
* → SiteSettingsではなくサイトデータ直下の項目のため、
* 部分更新updatesitesettingsには含められません。
* 反映したい場合は Mode:"full"updatesite用の別JSONを用意し、
* Title/ReferenceType等の必須項目とあわせて指定してください。
* このスクリプトはhtml/配下に抽出物がある場合、警告のみ表示します。
* ------------------------------------------------------------
*/
const fs = require("fs");
const path = require("path");
const { resolveProjectRoot } = require("./resolve-project");
function readJson(p) {
return JSON.parse(fs.readFileSync(p, "utf-8"));
}
// フォルダ名は "site-{SiteId}_{サイト名}" 形式。"site-{SiteId}" のみの指定でも
// configs/ 配下から前方一致で該当フォルダを探して解決する。
// 新形式(サイト名付き)を優先し、裸の "site-{SiteId}" 完全一致(リネーム前の古い抽出結果の可能性)は
// 他に候補が無い場合のみ後方互換フォールバックとして使う。
function resolveSiteDir(baseDir, arg, env) {
const configsDir = path.join(baseDir, "configs", env);
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, env, argv } = resolveProjectRoot();
const arg = argv[0];
if (!arg) {
console.error("[エラー] 対象フォルダを指定してください(例: node build-desired-config.js site-214812 --env=production");
process.exit(1);
}
const siteDir = resolveSiteDir(baseDir, arg, env);
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.Guide && manifest.Guide.length > 0) {
console.log("\n[注意] guide/ 配下のガイドは、この 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();