From d5c58b5b0c5de7ac7eb4bd33141052d5472025f0 Mon Sep 17 00:00:00 2001 From: que01 Date: Tue, 25 Aug 2026 17:15:15 +0800 Subject: [PATCH] refactor: move native road checks into package --- packages/road-compiler/src/check.js | 27 +++++++++++++++++++++++++++ packages/road-compiler/src/index.js | 1 + packages/road-compiler/test/index.js | 1 + scripts/check-native-roads.js | 20 ++------------------ 4 files changed, 31 insertions(+), 18 deletions(-) create mode 100644 packages/road-compiler/src/check.js diff --git a/packages/road-compiler/src/check.js b/packages/road-compiler/src/check.js new file mode 100644 index 0000000..bab9cff --- /dev/null +++ b/packages/road-compiler/src/check.js @@ -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 }; diff --git a/packages/road-compiler/src/index.js b/packages/road-compiler/src/index.js index a435240..6b58c4a 100644 --- a/packages/road-compiler/src/index.js +++ b/packages/road-compiler/src/index.js @@ -10,4 +10,5 @@ module.exports = { nativeTrafficSignals: require("./native-traffic-signals"), nativeRoad: require("./compile/native-road"), compiler: require("./compile/compiler"), + check: require("./check"), }; diff --git a/packages/road-compiler/test/index.js b/packages/road-compiler/test/index.js index 23fb241..e3311bf 100644 --- a/packages/road-compiler/test/index.js +++ b/packages/road-compiler/test/index.js @@ -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/); diff --git a/scripts/check-native-roads.js b/scripts/check-native-roads.js index 67b179e..c51eac3 100644 --- a/scripts/check-native-roads.js +++ b/scripts/check-native-roads.js @@ -1,35 +1,19 @@ #!/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}`); - } - 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 }; + return checkOutput({ areaId: area.id, outDir: area.outputs.nativeRoadDir }); } -function readJson(file) { return JSON.parse(fs.readFileSync(file, "utf8")); } - function main() { const args = parseArgs(process.argv.slice(2)); const configPath = path.resolve(args.config || path.join(repoRoot, "config", "areas", "nantaizi-lake-innovation-valley.json"));