feat: compile revisions from area config snapshots
This commit is contained in:
@@ -9,7 +9,7 @@ const { generate, validateDocument, runtime } = require('../src/native-traffic-s
|
||||
const { convertGeoJson } = require('../src/reference/gaode');
|
||||
const { exportNativeRoadPackage } = require('../src/export/native-road-package');
|
||||
const { compileInput } = require('../src/compile/compiler');
|
||||
const { ensureRevisionStore } = require('../src/compile/road-revisions');
|
||||
const { ensureRevisionStore, setActiveAreaConfig } = require('../src/compile/road-revisions');
|
||||
|
||||
function startWorkbench({
|
||||
area = null,
|
||||
@@ -39,7 +39,7 @@ function startWorkbench({
|
||||
};
|
||||
if (input) {
|
||||
session.context.compileFresh = () => {
|
||||
const compiled = compileInput(input);
|
||||
const compiled = compileWorkbenchInput(input);
|
||||
session.area = compiled.area;
|
||||
return compiled;
|
||||
};
|
||||
@@ -143,16 +143,15 @@ function handle(request, response, session) {
|
||||
.then((body) => {
|
||||
if (!area) throw new Error('请先导入 OSM 文件。');
|
||||
if (!debug) throw new Error('该接口仅在 --debug 模式下可用。');
|
||||
const added = addJunctionCluster(
|
||||
context.configPath,
|
||||
body,
|
||||
readCompiled(area),
|
||||
context.readAreaConfig,
|
||||
context.repoRoot,
|
||||
);
|
||||
const added = addJunctionCluster(body, readCompiled(area), area.nativeRoad);
|
||||
setActiveAreaConfig(path.dirname(area.input), added.options);
|
||||
context.compileFresh();
|
||||
const refreshed = context.readAreaConfig(context.configPath, { repoRoot: context.repoRoot });
|
||||
sendJson(response, 200, { ok: true, added, ...state(refreshed, junctionReference, debug) });
|
||||
sendJson(response, 200, {
|
||||
ok: true,
|
||||
added: added.cluster,
|
||||
configSnippet: { nativeRoad: { junctionTemplates: added.options.junctionTemplates } },
|
||||
...state(session.area, junctionReference, debug),
|
||||
});
|
||||
})
|
||||
.catch((error) => sendJson(response, 400, { ok: false, error: error.message }));
|
||||
if (request.method === 'POST' && url.pathname === '/api/compile')
|
||||
@@ -170,7 +169,7 @@ function handle(request, response, session) {
|
||||
function state(area, junctionReference = null, debug = false) {
|
||||
// This is the read entry point for both a fresh import and a reopened legacy
|
||||
// workspace. Initialization only adds the v2 layout; it never rewrites v1 files.
|
||||
ensureRevisionStore(path.dirname(area.input));
|
||||
ensureRevisionStore(path.dirname(area.input), area.nativeRoad);
|
||||
const nativeDir = area.outputs.nativeRoadDir;
|
||||
const osm2streetsRoadSurface = area.outputs.geojsonDir
|
||||
? path.join(area.outputs.geojsonDir, 'road_surface.geojson')
|
||||
@@ -214,18 +213,16 @@ function state(area, junctionReference = null, debug = false) {
|
||||
// The compiler reports candidates as advisory diagnostics. Lift them into their
|
||||
// own payload with a stable index so the map can label them "#1, #2, ..." and
|
||||
// the inspector can offer a ready-to-paste cluster配置.
|
||||
// Append one detected cluster to the hand-authored area config. The candidate
|
||||
// Append one detected cluster to the active area-config snapshot. The candidate
|
||||
// must still be present in the latest compile, so a stale browser tab cannot
|
||||
// write a cluster that no longer exists. The edited config is validated by the
|
||||
// real loader before it replaces the file: an invalid write would break every
|
||||
// later command, and the file is git-tracked so a bad accept stays revertible.
|
||||
function addJunctionCluster(configPath, body, compiled, readAreaConfig, repoRoot) {
|
||||
// write a cluster that no longer exists. The external config remains untouched;
|
||||
// the response carries a copyable snippet while future compiles use the snapshot.
|
||||
function addJunctionCluster(body, compiled, options) {
|
||||
const index = Number(body?.index);
|
||||
if (!Number.isInteger(index)) throw new Error('请求缺少候选编号 index。');
|
||||
const candidate = junctionCandidates(compiled).find((item) => item.index === index);
|
||||
if (!candidate) throw new Error(`候选 #${index} 不在最新一次编译结果里,请刷新页面后重试。`);
|
||||
const raw = readJson(configPath);
|
||||
const templates = raw.nativeRoad?.junctionTemplates;
|
||||
const templates = options?.junctionTemplates;
|
||||
if (!templates) throw new Error('区域配置缺少 nativeRoad.junctionTemplates,请先手工建立该节点。');
|
||||
const clusters = Array.isArray(templates.clusters) ? templates.clusters : [];
|
||||
const taken = new Set(clusters.flatMap((cluster) => (cluster.nodeIds || []).map(String)));
|
||||
@@ -240,24 +237,11 @@ function addJunctionCluster(configPath, body, compiled, readAreaConfig, repoRoot
|
||||
outerRadiusExtraMeters: 18,
|
||||
nodeIds: candidate.nodeIds.map(String),
|
||||
};
|
||||
const next = {
|
||||
...raw,
|
||||
nativeRoad: {
|
||||
...raw.nativeRoad,
|
||||
junctionTemplates: { ...templates, enabled: true, clusters: [...clusters, cluster] },
|
||||
},
|
||||
const nextOptions = {
|
||||
...options,
|
||||
junctionTemplates: { ...templates, enabled: true, clusters: [...clusters, cluster] },
|
||||
};
|
||||
const staging = `${configPath}.candidate-${process.pid}.json`;
|
||||
fs.writeFileSync(staging, `${JSON.stringify(next, null, 2)}\n`);
|
||||
try {
|
||||
readAreaConfig(staging, { repoRoot });
|
||||
} catch (error) {
|
||||
fs.unlinkSync(staging);
|
||||
throw new Error(`写入后的配置无法通过校验,已放弃:${error.message}`);
|
||||
}
|
||||
fs.unlinkSync(staging);
|
||||
writeJsonAtomic(configPath, next);
|
||||
return cluster;
|
||||
return { cluster, options: nextOptions };
|
||||
}
|
||||
function uniqueClusterId(base, taken) {
|
||||
if (!taken.has(base)) return base;
|
||||
@@ -328,8 +312,7 @@ function readUpload(request, session) {
|
||||
),
|
||||
);
|
||||
try {
|
||||
const compiled = compileInput(input);
|
||||
ensureRevisionStore(root);
|
||||
const compiled = compileWorkbenchInput(input);
|
||||
session.area = compiled.area;
|
||||
return compiled;
|
||||
} catch (error) {
|
||||
@@ -338,6 +321,11 @@ function readUpload(request, session) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function compileWorkbenchInput(input) {
|
||||
const workspace = path.dirname(input.osmFile);
|
||||
const initialized = ensureRevisionStore(workspace, input.options);
|
||||
return compileInput({ ...input, areaConfigSnapshotFile: initialized.paths.activeAreaConfig });
|
||||
}
|
||||
function readMultipart(request, limit) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const type = request.headers['content-type'] || '';
|
||||
|
||||
Reference in New Issue
Block a user