# Pipeline:Node 构建管线 > 覆盖 `scripts/*.js` 与 `scripts/lib/scene-layers.js`。 > 运行时:宿主机 Node(CommonJS,无构建步骤)。 > 这是管线里**唯一**能启动外部进程的层。 --- ## 先读哪一篇 | 你要做的事 | 读 | |---|---| | 改九个 osm2streets 图层(增/删/改顺序/改色) | [图层表](./layer-registry.md) ← **最容易出静默错误** | | 调 QGIS / GDAL / Blender 子进程 | [外部工具调用](./external-tools.md) | | 加阶段、加 CLI 参数、改配置字段 | [CLI 与阶段](./cli-and-stages.md) | | 改区域诊断/质量门命令或共享区域配置归一化 | [CLI 与阶段](./cli-and-stages.md#区域诊断命令) 和 [质量门](./cli-and-stages.md#区域质量门命令) | | 改 stage manifest 写入、读取或 stale 判断 | [CLI 与阶段](./cli-and-stages.md#stage-manifest-契约) | | 改预览页生成 | [../preview/](../preview/index.md) | | 声称"纯重构,产物不变" | [产物一致性指南](../guides/artifact-parity-guide.md) | --- ## 数据流全景 ``` config/areas/.json │ ▼ lib/area-config.js — normalizeAreaConfig() 推导全部输出路径 │ ▼ build-area.js — 阶段调度 _pipeline/osm2streets-qgis.config.json (派生配置) │ ├─[intermediates]─▶ build-osm2streets-qgis.js │ osm2streets-js-node 解析 .osm │ → splitLayers() 拆成九个图层 │ → normalize-lane-arrows.py(QGIS Python) │ → osm2streets_web_out/*.geojson │ → osm2streets_scene.geojson + _scene_style.json │ → ogr2ogr 导入 .gpkg │ → QGIS 生成 .qgz + -preview.png │ → _pipeline/stages/intermediates.manifest.json │ ├─[reimport]──────▶ reimport-gpkg.js (反向,与 intermediates 互斥) │ ogr2ogr 从 .gpkg 导出 → 校验 → 覆写 *.geojson │ → 重建 scene.geojson + scene_style.json │ → _pipeline/stages/reimport.manifest.json │ ├─[blender]───────▶ Blender + blender/generate_scene.py │ 读 .osm + osm2streets_web_out/ │ → .blend + .png │ → _pipeline/stages/blender.manifest.json │ ├─[cesium]────────▶ Blender + blender/export_cesium.py │ 读 .blend → .glb + .json │ → 并自动执行 preview │ → _pipeline/stages/cesium.manifest.json │ ├─[preview]───────▶ 生成 -cesium-preview.html │ + 拷贝 lib/cesium-preview.{js,css} │ + 车辆巡航路线与模型 │ → _pipeline/stages/preview.manifest.json │ └─[compress]──────▶ 生成并列压缩 GLB / metadata / preview → _pipeline/stages/compress.manifest.json ``` **阶段之间只通过磁盘产物耦合**,不传内存状态。这是单跑任意阶段能work 的前提。 --- ## 三条贯穿全层的约定 1. **单一事实源优先于同步** 九个图层的定义在 `lib/scene-layers.js`,四个派生函数覆盖了全部合法用法。看到第二处 枚举这些图层,就是 bug 温床。详见 [图层表](./layer-registry.md)。 2. **有副作用之前先把能验的都验完** 数值参数 → 输入文件 → 外部可执行文件 → 才 `mkdirSync`。 见 `build-osm2streets-qgis.js:41-70`。 3. **外部工具的产物先落 staging,校验通过才覆盖** `ogr2ogr` 失败会留 0 字节文件。详见 [外部工具调用](./external-tools.md)。 --- ## 文件速查 | 文件 | 行数 | 职责 | |---|---|---| | `build-area.js` | 961 | 主入口:区域配置读取、阶段调度、Cesium 预览页、车辆巡航和 stage manifest 写入 | | `diagnose-area.js` | 36 | 快速诊断入口:调用共享 area diagnostics 并打印完整报告 | | `check-area.js` | 74 | 区域质量门入口:调用共享 area diagnostics,输出 PASS/FAIL 并设置退出码 | | `lib/area-diagnostics.js` | 776 | 共享区域诊断事实源:OSM、产物、metadata、stage manifest、GLB digest 和质量门分类 | | `lib/area-config.js` | 135 | 区域配置归一化与输出路径推导,供 build / diagnose 复用 | | `lib/stage-manifest.js` | 100 | stage manifest 路径、文件记录、GLB budget warning 和原子 JSON 写入 | | `build-osm2streets-qgis.js` | 1468 | intermediates:osm2streets 解析、图层拆分、人行道转角合成、GeoPackage 与 QGIS 工程生成 | | `reimport-gpkg.js` | 179 | reimport:GeoPackage → GeoJSON 反向导出 | | `lib/scene-layers.js` | 164 | 九个图层的单一事实源 + 四个派生函数 | | `lib/cesium-preview.js` / `.css` | 672 / 230 | 预览页运行时,见 [../preview/](../preview/index.md) | | `normalize-lane-arrows.py` | 182 | 合并 osm2streets 的三角网箭头(跑在 QGIS Python 里) | | `parity.js` | 270 | 产物一致性校验驱动 | | `glb-digest.js` | 132 | GLB 结构摘要,CLI、build manifest 和诊断脚本共用 | --- ## 技术选型现状 - **CommonJS,无构建、无 TypeScript、无 lint 配置**。保持现状;引入工具链是独立决定, 不要夹带在功能改动里 - **零运行时依赖**(`osm2streets-js-node` 是唯一 dependency)。加依赖前先确认标准库 真的做不到 - **同步 API 优先**(`execFileSync` / `spawnSync` / `readFileSync`)。这是一次性跑完 的批处理工具,不是服务,异步只会增加错误处理复杂度 - **macOS 专用路径假设**(`.app/Contents/MacOS/...`)。跨平台不在当前范围内