feat: name live feed routes and sources for what they serve

The flight, military and vessel feeds were named after the providers the
bundled server uses (/api/opensky, /api/adsblol/mil, /api/ais-live and
their track routes; createOpenSkySource, createAdsbLolSource,
createAisStreamSource). Any server should be able to answer a feed from
its own provider, so the feeds are now:

  /api/flights   /api/flights/track?icao24=
  /api/military  /api/military/track?hex=
  /api/vessels   /api/vessels/track?mmsi=

with createFlightSource, createMilitarySource and createVesselSource. The
old routes are removed. Each server names its provider in X-Feed-Source
(the bundled server sends OpenSky Network, adsb.lol and AISStream, so its
attribution is unchanged) and the military feed's cache state and age in
X-Feed-Cache and X-Feed-Age-Ms. Sources report the provider the server
names and fall back to the feed's name.
This commit is contained in:
Sameh Khamis committed 2026-10-03 23:10:32 -07:00
1 parent 5bf3beea84
commit 60644c5f5d
43 files changed
+564 -312

No files matched your search

+2 -2
View File
@@ -189,7 +189,7 @@ test('a conversion survives a poll refresh, in both the billboard and the tracke
const realFetch = globalThis.fetch;
const nowSec = Math.floor(Date.now() / 1000);
globalThis.fetch = async (url) => {
if (!String(url).startsWith('/api/opensky')) {
if (!String(url).startsWith('/api/flights')) {
return { ok: true, status: 200, json: async () => ({ ac: [] }) };
}
return {
@@ -309,7 +309,7 @@ test('conversions are session-scoped and no lifecycle path clears them', async (
meta: { callsign: 'OLD1', altitude: 9_000, klass: 'airliner', rawLat: 30.2, rawLon: -97.7 },
});
const realFetch = globalThis.fetch;
globalThis.fetch = async (url) => (String(url).startsWith('/api/opensky')
globalThis.fetch = async (url) => (String(url).startsWith('/api/flights')
? { ok: true, status: 200, headers: { get: () => null }, json: async () => ({ time: 0, states: [] }) }
: { ok: true, status: 200, json: async () => ({ ac: [] }) });
try {