feat(tools): setup-links 批量重建 framework junction

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 12:10:19 +08:00
co-authored by Claude Opus 4.8
parent 5ef65c0d05
commit 9a0a7f60c1
2 changed files with 66 additions and 0 deletions
@@ -0,0 +1,30 @@
#!/usr/bin/env node
import { join } from 'node:path';
import { mkdirSync, existsSync } from 'node:fs';
import { pathToFileURL } from 'node:url';
import { GAMES_DIR, FRAMEWORK_SRC, listGameProjects } from './lib/paths.mjs';
import { ensureJunction } from './lib/junction.mjs';
// 为 gamesDir 下每个工程在 assets/framework 建指向 frameworkSrc 的 junction
export function setupLinks(gamesDir, frameworkSrc) {
const results = [];
for (const proj of listGameProjects(gamesDir)) {
const assetsDir = join(proj, 'assets');
if (!existsSync(assetsDir)) mkdirSync(assetsDir, { recursive: true });
const link = join(assetsDir, 'framework');
const status = ensureJunction(link, frameworkSrc);
results.push({ project: proj, link, status });
}
return results;
}
// CLI 入口
if (import.meta.url === pathToFileURL(process.argv[1]).href) {
const results = setupLinks(GAMES_DIR, FRAMEWORK_SRC);
if (results.length === 0) {
console.log('games/ 下暂无子游戏工程。');
}
for (const r of results) {
console.log(`[${r.status}] ${r.link}`);
}
}
@@ -0,0 +1,36 @@
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { join } from 'node:path';
import { readFileSync } from 'node:fs';
import { makeTempMonorepo, makeGameProject, cleanup } from './helpers.mjs';
import { setupLinks } from '../setup-links.mjs';
import { isLink } from '../lib/junction.mjs';
test('setupLinks 为每个子游戏工程建立 assets/framework junction', () => {
const mono = makeTempMonorepo();
try {
makeGameProject(mono.games, 'doudizhu');
makeGameProject(mono.games, 'niuniu');
const results = setupLinks(mono.games, mono.framework);
assert.equal(results.length, 2);
for (const r of results) {
assert.equal(r.status, 'created');
assert.ok(isLink(r.link));
assert.equal(readFileSync(join(r.link, 'README.md'), 'utf8'), '# framework src\n');
}
} finally {
cleanup(mono.root);
}
});
test('setupLinks 二次运行幂等(已存在则 exists)', () => {
const mono = makeTempMonorepo();
try {
makeGameProject(mono.games, 'doudizhu');
setupLinks(mono.games, mono.framework);
const second = setupLinks(mono.games, mono.framework);
assert.equal(second[0].status, 'exists');
} finally {
cleanup(mono.root);
}
});