refactor: move native road checks into package

This commit is contained in:
2026-08-25 17:15:15 +08:00
parent 73707dabbe
commit d5c58b5b0c
4 changed files with 31 additions and 18 deletions

View File

@@ -0,0 +1,27 @@
"use strict";
const fs = require("fs");
const path = require("path");
function checkOutput({ areaId, outDir }) {
if (typeof areaId !== "string" || !areaId) throw new Error("RoadCompilerCheckInput.areaId must be a non-empty string");
if (typeof outDir !== "string" || !outDir) throw new Error("RoadCompilerCheckInput.outDir must be a non-empty string");
const compiledPath = path.join(outDir, "compiled.json");
if (!fs.existsSync(compiledPath)) throw new Error(`Native road output is missing: ${compiledPath}`);
const compiled = readJson(compiledPath);
const connectors = readJson(path.join(outDir, "layers", "connectors.geojson"));
const published = new Set(connectors.features.map((feature) => feature.properties.movement_id));
const failures = [];
for (const movement of compiled.movements || []) {
if (movement.geometryPublished && !published.has(movement.id)) failures.push(`Published movement has no connector: ${movement.id}`);
if (!movement.geometryPublished && published.has(movement.id)) failures.push(`Non-published movement has a connector: ${movement.id}`);
if (!movement.geometryStatus) failures.push(`Movement has no geometry status: ${movement.id}`);
}
const errors = (compiled.diagnostics || []).filter((item) => item.severity === "error");
const warnings = (compiled.diagnostics || []).filter((item) => item.severity === "warning");
return { schema: "native-road-check/v1", areaId, ok: failures.length === 0 && errors.length === 0, movementCount: (compiled.movements || []).length, connectorCount: connectors.features.length, errors: errors.map((item) => ({ id: item.id, rule: item.rule, message: item.message })), warningCount: warnings.length, failures };
}
function readJson(file) { return JSON.parse(fs.readFileSync(file, "utf8")); }
module.exports = { checkOutput };

View File

@@ -10,4 +10,5 @@ module.exports = {
nativeTrafficSignals: require("./native-traffic-signals"),
nativeRoad: require("./compile/native-road"),
compiler: require("./compile/compiler"),
check: require("./check"),
};

View File

@@ -10,6 +10,7 @@ assert.equal(typeof compiler.gaodeReference.convertGeoJson, "function");
assert.equal(typeof compiler.turnLaneArrows.buildCustomTurnLaneArrows, "function");
assert.equal(typeof compiler.complexJunction.buildComplexJunctionGeometry, "function");
assert.equal(typeof compiler.nativeRoad.compileRoadModel, "function");
assert.equal(typeof compiler.check.checkOutput, "function");
const fixture = path.join(__dirname, "fixtures", "fengshu-er-road.osm");
assert.ok(fs.existsSync(fixture));
assert.throws(() => compiler.compiler.validateInput({ id: "area" }), /RoadCompilerInput/);

View File

@@ -1,34 +1,18 @@
#!/usr/bin/env node
"use strict";
const fs = require("fs");
const path = require("path");
const { readAreaConfig } = require("./lib/area-config");
const { compileArea, parseArgs } = require("./compile-native-roads");
const { checkOutput } = require("../packages/road-compiler/src/check");
const repoRoot = path.resolve(__dirname, "..");
function checkArea(configPath, options = {}) {
if (options.compile) compileArea(configPath);
const area = readAreaConfig(configPath, { repoRoot });
const root = area.outputs.nativeRoadDir;
const compiledPath = path.join(root, "compiled.json");
if (!fs.existsSync(compiledPath)) throw new Error(`Native road output is missing: ${compiledPath}`);
const compiled = readJson(compiledPath);
const connectors = readJson(path.join(root, "layers", "connectors.geojson"));
const published = new Set(connectors.features.map((feature) => feature.properties.movement_id));
const failures = [];
for (const movement of compiled.movements || []) {
if (movement.geometryPublished && !published.has(movement.id)) failures.push(`Published movement has no connector: ${movement.id}`);
if (!movement.geometryPublished && published.has(movement.id)) failures.push(`Non-published movement has a connector: ${movement.id}`);
if (!movement.geometryStatus) failures.push(`Movement has no geometry status: ${movement.id}`);
return checkOutput({ areaId: area.id, outDir: area.outputs.nativeRoadDir });
}
const errors = (compiled.diagnostics || []).filter((item) => item.severity === "error");
const warnings = (compiled.diagnostics || []).filter((item) => item.severity === "warning");
return { schema: "native-road-check/v1", areaId: area.id, ok: failures.length === 0 && errors.length === 0, movementCount: (compiled.movements || []).length, connectorCount: connectors.features.length, errors: errors.map((item) => ({ id: item.id, rule: item.rule, message: item.message })), warningCount: warnings.length, failures };
}
function readJson(file) { return JSON.parse(fs.readFileSync(file, "utf8")); }
function main() {
const args = parseArgs(process.argv.slice(2));