/** * adminテナントに「プリザンター」ページツリーを一括構築するスキーム投入スクリプト。 * 参照: ClaudePleasanter/xwiki-doc-upload-scheme.md * * 使い方: * node xwiki-pleasanter-scheme.js --dry-run … PUT先URLとタイトルのみ出力(実際には投げない) * node xwiki-pleasanter-scheme.js --execute … 実際にXWikiへPUTする */ const fs = require("fs"); const path = require("path"); const ENV_PATH = "c:/Users/k.nogi/#GitHub/NodeSrv/apps/xwiki/.env"; function loadEnv(p) { const text = fs.readFileSync(p, "utf8"); const env = {}; for (const line of text.split(/\r?\n/)) { const m = line.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/); if (!m) continue; let v = m[2]; if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) { v = v.slice(1, -1); } env[m[1]] = v; } return env; } const env = loadEnv(ENV_PATH); const BASE_URL = env.XWIKI_BASE_URL; const AUTH = "Basic " + Buffer.from(`${env.XWIKI_ADMIN_USER}:${env.XWIKI_ADMIN_PASSWORD}`).toString("base64"); const WIKI_ID = "admin"; function xmlEscape(s) { return String(s) .replace(/&/g, "&") .replace(//g, ">"); } function buildUrl(spacePath) { const segs = spacePath.map((s) => "spaces/" + encodeURIComponent(s)); return `${BASE_URL}/rest/wikis/${WIKI_ID}/${segs.join("/")}/pages/WebHome`; } async function putPage(spacePath, title, content) { const url = buildUrl(spacePath); const body = ` ${xmlEscape(title)} markdown/1.2 ${xmlEscape(content)} `; const res = await fetch(url, { method: "PUT", headers: { "Content-Type": "application/xml; charset=utf-8", Authorization: AUTH, }, body, }); const text = await res.text(); return { status: res.status, ok: res.status === 201 || res.status === 202, url, text }; } // ------------------------------------------------------------ // ツリー定義 // ------------------------------------------------------------ // spaceName: XWikiスペース名。SiteId_サイト名 の形式(末端以外もこの形式で統一) // repoPath: リポジトリ内の対応パス(あれば)。無ければ null → 未取得と明記 // note: 補足(共有参照など) const REPO_ROOT = "新・稟議申請システム、★マスターシート等は ClaudePleasanter直下の各プロジェクトフォルダ"; function space(siteId, title) { return `${siteId}_${title}`; } // 各ツリーノード: { siteId, title, repoPath, note, children: [...] } const tree63543 = { siteId: 63543, title: "契約コード管理(全社)", repoPath: "★マスターシート/configs/site-63543_契約コード管理(全社)", children: [ { siteId: 61259, title: "契約コード(全社)", repoPath: "★マスターシート/configs/site-61259_契約コード(全社)" }, { siteId: 64583, title: "派生契約コード(全社)", repoPath: "★マスターシート/configs/site-64583_派生契約コード(全社)" }, { siteId: 319014, title: "新・稟議申請", repoPath: "新・稟議申請システム/configs/site-319014_新・稟議申請", children: [ { siteId: 319015, title: "新・稟議申請書", repoPath: "新・稟議申請システム/configs/site-319015_新・稟議申請書" }, { siteId: 319016, title: "【ISO】稟議管理", repoPath: "新・稟議申請システム/configs/site-319016_【ISO】稟議管理" }, { siteId: 319017, title: "【ISO】部署担当者別稟議集計", repoPath: "新・稟議申請システム/configs/site-319017_【ISO】部署担当者別稟議集計" }, { siteId: 319022, title: "【部署別】稟議改善", repoPath: "新・稟議申請システム/configs/site-319022_【部署別】稟議改善" }, { siteId: 319018, title: "マスタ", repoPath: null, note: "ParentId実測で新規判明(旧docsでは63543とは別系統と誤記載されていた)。ローカル未取得。", children: [ { siteId: 319020, title: "稟議項目", repoPath: "新・稟議申請システム/configs/site-319020_稟議項目" }, { siteId: 319021, title: "稟議通知管理", repoPath: "新・稟議申請システム/configs/site-319021_稟議通知管理" }, { siteId: 335730, title: "組織エリアマスタ", repoPath: "新・稟議申請システム/configs/site-335730_組織エリアマスタ" }, { siteId: 319027, title: "事前稟議一覧", repoPath: "新・稟議申請システム/configs/site-319027_事前稟議一覧" }, ], }, ], }, { siteId: 160926, title: "稟議コード管理", repoPath: "新・稟議申請システム/configs/site-160926_稟議コード管理" }, ], }; const tree96230 = { siteId: 96230, title: "【新版】注文住宅MSS", repoPath: null, note: "IC(東京)/MSS回覧板/★マスターシート/事業計画(実績計上)が共有する外部ルート。ローカル未取得。", children: [ { siteId: 373518, title: "IC(東京)【引継依頼】", repoPath: "IC(東京)【引継依頼】/configs/site-373518_IC(東京)【引継依頼】" }, { siteId: 471918, title: "【試作】MSS回覧版", repoPath: "MSS回覧板システム/configs/site-471918_【試作】MSS回覧版", children: [ { siteId: 475431, title: "M", repoPath: "MSS回覧板システム/configs/site-475431_M", children: [ { siteId: 471919, title: "マスタ", repoPath: "MSS回覧板システム/configs/site-471919_マスタ", children: [ { siteId: 475388, title: "図確回覧マスタ", repoPath: "MSS回覧板システム/configs/site-475388_図確回覧マスタ", children: [ { siteId: 471920, title: "図確回覧エリア別担当者", repoPath: "MSS回覧板システム/configs/site-471920_図確回覧エリア別担当者" }, { siteId: 471921, title: "図確回覧テンプレート", repoPath: "MSS回覧板システム/configs/site-471921_図確回覧テンプレート" }, { siteId: 475389, title: "図確回覧共通担当者", repoPath: "MSS回覧板システム/configs/site-475389_図確回覧共通担当者" }, ], }, { siteId: 483434, title: "回覧資料マスタ", repoPath: "MSS回覧板システム/configs/site-483434_回覧資料マスタ" }, { siteId: 492050, title: "四者回覧マスタ", repoPath: "MSS回覧板システム/configs/site-492050_四者回覧マスタ", children: [ { siteId: 492020, title: "四者MTG回覧テンプレート", repoPath: "MSS回覧板システム/configs/site-492020_四者MTG回覧テンプレート" }, { siteId: 492051, title: "四者MTG回覧エリア別担当者", repoPath: "MSS回覧板システム/configs/site-492051_四者MTG回覧エリア別担当者" }, { siteId: 492052, title: "四者MTG回覧共通担当者", repoPath: "MSS回覧板システム/configs/site-492052_四者MTG回覧共通担当者" }, ], }, { siteId: 492182, title: "承認図回覧マスタ", repoPath: "MSS回覧板システム/configs/site-492182_承認図回覧マスタ", children: [ { siteId: 492183, title: "承認図回覧テンプレート", repoPath: "MSS回覧板システム/configs/site-492183_承認図回覧テンプレート" }, { siteId: 492184, title: "承認図回覧エリア別担当者", repoPath: "MSS回覧板システム/configs/site-492184_承認図回覧エリア別担当者" }, { siteId: 492185, title: "承認図回覧共通担当者", repoPath: "MSS回覧板システム/configs/site-492185_承認図回覧共通担当者" }, ], }, ], }, ], }, { siteId: 475384, title: "図確回覧", repoPath: "MSS回覧板システム/configs/site-475384_図確回覧" }, { siteId: 492045, title: "四者MTG回覧", repoPath: "MSS回覧板システム/configs/site-492045_四者MTG回覧" }, { siteId: 492169, title: "承認図回覧", repoPath: "MSS回覧板システム/configs/site-492169_承認図回覧" }, ], }, { siteId: 189112, title: "★マスターシート", repoPath: "★マスターシート/configs/site-189112_★マスターシート", note: "営業積算システムからも参照(neo999環境、実体はここ)" }, { siteId: 116503, title: "★リードタイム算定", repoPath: "★マスターシート/configs/site-116503_★リードタイム算定" }, { siteId: 189113, title: "★粗利益確認書", repoPath: "★マスターシート/configs/site-189113_★粗利益確認書" }, { siteId: 190731, title: "★追加変更工事", repoPath: "★マスターシート/configs/site-190731_★追加変更工事" }, { siteId: 203147, title: "★工期計算表", repoPath: "★マスターシート/configs/site-203147_★工期計算表" }, { siteId: 212512, title: "お客様データファイル", repoPath: "★マスターシート/configs/site-212512_お客様データファイル", note: "MSS回覧板システムのconfigsにも同一SiteIdの取得コピーあり" }, { siteId: 212533, title: "【WF】追加変更申請", repoPath: "★マスターシート/configs/site-212533_【WF】追加変更申請" }, { siteId: 263191, title: "実績計上", repoPath: "★マスターシート/configs/site-263191_実績計上", note: "事業計画のconfigsにも同一SiteIdの取得コピーあり" }, { siteId: 488755, title: "【開発中】★建売マスターシート", repoPath: "★マスターシート/configs/site-488755_【開発中】★建売マスターシート" }, { siteId: 96233, title: "M", repoPath: null, note: "ローカル未取得", children: [ { siteId: 96234, title: "マスターデータ", repoPath: "★マスターシート/configs/site-96234_マスターデータ", note: "営業積算システムのconfigsにも同一SiteIdの取得コピーあり", children: [ { siteId: 109029, title: "施工会社", repoPath: "★マスターシート/configs/site-109029_施工会社" }, { siteId: 109100, title: "ブランド", repoPath: "★マスターシート/configs/site-109100_ブランド", note: "営業積算システムにも同一SiteIdの取得コピーあり" }, { siteId: 109109, title: "ブランド別タイプ", repoPath: "★マスターシート/configs/site-109109_ブランド別タイプ" }, { siteId: 210699, title: "エリア", repoPath: "★マスターシート/configs/site-210699_エリア", note: "営業積算システムにも同一SiteIdの取得コピーあり" }, { siteId: 210707, title: "担当IC", repoPath: "★マスターシート/configs/site-210707_担当IC" }, { siteId: 210711, title: "担当設計", repoPath: "★マスターシート/configs/site-210711_担当設計" }, { siteId: 210712, title: "担当監督", repoPath: "★マスターシート/configs/site-210712_担当監督", note: "営業積算システムにも同一SiteIdの取得コピーあり" }, { siteId: 211715, title: "集客事由", repoPath: "★マスターシート/configs/site-211715_集客事由" }, { siteId: 96235, title: "契約会社", repoPath: "★マスターシート/configs/site-96235_契約会社" }, { siteId: 96243, title: "営業所", repoPath: "★マスターシート/configs/site-96243_営業所", note: "営業積算システムにも同一SiteIdの取得コピーあり" }, ], }, ], }, ], }; const tree214975 = { siteId: 214975, title: "NEXTGROUP経営計画", repoPath: null, note: "ローカル未取得", children: [ { siteId: 214737, title: "事業計画", repoPath: "事業計画/configs/site-214737_事業計画" }, { siteId: 214922, title: "事業計画-集計", repoPath: "事業計画/configs/site-214922_事業計画-集計" }, ], }; const tree426945 = { siteId: 426945, title: "【開発中】新・着工要因管理", repoPath: "新・着工要因システム/configs/site-426945_新・着工要因管理", children: [ { siteId: 480111, title: "新・着工要因(東京)", repoPath: "新・着工要因システム/configs/site-480111_新・着工要因(東京)" }, { siteId: 496626, title: "新・着工要因(東京)v2", repoPath: "新・着工要因システム/configs/site-496626_新・着工要因(東京)v2" }, ], }; const tree320332 = { siteId: 320332, title: "助っ人クラウド", repoPath: "助っ人クラウド/configs/site-collection_spec.md", note: "config.jsonはMSS回覧板システムの値が誤ってコピーされたもの(参考にしない)。実体はsite-collection_spec.md。個別サイトフォルダは一部のみ存在。", children: [ { siteId: 439118, title: "機能要望・改善案", repoPath: null, note: "site-collection_spec.mdに記載あり、個別フォルダ未取得" }, { siteId: 397527, title: "案件情報", repoPath: "助っ人クラウド/configs/site-397527_spec.md" }, { siteId: 397526, title: "物件情報", repoPath: "助っ人クラウド/configs/site-397526_spec.md" }, { siteId: 397528, title: "顧客情報", repoPath: "助っ人クラウド/configs/site-397528_spec.md" }, { siteId: 423099, title: "フォルダ", repoPath: null, note: "旧データ用フォルダ。site-collection_spec.mdに記載あり、個別フォルダ未取得", children: [ { siteId: 320563, title: "顧客情報old", repoPath: null }, { siteId: 320356, title: "物件情報old", repoPath: null }, { siteId: 320562, title: "案件情報old", repoPath: null }, { siteId: 320333, title: "ログ", repoPath: null }, ], }, ], }; const tree74663 = { siteId: 74663, title: "積算問合せ", repoPath: "営業積算システム/configs/site-74663_積算問合せ", children: [ { siteId: 335410, title: "①物件基本情報 Ver0.3", repoPath: "営業積算システム/configs/site-335410_①物件基本情報 Ver0.3" }, { siteId: 335411, title: "②問い合わせ内容管理 Ver0.3", repoPath: "営業積算システム/configs/site-335411_②問い合わせ内容管理 Ver0.3" }, { siteId: 335450, title: "遅延理由テンプレ管理", repoPath: "営業積算システム/configs/site-335450_遅延理由テンプレ管理" }, { siteId: 335603, title: "問い合わせ不要理由テンプレ管理", repoPath: "営業積算システム/configs/site-335603_問い合わせ不要理由テンプレ管理" }, ], }; // ------------------------------------------------------------ // ページ生成 // ------------------------------------------------------------ const pages = []; // { spacePath: [...], title, content } function pageContent({ siteId, title, repoPath, note, baseUrl, hasChildren }) { const lines = []; lines.push(`# ${title}`); lines.push(""); lines.push(`- SiteId: ${siteId}`); if (baseUrl) lines.push(`- Pleasanter環境: ${baseUrl}`); lines.push(`- リポジトリ内パス: ${repoPath ? "\`" + repoPath + "\`" : "未取得(このサイトのローカルJSON/仕様書は未取得)"}`); if (note) lines.push(`- 備考: ${note}`); lines.push(""); if (hasChildren) { lines.push("子サイトは下記ページツリー参照。"); } else { lines.push("仕様書・バックアップ・取得情報mdファイルは未投入。指示があり次第このページ配下にアップロードする。"); } return lines.join("\n"); } function walk(node, spacePath, baseUrl) { const sp = spacePath.concat(space(node.siteId, node.title)); pages.push({ spacePath: sp, title: `${node.title}(SiteId:${node.siteId})`, content: pageContent({ ...node, baseUrl, hasChildren: !!(node.children && node.children.length) }), }); if (node.children) { for (const child of node.children) walk(child, sp, baseUrl); } } // ルート: プリザンター pages.push({ spacePath: ["プリザンター"], title: "プリザンター", content: [ "# プリザンター", "", "プリザンター(Pleasanter)の仕様書・取得情報md・バックアップの保管スキーム。", "環境(ホスト名)別にページを分け、各配下にPleasanterの実サイトツリー構造(親子関係)をそのまま再現している。", "", "## 環境一覧", "- [[nextoffice]] : 本番/検証環境 (nextoffice.next-hd.co.jp)", "- [[nextoffice2]] : 予約(現時点で対応案件なし)", "- [[neo999]] : 開発環境 (neo999.next-hd.net)", "", "各末端サイトページに、Claude Code側リポジトリ(ClaudePleasanter)内の対応パスを記載している。", "仕様書・バックアップの実ファイルは指示があった際に個別ページへアップロードする(本構築ではスキームのみ)。", ].join("\n"), }); pages.push({ spacePath: ["プリザンター", "nextoffice"], title: "nextoffice", content: [ "# nextoffice", "", "- Pleasanterホスト: `https://nextoffice.next-hd.co.jp/pleasanter/`", "- 用途: 本番/検証環境", "", "配下ページはPleasanter上の実サイトツリー(ParentId階層)をそのまま再現したもの。", "スペース名は `SiteId_サイト名` 形式。", ].join("\n"), }); pages.push({ spacePath: ["プリザンター", "nextoffice2"], title: "nextoffice2", content: [ "# nextoffice2", "", "現時点で対応するPleasanter案件なし。将来の環境追加用に予約したページ。", ].join("\n"), }); pages.push({ spacePath: ["プリザンター", "neo999"], title: "neo999", content: [ "# neo999", "", "- Pleasanterホスト: `https://neo999.next-hd.net/pleasanter/`", "- 用途: 開発環境", "", "配下ページはPleasanter上の実サイトツリー(ParentId階層)をそのまま再現したもの。", "スペース名は `SiteId_サイト名` 形式。", ].join("\n"), }); const NEXTOFFICE_BASE = "https://nextoffice.next-hd.co.jp/pleasanter/"; const NEO999_BASE = "https://neo999.next-hd.net/pleasanter/"; for (const root of [tree63543, tree96230, tree214975, tree426945, tree320332]) { walk(root, ["プリザンター", "nextoffice"], NEXTOFFICE_BASE); } walk(tree74663, ["プリザンター", "neo999"], NEO999_BASE); // ------------------------------------------------------------ // 実行 // ------------------------------------------------------------ async function main() { const args = process.argv.slice(2); const dryRun = args.includes("--dry-run") || !args.includes("--execute"); console.log(`[INFO] 総ページ数: ${pages.length}`); console.log(`[INFO] モード: ${dryRun ? "dry-run(投げない)" : "execute(実投入)"}`); console.log(""); let ok = 0, ng = 0; for (const p of pages) { const url = buildUrl(p.spacePath); if (dryRun) { console.log(`[DRY] ${p.spacePath.join(" / ")}`); console.log(` ${url}`); continue; } const result = await putPage(p.spacePath, p.title, p.content); if (result.ok) { ok++; console.log(`[OK ${result.status}] ${p.spacePath.join(" / ")}`); } else { ng++; console.log(`[NG ${result.status}] ${p.spacePath.join(" / ")}`); console.log(` ${result.text.slice(0, 300)}`); } } if (!dryRun) { console.log(""); console.log(`[SUMMARY] OK=${ok} NG=${ng} / TOTAL=${pages.length}`); } } main();