chore: drop exports nothing imports

Knip, configured with the application, package exports, scripts, QA
harnesses, workers, tools and tests as entry points, reports exports
that no module imports. Each was checked by hand against string-based
and namespace imports.

- Symbols that are still used inside their own module lose only the
  `export` keyword (176 constants and helpers).
- Unused re-exports are removed from barrel modules (flight, military,
  vessel, CCTV, directions, transit history, local ADS-B and street-level
  policy modules).
- Declarations that nothing uses at all are deleted, among them
  AIS_WATCHDOG_STATUSES, applyFilter, isRadioCountryCode, compactText,
  DENSITY_STOPS, the unused CCTV endpoint constants, and the SDR band
  constants.
- Default exports that nothing imports are removed. The ones in
  src/data/earthquakes.js, src/data/telegeographySubmarineCables.js,
  src/data/wind.js and src/data/bhoteKoshiLocator.js each constructed a
  layer instance at import time that nothing used; those instances are
  no longer created.

Every export of a package.json entry stays, as does TOMTOM_CREDIT,
which the traffic layer reads from the credits namespace it is given.
This commit is contained in:
Sameh Khamis committed 2026-10-22 19:00:40 -07:00
1 parent 504f9342aa
commit 73e789489b
106 files changed
+180 -342

No files matched your search

+3 -3
View File
@@ -1,11 +1,11 @@
import { QUERY_LIMIT, QUERY_SNAP_DEGREES } from './policy.js';
export function textTag(value) {
function textTag(value) {
const t = String(value ?? '').trim();
return t || null;
}
export function numTag(value) {
function numTag(value) {
// `Number('')` and `Number(' ')` are 0, not NaN — a blank or whitespace-only
// tag value must read as missing, never as a due-north bearing.
if (value == null) return null;
@@ -102,7 +102,7 @@ export function normalizeAlprNode(el) {
};
}
export function normalizeDirection(value) {
function normalizeDirection(value) {
const degrees = numTag(value);
return degrees != null && degrees >= 0 && degrees <= 360
? degrees % 360
+1 -1
View File
@@ -3,7 +3,7 @@ import { VectorTile } from '@mapbox/vector-tile';
import { normalizeAlprNode } from './records.js';
/** Map extract attributes without treating an OSM edit date as a field verification. */
export function normalizeAlprTileFeature(feature) {
function normalizeAlprTileFeature(feature) {
const p = feature?.properties || {};
if (feature?.geometry?.type !== 'Point' || p.osmType !== 'node') return null;
const [lon, lat] = feature.geometry.coordinates;
+1 -4
View File
@@ -1,9 +1,6 @@
export const AIRCRAFT_DEPENDENCIES = ['flights', 'military'];
export const DEFERRED_DEPENDENCIES = [
'ais-live-vessels',
'military-installations',
];
const DEFERRED_DEPENDENCIES = ['ais-live-vessels', 'military-installations'];
export const DEPENDENCIES = [
...AIRCRAFT_DEPENDENCIES,
+1 -1
View File
@@ -11,7 +11,7 @@ export const BIKESHARE_SELECTED_OVERLAY_SOURCE_OPTIONS = Object.freeze({
// --- Activation / display thresholds ---
/** Altitude (m) at which bikeshare layer becomes eligible for display. */
export const ACTIVATION_ALTITUDE_M = 50000;
const ACTIVATION_ALTITUDE_M = 50000;
/** Hysteresis enter threshold — layer activates when camera drops below this. */
+1 -10
View File
@@ -1,10 +1,4 @@
export {
FRAME_ENDPOINT,
SOURCE_ENDPOINT,
HEALTH_ENDPOINT,
MEDIA_ENDPOINT,
ACTIVE_FRAME_REFRESH_MS,
} from './sourcePolicy.js';
export { ACTIVE_FRAME_REFRESH_MS } from './sourcePolicy.js';
import * as Cesium from 'cesium';
import { CCTV_CARD_FETCH_BURST_SPACING_MS } from '../../data/cctvCards.js';
import { CCTV_AMBIENT_CARD_MAX } from '../../data/cctvLod.js';
@@ -90,9 +84,6 @@ export const CCTV_CALIBRATION_STORAGE_KEY_V2 =
export const PROJECTION_TEXTURE_SWAP_MS = 1000;
export const PROJECTION_VERT_ASPECT =
PROJECTION_CANVAS_WIDTH / PROJECTION_CANVAS_HEIGHT;
// V2 frustum geometry (design §2a/§6): the far-cap center + corners never sink
// below groundAlt + this clearance, so a fabricated pitch (-24°) cannot bury
// the monitor plane in the 3D tiles. Exported for the unit suite.
-4
View File
@@ -1,9 +1,5 @@
export const FRAME_ENDPOINT = '/api/cctv/frame';
export const SOURCE_ENDPOINT = '/api/cctv/sources';
export const HEALTH_ENDPOINT = '/api/cctv/health';
export const MEDIA_ENDPOINT = '/api/cctv/media';
export const ACTIVE_FRAME_REFRESH_MS = 10000;
+2 -2
View File
@@ -64,7 +64,7 @@ const SHARED_CARD = Object.freeze({
* @param {boolean} selected
* @returns {object}
*/
export function cycloneStormEntry(storm, selected) {
function cycloneStormEntry(storm, selected) {
return {
...SHARED_CARD,
...markerClearance(
@@ -92,7 +92,7 @@ export function cycloneStormEntry(storm, selected) {
* @param {{tauHours:number,position:object}} point
* @returns {object}
*/
export function cycloneLeadEntry(stormId, point) {
function cycloneLeadEntry(stormId, point) {
return {
...SHARED_CARD,
...markerClearance(CYCLONE_MARKER_PX.forecast),
-8
View File
@@ -1,11 +1,3 @@
export {
GROUND_FLOOR_CLAMP_RADIUS_KM,
GROUND_FLOOR_WARM_MAX_ALT_M,
POSITION_HISTORY_LIMIT,
LANDED_MISSING_POLL_LIMIT,
MISSING_POLL_LIMIT,
ERROR_BACKOFF_INTERVAL,
} from './recordPolicy.js';
import * as Cesium from 'cesium';
import { EMERGENCY_TINT_CSS } from '../../data/aircraftEmergency.js';
-2
View File
@@ -2,8 +2,6 @@ export const LAYER_ID = 'military-installations';
export const REQUEST_DEBOUNCE_MS = 180;
export const MAX_VIEWPORT_DEGREES = 10;
export const MAX_RENDERED = 700;
export const GOOGLE_MILITARY_PLACE_TYPES = new Set(['military_base']);
+2 -2
View File
@@ -5,12 +5,12 @@ import {
/** Same-origin route served by `server/providers/local-receivers.js`. */
export const LOCAL_RECEIVERS_URL = '/api/local-receivers/aircraft';
export const LOCAL_RECEIVER_POLL_MS = 1_000;
const LOCAL_RECEIVER_POLL_MS = 1_000;
/**
* Browser-side deadline for one route request, body included. The server
* bounds each upstream read at 2 s; this bounds the browser-to-server leg.
*/
export const LOCAL_RECEIVER_REQUEST_TIMEOUT_MS = 5_000;
const LOCAL_RECEIVER_REQUEST_TIMEOUT_MS = 5_000;
function abortError() {
const error = new Error('Local receiver request aborted');
+2 -12
View File
@@ -36,18 +36,8 @@ import {
} from './policy.js';
import { localAdsbStatus } from './status.js';
export {
LAYER_ID as LOCAL_ADSB_LAYER_ID,
HEARD_BY_RECEIVER,
} from './policy.js';
export {
localAdsbCardModel,
localAdsbClassLine,
localAdsbIsUat,
localAdsbReceiverLine,
localAdsbTitle,
} from './card.js';
export { localAdsbClass } from './enrichment.js';
export { HEARD_BY_RECEIVER } from './policy.js';
export { localAdsbCardModel, localAdsbReceiverLine } from './card.js';
export { localAdsbStatus } from './status.js';
const FEET_TO_METERS = 0.3048;
+1 -1
View File
@@ -26,7 +26,7 @@ import {
export const LOCAL_ADSB_HISTORY_MS = 10 * 60_000;
export const LOCAL_ADSB_HISTORY_POINTS = 600;
/** A display correction larger than this snaps instead of sliding. */
export const LOCAL_ADSB_SNAP_M = 3_000;
const LOCAL_ADSB_SNAP_M = 3_000;
/** Chord course uses the newest fix at least this much older than the anchor. */
const CHORD_BASELINE_MS = 2_000;
/** Turn rate is estimated over this window of heard fixes. */
+2 -2
View File
@@ -24,7 +24,7 @@ function plural(count, one, many) {
* @param {object[]} feeds Feed statuses from the route.
* @returns {string}
*/
export function describeFeedProblems(feeds) {
function describeFeedProblems(feeds) {
const byStatus = new Map();
for (const feed of feeds) {
if (feed?.status === 'live') continue;
@@ -41,7 +41,7 @@ export function describeFeedProblems(feeds) {
}
/** Whether the server reported at least one configured feed. */
export function feedsConfigured(feedState) {
function feedsConfigured(feedState) {
return Boolean(
feedState?.configured === true &&
Array.isArray(feedState.feeds) &&
-7
View File
@@ -1,10 +1,3 @@
export {
GROUND_FLOOR_WARM_MAX_ALT_M,
POSITION_HISTORY_LIMIT,
LANDED_MISSING_POLL_LIMIT,
MISSING_POLL_LIMIT,
ERROR_BACKOFF_INTERVAL,
} from './recordPolicy.js';
import * as Cesium from 'cesium';
import { EMERGENCY_TINT_CSS } from '../../data/aircraftEmergency.js';
+1 -1
View File
@@ -10,7 +10,7 @@ export const MARKER_LIFT_M = 2.5;
export const SELECTED_LIFT_M = 5;
export const RADIO_PICK_TOLERANCE_PX = 8;
const RADIO_PICK_TOLERANCE_PX = 8;
export const RADIO_TUNER_DIRECTORY_LIMIT = 750;
+1 -1
View File
@@ -300,7 +300,7 @@ export function hhmm(iso) {
}
/** Candidate key: `PRODUCT:YYYY-MM-DD`. */
export function candidateKey(product, day) {
function candidateKey(product, day) {
return `${product}:${day}`;
}
+2 -2
View File
@@ -94,9 +94,9 @@ export const TRACK_VIEW_FROM_HIGH_SCALE = 4;
* attribute, so classification costs nothing per frame.
*/
export const POINT_OUTLINE = Cesium.Color.WHITE.withAlpha(0.3);
const POINT_OUTLINE = Cesium.Color.WHITE.withAlpha(0.3);
export const _classColor = (group) =>
const _classColor = (group) =>
Cesium.Color.fromCssColorString(satelliteClassColor(group));
export const POINT_STYLES = {
+5 -5
View File
@@ -17,18 +17,18 @@ const EXPANDED_SELECTORS = [
];
/** A photo download (tens of kilobytes to a few megabytes). */
export const IMAGE_TIMEOUT_MS = 15_000;
const IMAGE_TIMEOUT_MS = 15_000;
/** A picture file or decoded side past these is refused (a photo is a few MB). */
export const MAX_IMAGE_BYTES = 48 * 1024 * 1024;
export const MAX_IMAGE_SIDE = 16_384;
/** 64 MP: 256 MB once decoded to RGBA. A 16,384 px square is four times that. */
export const MAX_IMAGE_PIXELS = 8_192 * 8_192;
const MAX_IMAGE_PIXELS = 8_192 * 8_192;
/** Where in a file to look for its dimensions (a JPEG's EXIF comes first). */
const HEADER_BYTES = 256 * 1024;
/** Whether a picture this size is past what the viewer decodes. */
export function tooManyPixels(width, height) {
function tooManyPixels(width, height) {
return (
width > MAX_IMAGE_SIDE ||
height > MAX_IMAGE_SIDE ||
@@ -37,7 +37,7 @@ export function tooManyPixels(width, height) {
}
/** Panorama texture widths: enough for a docked viewer, and for an expanded one. */
export const PANO_MID_SIZE = Object.freeze([2048, 1024]);
const PANO_MID_SIZE = Object.freeze([2048, 1024]);
export const PANO_FULL_SIZE = Object.freeze([4096, 2048]);
/**
@@ -155,7 +155,7 @@ async function loadBitmap(url, timeoutMs, resize, failure, signal) {
* A picture refused for its size (`tooLarge`): the viewer will not load
* that file another way, an <img> having no size limit at all.
*/
export function oversized(failure) {
function oversized(failure) {
return Object.assign(new Error(failure), { tooLarge: true });
}
@@ -14,7 +14,7 @@ export const KARTAVIEW_LABEL = 'KARTAVIEW';
*/
export const KARTAVIEW_API_HOST = 'https://api.kartaview.org';
/** KartaView's image proxy: resizes a photo given its base64url address. */
export const KARTAVIEW_CDN_HOST = 'https://cdn.kartaview.org';
const KARTAVIEW_CDN_HOST = 'https://cdn.kartaview.org';
/** Stable id prefixes for picked primitives; every one starts with `kv:`. */
export const PICK_PREFIX = Object.freeze({
@@ -140,8 +140,6 @@ export const MASK_SLOW_MESSAGE = msg(
export const FILTERED_OUT_MESSAGE = msg(
'None of KartaView’s photos here pass the imagery filter',
);
/** Under the SINCE slider while KartaView is lit. */
export const SINCE_NOTE = '(by upload date)';
/** The UTC calendar day of `ms`, as KartaView's startDate reads it. */
function utcDay(ms) {
@@ -41,8 +41,6 @@ import {
normalizeItem,
} from './policy.js';
export { PANORAMAX_PROVIDER_ID } from './policy.js';
/**
* A tile's bytes decoded by `decode`; a body that is not a vector tile
* (an HTML error page, a cut-off answer) reads as such, not as a parser's
@@ -15,7 +15,7 @@ export const PANORAMAX_LABEL = 'PANORAMAX';
*/
export const PANORAMAX_API = 'https://api.panoramax.xyz/api';
/** The meta-catalogue's web viewer, where the caption link goes. */
export const PANORAMAX_VIEWER = 'https://api.panoramax.xyz/';
const PANORAMAX_VIEWER = 'https://api.panoramax.xyz/';
/** Stable id prefixes for picked primitives; every one starts with `pnx:`. */
export const PICK_PREFIX = Object.freeze({
+1 -1
View File
@@ -1,6 +1,6 @@
import { encodeIdSwitches } from '../../data/idSwitches.js';
export const IMAGERY_FILTERS = Object.freeze(['pano', 'since']);
const IMAGERY_FILTERS = Object.freeze(['pano', 'since']);
export function filtersOf(provider) {
return provider?.filters ?? IMAGERY_FILTERS;
+2 -2
View File
@@ -5,8 +5,8 @@ import { createHorizonCull, metresBetween } from './view.js';
import { msg } from '../../i18n/index.js';
/** Cones closer than this to the previous kept one are dropped. */
export const IMAGE_CONE_MIN_SPACING_M = 3;
export const IMAGE_CONE_SIZE_PX = 26;
const IMAGE_CONE_MIN_SPACING_M = 3;
const IMAGE_CONE_SIZE_PX = 26;
/**
* @typedef {object} ConeImage One image of a sequence, as the cones draw it.
+2 -2
View File
@@ -1,6 +1,6 @@
/** Decoded coverage tiles kept, and for how long. */
export const TILE_CACHE_SIZE = 24;
export const TILE_CACHE_TTL_MS = 10 * 60_000;
const TILE_CACHE_SIZE = 24;
const TILE_CACHE_TTL_MS = 10 * 60_000;
/** Least-recently-used map: reading an entry renews it. */
export function createLru(limit) {
+2 -2
View File
@@ -64,7 +64,7 @@ export function keyAlternatives(providers) {
* The filter controls a switched-on provider honours (both when none is on).
* @param {Array<ProviderSnapshot>} providers
*/
export function filterControls(providers) {
function filterControls(providers) {
const active = providers.filter((p) => p.on);
const honoured = (key) =>
active.length === 0 ||
@@ -78,7 +78,7 @@ export function filterControls(providers) {
* note needs no provider name.
* @param {Array<ProviderSnapshot>} providers
*/
export function sinceNote(providers) {
function sinceNote(providers) {
return providers.some((p) => p.on && p.sinceBasis === 'upload')
? t('(by upload date)')
: null;
+3 -3
View File
@@ -33,7 +33,7 @@ export function featureReference(feature) {
};
}
export function coordsFromProperty(value) {
function coordsFromProperty(value) {
if (!Array.isArray(value) || value.length < 2) return null;
const lon = Number(value[0]);
const lat = Number(value[1]);
@@ -41,7 +41,7 @@ export function coordsFromProperty(value) {
return [lon, lat];
}
export function coordsFromPoint(value) {
function coordsFromPoint(value) {
if (!Array.isArray(value) || value.length < 2) return null;
const lon = Number(value[0]);
const lat = Number(value[1]);
@@ -49,7 +49,7 @@ export function coordsFromPoint(value) {
return [lon, lat];
}
export function collectLonLat(value, out) {
function collectLonLat(value, out) {
if (!Array.isArray(value)) return;
if (typeof value[0] === 'number' && typeof value[1] === 'number') {
const lon = Number(value[0]);
+3 -3
View File
@@ -1,9 +1,9 @@
import * as Cesium from 'cesium';
import { tilesForBounds, tileToBBox } from '../../data/tomtomTiles.js';
export const RETICLE_RANGE_KM = 10;
export const RETICLE_TILE_CAP = 16;
export const tileKey = (tile) => `${tile.z}/${tile.x}/${tile.y}`;
const RETICLE_RANGE_KM = 10;
const RETICLE_TILE_CAP = 16;
const tileKey = (tile) => `${tile.z}/${tile.x}/${tile.y}`;
const cross = (a, b, c) =>
(b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
-10
View File
@@ -175,13 +175,3 @@ export const STYLED_MIN_BASE_PX = 5;
/** @const {number} Maximum tile cache entries before LRU eviction */
export const TILE_CACHE_MAX_ENTRIES = 64;
/**
* Milliseconds the first dot paint will wait for flow data. Cached flow
* settles within this window (decode cache, 120 s TTL) and renders fully
* colored; a cold tile fetch loses the race, dots paint immediately in
* white, and recolorDotsInPlace applies the colors when flow arrives —
* field-test round 1's "takes forever to load" was the sequential wait.
*/
export const FLOW_RENDER_RACE_MS = 250;
+7 -7
View File
@@ -99,7 +99,7 @@ export const VISIBILITY_REFRESH_MS = 250;
* on screen. Generous on purpose: a vehicle that crosses the edge mid-glide
* should already have been moving, not pop into motion at the border.
*/
export const VIEW_MARGIN_RATIO = 0.6;
const VIEW_MARGIN_RATIO = 0.6;
/**
* Whether a vehicle is close enough to the camera's look-at area to be worth
@@ -516,10 +516,10 @@ export function createTransitSelectedOverlayEntry(key, position, copy, mode) {
}
/** Modes that ordinarily run below the street, drawn on the surface above themselves. */
export const UNDERGROUND_MODES = new Set(['subway']);
const UNDERGROUND_MODES = new Set(['subway']);
/** The mode in plain words, for a card a person reads rather than scans. */
export const TRANSIT_MODE_WORD = Object.freeze({
const TRANSIT_MODE_WORD = Object.freeze({
bus: msg('Bus'),
tram: msg('Tram'),
subway: msg('Subway'),
@@ -529,7 +529,7 @@ export const TRANSIT_MODE_WORD = Object.freeze({
});
/** Short, fixed-width mode word for the detection card's class field. */
export const TRANSIT_MODE_ABBR = Object.freeze({
const TRANSIT_MODE_ABBR = Object.freeze({
bus: 'BUS',
tram: 'TRAM',
subway: 'METRO',
@@ -588,7 +588,7 @@ export function transitDetectionId(record, feed = null) {
}
/** Longest route text the single-line detection label can carry. */
export const DETECTION_ID_MAX_CHARS = 14;
const DETECTION_ID_MAX_CHARS = 14;
/**
* Cut long route text with an ellipsis, so a reader can see it was cut.
@@ -600,7 +600,7 @@ export const DETECTION_ID_MAX_CHARS = 14;
* @param {string} text
* @returns {string} Uppercase, at most DETECTION_ID_MAX_CHARS characters.
*/
export function elideRouteText(text) {
function elideRouteText(text) {
const value = String(text || '').toUpperCase();
if (value.length <= DETECTION_ID_MAX_CHARS) return value;
return `${value.slice(0, DETECTION_ID_MAX_CHARS - 1)}\u2026`;
@@ -659,6 +659,6 @@ export function transitDetectionMetric(
* @param {number} [nowMs]
* @returns {string}
*/
export function transitVehicleState(entry, nowMs = Date.now()) {
function transitVehicleState(entry, nowMs = Date.now()) {
return displayMotion(entry, nowMs).word;
}
-5
View File
@@ -1,8 +1,3 @@
export {
PARTIAL_RETENTION_MS,
SELECTED_PIN_REFRESHES,
AIS_FIRST_CONNECT_LABEL,
} from './recordPolicy.js';
import { VESSEL_LABEL_GRID_PX } from '../../data/vesselLabels.js';
import { msg } from '../../i18n/index.js';
+1 -1
View File
@@ -4,7 +4,7 @@ import { readResponseJsonCapped } from '../../sources/httpBody.js';
// the weather layer translates them where it shows them (t / translateKnown).
const msg = (text) => text;
export const WEATHER_PRODUCTS = Object.freeze([
const WEATHER_PRODUCTS = Object.freeze([
'radar',
'clouds',
'clouds-regional',
+2 -2
View File
@@ -6,8 +6,8 @@ import {
WIND_NARROW_PATH_LIMIT,
} from './streamlines.js';
export const WIND_FADE_LOW_METERS = 15000;
export const WIND_FADE_HIGH_METERS = 60000;
const WIND_FADE_LOW_METERS = 15000;
const WIND_FADE_HIGH_METERS = 60000;
// Original material: a persistent fine curve plus a moving, tapered highlight.
// The integer part of s identifies a path; its fractional part follows the wind.