fix(preview): 流式文件服务与 HEAD 跳读;静默开关;redirect 转义;argv 缺值报错

复审四项:
- serveFile 改 createReadStream 直 pipe(Content-Length 取自先行 stat)——
  64MB 文件 RSS 平坦(冒烟实测 -53MB 增长,此前整读驻留);HEAD 只发头
  零读盘;流错误掐断连接不崩进程;头纪律抽 applyHeaders 唯一出口。
- createPreviewServer 增 quiet 选项(缺省 verbose);sf.ts preview:start
  与 server.mjs 直跑入口各加 --quiet;CLI 透传经子进程冒烟验证。
- redirect 迁移页内嵌 location 时 HTML 转义(</&/"——Location 头原样)。
- parseCliArgs 末尾缺值 flag 显式报错(不再静默 undefined 漏成默认值)。

测试 12→13(新增 quiet 开关用例;用例 12 增 --quiet stdout 断言):
根套件 380 + 主题 26 = 406 全绿;typecheck/lint 干净。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-22 13:58:15 +08:00
parent 7194d1bcef
commit 5f78dde9ee
4 changed files with 95 additions and 19 deletions
+9 -2
View File
@@ -358,7 +358,8 @@ program
.requiredOption('--build <jobId>', '构建 job id(须 succeeded——dist 产物只在成功终态存在)')
.option('--port <port>', '监听端口(0 = 随机可用端口)', '4173')
.option('--host <host>', '绑定地址——仅允许 127.0.0.1 / localhost(回环纪律,外值拒绝)', '127.0.0.1')
.action(async (opts: { build: string; port: string; host: string }) => {
.option('--quiet', '静默逐请求访问日志(缺省逐请求一行 stdout)')
.action(async (opts: { build: string; port: string; host: string; quiet?: boolean }) => {
// 回环校验先于一切(含 DB 访问)——预览永不对外,外值在触碰任何资源前拒绝
if (opts.host !== '127.0.0.1' && opts.host !== 'localhost') {
throw new Error(`--host 仅允许 127.0.0.1 / localhost(回环绑定纪律,外值拒绝):${opts.host}`)
@@ -404,7 +405,13 @@ program
}
// server.mjs 是纯 JS 包(零依赖、不进 TS 链)——动态导入直连源文件,类型面由 server.d.mts 供给
const { createPreviewServer } = await import('../apps/preview-server/server.mjs')
const preview = createPreviewServer({ distDir: distPath, routeManifest: manifestRaw, host: opts.host, port })
const preview = createPreviewServer({
distDir: distPath,
routeManifest: manifestRaw,
host: opts.host,
port,
quiet: opts.quiet === true,
})
const addr = await preview.start()
console.log(`[preview:start] job=${opts.build}`)
console.log(` dist: ${distPath}`)