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>
186 lines
8.0 KiB
JavaScript
186 lines
8.0 KiB
JavaScript
/**
|
||
* resolve-project.js
|
||
* ------------------------------------------------------------
|
||
* 各スクリプトを ClaudePleasanter直下から直接実行する運用に合わせ、
|
||
* 「どのプロジェクト(サイト)フォルダに対して実行するか」「どのサーバー環境
|
||
* (本番/テスト)に対して実行するか」を解決する共通ヘルパー。
|
||
*
|
||
* 使い方(各スクリプトの実行時):
|
||
* node .claude/js/get-site-config.js --project="IC(東京)【引継依頼】" --env=production
|
||
* node .claude/js/get-site-config.js -p IC東京 --env=development
|
||
* (フォルダ名の完全一致が無い場合、部分一致(大文字小文字無視)で1件に絞れれば採用する)
|
||
*
|
||
* --env は production(本番: nextoffice.next-hd.co.jp) / development(テスト: neo999.next-hd.net) /
|
||
* staging(検証: nextoffice2.next-hd.net、2026-08-29追加)のいずれかを必須指定する
|
||
* (誤送信事故防止のためデフォルト値は設けない)。
|
||
* 接続先情報(BaseUrl/ApiKey/ApiVersion)はリポジトリルート直下の
|
||
* config_production.json / config_development.json / config_staging.json に集約されており、
|
||
* loadServerConfig(env) で読み込む。各プロジェクトのSiteIdはプロジェクト直下の
|
||
* siteid.json({"SiteId": "..."}) に置き、loadSiteId(baseDir) で読み込む
|
||
* (旧config.jsonからの移行。config.jsonにはBaseUrl/ApiKeyも同居していたため、
|
||
* 本番/テストのconfigsデータが同一フォルダに混在する事故要因になっていた)。
|
||
*
|
||
* 複数コマンドを同じプロジェクト向けに連続実行する場合は、--project の代わりに
|
||
* 環境変数 PLEASANTER_PROJECT_ROOT にプロジェクトフォルダの絶対パスを設定してもよい
|
||
* (--project指定があればそちらを優先する)。--env も同様に環境変数
|
||
* PLEASANTER_ENV で指定可能(--env指定があればそちらを優先する)。
|
||
* ------------------------------------------------------------
|
||
*/
|
||
|
||
const fs = require("fs");
|
||
const path = require("path");
|
||
|
||
const REPO_ROOT = path.join(__dirname, "..", "..");
|
||
const VALID_ENVS = ["production", "development", "staging"];
|
||
|
||
function listProjectCandidates() {
|
||
return fs.readdirSync(REPO_ROOT).filter((name) => {
|
||
if (name.startsWith(".")) return false;
|
||
const full = path.join(REPO_ROOT, name);
|
||
return fs.statSync(full).isDirectory();
|
||
});
|
||
}
|
||
|
||
// argvから --project=X / --project X / -p X を取り除き、{ value, argv(残り) } を返す
|
||
function extractProjectFlag(argv) {
|
||
const rest = [];
|
||
let value = null;
|
||
for (let i = 0; i < argv.length; i++) {
|
||
const a = argv[i];
|
||
if (a.startsWith("--project=")) {
|
||
value = a.slice("--project=".length);
|
||
} else if (a === "--project" || a === "-p") {
|
||
value = argv[++i];
|
||
} else {
|
||
rest.push(a);
|
||
}
|
||
}
|
||
return { value, argv: rest };
|
||
}
|
||
|
||
// argvから --env=production|development を取り除き、{ value, argv(残り) } を返す
|
||
function extractEnvFlag(argv) {
|
||
const rest = [];
|
||
let value = null;
|
||
for (let i = 0; i < argv.length; i++) {
|
||
const a = argv[i];
|
||
if (a.startsWith("--env=")) {
|
||
value = a.slice("--env=".length);
|
||
} else if (a === "--env") {
|
||
value = argv[++i];
|
||
} else {
|
||
rest.push(a);
|
||
}
|
||
}
|
||
return { value, argv: rest };
|
||
}
|
||
|
||
function printCandidates() {
|
||
console.error("利用可能なプロジェクト:");
|
||
for (const c of listProjectCandidates()) console.error(` - ${c}`);
|
||
}
|
||
|
||
// argv(既定: process.argv.slice(2))からサーバー環境(production/development)を解決する。
|
||
// 未指定・不正値は誤送信事故防止のためエラー終了する(デフォルト値は設けない)。
|
||
// 戻り値: { env: "production"|"development", argv: --env指定を取り除いた残りの引数配列 }
|
||
function resolveEnv(argv) {
|
||
const { value, argv: rest } = extractEnvFlag(argv);
|
||
const env = value || process.env.PLEASANTER_ENV;
|
||
|
||
if (!env) {
|
||
console.error("[エラー] サーバー環境が指定されていません。");
|
||
console.error('使い方: --env=production (本番) / --env=development (テスト) / --env=staging (検証) のいずれかを指定するか、環境変数 PLEASANTER_ENV を設定してください。');
|
||
process.exit(1);
|
||
}
|
||
if (!VALID_ENVS.includes(env)) {
|
||
console.error(`[エラー] 不正な --env 値です: ${env}`);
|
||
console.error(`指定可能な値: ${VALID_ENVS.join(" / ")}`);
|
||
process.exit(1);
|
||
}
|
||
|
||
return { env, argv: rest };
|
||
}
|
||
|
||
// argv(既定: process.argv.slice(2))からプロジェクトフォルダとサーバー環境を解決する。
|
||
// 戻り値: { baseDir: 絶対パス, env: "production"|"development", argv: 残りの引数配列 }
|
||
function resolveProjectRoot(argv = process.argv.slice(2)) {
|
||
const { value, argv: afterProject } = extractProjectFlag(argv);
|
||
const { env, argv: rest } = resolveEnv(afterProject);
|
||
const name = value || process.env.PLEASANTER_PROJECT_ROOT;
|
||
|
||
if (!name) {
|
||
console.error("[エラー] 対象プロジェクトが指定されていません。");
|
||
console.error('使い方: --project="<フォルダ名>" を指定するか、環境変数 PLEASANTER_PROJECT_ROOT にプロジェクトフォルダの絶対パスを設定してください。');
|
||
printCandidates();
|
||
process.exit(1);
|
||
}
|
||
|
||
if (path.isAbsolute(name) && fs.existsSync(name)) return { baseDir: name, env, argv: rest };
|
||
|
||
const direct = path.join(REPO_ROOT, name);
|
||
if (fs.existsSync(direct) && fs.statSync(direct).isDirectory()) return { baseDir: direct, env, argv: rest };
|
||
|
||
const candidates = listProjectCandidates().filter((c) => c.toLowerCase().includes(name.toLowerCase()));
|
||
if (candidates.length === 1) return { baseDir: path.join(REPO_ROOT, candidates[0]), env, argv: rest };
|
||
if (candidates.length > 1) {
|
||
console.error(`[エラー] "${name}" に一致するプロジェクトが複数見つかりました: ${candidates.join(", ")}`);
|
||
console.error("フォルダ名をフルで指定してください。");
|
||
process.exit(1);
|
||
}
|
||
|
||
console.error(`[エラー] プロジェクトフォルダが見つかりません: ${name}`);
|
||
printCandidates();
|
||
process.exit(1);
|
||
}
|
||
|
||
// リポジトリルート直下の config_{env}.json(BaseUrl/ApiKey/ApiVersion。
|
||
// LoginId/Password等はget-page-html.js用の任意項目としてそのまま透過)を読み込む。
|
||
function loadServerConfig(env) {
|
||
if (!VALID_ENVS.includes(env)) {
|
||
console.error(`[エラー] 不正な env 値です: ${env}`);
|
||
process.exit(1);
|
||
}
|
||
const configPath = path.join(REPO_ROOT, `config_${env}.json`);
|
||
if (!fs.existsSync(configPath)) {
|
||
console.error(`[エラー] サーバー接続設定ファイルが見つかりません: ${configPath}`);
|
||
process.exit(1);
|
||
}
|
||
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
||
if (!config.BaseUrl || !config.ApiKey) {
|
||
console.error(`[エラー] ${configPath} に BaseUrl / ApiKey を設定してください。`);
|
||
process.exit(1);
|
||
}
|
||
return config;
|
||
}
|
||
|
||
// プロジェクト直下の siteid.json({"SiteId": "..."}) からSiteIdを読み込む。
|
||
// 旧config.jsonが残っている場合は移行を促すエラーにする。
|
||
function loadSiteId(baseDir) {
|
||
const siteIdPath = path.join(baseDir, "siteid.json");
|
||
if (!fs.existsSync(siteIdPath)) {
|
||
const legacyConfigPath = path.join(baseDir, "config.json");
|
||
if (fs.existsSync(legacyConfigPath)) {
|
||
console.error(`[エラー] ${legacyConfigPath} は廃止されました。siteid.json({"SiteId": "..."}) に移行してください。`);
|
||
} else {
|
||
console.error(`[エラー] siteid.json が見つかりません: ${siteIdPath}`);
|
||
}
|
||
process.exit(1);
|
||
}
|
||
const siteid = JSON.parse(fs.readFileSync(siteIdPath, "utf-8"));
|
||
if (!siteid.SiteId) {
|
||
console.error(`[エラー] ${siteIdPath} に SiteId を設定してください。`);
|
||
process.exit(1);
|
||
}
|
||
return siteid.SiteId;
|
||
}
|
||
|
||
module.exports = {
|
||
resolveProjectRoot,
|
||
resolveEnv,
|
||
loadServerConfig,
|
||
loadSiteId,
|
||
REPO_ROOT,
|
||
VALID_ENVS,
|
||
listProjectCandidates,
|
||
};
|