mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
Merge feat/voice-geometry onto main
Both stack parents (#837, #842) are on main, so the voice geometry branch now builds on main directly. Conflict resolutions keep main's behaviour and add the geometry work on top: osm_query gating on every provider, restored admin identity for Nominatim outlines, merged analyst follow-up memory, and the cancelled Globe View reset instruction ahead of the generic cancellation.
This commit is contained in:
commit
ecaddd838b
102 files changed
+12925
-1006
No files matched your search
@@ -159,6 +159,8 @@ export function createNominatimOutlineClient({
|
||||
const outline = {
|
||||
polygons,
|
||||
name: body.outline.name || null,
|
||||
adminArea: body.outline.adminArea || null,
|
||||
adminLevel: body.outline.adminLevel || null,
|
||||
class: body.outline.class || null,
|
||||
type: body.outline.type || null,
|
||||
osm: body.outline.osm || null,
|
||||
|
||||
@@ -44,20 +44,29 @@ test('an accepted outline comes back with its polygons and is remembered', async
|
||||
reply(200, {
|
||||
status: 'OK',
|
||||
outline: {
|
||||
name: 'Paris',
|
||||
name: 'Bagmati Province',
|
||||
adminArea: 'Bagmati Province',
|
||||
adminLevel: 'admin1',
|
||||
class: 'boundary',
|
||||
type: 'administrative',
|
||||
polygons: [[ring, hole]],
|
||||
},
|
||||
}),
|
||||
);
|
||||
const ask = { query: 'Paris', kind: 'city', lat: 48.85, lon: 2.35 };
|
||||
const ask = {
|
||||
query: 'Bagmati Province',
|
||||
kind: 'admin',
|
||||
lat: 27.72,
|
||||
lon: 85.32,
|
||||
};
|
||||
const outline = await lookup(ask);
|
||||
assert.deepEqual(outline.polygons, [[ring, hole]]);
|
||||
assert.equal(outline.class, 'boundary');
|
||||
assert.equal(outline.adminArea, 'Bagmati Province');
|
||||
assert.equal(outline.adminLevel, 'admin1');
|
||||
assert.match(
|
||||
calls[0],
|
||||
/^\/api\/geocode\/outline\?q=Paris&kind=city&lat=48\.850&lon=2\.350$/,
|
||||
/^\/api\/geocode\/outline\?q=Bagmati\+Province&kind=admin&lat=27\.720&lon=85\.320$/,
|
||||
);
|
||||
await lookup(ask);
|
||||
assert.equal(calls.length, 1, 'one request per ask in a session');
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Browser client for `/api/osm/features`: one curated preset inside a box,
|
||||
* as a count or as features. The server writes and bounds the Overpass
|
||||
* query and answers only when an operator configured Overpass; this only
|
||||
* names the preset, box, mode and limit.
|
||||
* @module sources/osmFeatures
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {{fetchImpl?: typeof fetch, endpoint?: string}} [options]
|
||||
* @returns {(request: {preset: string, bbox: number[], mode?: 'count'|'features', limit?: number}, options?: {signal?: AbortSignal}) => Promise<object>}
|
||||
*/
|
||||
export function createOsmFeatureSource({
|
||||
fetchImpl = (...args) => globalThis.fetch(...args),
|
||||
endpoint = '/api/osm/features',
|
||||
} = {}) {
|
||||
return async function searchOsmFeatures(
|
||||
{ preset, bbox, mode = 'features', limit },
|
||||
{ signal } = {},
|
||||
) {
|
||||
const params = new URLSearchParams({
|
||||
preset,
|
||||
bbox: bbox.map((v) => Number(v).toFixed(5)).join(','),
|
||||
mode,
|
||||
});
|
||||
if (Number.isFinite(limit)) params.set('limit', String(limit));
|
||||
let response;
|
||||
try {
|
||||
response = await fetchImpl(`${endpoint}?${params}`, { signal });
|
||||
} catch (error) {
|
||||
if (signal?.aborted) throw error;
|
||||
return {
|
||||
ok: false,
|
||||
status: 0,
|
||||
error: 'OpenStreetMap search is unreachable.',
|
||||
};
|
||||
}
|
||||
let body = null;
|
||||
try {
|
||||
body = await response.json();
|
||||
} catch {
|
||||
body = null;
|
||||
}
|
||||
if (!response.ok)
|
||||
return {
|
||||
ok: false,
|
||||
status: response.status,
|
||||
code: body?.code || null,
|
||||
error:
|
||||
body?.error || `OpenStreetMap search failed (${response.status}).`,
|
||||
};
|
||||
return { ok: true, ...body };
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user