feat: ask for vessels by area

The vessel source accepts an optional area and sends it as lat, lon and
radius_km. The vessel layer asks for the area the camera shows (centered
on the middle of the screen, sized by camera height), or every vessel
from high enough up, and asks again when the view moves or zooms by a
quarter of that radius. vessels_in_area names its area too. Servers that
hold every vessel may ignore the area; callers still keep only what is
inside it.
This commit is contained in:
Sameh Khamis committed 2026-10-03 22:44:45 -07:00
1 parent 88b8406073
commit e8e49a49e0
11 files changed
+240 -8

No files matched your search

+23
View File
@@ -201,3 +201,26 @@ test('vessel searches ask for every vessel the server retains', async () => {
for (const maxRows of requested)
assert.ok(Number(maxRows) >= AISSTREAM_CACHE_MAX, maxRows);
});
test('an area search names its area to the server; a vessel lookup asks for every vessel', async () => {
const requested = [];
const source = createAisStreamSource({
origin: () => 'http://localhost',
fetchImpl: async (url) => {
requested.push(new URL(url).searchParams);
return Response.json({ rows: [], source: 'AISStream', status: 'live' });
},
});
const catalog = composeCatalog({
tools: coreTools,
services: { vessels: source },
});
await catalog.call('vessels_in_area', { area: bay });
await catalog.call('find_vessel', { mmsi: '366999712' });
const [area, lookup] = requested;
assert.equal(area.get('lat'), '37.78000');
assert.equal(area.get('lon'), '-122.40000');
assert.equal(area.get('radius_km'), '20.0');
assert.equal(lookup.has('lat'), false);
assert.equal(lookup.has('radius_km'), false);
});