106 lines
3.8 KiB
JavaScript
106 lines
3.8 KiB
JavaScript
/**
|
||
* site-paths.js
|
||
* ------------------------------------------------------------
|
||
* configs/ 配下のフォルダ構成を一箇所で管理する共有ヘルパー。
|
||
*
|
||
* 構成:
|
||
* configs/
|
||
* master/ … ユーザー/組織/グループのマスターデータ(get-master-data.js)
|
||
* site-{SiteId}_{サイト名}/
|
||
* sitesettings/ … getsiteの生JSON(site-{SiteId}_latest.json / _{timestamp}.json)
|
||
* scripts/ styles/ serverscripts/ html/ processes.json / manifest.json
|
||
* … extract-site-config.js による分割済みファイル(従来通り)
|
||
* docs/ … 仕様書(.md)や改善要望プラン等、sitesettings以外の関連ドキュメント
|
||
* modify/{request}/ … 修正依頼ごとに新規作成。変更前後のconfigファイルや差分・結果を保管
|
||
* ------------------------------------------------------------
|
||
*/
|
||
|
||
const fs = require("fs");
|
||
const path = require("path");
|
||
|
||
function sanitize(name) {
|
||
return (
|
||
String(name || "untitled")
|
||
.replace(/[\\/:*?"<>|]/g, "_")
|
||
.trim()
|
||
.slice(0, 60) || "untitled"
|
||
);
|
||
}
|
||
|
||
function ensureDir(dir) {
|
||
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||
return dir;
|
||
}
|
||
|
||
// configs/ 配下から "site-{siteId}_*"(前方一致)または "site-{siteId}"(完全一致)の
|
||
// フォルダを探す。見つからなければ null。
|
||
function findSiteDir(configsDir, siteId) {
|
||
if (!fs.existsSync(configsDir)) return null;
|
||
const bare = `site-${siteId}`;
|
||
const prefix = `site-${siteId}_`;
|
||
|
||
const candidates = fs.readdirSync(configsDir).filter((name) => {
|
||
const full = path.join(configsDir, name);
|
||
return fs.statSync(full).isDirectory() && (name === bare || name.startsWith(prefix));
|
||
});
|
||
|
||
const suffixed = candidates.filter((n) => n !== bare);
|
||
if (suffixed.length >= 1) return path.join(configsDir, suffixed[0]);
|
||
if (candidates.includes(bare)) return path.join(configsDir, bare);
|
||
return null;
|
||
}
|
||
|
||
// 既存フォルダがあればそれを使い、無ければ site-{siteId}_{sanitize(title)} を新規作成する
|
||
function ensureSiteDir(configsDir, siteId, title) {
|
||
const existing = findSiteDir(configsDir, siteId);
|
||
if (existing) return existing;
|
||
const dir = path.join(configsDir, `site-${siteId}_${sanitize(title)}`);
|
||
return ensureDir(dir);
|
||
}
|
||
|
||
function sitesettingsDir(siteDir) {
|
||
return ensureDir(path.join(siteDir, "sitesettings"));
|
||
}
|
||
|
||
function docsDir(siteDir) {
|
||
return ensureDir(path.join(siteDir, "docs"));
|
||
}
|
||
|
||
// 修正依頼用の新規フォルダを作成する(labelを省略した場合はタイムスタンプを使う)
|
||
function newModifyDir(siteDir, label) {
|
||
const name = label || new Date().toISOString().replace(/[:.]/g, "-");
|
||
return ensureDir(path.join(siteDir, "modify", name));
|
||
}
|
||
|
||
// 既存のmodifyフォルダの中で最も新しいもの(フォルダ名の降順ソート)を返す。無ければnull。
|
||
function latestModifyDir(siteDir) {
|
||
const modifyRoot = path.join(siteDir, "modify");
|
||
if (!fs.existsSync(modifyRoot)) return null;
|
||
const dirs = fs
|
||
.readdirSync(modifyRoot)
|
||
.filter((n) => fs.statSync(path.join(modifyRoot, n)).isDirectory())
|
||
.sort();
|
||
if (dirs.length === 0) return null;
|
||
return path.join(modifyRoot, dirs[dirs.length - 1]);
|
||
}
|
||
|
||
// サイトの最新getsiteダンプ(site-{siteId}_latest.json)のパスを返す。
|
||
// フォルダ自体が無い場合は null。
|
||
function latestJsonPath(configsDir, siteId) {
|
||
const siteDir = findSiteDir(configsDir, siteId);
|
||
if (!siteDir) return null;
|
||
return path.join(siteDir, "sitesettings", `site-${siteId}_latest.json`);
|
||
}
|
||
|
||
module.exports = {
|
||
sanitize,
|
||
ensureDir,
|
||
findSiteDir,
|
||
ensureSiteDir,
|
||
sitesettingsDir,
|
||
docsDir,
|
||
newModifyDir,
|
||
latestModifyDir,
|
||
latestJsonPath,
|
||
};
|