Files
cms-website/docs/adr/ADR-016-阶段2依赖与接线决策.md
T
浅念 2a0d830520 docs: 阶段2收尾——ADR-016/typecheck链/阶段3移交清单/README
- ADR-016:saxes ^6.0.0(勘误:计划曾误写 ^0.9)/commander ^14 根依赖/清洗三件套
  同 range + 镜像直调 launder.naughtyHref/tsx ^4 CLI 直吃 TS;跨包接线(根 tsconfig
  paths 三方消费、build 侧 dist+prebuild、tsconfig 双链型并存);根 engines 升
  >=22.12(对齐 sanitize-html 2.18 engines,CI node 22 与本机 24 均满足)
- 根 typecheck 链扩为四段:追加 pnpm --filter @sf/adapter-wp typecheck
- Plan 2 文末新增"移交阶段 3 清单"定稿(7 项:taxonomyRefs 自建缺失 term、
  media_bundle 映射、connection 库级唯一索引、REST 重审项、导入消费接口、
  Task 0.2 cms 备份续传携带、versions.ts bump 纪律);Task 9 与验收节勾选
- README:快速开始加 pnpm sf 示例;目录结构/文档导航/当前状态更新为阶段 2 完成
- 三绿:lint / typecheck(四段)/ test 263 全部通过(数量不变)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-21 13:34:15 +08:00

4.6 KiB
Raw Blame History

ADR-016:阶段 2 新增依赖与跨包接线

  • 状态:已采纳(Plan 2 Task 9 收尾,阶段 2;许可证已逐项核验——saxes ISC,commander/sanitize-html/parse-srcset/launder/tsx 均 MIT)

决策一:新增依赖(选型 / 版本范围 / 定位)

  1. saxes ^6.0.0(@sf/adapter-wp 运行时依赖)——WXR 流式 SAX 解析的唯一解析库。勘误:Plan 2 Task 3 曾误写"锁 ^0.9"(0.x 是多年前的旧版本线),实施时按 npm 实际主线锁 ^6.0.0;默认不解析外部实体(XXE 面由测试钉死)。versions.ts 的 PARSER_VERSION 常量须与实际解析版本同步(当前 'saxes 6.0.0')。
  2. commander ^14.0.0(根依赖)——CLI 入口在仓库根 scripts/sf.ts,而 @sf/adapter-wp 定位纯函数包、不消费 CLI 框架;commander 放根,不给库包带入无关运行时依赖。
  3. 清洗三件套 sanitize-html ^2 + parse-srcset ^1 + launder ^1(@sf/adapter-wp 运行时依赖,三条 range 并存)——sanitize-html 是清洗本体;srcset/imagesrcset 审计用 parse-srcset(sanitize-html 内部即同库依赖);URL 拒绝判定直接调用 launder.naughtyHref——sanitize-html 2.18 内部即解构调用同一函数,镜像判定与库本体零漂移(依赖升级时由参数化对抗测试护栏兜底)。三件套用同一主版本 range 跟随解析:launder/parse-srcset 本是 sanitize-html 的传递依赖,若单独锁死版本,会造成"镜像调用的 launder"与"库内部用的 launder"版本 skew。类型:@types/sanitize-html、@types/parse-srcset 走 devDependencies;launder 无官方类型,本包自带 d.ts 垫片(src/types/launder.d.ts)。
  4. tsx ^4(根 devDependency)——CLI 直吃 TS 源码:pnpm sf = tsx scripts/sf.ts,无需预构建 dist(apps/api 的 Nest 装饰器源码同样可跑);tsx 属开发工具链,不进任何运行时依赖。

决策二:跨包接线

  1. 根 tsconfig paths 三方消费(单源):@sf/contracts 与 @sf/adapter-wp 到各自 src/index.ts 的映射只在根 tsconfig.json compilerOptions.paths 维护一份——包级 tsc 经 extends 继承;vitest 不读 tsconfig paths,由 vitest.config.ts 的 resolve.alias 镜射同一映射;tsx 原生读 tsconfig paths。三方(包级 tsc / vitest / tsx)全部直连 src/index.ts——日常开发链 import 不经 dist、无预构建依赖。
  2. build 侧 dist + prebuild:@sf/adapter-wp 的 tsconfig.build.json 把 @sf/contracts 改指 packages/contracts/dist/src/index.d.ts(emit 程序不得包含包外源文件,TS6059),由 prebuild 先 pnpm --filter @sf/contracts build 供给 dist 声明。dist 只为发布产物完整性负责;typecheck / test / CLI 通道不依赖它。
  3. tsconfig 双链型并存:contracts extends tsconfig.base.json(无跨包 import,不需要 paths);adapter-wp extends 根 tsconfig.json(为继承 baseUrl/paths 跨包映射)。两条 extends 链并存是有意的:包是否需要跨包映射决定挂哪条链,不为形式统一强行并链。src-vs-dist 的最终口径即上述 5+6:开发链 src 直连、build 链 dist+prebuild,双轨并存(Plan 1 终审前瞻项在此落定)。

决策三:engines 口径

  1. 根 engines 升 >=22.12:sanitize-html 2.18 的 engines 要求 node >=22.12.0,根原口径 >=22 会放行 sanitize-html 不支持的 22.0–22.11。升根一行对齐(CI 的 node 22 取最新 22.x、本机 24 均满足);否决的替代方案是 pin sanitize-html 旧版——为迁就旧 patch 版 node 反向锁死清洗库,不取。后续新增依赖若 engines 高于根,同理评估升根而非降依赖。
  • 理由:全部依赖均为单一职责引入(解析/清洗/CLI/TS 执行各一),无重叠;版本范围统一锁主版本(^),与"锁版本 + 核许可证 + 记 ADR"的新增依赖三纪律一致;跨包接线坚持单源配置(paths 一份、alias 镜射),把 skew 面压到最小。
  • 权衡/陷阱:① vitest alias 是根 paths 的人工镜射,新增 workspace 包时两处要同步改;② build 链与开发链对 @sf/contracts 的解析目标不同(dist 声明 vs src),dist 过期只影响产物不影响日常——发布前跑 build 即可暴露;③ launder 镜像判定的等价性依赖"sanitize-html 内部继续用 launder 同一函数",升级 sanitize-html 大版本时须重验(对抗测试在 test/html-sanitize.test.ts);④ engines 对齐的是传递依赖里最严的要求,属"就高"策略,接受它对低版本 node 的排斥。