'use strict'; const crypto = require('crypto'); const fs = require('fs'); const path = require('path'); const root = path.resolve(__dirname, '..'); function fixtureInputs() { return ['fengshu-er-road', 'nantaizi-lake-innovation-valley'].map((areaId) => { const isFengshu = areaId === 'fengshu-er-road'; const outputRoot = path.join(root, 'outputs', areaId); return { areaId, osmFile: path.join(root, 'inputs', 'osm', isFengshu ? '枫树二路.osm' : '南台子湖创新谷OSM.osm'), outDir: path.join(outputRoot, 'native-road'), stagingDir: path.join(outputRoot, '_pipeline'), overridesFile: path.join(outputRoot, 'native-road-overrides.json'), trafficSignalsFile: path.join(outputRoot, 'native-traffic-signals.json'), comparisonDir: path.join(outputRoot, 'osm2streets_web_out'), options: { edgeLines: false, junctionTemplates: { enabled: false, references: [] } }, }; }); } function digest(value) { return crypto.createHash('sha256').update(value).digest('hex'); } function canonicalContent(file) { const raw = fs.readFileSync(file, 'utf8'); if (!file.endsWith('.json') && !file.endsWith('.geojson')) return raw; return `${JSON.stringify(normalize(JSON.parse(raw)))}\n`; } function normalize(value) { if (Array.isArray(value)) return value.map(normalize); if (value && typeof value === 'object') return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, normalize(item)])); return typeof value === 'string' ? value.split(root).join('') : value; } function snapshot(input) { const files = {}; const candidates = [ ['../native-traffic-signals.json', input.trafficSignalsFile], ...walk(input.outDir).filter(([relative]) => relative !== 'manifest.json'), ]; for (const [relative, file] of candidates) { const content = canonicalContent(file); files[relative] = { contentHash: digest(content), bytes: Buffer.byteLength(content) }; } return { contract: 'native-road-package/v1.1', areaId: input.areaId, files }; } function walk(directory, prefix = '') { return fs .readdirSync(directory, { withFileTypes: true }) .sort((first, second) => first.name.localeCompare(second.name)) .flatMap((entry) => { const relative = path.join(prefix, entry.name); const file = path.join(directory, entry.name); return entry.isDirectory() ? walk(file, relative) : [[relative, file]]; }); } function baselineFile(areaId) { return path.join(root, 'test', 'baseline', `${areaId}.json`); } module.exports = { root, fixtureInputs, snapshot, baselineFile };