"use strict"; const fs = require("fs"); const { parseOsm } = require("./osm"); const { buildTrafficSignalFeatures, buildTrafficSignalsFromFeatures, validateTrafficSignalFeatures, validateTrafficSignalSourceReferences, } = require("./traffic-signals"); const SCHEMA = "native-traffic-signals/v1"; function loadOrGenerate(file, osmText, stopLines, intersections) { if (fs.existsSync(file)) { const document = JSON.parse(fs.readFileSync(file, "utf8")); try { return validateDocument(document, osmText); } catch (error) { // OSM edits can invalidate the stable identities in a document that was // itself generated from OSM. User-authored documents must remain strict. if (document?.provenance === "generated:osm-controls" && isStaleSourceReferenceError(error)) { return generate(osmText, stopLines, intersections); } throw error; } } return generate(osmText, stopLines, intersections); } function isStaleSourceReferenceError(error) { return error instanceof Error && /^traffic signal feature \d+: (approach_id .* is not present on OSM control|control_id .* is not present in the current OSM)/.test(error.message); } function generate(osmText, stopLines, intersections) { const controls = parseOsm(osmText).trafficSignalControls; return { schema: SCHEMA, provenance: "generated:osm-controls", assemblies: buildTrafficSignalFeatures(stopLines, intersections, controls) }; } function validateDocument(value, osmText) { if (value?.schema !== SCHEMA) throw new Error(`Expected ${SCHEMA} signal document`); const assemblies = validateTrafficSignalFeatures(value.assemblies); if (osmText) validateTrafficSignalSourceReferences(assemblies, parseOsm(osmText).trafficSignalControls); return { schema: SCHEMA, provenance: value.provenance || "native", assemblies }; } function runtime(document) { return buildTrafficSignalsFromFeatures(document.assemblies); } module.exports = { SCHEMA, generate, loadOrGenerate, validateDocument, runtime };