feat(阶段3): oj 侧端点铺开(基线提交,未经评审)
由外部 agent (Codex) 在本会话额度中断期间完成。原样提交作为基线, 后续修复单独成 commit,便于区分与回退。 覆盖 oj 侧 65 个端点,新增 9 组路由(account/achievement/ai/classroom/ content/contest/flowchart/problemset/site)与对应 Zod 契约。 已核验:tsc --noEmit 退出码 0;API 可启动;/api/problems 返回真实数据; judge 与 flowchart worker 均 ready。 未核验:权限边界与数据泄露,评审进行中。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ec274419c3
commit
8c00cdc947
52 files changed
+4273
-300
No files matched your search
@@ -0,0 +1,75 @@
|
||||
import { config } from "../config"
|
||||
|
||||
export class CodeFormatError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
readonly kind: "syntax" | "tool",
|
||||
) {
|
||||
super(message)
|
||||
}
|
||||
}
|
||||
|
||||
async function runFormatter(command: string[], code: string) {
|
||||
let process: ReturnType<typeof Bun.spawn>
|
||||
try {
|
||||
process = Bun.spawn(command, {
|
||||
stdin: new Blob([code]),
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
})
|
||||
} catch (error) {
|
||||
throw new CodeFormatError(String(error), "tool")
|
||||
}
|
||||
|
||||
const timeout = setTimeout(() => process.kill(), 5_000)
|
||||
const [exitCode, stdout, stderr] = await Promise.all([
|
||||
process.exited,
|
||||
new Response(process.stdout as ReadableStream<Uint8Array>).text(),
|
||||
new Response(process.stderr as ReadableStream<Uint8Array>).text(),
|
||||
])
|
||||
clearTimeout(timeout)
|
||||
return { exitCode, stdout, stderr }
|
||||
}
|
||||
|
||||
function formatSql(code: string) {
|
||||
return code
|
||||
.split(";")
|
||||
.map((statement) => statement.trim())
|
||||
.filter(Boolean)
|
||||
.map((statement) =>
|
||||
statement.replace(
|
||||
/\b(select|from|where|join|left|right|inner|outer|on|group by|order by|having|limit|insert into|values|update|set|delete from|create table|drop table|alter table|and|or|as)\b/gi,
|
||||
(keyword) => keyword.toUpperCase(),
|
||||
),
|
||||
)
|
||||
.join(";\n\n") + (code.trim().endsWith(";") ? ";" : "")
|
||||
}
|
||||
|
||||
export async function formatCode(code: string, language: "python" | "c" | "cpp" | "sql") {
|
||||
if (language === "sql") return formatSql(code)
|
||||
|
||||
if (language === "python") {
|
||||
const result = await runFormatter(
|
||||
[config.ruffPath, "format", "--stdin-filename", "code.py", "-"],
|
||||
code,
|
||||
)
|
||||
if (result.exitCode !== 0) {
|
||||
throw new CodeFormatError(result.stderr || "Invalid Python syntax", "syntax")
|
||||
}
|
||||
return result.stdout
|
||||
}
|
||||
|
||||
const filename = language === "c" ? "code.c" : "code.cpp"
|
||||
const result = await runFormatter(
|
||||
[
|
||||
config.clangFormatPath,
|
||||
`-assume-filename=${filename}`,
|
||||
"-style={BasedOnStyle: LLVM, IndentWidth: 4, BreakBeforeBraces: Attach}",
|
||||
],
|
||||
code,
|
||||
)
|
||||
if (result.exitCode !== 0) {
|
||||
throw new CodeFormatError(result.stderr || "Formatting failed", "tool")
|
||||
}
|
||||
return result.stdout
|
||||
}
|
||||
Reference in new issue
Block a user