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>
380 lines
20 KiB
JavaScript
380 lines
20 KiB
JavaScript
/**
|
||
* 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, "<")
|
||
.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 = `<?xml version="1.0" encoding="UTF-8"?>
|
||
<page xmlns="http://www.xwiki.org">
|
||
<title>${xmlEscape(title)}</title>
|
||
<syntax>markdown/1.2</syntax>
|
||
<content>${xmlEscape(content)}</content>
|
||
</page>`;
|
||
|
||
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();
|