refactor: enforce import directions and expose source factories

This commit is contained in:
Sameh Khamis committed 2026-09-14 21:12:01 -07:00
1 parent 704e0fcc51
commit cc960b0dbe
41 files changed
+1080 -417

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
import { defaultSurface } from './surfaceServices.js';
import { createApplicationAlpr } from '../app/layers/alprCameras.js';
import { createSourceSlot } from '../app/sourceSlot.js';
import { createSourceSlot } from '../sources/sourceSlot.js';
import { createOverpassAlprSource } from '../layers/alpr/index.js';
export * from '../layers/alpr/index.js';
const slot = createSourceSlot(
+1 -1
View File
@@ -1,5 +1,5 @@
import { createApplicationBikeshare } from '../app/layers/bikeshare.js';
import { createSourceSlot } from '../app/sourceSlot.js';
import { createSourceSlot } from '../sources/sourceSlot.js';
import { createBikeshareSource } from '../layers/bikeshare/source.js';
const sourceSlot = createSourceSlot(
+1 -1
View File
@@ -1,6 +1,6 @@
import { defaultSurface } from './surfaceServices.js';
import { createApplicationCctv } from '../app/layers/cctv.js';
import { createSourceSlot } from '../app/sourceSlot.js';
import { createSourceSlot } from '../sources/sourceSlot.js';
import { createCctvSource } from '../layers/cctv/source.js';
const sourceSlot = createSourceSlot(
+54
View File
@@ -0,0 +1,54 @@
import { GUIDANCE_STATUSES } from '../loadingFeedback.js';
/**
* Normalize heterogeneous layer stats into one honest control-chip state.
* @param {object|null} stats Layer getStats() result.
* @returns {'nominal'|'loading'|'degraded'|'stale'|'fallback'|'unavailable'} Feed state.
*/
export function layerFeedState(stats = {}) {
const state = stats || {};
const status =
typeof state.status === 'string' ? state.status.toLowerCase() : '';
const source = `${state.source || ''} ${state.coverage || ''}`;
const hasExplicitFallback = typeof state.fallback === 'boolean';
const hasPriorData = Number(state.count) > 0 || Boolean(state.lastUpdate);
const presentedError =
state.error || state.lastError || state.managerRefreshError;
if (['unavailable', 'offline', 'down', 'error'].includes(status))
return 'unavailable';
if (
(presentedError ||
state.unavailable === true ||
state.available === false) &&
!hasPriorData &&
!GUIDANCE_STATUSES.includes(status)
) {
return 'unavailable';
}
if (state.loading) return 'loading';
// Guidance states ask the user to act (zoom in, run a search) — normal
// operation, not feed faults. One honesty carve-out: layers keep their
// rendered records through the guidance state, so a genuinely stale cache
// still reads STALE; a guidance prompt alone never reads DEGRADED.
if (GUIDANCE_STATUSES.includes(status)) {
return state.stale ? 'stale' : 'nominal';
}
if (
state.fallback === true ||
status === 'fallback' ||
state.mode === 'sim' ||
/\bfallback\b/i.test(source) ||
(!hasExplicitFallback && /\badsb\.lol\b/i.test(source))
) {
return 'fallback';
}
if (state.stale || status === 'stale') return 'stale';
if (
state.degraded ||
presentedError ||
state.unavailable === true ||
state.available === false
)
return 'degraded';
return 'nominal';
}
+1 -1
View File
@@ -1,6 +1,6 @@
import { defaultSurface } from './surfaceServices.js';
import { createApplicationFirms, firmsServices } from '../app/layers/firms.js';
import { createSourceSlot } from '../app/sourceSlot.js';
import { createSourceSlot } from '../sources/sourceSlot.js';
import {
createFirmsHelpers,
createFirmsSource,
+2 -26
View File
@@ -1,15 +1,5 @@
import { governorRequestRender } from '../renderGovernor.js';
import {
clearSelectedEntityContextForLayer,
registerEntityContext,
removeEntityContextsForLayer,
selectEntityContext,
} from './contextStore.js';
import {
clearOverlaySource,
setOverlayEntries,
setOverlaySourceVisible,
} from '../overlays/worldOverlay.js';
import { localGeoJsonServices } from '../app/localGeojsonServices.js';
export { localGeoJsonServices } from '../app/localGeojsonServices.js';
import {
createLocalGeoJsonLayer as createLayer,
createLocalInfrastructureOverlayPublisher as createPublisher,
@@ -17,20 +7,6 @@ import {
export * from './localGeojsonCore.js';
/** Existing standalone application operations, shared by its local layers. */
export const localGeoJsonServices = Object.freeze({
overlayHost: Object.freeze({
clearSource: clearOverlaySource,
setEntries: setOverlayEntries,
setVisible: setOverlaySourceVisible,
}),
clearSelectedEntityContextForLayer,
registerEntityContext,
removeEntityContextsForLayer,
selectEntityContext,
governorRequestRender,
});
/** Create a layer using the standalone app's operations; retain overlay overrides. */
export function createLocalGeoJsonLayer(options) {
return createLayer(options, {
+1 -1
View File
@@ -1,6 +1,6 @@
import { defaultSurface } from './surfaceServices.js';
import { createApplicationInstallations } from '../app/layers/militaryInstallations.js';
import { createSourceSlot } from '../app/sourceSlot.js';
import { createSourceSlot } from '../sources/sourceSlot.js';
import { createInstallationSource } from '../layers/installations/index.js';
const sourceSlot = createSourceSlot(
+1 -1
View File
@@ -1,6 +1,6 @@
import { defaultSurface } from './surfaceServices.js';
import { createApplicationRadio } from '../app/layers/radio.js';
import { createSourceSlot } from '../app/sourceSlot.js';
import { createSourceSlot } from '../sources/sourceSlot.js';
import { createRadioSource } from '../layers/radio/source.js';
const sourceSlot = createSourceSlot(
+1 -1
View File
@@ -1,5 +1,5 @@
import { createApplicationLaunches } from '../app/layers/rocketLaunches.js';
import { createSourceSlot } from '../app/sourceSlot.js';
import { createSourceSlot } from '../sources/sourceSlot.js';
import { createLaunchSource } from '../layers/launches/index.js';
import * as satellites from './satellites.js';
+1 -1
View File
@@ -1,5 +1,5 @@
import { createApplicationSatellites } from '../app/layers/satellites.js';
import { createSourceSlot } from '../app/sourceSlot.js';
import { createSourceSlot } from '../sources/sourceSlot.js';
import { createSatelliteSource } from '../layers/satellites/index.js';
const sourceSlot = createSourceSlot(
+1 -1
View File
@@ -1,5 +1,5 @@
import { createApplicationTraffic } from '../app/layers/traffic.js';
import { createSourceSlot } from '../app/sourceSlot.js';
import { createSourceSlot } from '../sources/sourceSlot.js';
import { createTrafficSource } from '../layers/traffic/source.js';
const sourceSlot = createSourceSlot(