feat: compile revisions from area config snapshots

This commit is contained in:
2026-08-26 18:08:55 +08:00
parent c0c8a16dd4
commit ba8eaba9d9
11 changed files with 403 additions and 210 deletions

View File

@@ -1,105 +1,78 @@
{
"contract": "native-road-package/v1",
"contract": "native-road-package/v1.1",
"areaId": "fengshu-er-road",
"files": {
"../native-traffic-signals.json": {
"contentHash": "88e7f0ef4fc7bdb9ef202af018b3fb3179035ffc8ed5eeba03276c263e1f0476",
"bytes": 5886
"contentHash": "ad4a30a53be21381c7d203093f2ab1e55b444f01c1bf83388321f130cf6702d6",
"bytes": 3819
},
"comparison.json": {
"contentHash": "651eb4000a44a7521a79c3e1429795b83d20f8899e0c67c4bb25b56cf4a6f75d",
"bytes": 1295
"contentHash": "a08cdd67cf9a0a2fde8892dccc35f1a5c6b63e8bdda2aaec1774d36370fc6300",
"bytes": 1045
},
"compiled.json": {
"contentHash": "2ab82eafcdab70155078fae3559692ef1fde0645a52c6decbaea762a9ffeb24a",
"bytes": 159230
"contentHash": "3f1bc0dd16fd3cd566716ba034095200518f2ada5f02619667520fd3024e572a",
"bytes": 126674
},
"diagnostics.json": {
"contentHash": "1d9fdae06ddcbc19b5262b797a4a35c494fc30a98a66dbfa111533b12c5fdfc7",
"bytes": 6862
"contentHash": "9ecc0aceaceb65c5c0cdb04a1389169f147c2ff193584838acbb1717abf06912",
"bytes": 6261
},
"layers/center_lines.geojson": {
"contentHash": "04db66df5821b319d59297b8515502fabcad95faf083cae19edb338be2f6024b",
"orderHash": "04db66df5821b319d59297b8515502fabcad95faf083cae19edb338be2f6024b",
"features": 5,
"bytes": 6909
"contentHash": "dd2d659415c0d2c0a0872bb658153c74cf3578384cbce03055abbd16c5c22249",
"bytes": 4152
},
"layers/connectors.geojson": {
"contentHash": "e7979d4642c7c10f33fb23e92721f22533a851ae1a2b4d35f224d50927bf2fe9",
"orderHash": "c327b7b154d4d9ca04cd895523eb0d8ad67c37051ef1d2135b2b46c51e12df58",
"features": 90,
"bytes": 197885
"contentHash": "e829361a9223676dc27bda1719910fdcf82e125f4eaec53c3d348a2d328812ce",
"bytes": 124749
},
"layers/crosswalks.geojson": {
"contentHash": "354cd4d7ed105a11b95904b44848dce567b3a3383f76755936d8c00691fe29af",
"orderHash": "d24376438ac956bde52fcbfa955dd72c2ba31a97995608aaed1c79f6fd3633ab",
"features": 152,
"bytes": 219286
"contentHash": "6d18edfe75b3149104038dcbca4d0096bbcb923f0f9fa4b49f4815344e75bb90",
"bytes": 43
},
"layers/direction_arrows.geojson": {
"contentHash": "7b8362ad4912c997a7661befde55ddfe58757c3c8d139c15867e1938ea8f6918",
"orderHash": "5274e8b433946410a7cdffdaa452c1750e04f53e73a86bf81d034cfb26d4c254",
"features": 686,
"bytes": 1053308
"contentHash": "2baaf72199630df794c2551c900ff3c478b294554c1f31e7f14f8131d43df7d3",
"bytes": 567748
},
"layers/edge_lines.geojson": {
"contentHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8",
"orderHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8",
"features": 0,
"bytes": 52
"contentHash": "6d18edfe75b3149104038dcbca4d0096bbcb923f0f9fa4b49f4815344e75bb90",
"bytes": 43
},
"layers/intersection_surface.geojson": {
"contentHash": "b2022ca70339aa470f3be451bf3ba2f55b59c3900645c864538372173811309f",
"orderHash": "b2022ca70339aa470f3be451bf3ba2f55b59c3900645c864538372173811309f",
"features": 5,
"bytes": 13048
"contentHash": "8e46c1f1594022010a123fc69632100f7bd7d09e33e9decad5d53e9b5736fd2d",
"bytes": 14887
},
"layers/lane_centerlines.geojson": {
"contentHash": "19c550c794810c1071de55dee158295235106a56e3877a2ba10da920ee214593",
"orderHash": "67f8e7d33ec578644416e4837dd4aafef62a55aaeb4d438d07ab07eddfbb1df1",
"features": 84,
"bytes": 73294
"contentHash": "a768fc2382a5eb2c35b19a34836a5f74d9957b035a3c33bb21aa1ee4899c7191",
"bytes": 32242
},
"layers/lane_separators.geojson": {
"contentHash": "02fdf2c7b6e89c2850a60ea2ac72b9f62910259bdb2949681fcaa7e67d2b51f0",
"orderHash": "81782a059c4ff9f69fdf7de9107d20a8d6cf55d34bb0620ec28a9a8c5106c982",
"features": 3596,
"bytes": 4164106
"contentHash": "32fd4ff71195e48e5b087fba388b5caf9f51de40ecebbabc556d04858e2c912e",
"bytes": 2367951
},
"layers/road_surface.geojson": {
"contentHash": "5a2936a705e64338d0d79b395a13d761f1893dd72330a9b9ee4696ae75eab295",
"orderHash": "d8402ae6e772e0778b862b190abfa291de1b02a15537d455f7dcd8596245dfd8",
"features": 30,
"bytes": 49554
"contentHash": "880f4c338eceb112364e25738f94572c0c3b4aff68a53da319ef76bbda2cba61",
"bytes": 17464
},
"layers/sidewalk_surface.geojson": {
"contentHash": "b6f8f876e9f18fd2ef6749125a09d654c73d986e916bd262ceb9967bca1a54c6",
"orderHash": "3fd42a67e18e3b8743fa538428e039ef66a1f44150a6881a7aaa18326607b5cb",
"features": 26,
"bytes": 54997
"contentHash": "6d18edfe75b3149104038dcbca4d0096bbcb923f0f9fa4b49f4815344e75bb90",
"bytes": 43
},
"layers/turn_arrows.geojson": {
"contentHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8",
"orderHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8",
"features": 0,
"bytes": 52
"contentHash": "6d18edfe75b3149104038dcbca4d0096bbcb923f0f9fa4b49f4815344e75bb90",
"bytes": 43
},
"layers/vehicle_stop_lines.geojson": {
"contentHash": "cb904550ab8eec011cf33e5edfa81044de6dfca0280dbfe488e77229055ed590",
"orderHash": "8a4b877a17a5af60adc8656465afad6756944736291664139e878d46c5a4f363",
"features": 4,
"bytes": 4191
"contentHash": "6d18edfe75b3149104038dcbca4d0096bbcb923f0f9fa4b49f4815344e75bb90",
"bytes": 43
},
"traffic-signal-assemblies.json": {
"contentHash": "1788026a0c8c531b2fc7dd49628f7fbadd809c7b2f7f8819cffb3ac7d30689ca",
"orderHash": "b409ea6b77b6c8639f63c33a156581f9b184a84fde34d265b5deb05705828251",
"features": 7,
"bytes": 5411
"contentHash": "51ce257c59336d4901b478cba30facb55a284d61695ceedb22fb3a8ea881dde3",
"bytes": 3729
},
"traffic-signals.json": {
"contentHash": "625b79b6eb82b41f2099ba51960717c7f794fdfbd87310eb12e99da966540d89",
"bytes": 15491
"contentHash": "8f5a6007bce6effa49bdc613faaecbe6be2bc9f4a1bbdd5f68f8934da53587ca",
"bytes": 10068
}
},
"volatileExcluded": ["absolute paths -> <repo> or <external>", "native-road-* staging directory -> <staging>"]
}
}

View File

@@ -1,105 +1,78 @@
{
"contract": "native-road-package/v1",
"contract": "native-road-package/v1.1",
"areaId": "nantaizi-lake-innovation-valley",
"files": {
"../native-traffic-signals.json": {
"contentHash": "36cb9f069fb44a6e24f0af0d130ef8cb5b4a93250dc9fb0891191d1ba039a5b2",
"bytes": 28329
"contentHash": "35a57a62f211a6f6a3b38e0a378eddd63cb38fa9807c409d1d3c5e52c70c0d6f",
"bytes": 18111
},
"comparison.json": {
"contentHash": "5aa11da443221a48288641ac6950c6e4d75d834713a93110bbf265859202a265",
"bytes": 1153
"contentHash": "d8d4fc7d72527fce08c766f1619777a69813080a2def35652c402edd55a64a2e",
"bytes": 1015
},
"compiled.json": {
"contentHash": "ea5ae4a04f1259b1ccec9fc1cca7ef8ba81426a77584a447480b6047b37f5e01",
"bytes": 184985
"contentHash": "ba7c97c7117b882e798185e3f023b8358ff0330e9ce8fe38ee6c8d88dbbda0b6",
"bytes": 135855
},
"diagnostics.json": {
"contentHash": "7e9327f0424dd612f389c560c114a4cafee1349bbfa36f49b2b4eab846e5ca91",
"bytes": 9755
"contentHash": "05b09f50df213c162978941b5f771c970e9928d73d4f9041c4209db8ffd5d579",
"bytes": 7037
},
"layers/center_lines.geojson": {
"contentHash": "2b2710fce06e75b0a3e4941c2da6119cea7b8bb7834345607bbee384de20ee6b",
"orderHash": "ea71a8841370689d6fc2b75d0b30ec7104638fb2904da6d707dc82ff3131e065",
"features": 511,
"bytes": 694102
"contentHash": "04a2de8ac58ae27f10be9e2ee0c817b27f41e990caa65e626391cb1f3e1a18c8",
"bytes": 413551
},
"layers/connectors.geojson": {
"contentHash": "901a86bc6c536d38bb73ae4654ec1ce7d1c0790c2d6eba92543c48f584cd15ac",
"orderHash": "4df882ad59b65a97d892df64de0156b35beaf071b04eed671ef7b535e9e2a7b9",
"features": 76,
"bytes": 160866
"contentHash": "3647dfb768370d66b9b316a7a69356f6217233627804bea7e2566c27023eec05",
"bytes": 99978
},
"layers/crosswalks.geojson": {
"contentHash": "53fda76182c0d1db5f9e7ac284337ece62655d7fee8bb446fe170ea26abe8bbc",
"orderHash": "53fda76182c0d1db5f9e7ac284337ece62655d7fee8bb446fe170ea26abe8bbc",
"features": 48,
"bytes": 50536
"contentHash": "72079521c1f6891b77b226b87ee3656c113f3a72c4fb51981dfdaa9dafc4eeb2",
"bytes": 28012
},
"layers/direction_arrows.geojson": {
"contentHash": "38e80bbfe02d4f12ce40e7d0c8342e3bef6b602c64f81dd320b366b6a6b3d205",
"orderHash": "579aa6c37585bf4edf9d6b6b1e120f976b93ec2d0c303d82a154b75c114a45f5",
"features": 324,
"bytes": 493431
"contentHash": "5e60d48520fa09aa75a8aa9bb89c4701c7f5dabc4e5ce57c9dc87bdefbbf3d1c",
"bytes": 270831
},
"layers/edge_lines.geojson": {
"contentHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8",
"orderHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8",
"features": 0,
"bytes": 52
"contentHash": "6d18edfe75b3149104038dcbca4d0096bbcb923f0f9fa4b49f4815344e75bb90",
"bytes": 43
},
"layers/intersection_surface.geojson": {
"contentHash": "7f79e57215e3fd07c5c0f703c71e516873db770cb869efdf18925a3184059ca3",
"orderHash": "d69df8d92d0fce8f7ee172959b978d941fd011e094857e9ab7304b3d1e98bf92",
"features": 12,
"bytes": 38528
"contentHash": "d0620e5c1cda3fd46ca2a3c6484d1e51aa97e717b7326d118f3f2659e5d0dd95",
"bytes": 18960
},
"layers/lane_centerlines.geojson": {
"contentHash": "3fea4ebfe62e0d720c6977e2289f4e6517ed7b3c5ab361270d03378971aec780",
"orderHash": "69a8ebaa42a74da4f7d5940c5a81bd82ceb104efd3f858723dccfadbae12121e",
"features": 50,
"bytes": 43582
"contentHash": "6589ee8a94f106b05b426b320e78b86b86d390ab6c38fbc7b5bf8e28332509ed",
"bytes": 26292
},
"layers/lane_separators.geojson": {
"contentHash": "dc0b50b53da191e65f3dba01162acb7561966d1796a9c0789527cebfd6ed06a4",
"orderHash": "0bfd873e5698869fb4855783fe30bb6db29456958e4d154b7264374a5fdb4a10",
"features": 731,
"bytes": 835933
"contentHash": "545a1ed21674d7e6ead04c70eeb511ae59760f49b0a734b79d3ad01ef4f39382",
"bytes": 471152
},
"layers/road_surface.geojson": {
"contentHash": "81af19c71cf6fc8a3884488c00cfb590e1a7fe9ed9e4351fce65825ceadd50fa",
"orderHash": "f2ddec5258411fbdbc050b7ecefbb157b59e00b8226afcc30d2b772e1859e357",
"features": 25,
"bytes": 38275
"contentHash": "176e2dd1e7bc73687283eece17827d7aeaa0e3b0840a31583dd88b821a93f987",
"bytes": 20244
},
"layers/sidewalk_surface.geojson": {
"contentHash": "bb8f4516e27b16238d753b112d18b8acfa5cfad2cea522a65b7972a609be9563",
"orderHash": "4fa773a6f39c5b6d23551e1338c6d99ef8a5ecd9ebfcafa16154c9765fef8c6e",
"features": 73,
"bytes": 122432
"contentHash": "7ce873294a163973cfd4a4a439e3c55fb003e22985943165210268288fe8f690",
"bytes": 32236
},
"layers/turn_arrows.geojson": {
"contentHash": "a65bb8fe079f27e00bf2e6208148fc6b73d2d07e76d48b1cd1bf8a610d7e2d66",
"orderHash": "66966ac2c65464f9c6715ca9cda5a3620520bf1d066cba2dee36114dc46af936",
"features": 108,
"bytes": 132536
"contentHash": "599820effb9db9e497e8415f3191870baf1f1273aeb81cb4f0034f76c5ca6b40",
"bytes": 75592
},
"layers/vehicle_stop_lines.geojson": {
"contentHash": "4f45caf3c0bf13bbf10d9cac15fa80b1a9be3969ed84803ba48e56c4a0080992",
"orderHash": "4f45caf3c0bf13bbf10d9cac15fa80b1a9be3969ed84803ba48e56c4a0080992",
"features": 8,
"bytes": 8475
"contentHash": "c4cb8c3235fae7e2fd64306fe1b853d604ee1811286162f79f9ca8286b6a922f",
"bytes": 4711
},
"traffic-signal-assemblies.json": {
"contentHash": "9f8d032c00784bb72bb1322238cd7b0a80e621d435b43c728da86f1e77ca352a",
"orderHash": "0b9cae13094dba1994faca4bf1d4d80e8bc5497daa46df5899bf5e6fc7f26d61",
"features": 35,
"bytes": 26398
"contentHash": "14a66bd60cae387891dc6e29d8bdcbe4a021dc0c7f75dc3629cae6f25195959e",
"bytes": 18021
},
"traffic-signals.json": {
"contentHash": "c4b68cc1cefeb0d393a18eef6c7eb79933fba28630826745165ed433c25779d0",
"bytes": 74151
"contentHash": "f405a47d61c69ebd76f19339b54d468dfab39d7c7115417c6f790c26fc661c79",
"bytes": 47678
}
},
"volatileExcluded": ["absolute paths -> <repo> or <external>", "native-road-* staging directory -> <staging>"]
}
}

71
test/fixture-baseline.js Normal file
View File

@@ -0,0 +1,71 @@
'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('<repo>') : 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 };

View File

@@ -8,25 +8,14 @@ const path = require('path');
const { unzipSync, strFromU8 } = require('fflate');
const { compiler } = require('../src');
const { exportNativeRoadPackage } = require('../src/export/native-road-package');
const { root, fixtureInputs, snapshot, baselineFile } = require('./fixture-baseline');
const root = path.resolve(__dirname, '..');
for (const areaId of ['fengshu-er-road', 'nantaizi-lake-innovation-valley']) {
const isFengshu = areaId === 'fengshu-er-road';
const outputRoot = path.join(root, 'outputs', areaId);
const input = {
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: [] } },
};
assert.ok(fs.existsSync(path.join(root, 'test', 'baseline', `${areaId}.json`)));
for (const input of fixtureInputs()) {
assert.ok(fs.existsSync(baselineFile(input.areaId)));
const { result } = compiler.compileInput(input);
assert.equal(result.areaId, areaId);
assert.equal(result.areaId, input.areaId);
assert.ok(fs.existsSync(path.join(input.outDir, 'compiled.json')));
assert.deepEqual(snapshot(input), JSON.parse(fs.readFileSync(baselineFile(input.areaId), 'utf8')));
const first = exportNativeRoadPackage(input.outDir);
const second = exportNativeRoadPackage(input.outDir);
assert.equal(
@@ -35,7 +24,7 @@ for (const areaId of ['fengshu-er-road', 'nantaizi-lake-innovation-valley']) {
);
const entries = unzipSync(first.bytes);
const manifest = JSON.parse(strFromU8(entries['manifest.json']));
assert.equal(manifest.areaId, areaId);
assert.equal(manifest.areaId, input.areaId);
assert.equal(manifest.contract, 'native-road-package/v1.1');
assert.deepEqual(manifest.generator, { name: 'road-compiler', version: '0.3.0' });
assert.equal('source' in JSON.parse(strFromU8(entries['compiled.json'])), false);
@@ -44,9 +33,9 @@ for (const areaId of ['fengshu-er-road', 'nantaizi-lake-innovation-valley']) {
false,
);
assert.equal(Object.keys(entries).length, 18);
if (isFengshu) {
const inputFile = path.join(outputRoot, 'road-compiler-input.json');
const archive = path.join(outputRoot, 'export.zip');
if (input.areaId === 'fengshu-er-road') {
const inputFile = path.join(path.dirname(input.outDir), 'road-compiler-input.json');
const archive = path.join(path.dirname(input.outDir), 'export.zip');
fs.writeFileSync(inputFile, `${JSON.stringify(input)}\n`);
execFileSync(process.execPath, [
path.join(root, 'bin', 'road-compiler.js'),

View File

@@ -6,6 +6,7 @@ const fs = require('fs');
const os = require('os');
const path = require('path');
const { nativeRoadEdits, roadRevisions } = require('../src');
const { compileInput } = require('../src/compile/compiler');
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'road-revisions-'));
const source = '<osm version="0.6"><node id="1" lon="114.1" lat="22.5"/></osm>\n';
@@ -15,6 +16,7 @@ const signals = {
provenance: 'empty',
assemblies: { type: 'FeatureCollection', features: [] },
};
const options = { edgeLines: false, junctionTemplates: { enabled: false, references: [] } };
fs.writeFileSync(path.join(directory, 'source.osm'), source);
fs.writeFileSync(path.join(directory, 'native-road-overrides.json'), `${JSON.stringify(overrides, null, 2)}\n`);
@@ -26,19 +28,21 @@ const legacyBytes = new Map(
]),
);
const first = roadRevisions.ensureRevisionStore(directory);
const first = roadRevisions.ensureRevisionStore(directory, options);
assert.equal(first.baseline.manifest.id, 'rev-0001');
assert.equal(first.baseline.manifest.schema, roadRevisions.REVISION_SCHEMA);
assert.equal(first.active.activeRevisionId, 'rev-0001');
assert.equal(first.baseline.directEdits.schema, nativeRoadEdits.EDITS_SCHEMA);
assert.equal(first.baseline.directEdits.documentVersion, 0);
assert.equal(first.baseline.directEdits.base.areaConfigSha256, first.baseline.manifest.source.areaConfigSha256);
assert.deepEqual(first.baseline.areaConfig, options);
for (const [file, bytes] of legacyBytes)
assert.deepEqual(fs.readFileSync(path.join(directory, file)), bytes, `${file} remains byte-for-byte unchanged`);
const digest = crypto.createHash('sha256').update(source).digest('hex');
assert.equal(first.baseline.manifest.source.osmSha256, digest);
assert.equal(fs.readdirSync(path.join(directory, 'osm')).filter((file) => file.endsWith('.osm')).length, 1);
roadRevisions.ensureRevisionStore(directory);
roadRevisions.ensureRevisionStore(directory, options);
assert.equal(
fs.readdirSync(path.join(directory, 'osm')).filter((file) => file.endsWith('.osm')).length,
1,
@@ -47,6 +51,7 @@ assert.equal(
const activeEdits = nativeRoadEdits.emptyEditDocument({
osmSha256: digest,
areaConfigSha256: first.baseline.manifest.source.areaConfigSha256,
compilerGeometryVersion: 'native-road-package/v1.1',
});
activeEdits.operations = [{ id: 'op-1', createdAt: '2026-08-26T12:00:00.000Z', constraintIds: [] }];
@@ -58,6 +63,7 @@ assert.equal(checkpoint.manifest.parentRevisionId, 'rev-0001');
assert.deepEqual(checkpoint.nativeRoadOverrides, overrides);
assert.deepEqual(checkpoint.trafficSignals, signals);
assert.deepEqual(checkpoint.directEdits, activeEdits);
assert.deepEqual(checkpoint.areaConfig, options);
assert.equal(
checkpoint.manifest.digests.nativeRoadOverrides,
crypto
@@ -72,6 +78,54 @@ assert.deepEqual(
);
assert.throws(() => roadRevisions.createCheckpoint(directory, ''), /label must be a non-empty string/);
assert.throws(() => roadRevisions.readRevision(directory, '../rev-0002'), /Invalid revision id/);
const changedOptions = { edgeLines: true, junctionTemplates: { enabled: false, references: [] } };
const changedSnapshot = roadRevisions.setActiveAreaConfig(directory, changedOptions);
assert.equal(
nativeRoadEdits.loadEditDocument(path.join(directory, 'active', 'native-road-edits.json')).base.areaConfigSha256,
changedSnapshot.areaConfig.digest,
'the active document points to the current snapshot',
);
assert.equal(
nativeRoadEdits.loadEditDocument(path.join(directory, 'active', 'native-road-edits.json')).documentVersion,
1,
'updating the active snapshot is a versioned document write',
);
assert.deepEqual(
roadRevisions.readRevision(directory, 'rev-0002').areaConfig,
options,
'old revisions retain their snapshot',
);
roadRevisions.setActiveAreaConfig(directory, options);
const fixture = path.join(__dirname, 'fixtures', 'fengshu-er-road.osm');
fs.copyFileSync(fixture, path.join(directory, 'source.osm'));
const frozen = roadRevisions.createCheckpoint(directory, 'Fixture baseline');
const snapshot = path.join(directory, 'active', 'area-config.snapshot.json');
const compileBase = {
areaId: 'snapshot-test',
osmFile: path.join(directory, 'source.osm'),
outDir: path.join(directory, 'snapshot-output'),
stagingDir: path.join(directory, 'snapshot-pipeline'),
overridesFile: path.join(directory, 'native-road-overrides.json'),
trafficSignalsFile: path.join(directory, 'native-traffic-signals.json'),
options: { edgeLines: true, junctionTemplates: { enabled: false, references: [] } },
areaConfigSnapshotFile: snapshot,
};
const fromSnapshot = compileInput(compileBase);
assert.equal(fromSnapshot.area.nativeRoad.edgeLines, false, 'the snapshot wins over changed external options');
const fromRevision = compileInput({
...compileBase,
areaId: 'frozen-revision-test',
outDir: path.join(directory, 'revision-output'),
stagingDir: path.join(directory, 'revision-pipeline'),
osmFile: path.join(directory, frozen.manifest.source.osmFile),
areaConfigSnapshotFile: path.join(directory, 'revisions', frozen.manifest.id, 'area-config.snapshot.json'),
});
assert.equal(fromRevision.area.nativeRoad.edgeLines, false, 'a frozen revision ignores later external config changes');
assert.throws(
() => compileInput({ ...compileBase, areaConfigSnapshotFile: path.join(directory, 'missing.snapshot.json') }),
/Area config snapshot is missing/,
);
fs.rmSync(directory, { recursive: true, force: true });
console.log('road revision storage tests passed');

View File

@@ -0,0 +1,12 @@
'use strict';
const fs = require('fs');
const { compiler } = require('../src');
const { fixtureInputs, snapshot, baselineFile } = require('./fixture-baseline');
for (const input of fixtureInputs()) {
compiler.compileInput(input);
fs.writeFileSync(baselineFile(input.areaId), `${JSON.stringify(snapshot(input), null, 2)}\n`);
}
console.log('road compiler fixture baselines updated');