feat(cli): add interactive area build menu

This commit is contained in:
2026-08-11 14:08:22 +08:00
parent d26921c6d1
commit b68be063ad
7 changed files with 517 additions and 55 deletions

View File

@@ -0,0 +1,41 @@
"use strict";
const STAGES = [
{ id: "intermediates", label: "OSM / QGIS intermediates", description: "Rebuild GeoJSON and GeoPackage from OSM" },
{ id: "reimport", label: "Reimport QGIS edits", description: "Copy GeoPackage layers back to GeoJSON" },
{ id: "blender", label: "Blender scene", description: "Generate the editable scene and render" },
{ id: "cesium", label: "Cesium export", description: "Export GLB, metadata, and preview" },
{ id: "preview", label: "Preview refresh", description: "Regenerate preview HTML and vehicles" },
{ id: "compress", label: "Compressed preview", description: "Create optional compressed GLB artifacts" },
];
const ALIASES = {
all: ["intermediates", "blender", "cesium"],
qgis: ["intermediates"], osm2streets: ["intermediates"], geojson: ["intermediates"], intermediate: ["intermediates"],
intermediates: ["intermediates"], reimport: ["reimport"], gpkg: ["reimport"], blender: ["blender"], scene: ["blender"],
cesium: ["cesium"], glb: ["cesium"], preview: ["preview"], html: ["preview"], cesiumPreview: ["preview"],
compress: ["compress"], compression: ["compress"], compressedCesium: ["compress"],
};
function resolveStages(defaults, requested) {
const selected = requested || Object.keys(defaults).filter((key) => defaults[key]);
const result = Object.fromEntries(STAGES.map(({ id }) => [id, false]));
for (const stage of selected) {
const mapped = ALIASES[stage];
if (!mapped) throw new Error(`Unknown stage '${stage}'. Use ${stageNames().join(", ")}, or all.`);
for (const id of mapped) result[id] = true;
}
assertCompatible(result);
return result;
}
function assertCompatible(stages) {
if (stages.intermediates && stages.reimport) {
throw new Error("Stages 'intermediates' and 'reimport' are mutually exclusive: intermediates rebuilds the GeoPackage from OSM and would discard the QGIS edits reimport reads back.");
}
}
function stageNames() { return STAGES.map(({ id }) => id); }
function canonicalStages(stages) { return stageNames().filter((id) => stages[id]); }
module.exports = { STAGES, resolveStages, canonicalStages, stageNames };