feat: プロセスフローチャート生成の土台(サイトフォルダ解決・ChoicesTextパーサー)を追加

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Kenichiro NOGI 2026-08-01 10:42:16 +09:00
parent 67cc3da6c8
commit c3e52961aa
7 changed files with 107 additions and 140 deletions

View File

@ -0,0 +1,76 @@
/**
* generate-process-flowchart.js
* ------------------------------------------------------------
* configs/site-{SiteId}_{サイト名}/processes.json
* siteSettingJsons/site-{SiteId}_latest.jsonStatus列ChoicesTextから
* Mermaid横向きフローチャートStatus遷移図を生成し標準出力へ表示します
*
* このスクリプトはファイル書き込みAPI送信を一切行いません標準出力のみ
* 出力された```mermaid```ブロックは仕様書8. プロセス設定節へ手動で組み込んでください
*
* 使い方:
* node generate-process-flowchart.js site-335411
* フォルダ名は "site-{SiteId}_{サイト名}" 形式だが"site-{SiteId}" だけの
* 前方一致指定でも configs/ 配下から自動的に該当フォルダを探して解決する
* ------------------------------------------------------------
*/
const fs = require("fs");
const path = require("path");
function readJson(p) {
return JSON.parse(fs.readFileSync(p, "utf-8"));
}
// フォルダ名は "site-{SiteId}_{サイト名}" 形式。"site-{SiteId}" のみの指定でも
// configs/ 配下から前方一致で該当フォルダを探して解決する。
// (build-desired-config.js の resolveSiteDir と同一ロジック)
function resolveSiteDir(baseDir, arg) {
const configsDir = path.join(baseDir, "configs");
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);
}
// "値,ラベル,短縮ラベル,色" 形式改行区切りのChoicesTextを 値→ラベル のMapへ変換する
function parseChoicesText(choicesText) {
const map = new Map();
if (!choicesText) return map;
const lines = choicesText.split("\n").filter((line) => line.trim().length > 0);
for (const line of lines) {
const parts = line.split(",");
const value = (parts[0] || "").trim();
if (!value) continue;
const label = (parts[1] || value).trim();
map.set(value, label);
}
return map;
}
module.exports = {
resolveSiteDir,
parseChoicesText,
};

View File

@ -0,0 +1,31 @@
const test = require("node:test");
const assert = require("node:assert/strict");
const path = require("path");
const os = require("os");
const fs = require("fs");
const { parseChoicesText, resolveSiteDir } = require("./generate-process-flowchart");
test("parseChoicesText: 値,ラベル,短縮ラベル,色 形式を 値→ラベル のMapへ変換する", () => {
const input = "100,新規,新規,new-status-white\n450,依頼者質疑中,質疑中,new-status-yellow";
const result = parseChoicesText(input);
assert.equal(result.get("100"), "新規");
assert.equal(result.get("450"), "依頼者質疑中");
assert.equal(result.size, 2);
});
test("parseChoicesText: undefinedやから文字列は空Mapを返す", () => {
assert.equal(parseChoicesText(undefined).size, 0);
assert.equal(parseChoicesText("").size, 0);
});
test("parseChoicesText: ラベル省略時は値をラベルとして使う", () => {
const result = parseChoicesText("999");
assert.equal(result.get("999"), "999");
});
test("resolveSiteDir: site-{id}_{name}形式のフォルダを前方一致で解決する", () => {
const tmpBase = fs.mkdtempSync(path.join(os.tmpdir(), "gpf-test-"));
fs.mkdirSync(path.join(tmpBase, "configs", "site-999_テストサイト"), { recursive: true });
const result = resolveSiteDir(tmpBase, "site-999");
assert.equal(result, path.join(tmpBase, "configs", "site-999_テストサイト"));
});

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtzzwneLOn8XcL
uR/qxOqifCbEEKdF2NH2/mLqa/eGmHIy4nvlKH9O0b0Rt8idACu5o/x4iZoljIQd
YztoxyGKEEy9NfySUYXZt2pECeR4lbqryEK11KAZW5slcmStki+Eval/ccOvxFqj
TgzaJOGpjlExlxPwPxp39sV35T1KzOX+aSg0WlHtioMF6nn1ErNX0tSfjQxFbMQ4
Np+CIgLsYlEbzG7QUcgLi0verAlf9x0r+9v2aeZuPA4InCtFFJJSV2AyQQ2lPVle
Z+SkyUEgqwoDBVUduLHsTCGj88FG9S/YRzFVNRQRojoebYxomJEpfHgwG9+QX544
5mGszzJRAgMBAAECggEAKM9AgMUQq8VgjgZaxeET9XBAmucNG3OIAx4iJAgTL41i
POvcKsdqMtvAsKUOC70DRzyHdlbatGfMimjnBVhCGfxvRDrlkYZmLuMnpo+LDzwa
vyRPc4mXyLRvVmjIVk+9bAWrQ1L3HzEzleXo0xx3Rrw1eLcQFaf/Yzz0Cw1uaX4U
8tJGA7waPHEmY6AW53ibvXaYtPsVqDstfrQyjtOegrJtoJ0wgf+KujojgiB2Rolu
QOCVeffJi6KWcao+yvUndbuhYfuSf3f8kg3/KPOqSRqMYM/8L5vEqA8zOTNjXRHc
6ajjdxQd8R+TD/KnyY0lWDRtbOXfNeGKGYSgbh5vBQKBgQDI4knTTxu2zFlF2gXR
Ta4OYBYIf1gS7Vl4FcABKMUKJ7wgRTgrI6S3/XfDm5rBxJBS6Cuo4VhGID5E9Qbx
2gNq2turq2bxumZRve4WgrbRJzrWq5LGk9bI1LbN/rsIwseDx3qmqajapgEBgHbs
A60EidcJsiwzSoL0xBb0zxTkNQKBgQDdf0oemx5BrqOBk51P7Pitd8RqApbC/sw5
6DLg1B0LS8w2ZwaBhJsdytd3TgtDVvrjdtg5mDxenLSLrdWb0gYHoVsnWtyDa9x9
d6pCilHm8USwE69Hy0TubmIPe5Hol7j/98Oihf0+qT9R54GNAUWnqRyxcdlUAu/h
t1g4fF9hLQKBgDZh/HZ2Phx4qdpdMaH+E5bUsGJQhzlohAYcbURjEySyqR1bX99d
4OPmfJu57mVyn1eyfs9TYiBp7jGg2+ZxjOdKpJmO52mdesG6V1BExtVMd4NSI4Qa
1dS8sViHE39Fq9mjETM5TvsSYcdUTd2LCTXnUw3O7GReUaGNzGEuBovZAoGBALAl
5bUXWWWU1BVdZnLEmzOhFsPT0T+70ICQx72DEqIEIqB1KHhiE9YKlXYcy9o+1wGE
ZwrOpdv8NZ0Lnt/vk7oHuW0/1jRx2ASz4ORQCjhmUWDSFsg6wFP51uRHOk9GMerm
iF+8vRxTDrc9LAsOIu3mEJqRVut39nuECpXJWzT1AoGBAKOeVuHtf9zqlzcauUKU
ymcEIN96+/Jj1lk9dV5o0FDbn+SIeWPOlE8EfrwzfyokrvXRLcR7APdeF9VO1tDK
C4bk6eFQjbXj6SuWOTPu722b/raqGJU6spTECVYFWI1JD2zNsYM08p3qbsFVDPA9
nY4oYnYiafU5v1pGAUjkh9EK
-----END PRIVATE KEY-----

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtzzwneLOn8XcL
uR/qxOqifCbEEKdF2NH2/mLqa/eGmHIy4nvlKH9O0b0Rt8idACu5o/x4iZoljIQd
YztoxyGKEEy9NfySUYXZt2pECeR4lbqryEK11KAZW5slcmStki+Eval/ccOvxFqj
TgzaJOGpjlExlxPwPxp39sV35T1KzOX+aSg0WlHtioMF6nn1ErNX0tSfjQxFbMQ4
Np+CIgLsYlEbzG7QUcgLi0verAlf9x0r+9v2aeZuPA4InCtFFJJSV2AyQQ2lPVle
Z+SkyUEgqwoDBVUduLHsTCGj88FG9S/YRzFVNRQRojoebYxomJEpfHgwG9+QX544
5mGszzJRAgMBAAECggEAKM9AgMUQq8VgjgZaxeET9XBAmucNG3OIAx4iJAgTL41i
POvcKsdqMtvAsKUOC70DRzyHdlbatGfMimjnBVhCGfxvRDrlkYZmLuMnpo+LDzwa
vyRPc4mXyLRvVmjIVk+9bAWrQ1L3HzEzleXo0xx3Rrw1eLcQFaf/Yzz0Cw1uaX4U
8tJGA7waPHEmY6AW53ibvXaYtPsVqDstfrQyjtOegrJtoJ0wgf+KujojgiB2Rolu
QOCVeffJi6KWcao+yvUndbuhYfuSf3f8kg3/KPOqSRqMYM/8L5vEqA8zOTNjXRHc
6ajjdxQd8R+TD/KnyY0lWDRtbOXfNeGKGYSgbh5vBQKBgQDI4knTTxu2zFlF2gXR
Ta4OYBYIf1gS7Vl4FcABKMUKJ7wgRTgrI6S3/XfDm5rBxJBS6Cuo4VhGID5E9Qbx
2gNq2turq2bxumZRve4WgrbRJzrWq5LGk9bI1LbN/rsIwseDx3qmqajapgEBgHbs
A60EidcJsiwzSoL0xBb0zxTkNQKBgQDdf0oemx5BrqOBk51P7Pitd8RqApbC/sw5
6DLg1B0LS8w2ZwaBhJsdytd3TgtDVvrjdtg5mDxenLSLrdWb0gYHoVsnWtyDa9x9
d6pCilHm8USwE69Hy0TubmIPe5Hol7j/98Oihf0+qT9R54GNAUWnqRyxcdlUAu/h
t1g4fF9hLQKBgDZh/HZ2Phx4qdpdMaH+E5bUsGJQhzlohAYcbURjEySyqR1bX99d
4OPmfJu57mVyn1eyfs9TYiBp7jGg2+ZxjOdKpJmO52mdesG6V1BExtVMd4NSI4Qa
1dS8sViHE39Fq9mjETM5TvsSYcdUTd2LCTXnUw3O7GReUaGNzGEuBovZAoGBALAl
5bUXWWWU1BVdZnLEmzOhFsPT0T+70ICQx72DEqIEIqB1KHhiE9YKlXYcy9o+1wGE
ZwrOpdv8NZ0Lnt/vk7oHuW0/1jRx2ASz4ORQCjhmUWDSFsg6wFP51uRHOk9GMerm
iF+8vRxTDrc9LAsOIu3mEJqRVut39nuECpXJWzT1AoGBAKOeVuHtf9zqlzcauUKU
ymcEIN96+/Jj1lk9dV5o0FDbn+SIeWPOlE8EfrwzfyokrvXRLcR7APdeF9VO1tDK
C4bk6eFQjbXj6SuWOTPu722b/raqGJU6spTECVYFWI1JD2zNsYM08p3qbsFVDPA9
nY4oYnYiafU5v1pGAUjkh9EK
-----END PRIVATE KEY-----

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCimBufaDXu3jev
jE9UA249K9z+MMO67Habi8JKjzQwAua/NFWZ6uuPkBHuh71k3HQ1Mo6sATjJORjw
j+Yffl5tijf8WbnKOdaClHXAwXr0D4A2Sg8SPkXfhmwjFg0/7I6OwMKe8qJ989Xv
OqRXQ6qgohhQIIy3x20lIKsumGy61pP/eKPgysDyH/mDW4atrsejd7IBUg0ApTw5
dmIWrf8cqMzkKexQVKolNsoBfjrCJoKUi2bOtGKhqdpix8e/rVMtJ9ToON9Q/65d
SBO9pqA5Wcv5RJVK6NV9uj4z7kVnKybnlbKdMVHwNx/qZRuu0y+tFDYBYudflYEl
dsddkD7pAgMBAAECggEABTdLeuQ+h1nwyox+AVQ12GJcmHlLLNHdUTVH0kQAo4H9
pzMgLuFK1W7EqyoGxkz4hmSyOoGJ3JIHbd+JPUfncsH9H0w9P1KhLMxjRap/Ta6P
SU6RaAoANwDqiFVIBLMLn2KUK8IID/HUp7Qc0GGEQFsgMWEwmncG65VoyxnKh9OB
eDccUiZggIWD9GSL/0QwNZEYtYJhMlYdyikc8pyQXqkGnOOMJxfW+Nl6No0GVzRg
xmOdN60PqMJGsZapiT+r8Ifp5lv6Knlz91rJHHeuvNGh9o+6+FYmzi+dIvLTjABQ
TydtSW5f6C7CrajJInrrylvn8MqjJcuku50l931dHQKBgQDBtwPacWVZutcsQxGc
0swz5GVfE8bKWViLUdHcEVNyYlkjpuyrUpjj+8PFDJ/+szvXPvno0RZ9TIM0BiqZ
/hKkUWi+yb4AJlH9yVq+nbov93Td7umsWEgTr+iZ5wWzEffq8qukQZtdgi0+IzH9
+OO1qbykbQ0mTP0buFaar0qMHQKBgQDW337WkwTDssrMbiSgV5HcPH4VHpWDpkb2
gA2X3M3+uRDOs87wsMd3NxAJkepfoE62KLjCJ1keboQuVq9y0/SK7vZoCyeXgQPy
akC+1hkz30KqF6ovXs0P5Sq+kETmc9x4NCRrQtunghlnUB5ExmCFvUh+h5dH9zF4
n6RcS1GMPQKBgQCAVpsD7xqhfwqtdWXGy1Wkj42llvmd9+GUs8lgjk4FuyipWR71
RkyqxpLmCr45RU/BBCUX3OaUbsuB/Q/eZBi/qnvF4uyxNrIdfHhVTzQaMUzI+E7x
8q8V8/YbeJYrFB13F/0lXp3rLqKAx1qIk4txQJoNKX6LwHf0FIW0B6xQ9QKBgQDM
T/9fMLRbEOrcr+6LuDitXafVlRs97yGSyfgi6oXFK1vb8AVZv/4qUWUidGiTPO8b
LmVf1+JZmWR+W1bArOHeKZKLI/AlkzuZiYa+7v1P4X6WFaJxIIeEEbgvMycQqiJ8
+beXdh8+i+pz3i6p3qdxA6anCW7DszyLIeE7ETMdUQKBgQCvJZW+DIwdIQc9w7jN
h8swEYOM3SEajLfAiBiqUlvAde0BKJGXIsMtGU9ptbfIV0fa/5Ks+Xc8CM0VTyaR
uUpdFgX0Gtxb01fuYEO+lgE8/cxFYiHQwSQqtNQcIh6dQrlUsn1YhvGkQHJn+LRD
asVILYALim44EoNpb9pq2Vt7ew==
-----END PRIVATE KEY-----

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC4y+NNY1b9Xf0J
L3wzZGufiqfZyD62VH+8imzsC5A1D0DE0gvHz28LOYuy99wL0QaHlhl6zeUTV1nb
Bt5SFR86ZQH0X5bSV5T4tPDONs9a5+cCyat/fRJ9pNN0pp5alvi7/cNZWCbTwzzJ
9BudhLCq51mrxgNsbq6D/pO8N+6crnTK0iy1/F4bgbcafDhvVUdwER6KWXcSFjIz
QjnD9RAQ/aFh1TvNrNfdXOXfq+no9O64TrVQ6wc3cYiK1KebM8JOEG+MzbRbAUbt
gU8kDwep9z3G3YkkxaTnvVB7tj3KB5rOBpw5gy80AGrUs2Bq6VpE+sudRGVNqWpB
v5D/gSIJAgMBAAECggEAGNLOnFEpWMyc1nSJ/w9Qw7Qo+wDCp9Ru+kEwA39EJlR/
s1Cx42vSc1QOF4LjDLVN5r27e3sX+AKmX90q1STgNoRmAFEs3eGE8enAZTsInKIF
LqMvhecjqjwPaZ6OLAYWsI4UhTZptM2Hp2tCoGS4JKUCLyhgwlqV18ZFSyXKSEKO
CWwtlkq3xDFEqzvdG2mPSS9ZiMWtK4TeZ0PWloTGsjl/RjXhGpsNIi0tyc9M8qRL
M9Jw6LicNDcW58WSEqtFKVUGl1Fk/sL6Fjcen/WcmHP6VUtomS7WPS28QHV0rkZV
k8wlwEvA9W39lDp/kxXJ96VPYvojn93VhPp21tSn2QKBgQD6kOE2nyxhpkqJcNo8
GhTW+4FHbDuLrc/N1LBbbPtt0f3ctTRdl+BRgLMQJYJi5DNEJUVfVAwEhPLfQbYS
CO25HchEeNfh6EBvCgLHi50VLOgYkdzTZe4eG6PLBBPvdQyT++TuX4YaHejdZIOF
RpZzNY1/We4yurl0b7mVb2Q4VQKBgQC8zdyTjfw6i31DfJLIJGEIDakiCXqckQMt
a4v0hFQMvBBQfw587PcXDd0lekW2XIaGAPPET2IaNoVgBjVmylBkoCjDyu2KNeuM
/TzuavGPcUA1Wko9fDVeLEfGKchWc/MbWNXH1ecevD0Bpb+z5ZqJu2TknavCtKCB
Fjq85yXG5QKBgBt+QCf1KTKBw5X3GwsTNYwtRo8mshXueWm1V7CAccooC3nnLBrE
6mkm/P7djsP5FCL7D/SYzUTFrbyPgkHSVvtD6FCTDeUMzd0hNRLeH9tN9R2VC6zq
d0k4cS16ghF5P2sRbZo2QwmklIOOXtwF1cZIbwE1ReytDmJXS/64nT+NAoGATmis
DzdrJaEiX3GPv8Cj72VE9Va8beMnT6iXUe/WvAcqO1PY33bF0vQ2AEd8RhS85U/l
7IQPONWlpFBPwyWIJ5H/+/f9mGV2MnJE6LrPIQQmZ0HdDRXVUAvRrvFROt4iexv0
hG5H8pK4P0Pnjj1vZX3Gk88LMuwysAlcUXEpViUCgYAEiQmgR5jibRXasbSlPiQb
LbRCYQ7eY3Ci3RBJ1/Wo1glS4VU+yYqz67spcSefkY1equJbMUNVcef0mcawqi5y
towHdFmnfx1vwJudD2IKtopQWdhJWTsIIbwTrT4T1W+1iA6dN4EQYCPp5vdKxx65
371xr7uy3rz2R1Ky1P2Twg==
-----END PRIVATE KEY-----

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDyCeXM/bGWZCri
eqrX1rzN7URB+jysUjnJOyRy1ksTD8GpCPVTXIsEfqIOCoFGN+Ov9YmAEJkVV1il
oQpl6hoB+NhVqbvmKcFKgDNS8zQGS7okNkOJK+kGT9rvYyImymqZewUouRSxxu88
itQX4QuAF/6Zm6jn2X6lN0obgxqmp4boBzI+uX+pUTgSrveu6ZXtW3jvyBZbWcLS
5mdLvC3HpTb0ibH4Kt2qWiuhCgfGxSAi3Jx88FShR38U/HmH3xl9HcsKmr2BYO7r
3YGNRQ/JYeNp/yQHFgMcIPSUzBk5reOpIM7DJTrTG4YXnSvht6t3DmK6E+PdbvsV
OzJWe4+/AgMBAAECggEAAamcE1Hkyo3VQOlVy2tqsEFtIsTiGM7scwY9zwTLeY3g
pyrBa06rQnR6OX13UNupFo1/DHWmD4r3jWpd72rxvcoPS7CsR+hJLxv9U5hfEZyr
N9IgREzHFNIvRKNaLzOxvWx7vGwKXoQ+zXF+A8ykbxSlx46q/4NeHCq/5BDSTzW7
oIfFE80HtWfTYHo+yLdDCEm7H+0OzaI5g/lKFU+3HCvcEUDzLp27X1KlieVdZ8mf
LPkRP4PJXFjyviRBw/UsM7qAp+NQ2HFjEUssDFRvweX140isH6W8fKv+u8Erc2MA
1wERISit6aGOJv+OuKD6x8ZUpNpbB+fbmf3h8SvhGQKBgQD3Ar+pGqI7bGflFINW
sF49wR0IBdSn5/NOd7Ku3hpYHbphejfn5rF11dTgMnvNh58PqRAfk8Xq4E52K8GW
VxhQA1JFPzExjlprQc8WSCZMKcWpelT9KQFT9tAHQP5mbI1e4vUva7n/WxLS5nW7
7RTi6uwtUR6X9vbOVayz68epuQKBgQD62NO/mV33gMESXsa6s6RqJxIiQJIOnUbn
Hc0Ko8Vr9D3qK4w1y5Nhu613GeCb+P8JN/ps2Kd/klrkFd8ZSFErWDiuCx7SggK3
mHsIIRzRpme+xe1nOwtqAkIBd9/4DZp3T6dsaUBZ5/yw+0tscAUG3NKj0ZhiNufq
fO99uP9hNwKBgQCCR7ra8Cc8/FJX6tfS8zbhj2dGgfzFinszmcJupMp0S0mwfAvc
jjpvEhczIK1Xm/5y/hJ49THgTepUPYPfTZSPLxFHYKsLni9mftFAyVEZvrZ4SwNk
eyouJPFXwhnr37k4oK/9EO6LFnf5MIBMXCE2Bf4HcM+YCzPlZB6wzt0CUQKBgQCR
q1y8BSomUqTMMDGjtjKiWnITZf/rcLX9/LZXmWdKG5ng5M0VaFT8CmrfoS1oJh6k
kddhYidS1ADoNzNJkU9hpmez2k1Z3ZoKWAgKXoBH1ySkCnik3Ary0sDV7XEosW2k
H6OQN0bhbvC1LhlMrXid1ZqU+2BMmKnw6ACDt+zF3QKBgQDzjrav/FJuQ/UpdiaH
Xgpumzuthw+ih1mYzvPbe+DGk4vWVikK2dD1HMSAmOv36nYeozO98jIeb3n8VOYq
FtUVPMYAPUs2PqVawzpwKdINoTzaxym88JJASlGOAaa4LLVygbE/Vb59nZKCb3NF
SIjzWhRybR+otfa5MFOAj4D09g==
-----END PRIVATE KEY-----