原来只有 `apps/web` 在 Prettier 下(配置在 `apps/web/.prettierrc.toml`、脚本在 web 的 package.json),后端和契约从来没格式化过 —— 手写在 100 列上下,`db/schema.ts` 还是 drizzle-kit pull 留下的 tab 缩进。两套口径分叉久了,跨端改一处就得记着「这边 什么风格」。 - 配置搬到根目录 `.prettierrc.toml`,内容不变(`semi=false`,其余全默认, printWidth 80 —— 和前端已有的格式一致,不另立一套宽度); - 脚本统一成根目录 `bun run fmt`,覆盖 `apps/*/src`、`apps/web/tests` 和两个构建 配置;web 自己那份 `fmt` 和重复的 prettier 依赖删掉; - `.prettierignore` 挡掉两类不该碰的:drizzle-kit 生成的 `src/db/meta/` 结构快照 (它是 db:generate 的比对输入,只该由 drizzle-kit 写)、unplugin 每次 dev 都会 重写的 `auto-imports.d.ts` / `components.d.ts`; - 全量跑了一遍。纯格式,无行为改动:api typecheck / check:routes / check:ast、 前端 type-check 全过,起 api 打了接口确认正常。前端这 39 个文件的小改动是 prettier 版本漂移(类型断言的换行口径变了),不是新配置带来的。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e600fd24cf
commit
ed56a209ea
122 files changed
+10557
-4843
No files matched your search
@@ -95,13 +95,20 @@ export async function processTestCaseZip(
|
||||
|
||||
// 只按「精确文件名」取内容,不遍历压缩包里的条目 ——
|
||||
// 条目名一律不参与路径拼接,zip slip(`../../etc/passwd` 这类条目名)从设计上就进不来。
|
||||
const names = new Set(Object.keys(files).filter((name) => /^\d+\.(in|out|sql)$/.test(name)))
|
||||
const names = new Set(
|
||||
Object.keys(files).filter((name) => /^\d+\.(in|out|sql)$/.test(name)),
|
||||
)
|
||||
|
||||
const selected = options.sql ? collectSqlScripts(names) : collectPairs(names).flat()
|
||||
if (selected.length === 0) throw new TestCaseError("压缩包里没有找到从 1 开始连续编号的测试点")
|
||||
const selected = options.sql
|
||||
? collectSqlScripts(names)
|
||||
: collectPairs(names).flat()
|
||||
if (selected.length === 0)
|
||||
throw new TestCaseError("压缩包里没有找到从 1 开始连续编号的测试点")
|
||||
if (options.sql && selected.length < 2) {
|
||||
// 题目页会展示测试点 1 的期望结果,只有一个测试点时学生可以对照着硬编码 AC
|
||||
throw new TestCaseError("SQL 题至少需要 2 个数据不同的测试点,防止硬编码期望结果")
|
||||
throw new TestCaseError(
|
||||
"SQL 题至少需要 2 个数据不同的测试点,防止硬编码期望结果",
|
||||
)
|
||||
}
|
||||
|
||||
let total = 0
|
||||
@@ -109,12 +116,16 @@ export async function processTestCaseZip(
|
||||
for (const name of selected) {
|
||||
const raw = files[name]!
|
||||
if (raw.length > MAX_ENTRY_BYTES) {
|
||||
throw new TestCaseError(`测试点 ${name} 超过 ${MAX_ENTRY_BYTES / 1024 / 1024}MB`)
|
||||
throw new TestCaseError(
|
||||
`测试点 ${name} 超过 ${MAX_ENTRY_BYTES / 1024 / 1024}MB`,
|
||||
)
|
||||
}
|
||||
const content = normalizeNewlines(raw)
|
||||
total += content.length
|
||||
if (total > MAX_TOTAL_BYTES) {
|
||||
throw new TestCaseError(`测试点总大小超过 ${MAX_TOTAL_BYTES / 1024 / 1024}MB`)
|
||||
throw new TestCaseError(
|
||||
`测试点总大小超过 ${MAX_TOTAL_BYTES / 1024 / 1024}MB`,
|
||||
)
|
||||
}
|
||||
contents.set(name, content)
|
||||
}
|
||||
@@ -149,7 +160,9 @@ export async function processTestCaseZip(
|
||||
collectPairs(names).forEach(([input, output], index) => {
|
||||
const outputContent = contents.get(output)!
|
||||
const entry: TestCaseEntry = {
|
||||
stripped_output_md5: createHash("md5").update(rstrip(outputContent)).digest("hex"),
|
||||
stripped_output_md5: createHash("md5")
|
||||
.update(rstrip(outputContent))
|
||||
.digest("hex"),
|
||||
input_size: contents.get(input)!.length,
|
||||
output_size: outputContent.length,
|
||||
input_name: input,
|
||||
@@ -179,7 +192,9 @@ export async function packTestCaseZip(testCaseId: string) {
|
||||
throw new TestCaseError("Test case does not exists")
|
||||
}
|
||||
const names = new Set(entries)
|
||||
const isSql = await readInfo(testCaseId).then((info) => Boolean(info?.sql)).catch(() => false)
|
||||
const isSql = await readInfo(testCaseId)
|
||||
.then((info) => Boolean(info?.sql))
|
||||
.catch(() => false)
|
||||
const selected = isSql ? collectSqlScripts(names) : collectPairs(names).flat()
|
||||
const bundle: Record<string, Uint8Array> = {}
|
||||
for (const name of [...selected, "info"]) {
|
||||
@@ -207,7 +222,10 @@ export async function readSqlScripts(testCaseId: string) {
|
||||
const names = collectSqlScripts(new Set(await readdir(directory)))
|
||||
const scripts: { name: string; content: string }[] = []
|
||||
for (const name of names) {
|
||||
scripts.push({ name, content: await readFile(resolve(directory, name), "utf8") })
|
||||
scripts.push({
|
||||
name,
|
||||
content: await readFile(resolve(directory, name), "utf8"),
|
||||
})
|
||||
}
|
||||
return scripts
|
||||
}
|
||||
@@ -216,5 +234,7 @@ function randomId() {
|
||||
const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
const bytes = new Uint8Array(32)
|
||||
crypto.getRandomValues(bytes)
|
||||
return Array.from(bytes, (value) => alphabet[value % alphabet.length]).join("")
|
||||
return Array.from(bytes, (value) => alphabet[value % alphabet.length]).join(
|
||||
"",
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user