Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions scripts/generate-leaderboard.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -157,25 +157,38 @@ async function main() {
// 一次 fetch 失败(CF 临时挑战 / Vercel runner IP 信誉低 / 后端短暂抖动)
// 不应该把 commit 进 git 的好数据冲成空数组上线。
//
// 三种情况:
// 1. 文件已存在 + 内容是非空数组 → 保留旧数据 exit 0
// 2. 文件已存在但是空数组 / 不是数组 → 维持原状 exit 0(不主动覆盖)
// 3. 文件不存在(首次 build / 干净 cache)→ 写空数组兜底 exit 0
// 四种情况:
// 1. 文件已存在 + 是非空数组 → 保留旧数据 exit 0
// 2. 文件已存在 + 是空数组 → 保留空数组 exit 0(语义合法,下游 .filter 不挂)
// 3. 文件已存在 + JSON 损坏 / 非数组 → 视为无效,走兜底写 [] 覆盖
// 4. 文件不存在(首次 build) → 走兜底写 [] 覆盖
//
// 关键约束:下游有多处 import leaderboard 后直接 .filter/.map,
// 一旦内容是 null/object 等非数组类型,整个 Next build 会因
// "filter is not a function" 挂掉。所以"非数组"必须强制覆盖空数组,
// 不能跟"空数组"一样走 preserve 分支。
let preservedExisting = false;
try {
const existing = await fs.readFile(outputAbs, "utf-8");
try {
const parsed = JSON.parse(existing);
if (Array.isArray(parsed) && parsed.length > 0) {
console.warn(
`[generate-leaderboard] 后端不可用,但保留 ${OUTPUT} 已有 ${parsed.length} 条数据,不覆盖。 | Backend unreachable; keeping existing leaderboard with ${parsed.length} entries.`,
);
if (Array.isArray(parsed)) {
if (parsed.length > 0) {
console.warn(
`[generate-leaderboard] 后端不可用,但保留 ${OUTPUT} 已有 ${parsed.length} 条数据,不覆盖。 | Backend unreachable; keeping existing leaderboard with ${parsed.length} entries.`,
);
} else {
console.warn(
`[generate-leaderboard] 后端不可用,但保留 ${OUTPUT} 的空数组内容。 | Backend unreachable; keeping existing empty leaderboard array.`,
);
}
preservedExisting = true;
} else {
// 非数组(对象、字面量、null 等)→ 不 preserve,走下方兜底覆盖空数组
console.warn(
`[generate-leaderboard] 后端不可用,且 ${OUTPUT} 已有内容非有效非空数组,维持原状。`,
`[generate-leaderboard] ${OUTPUT} 已存在但内容不是数组(typeof=${typeof parsed}),按无效数据处理,兜底覆盖为 []。`,
);
Comment on lines +187 to 190
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

日志里用 typeof parsed 来提示“非数组”类型时,遇到 null 会显示为 object(JS 里 typeof null === "object"),容易误导排查。建议在日志中把 null 单独显示出来(例如显示为 null),或补充更明确的类型描述。

Copilot uses AI. Check for mistakes.
}
preservedExisting = true;
} catch {
// 文件存在但 JSON 损坏:当作没有,走下面写空兜底
console.warn(
Expand Down
Loading