mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Merge branch 'main' of https://github.com/bilawalsidhu/gods-eye-view into pr/mapillary-layer
# Conflicts: # CHANGELOG.md # README.md
This commit is contained in:
commit
91d8bba4a3
75 files changed
+1599
-381
No files matched your search
@@ -525,6 +525,7 @@
|
||||
"src/data/cctvEstonia.test.mjs",
|
||||
"src/data/cctvWarendorf.test.mjs",
|
||||
"src/data/cctvCalgary.test.mjs",
|
||||
"src/data/cctvVegvesen.test.mjs",
|
||||
"src/data/cctvNswSource.test.mjs",
|
||||
"src/data/cctvTxdotSource.test.mjs",
|
||||
"src/layers/cctv/source.test.mjs",
|
||||
|
||||
@@ -890,6 +890,8 @@
|
||||
"src/layers/vessels/evidence.js",
|
||||
"src/layers/vessels/index.js",
|
||||
"src/layers/vessels/ingestion.js",
|
||||
"src/layers/vessels/cameraArea.js",
|
||||
"src/layers/vessels/viewArea.js",
|
||||
"src/layers/vessels/lifecycle.js",
|
||||
"src/layers/vessels/policy.js",
|
||||
"src/layers/vessels/queries.js",
|
||||
@@ -1780,7 +1782,9 @@
|
||||
"src/layers/vessels/cards.js",
|
||||
"src/layers/vessels/evidence.js",
|
||||
"src/layers/vessels/index.js",
|
||||
"src/layers/vessels/cameraArea.js",
|
||||
"src/layers/vessels/ingestion.js",
|
||||
"src/layers/vessels/viewArea.js",
|
||||
"src/layers/vessels/lifecycle.js",
|
||||
"src/layers/vessels/policy.js",
|
||||
"src/layers/vessels/queries.js",
|
||||
@@ -2481,7 +2485,9 @@
|
||||
"src/layers/vessels/cards.js",
|
||||
"src/layers/vessels/evidence.js",
|
||||
"src/layers/vessels/index.js",
|
||||
"src/layers/vessels/cameraArea.js",
|
||||
"src/layers/vessels/ingestion.js",
|
||||
"src/layers/vessels/viewArea.js",
|
||||
"src/layers/vessels/lifecycle.js",
|
||||
"src/layers/vessels/policy.js",
|
||||
"src/layers/vessels/queries.js",
|
||||
@@ -2859,6 +2865,7 @@
|
||||
"exports": ["./layers/vessels/ingestion"],
|
||||
"modules": [
|
||||
"src/layers/vessels/ingestion.js",
|
||||
"src/layers/vessels/viewArea.js",
|
||||
"src/layers/vessels/recordPolicy.js"
|
||||
],
|
||||
"external": []
|
||||
@@ -3284,6 +3291,15 @@
|
||||
],
|
||||
"external": []
|
||||
},
|
||||
"tools-panel": {
|
||||
"exports": ["./tools/panel"],
|
||||
"modules": [
|
||||
"src/tools/panel.js",
|
||||
"src/tools/globePanel.js",
|
||||
"src/app/globePanelRuntime.js"
|
||||
],
|
||||
"external": []
|
||||
},
|
||||
"tools-services": {
|
||||
"exports": ["./tools/services"],
|
||||
"modules": [
|
||||
|
||||
@@ -253,19 +253,19 @@ async function main() {
|
||||
const url = new URL(request.url());
|
||||
if (url.origin !== APP_ORIGIN) return void request.continue();
|
||||
// Silence the live feeds: the injected field is the only population.
|
||||
if (url.pathname === '/api/ais-live') {
|
||||
if (url.pathname === '/api/vessels') {
|
||||
return void request.respond(stubJson({
|
||||
rows: [], source: 'QA', status: 'open', error: null, refreshing: false,
|
||||
newestPositionAt: null, lastMessageAt: null,
|
||||
}));
|
||||
}
|
||||
if (url.pathname === '/api/adsblol/mil') {
|
||||
if (url.pathname === '/api/military') {
|
||||
return void request.respond(stubJson({ msg: 'No error', now: Date.now(), ac: [] }));
|
||||
}
|
||||
if (url.pathname === '/api/opensky') {
|
||||
if (url.pathname === '/api/flights') {
|
||||
return void request.respond(stubJson({ time: Math.floor(Date.now() / 1000), states: [] }));
|
||||
}
|
||||
if (url.pathname === '/api/opensky-track') {
|
||||
if (url.pathname === '/api/flights/track') {
|
||||
return void request.respond(stubJson({ path: [] }));
|
||||
}
|
||||
if (url.pathname === '/api/openai/hud-summary') {
|
||||
|
||||
@@ -42,7 +42,7 @@ page.on('pageerror', (error) => consoleErrors.push(error.message));
|
||||
page.on('response', (response) => {
|
||||
const url = new URL(response.url());
|
||||
const expectedOptionalTrackMiss = response.status() === 404
|
||||
&& url.pathname === '/api/opensky-track';
|
||||
&& url.pathname === '/api/flights/track';
|
||||
if (
|
||||
url.origin === new URL(appUrl).origin
|
||||
&& response.status() >= 400
|
||||
@@ -108,7 +108,7 @@ try {
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (url.origin === new URL(appUrl).origin && url.pathname === '/api/ais-live') {
|
||||
if (url.origin === new URL(appUrl).origin && url.pathname === '/api/vessels') {
|
||||
request.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
@@ -124,7 +124,7 @@ try {
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (url.origin === new URL(appUrl).origin && url.pathname === '/api/adsblol/mil') {
|
||||
if (url.origin === new URL(appUrl).origin && url.pathname === '/api/military') {
|
||||
request.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
@@ -132,7 +132,7 @@ try {
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (url.origin === new URL(appUrl).origin && url.pathname === '/api/opensky-track') {
|
||||
if (url.origin === new URL(appUrl).origin && url.pathname === '/api/flights/track') {
|
||||
request.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
@@ -832,7 +832,7 @@ try {
|
||||
await readinessPage.setRequestInterception(true);
|
||||
readinessPage.on('request', (request) => {
|
||||
const url = new URL(request.url());
|
||||
if (url.origin === new URL(appUrl).origin && url.pathname === '/api/opensky') {
|
||||
if (url.origin === new URL(appUrl).origin && url.pathname === '/api/flights') {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
request.respond({
|
||||
status: 200, contentType: 'application/json',
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* least 60 m above the rendered surface under it and under the view centre.
|
||||
*
|
||||
* Contacts: serves two synthetic aircraft through the page's own
|
||||
* /api/opensky response (one flying north over Camp Mabry at 2,500 m, one
|
||||
* /api/flights response (one flying north over Camp Mabry at 2,500 m, one
|
||||
* near Fort Cavazos) and an empty military feed, starts from a wide Texas
|
||||
* view, and presses CONTACTS as a user would. Asserts the Mapped
|
||||
* installations row lists at least one site with a distance within 15 s,
|
||||
@@ -110,7 +110,7 @@ async function openPage({ aircraft = false } = {}) {
|
||||
} catch {
|
||||
return realFetch(input, init);
|
||||
}
|
||||
if (url.origin === location.origin && url.pathname === '/api/opensky') {
|
||||
if (url.origin === location.origin && url.pathname === '/api/flights') {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const seconds = (Date.now() - started) / 1000;
|
||||
const lat = 30.29 + (seconds * 120) / 111_320;
|
||||
@@ -159,7 +159,7 @@ async function openPage({ aircraft = false } = {}) {
|
||||
};
|
||||
return Promise.resolve(Response.json(json));
|
||||
}
|
||||
if (url.origin === location.origin && url.pathname === '/api/adsblol/mil')
|
||||
if (url.origin === location.origin && url.pathname === '/api/military')
|
||||
return Promise.resolve(
|
||||
Response.json({ ac: [], now: Date.now(), total: 0 }),
|
||||
);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* honoring the politeness bounds.
|
||||
*
|
||||
* Fetch shim (installed before app code, same pattern as qa-sprites-b5.mjs):
|
||||
* - /api/opensky → 12 straight-flying planes, category 0
|
||||
* - /api/flights → 12 straight-flying planes, category 0
|
||||
* - /api/adsbdb/type/:hex → varied REAL type codes (C172, B744, DH8D, H60,
|
||||
* F16, GLID, B77W, A320, B738, PC12, R44) + one
|
||||
* found:false miss; responses are HELD until the
|
||||
@@ -260,14 +260,14 @@ async function main() {
|
||||
});
|
||||
}
|
||||
if (url.includes('/api/adsbdb/')) return Promise.resolve(jsonResponse({ found: false }));
|
||||
if (url.includes('/api/opensky-track')) return Promise.resolve(jsonResponse({ path: [] }));
|
||||
if (url.includes('/api/adsblol/trace')) {
|
||||
if (url.includes('/api/flights/track')) return Promise.resolve(jsonResponse({ path: [] }));
|
||||
if (url.includes('/api/military/track')) {
|
||||
return Promise.resolve(jsonResponse({ timestamp: Math.floor(nowSec), trace: [] }));
|
||||
}
|
||||
if (url.includes('/api/adsblol/mil')) {
|
||||
if (url.includes('/api/military')) {
|
||||
return Promise.resolve(jsonResponse({ msg: 'No error', now: Date.now(), ac: [] }));
|
||||
}
|
||||
if (url.includes('/api/opensky')) {
|
||||
if (url.includes('/api/flights')) {
|
||||
const states = S.planes.map((f) => {
|
||||
const s = S.stateAt(f, tRel);
|
||||
return [
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* upstream failures so the run is deterministic and never depends on live
|
||||
* AISStream / CelesTrak availability:
|
||||
*
|
||||
* (i) AIS invalid key — /api/ais-live is answered with
|
||||
* (i) AIS invalid key — /api/vessels is answered with
|
||||
* {rows:[],status:'error',error:'invalid key'}. Assert the layer's
|
||||
* getStats().error is set (feed down) — NOT a clean 'just now · 0'.
|
||||
*
|
||||
@@ -193,10 +193,12 @@ async function main() {
|
||||
page.on('request', (req) => {
|
||||
const url = req.url();
|
||||
// (i) AIS invalid-key: the exact payload the spec calls for.
|
||||
if (url.includes('/api/ais-live') && !url.includes('/track')) {
|
||||
if (url.includes('/api/vessels') && !url.includes('/track')) {
|
||||
req.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
// The bundled server names its vessel provider; attribution reads it.
|
||||
headers: { 'X-Feed-Source': 'AISStream' },
|
||||
body: JSON.stringify({ rows: [], status: 'error', error: 'invalid key' }),
|
||||
});
|
||||
return;
|
||||
|
||||
@@ -89,7 +89,7 @@ await page.evaluateOnNewDocument((site, icao) => {
|
||||
window.__TERRAIN.ok += 1;
|
||||
return realFetch(input, init);
|
||||
}
|
||||
if (app && url.pathname === '/api/opensky') {
|
||||
if (app && url.pathname === '/api/flights') {
|
||||
const c = window.__CONTACT;
|
||||
const t = Math.floor(Date.now() / 1000);
|
||||
// baro_altitude (7) and geo_altitude (13) both null, on_ground true.
|
||||
@@ -99,7 +99,7 @@ await page.evaluateOnNewDocument((site, icao) => {
|
||||
null, true, 1.5, 90, 0, null, null, null, false, 0]],
|
||||
}));
|
||||
}
|
||||
if (app && url.pathname === '/api/opensky-track') return Promise.resolve(json({ path: [] }));
|
||||
if (app && url.pathname === '/api/flights/track') return Promise.resolve(json({ path: [] }));
|
||||
if (app && /^\/api\/adsbdb\//.test(url.pathname)) return Promise.resolve(json({}));
|
||||
return realFetch(input, init);
|
||||
};
|
||||
|
||||
@@ -268,11 +268,11 @@ async function installSyntheticFetches(page) {
|
||||
}));
|
||||
window.fetch = (input, init) => {
|
||||
const url = typeof input === 'string' ? input : input?.url || '';
|
||||
if (url.includes('/api/opensky-track')) return json({ path: [] });
|
||||
if (url.includes('/api/adsblol/trace')) return json({ timestamp: Date.now() / 1000, trace: [] });
|
||||
if (url.includes('/api/opensky')) return json({ time: Math.floor(Date.now() / 1000), states: [] });
|
||||
if (url.includes('/api/flights/track')) return json({ path: [] });
|
||||
if (url.includes('/api/military/track')) return json({ timestamp: Date.now() / 1000, trace: [] });
|
||||
if (url.includes('/api/flights')) return json({ time: Math.floor(Date.now() / 1000), states: [] });
|
||||
if (url.includes('/api/adsbdb/')) return json({ found: false });
|
||||
if (url.includes('/api/ais-live')) return json({ status: 'open', rows: [] });
|
||||
if (url.includes('/api/vessels')) return json({ status: 'open', rows: [] });
|
||||
return realFetch(input, init);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -525,11 +525,11 @@ async function main() {
|
||||
const nowSec = Date.now() / 1000 + (T.timeOffsetSec || 0);
|
||||
const tRel = nowSec - T.epochMs / 1000;
|
||||
|
||||
if (url.includes('/api/opensky-track')) return Promise.resolve(jsonResponse({ path: [] }));
|
||||
if (url.includes('/api/adsblol/trace')) {
|
||||
if (url.includes('/api/flights/track')) return Promise.resolve(jsonResponse({ path: [] }));
|
||||
if (url.includes('/api/military/track')) {
|
||||
return Promise.resolve(jsonResponse({ timestamp: Math.floor(nowSec), trace: [] }));
|
||||
}
|
||||
if (url.includes('/api/opensky')) {
|
||||
if (url.includes('/api/flights')) {
|
||||
T.__hitsGuard = ++window.__TURN_HITS.opensky;
|
||||
const row = (id, callsign, s, altM, category) => [
|
||||
id, callsign, 'Synthetica',
|
||||
@@ -548,7 +548,7 @@ async function main() {
|
||||
if (T.heli65.active) states.push(row(T.heli65.icao, T.heli65.callsign, T.stateAt(T.heli65, tRel), T.heli65.altM, T.heli65.category));
|
||||
return Promise.resolve(jsonResponse({ time: Math.floor(nowSec), states }));
|
||||
}
|
||||
if (url.includes('/api/adsblol/mil')) {
|
||||
if (url.includes('/api/military')) {
|
||||
window.__TURN_HITS.mil++;
|
||||
const ac = T.military.map((m) => {
|
||||
const s = T.stateAt(m, tRel);
|
||||
|
||||
+10
-10
@@ -738,9 +738,9 @@ check({
|
||||
});
|
||||
|
||||
check({
|
||||
id: 'B2', group: 'B', desc: 'Flights proxy returns live contacts (/api/opensky)',
|
||||
id: 'B2', group: 'B', desc: 'Flights proxy returns live contacts (/api/flights)',
|
||||
run: async () => {
|
||||
const r = await jget('/api/opensky?lamin=24&lomin=-125&lamax=50&lomax=-66', { timeoutMs: 45000 });
|
||||
const r = await jget('/api/flights?lamin=24&lomin=-125&lamax=50&lomax=-66', { timeoutMs: 45000 });
|
||||
if (!r.ok) return fail(`HTTP ${r.status}: ${r.text.slice(0, 120)}`);
|
||||
const n = r.json?.states?.length || 0;
|
||||
return n > 0 ? pass(`${n} states, cache=${r.headers.get('x-opensky-cache') || 'n/a'}`) : fail('0 states returned');
|
||||
@@ -750,7 +750,7 @@ check({
|
||||
check({
|
||||
id: 'B3', group: 'B', desc: 'OpenSky credentials are actually in use (not the anonymous/fallback path)',
|
||||
run: async () => {
|
||||
const r = await jget('/api/opensky?lamin=24&lomin=-125&lamax=50&lomax=-66', { timeoutMs: 45000 });
|
||||
const r = await jget('/api/flights?lamin=24&lomin=-125&lamax=50&lomax=-66', { timeoutMs: 45000 });
|
||||
// Header names are exact: X-OpenSky-Auth-Mode-Used / X-OpenSky-Auth-Reason.
|
||||
// (An earlier guess at these names made this check pass vacuously.)
|
||||
const reason = r.headers.get('X-OpenSky-Auth-Reason') || '';
|
||||
@@ -826,9 +826,9 @@ check({
|
||||
});
|
||||
|
||||
check({
|
||||
id: 'B8', group: 'B', desc: 'AIS vessel feed is live (/api/ais-live)', needsKey: 'AIS',
|
||||
id: 'B8', group: 'B', desc: 'AIS vessel feed is live (/api/vessels)', needsKey: 'AIS',
|
||||
run: async () => {
|
||||
const r = await jget('/api/ais-live', { timeoutMs: 40000 });
|
||||
const r = await jget('/api/vessels', { timeoutMs: 40000 });
|
||||
const rows = r.json?.rows?.length || 0;
|
||||
const status = r.json?.status;
|
||||
if (!r.ok) return fail(`HTTP ${r.status} status=${status}`);
|
||||
@@ -864,7 +864,7 @@ check({
|
||||
const guard = keyGuard('AIS', env.keys.AIS);
|
||||
if (guard) return guard;
|
||||
if (env.keys.AIS === true) return skip('server HAS an AISStream key', 'N/A');
|
||||
const r = await jget('/api/ais-live');
|
||||
const r = await jget('/api/vessels');
|
||||
return r.status === 503 && r.json?.status === 'missing-key' && Array.isArray(r.json?.rows)
|
||||
? pass(`503 status=missing-key, rows=[] — "${String(r.json?.error).slice(0, 60)}"`)
|
||||
: fail(`expected 503/missing-key, got ${r.status} ${r.text.slice(0, 120)}`);
|
||||
@@ -1022,7 +1022,7 @@ check({
|
||||
check({
|
||||
id: 'B21', group: 'B', desc: 'No proxy echoes credential material back to the client (P1-5 acceptance #4)',
|
||||
run: async () => {
|
||||
const paths = ['/api/cctv/sources', '/api/tomtom/status', '/api/firms/status', '/api/celestrak/stations', '/api/ais-live'];
|
||||
const paths = ['/api/cctv/sources', '/api/tomtom/status', '/api/firms/status', '/api/celestrak/stations', '/api/vessels'];
|
||||
const leaked = [];
|
||||
const unscannable = [];
|
||||
for (const p of paths) {
|
||||
@@ -1036,7 +1036,7 @@ check({
|
||||
// An error page is not a payload. Scanning five 500s and finding no key
|
||||
// is trivially true and proves nothing — a broken app must not satisfy a
|
||||
// negative assertion. The one documented exception is the keyless
|
||||
// 503 {status:'missing-key'} from /api/ais-live, which IS its real shape.
|
||||
// 503 {status:'missing-key'} from /api/vessels, which IS its real shape.
|
||||
const documentedKeyless = r.status === 503
|
||||
&& (r.json?.status === 'missing-key' || r.json?.error === 'no_key' || /OPENAI_API_KEY is not set/.test(r.text));
|
||||
if (!r.ok && !documentedKeyless) {
|
||||
@@ -2071,13 +2071,13 @@ async function preflight() {
|
||||
env.keys.FIRMS = await statusKey('/api/firms/status');
|
||||
env.keys.TOMTOM = await statusKey('/api/tomtom/status');
|
||||
try {
|
||||
const ais = await jget('/api/ais-live');
|
||||
const ais = await jget('/api/vessels');
|
||||
if (ais.status === 503 && ais.json?.status === 'missing-key') env.keys.AIS = false;
|
||||
else if (ais.status === 200 && ais.json && Array.isArray(ais.json.rows)) env.keys.AIS = true;
|
||||
else env.keys.AIS = 'error';
|
||||
} catch { env.keys.AIS = 'error'; }
|
||||
try {
|
||||
const os = await jget('/api/opensky?lamin=29&lomin=-99&lamax=31&lomax=-97', { timeoutMs: 40000 });
|
||||
const os = await jget('/api/flights?lamin=29&lomin=-99&lamax=31&lomax=-97', { timeoutMs: 40000 });
|
||||
const reason = os.headers.get('X-OpenSky-Auth-Reason') || '';
|
||||
const used = os.headers.get('X-OpenSky-Auth-Mode-Used') || os.headers.get('X-OpenSky-Auth') || '';
|
||||
if (!os.ok) env.keys.OPENSKY = 'error';
|
||||
|
||||
@@ -180,7 +180,7 @@ async function installDeterministicDevEndpoints(page) {
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (url.pathname === '/api/ais-live') {
|
||||
if (url.pathname === '/api/vessels') {
|
||||
await request.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
|
||||
@@ -219,7 +219,7 @@ async function main() {
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (url.origin === APP_ORIGIN && url.pathname === '/api/ais-live') {
|
||||
if (url.origin === APP_ORIGIN && url.pathname === '/api/vessels') {
|
||||
request.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
|
||||
@@ -229,11 +229,11 @@ async function main() {
|
||||
const nowSec = Date.now() / 1000 + (S.timeOffsetSec || 0);
|
||||
const tRel = nowSec - S.epochMs / 1000;
|
||||
|
||||
if (url.includes('/api/opensky-track')) return Promise.resolve(jsonResponse({ path: [] }));
|
||||
if (url.includes('/api/adsblol/trace')) {
|
||||
if (url.includes('/api/flights/track')) return Promise.resolve(jsonResponse({ path: [] }));
|
||||
if (url.includes('/api/military/track')) {
|
||||
return Promise.resolve(jsonResponse({ timestamp: Math.floor(nowSec), trace: [] }));
|
||||
}
|
||||
if (url.includes('/api/opensky')) {
|
||||
if (url.includes('/api/flights')) {
|
||||
window.__SPR_HITS.opensky++;
|
||||
const states = S.flights.map((f) => {
|
||||
const s = S.stateAt(f, tRel);
|
||||
@@ -249,7 +249,7 @@ async function main() {
|
||||
});
|
||||
return Promise.resolve(jsonResponse({ time: Math.floor(nowSec), states }));
|
||||
}
|
||||
if (url.includes('/api/adsblol/mil')) {
|
||||
if (url.includes('/api/military')) {
|
||||
window.__SPR_HITS.mil++;
|
||||
const ac = S.military.map((m) => {
|
||||
const s = S.stateAt(m, tRel);
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
* `fetch` shim in the page that intercepts the poll endpoints and returns
|
||||
* SYNTHETIC aircraft positioned near the camera, in the EXACT upstream payload
|
||||
* shapes the layers parse:
|
||||
* - flights → GET /api/opensky → { states: [ <state-vector[]> ] }
|
||||
* - military → GET /api/adsblol/mil → { ac: [ <adsblol-aircraft{}> ] }
|
||||
* - vessels → GET /api/ais-live → connected, zero-row snapshot
|
||||
* - flights → GET /api/flights → { states: [ <state-vector[]> ] }
|
||||
* - military → GET /api/military → { ac: [ <adsblol-aircraft{}> ] }
|
||||
* - vessels → GET /api/vessels → connected, zero-row snapshot
|
||||
* The shim stays installed so the layers' setInterval pollers keep the
|
||||
* synthetic planes alive (under MISSING_POLL_LIMIT=3 so they're never pruned).
|
||||
*
|
||||
@@ -343,7 +343,7 @@ async function main() {
|
||||
const url = new URL(requestUrl, window.location.href);
|
||||
const isAppRequest = url.origin === appOrigin;
|
||||
// OpenSky (commercial flights): { states: [ state-vector[] ] }
|
||||
if (isAppRequest && url.pathname === '/api/opensky') {
|
||||
if (isAppRequest && url.pathname === '/api/flights') {
|
||||
window.__SYNTH_HITS.opensky++;
|
||||
// A withheld contact models the ordinary case where the recipient's
|
||||
// first authoritative refresh does not yet carry the shared aircraft.
|
||||
@@ -371,11 +371,11 @@ async function main() {
|
||||
// Trail backfill (fires on trackById). Stub with valid-but-empty
|
||||
// payloads so the deterministic run never 404s against the dev proxy.
|
||||
// flights: { path: [ [time, lat, lon, baroAlt, true_track, on_ground] ] }
|
||||
if (isAppRequest && url.pathname === '/api/opensky-track') {
|
||||
if (isAppRequest && url.pathname === '/api/flights/track') {
|
||||
return Promise.resolve(jsonResponse({ path: [] }));
|
||||
}
|
||||
// military: { timestamp: <epochSec>, trace: [ [secAfter, lat, lon, ...] ] }
|
||||
if (isAppRequest && url.pathname === '/api/adsblol/trace') {
|
||||
if (isAppRequest && url.pathname === '/api/military/track') {
|
||||
return Promise.resolve(jsonResponse({ timestamp: Math.floor(Date.now() / 1000), trace: [] }));
|
||||
}
|
||||
// adsbdb enrichment (fires for tracked/model-eligible planes): empty
|
||||
@@ -388,7 +388,7 @@ async function main() {
|
||||
// Contacts enables the optional AIS source alongside aircraft. Keep
|
||||
// this tracking harness independent of local AIS credentials while
|
||||
// preserving the truthful "awaiting first message" lifecycle.
|
||||
if (isAppRequest && url.pathname === '/api/ais-live') {
|
||||
if (isAppRequest && url.pathname === '/api/vessels') {
|
||||
return Promise.resolve(jsonResponse({
|
||||
status: 'connected',
|
||||
rows: [],
|
||||
@@ -450,7 +450,7 @@ async function main() {
|
||||
return Promise.resolve(jsonResponse({ places: [] }));
|
||||
}
|
||||
// adsb.lol military: { ac: [ aircraft{} ] } (must come AFTER /trace check)
|
||||
if (isAppRequest && url.pathname === '/api/adsblol/mil') {
|
||||
if (isAppRequest && url.pathname === '/api/military') {
|
||||
window.__SYNTH_HITS.mil++;
|
||||
const ac = window.__SYNTH.military.map((m) => ({
|
||||
hex: m.hex,
|
||||
|
||||
Reference in new issue
Block a user