2a0d830520
- 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>
4.6 KiB
4.6 KiB
ADR-016:阶段 2 新增依赖与跨包接线
- 状态:已采纳(Plan 2 Task 9 收尾,阶段 2;许可证已逐项核验——saxes ISC,commander/sanitize-html/parse-srcset/launder/tsx 均 MIT)
决策一:新增依赖(选型 / 版本范围 / 定位)
- 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')。 - commander
^14.0.0(根依赖)——CLI 入口在仓库根scripts/sf.ts,而 @sf/adapter-wp 定位纯函数包、不消费 CLI 框架;commander 放根,不给库包带入无关运行时依赖。 - 清洗三件套
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)。 - tsx
^4(根 devDependency)——CLI 直吃 TS 源码:pnpm sf=tsx scripts/sf.ts,无需预构建 dist(apps/api 的 Nest 装饰器源码同样可跑);tsx 属开发工具链,不进任何运行时依赖。
决策二:跨包接线
- 根 tsconfig paths 三方消费(单源):
@sf/contracts与@sf/adapter-wp到各自src/index.ts的映射只在根tsconfig.jsoncompilerOptions.paths 维护一份——包级 tsc 经 extends 继承;vitest 不读 tsconfig paths,由vitest.config.ts的resolve.alias镜射同一映射;tsx 原生读 tsconfig paths。三方(包级 tsc / vitest / tsx)全部直连src/index.ts——日常开发链 import 不经 dist、无预构建依赖。 - 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 通道不依赖它。 - 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 口径
- 根 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 的排斥。