mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
The dock renders the chips from the map source controls' published view, so renderMapStackChips, syncMapStackChips and MAP_STACK_CHIP_CLASS have no callers. Their tests now pin the chip models; the dock test keeps the rendered chips' button type and native enablement.
766 lines
45 KiB
Markdown
766 lines
45 KiB
Markdown
# Formatting and component boundaries
|
||
|
||
Run `npm run format` to format the files in `scripts/format-scope.json` plus
|
||
automatically discovered runtime JavaScript in `scripts/format-runtime.json`, and
|
||
`npm run format:check` to check that same list without writing. CI checks the
|
||
combined scope on Linux and Windows. Prettier is pinned in the development
|
||
dependencies; use the installed version so local and CI output agree. The shared
|
||
configuration specifies two spaces, single quotes, semicolons and LF endings.
|
||
|
||
Owned runtime modules are discovered automatically; add their tests and other
|
||
non-runtime files to the explicit list as they are adopted.
|
||
Keep mechanical formatting in its own commit after behavior is stable. Existing
|
||
source-text regression assertions still apply; investigate failures and preserve
|
||
their behavioral coverage when a move or line wrap changes a tested shape.
|
||
Files outside the runtime roots and explicit list retain their surrounding style
|
||
until deliberately adopted.
|
||
Generated output, local configuration, browser evidence and bundled datasets are
|
||
excluded. The formatter validates every entry before writing any file.
|
||
|
||
New world text labels must use the world-overlay host; Cesium text labels are forbidden.
|
||
|
||
## Current component ownership
|
||
|
||
Package imports use `gods-eye-view`; `package.json` is the authoritative
|
||
export inventory. Use declared exports rather than reaching into internal files.
|
||
|
||
| Owner | Responsibility and lifetime |
|
||
| ---------------------- | ------------------------------------------------------------------------------------------------------- |
|
||
| `src/app/` | Construct supplied components, share scene/request services, cancel startup and dispose the application |
|
||
| `src/standalone/` | Select the default catalog, local sources and setup controls |
|
||
| `src/ui/` | Navigation generations, restoration, visual state, panel snapshots and their subscriptions |
|
||
| `src/data/` | Lifecycle, context and feed state; legacy default-layer facades |
|
||
| `src/layers/<family>/` | Source acquisition, records and Cesium resources with explicit controller/renderer owners |
|
||
| `src/sources/` | Portable protocols and source contracts; request state belongs to each factory instance |
|
||
| `src/services/` | Supplied application operations; scene construction owns caches and cancellation |
|
||
| `src/voice/` | Portable action schemas/session, common controls, action execution and separate protocol adapters |
|
||
| `server/providers/` | Node route factories, process-scoped provider caches and shutdown cleanup |
|
||
| `server/standalone/` | Environment, local settings writes and server composition |
|
||
|
||
See [application construction](APPLICATION.md) and the
|
||
[infrastructure contract](INFRASTRUCTURE-LAYERS.md) for construction interfaces.
|
||
|
||
## Import direction gates
|
||
|
||
`npm run check:boundaries` runs two complementary checks:
|
||
|
||
1. `scripts/check-import-directions.mjs` parses every runtime JS/MJS/CJS file in
|
||
`src/` and `server/`, including files unused by the current bundle. Static,
|
||
literal dynamic and re-export edges are checked; computed module imports and
|
||
CommonJS `require` are rejected. Browser graphs cannot reach Node, server or
|
||
test modules through helpers. Reusable modules cannot select standalone setup,
|
||
and provider modules cannot import application/rendering modules.
|
||
2. `scripts/check-package-boundaries.mjs` builds every declared export without
|
||
app Vite configuration or environment files. `scripts/package-boundaries.json`
|
||
assigns each export exactly once and lists its owned modules and external
|
||
dependencies. Unused imports still count. Node exports have only a `node`
|
||
condition; browser groups cannot use build-only dependency exceptions.
|
||
|
||
Portable source graphs cannot reach application/rendering, Node, Cesium or
|
||
browser globals. This includes `sources/*`, dedicated `layers/*/source` exports,
|
||
flight/military/vessel record and ingestion exports, action schemas, the session
|
||
interface, lifecycle and feed state. The browser-global rule reserves platform
|
||
names such as `document` and `window` in these modules; it is an architectural
|
||
check, not a JavaScript sandbox. Common voice controls cannot depend on a
|
||
Realtime protocol implementation. Negative fixtures cover indirect helpers,
|
||
self-package imports, symlinks and unreachable files.
|
||
|
||
Source-only factories use dedicated `layers/<family>/source` exports where
|
||
available, preserving the same factory implementation without loading rendering.
|
||
Record normalization and endpoint policies have plain owners separate from
|
||
geometry/cards. Source exports do not start acquisition at import time.
|
||
|
||
Other layer `ingestion.js` files may still coordinate Cesium resources; the
|
||
portable contract applies to the explicitly reviewed graphs above. Their layer
|
||
controller remains the owner of rendering/cleanup until a focused extraction
|
||
moves it. Do not label all ingestion modules platform-independent by filename.
|
||
|
||
## Compatibility entries and owners
|
||
|
||
| Retained entry | Owner and current reason |
|
||
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||
| `src/data/manager.js` | Lifecycle/panel compatibility and existing tests; normal assembly constructs lifecycle and presentation separately |
|
||
| `src/data/<layer>.js` | Legacy default instances; new assembly calls layer factories with supplied sources |
|
||
| `src/app/sources.js`, `src/services/application.js` | Existing default/override API; current application construction supplies its own instances |
|
||
| `server/providers/local.js` | Existing Node composition barrel and provider helper re-exports |
|
||
|
||
The one exact standalone-import exception is `server/providers/local.js` to
|
||
`server/standalone/key-setup.js`. It does not authorize new compatibility
|
||
back-edges. Voice actions use plain `src/data/feedState.js`, not the manager
|
||
facade. Settings filesystem hardening belongs in
|
||
`server/standalone/key-setup-hardening.mjs`; its settings policy is unchanged.
|
||
Test modules and the Node-only allocation benchmark are outside browser runtime.
|
||
|
||
## Build and standalone server configuration
|
||
|
||
`gods-eye-view/build/vite` is a separate Node-only export. `build/vite.js`
|
||
creates standard Cesium/Vite browser settings from explicit inputs. It imports
|
||
only the declared `vite-plugin-cesium` build dependency, discovers no environment,
|
||
and constructs no provider middleware. Call it from a Vite configuration:
|
||
|
||
```js
|
||
import { createBrowserViteConfig } from 'gods-eye-view/build/vite';
|
||
|
||
export default createBrowserViteConfig({
|
||
plugins: [],
|
||
googleApiKey: undefined,
|
||
cesiumToken: undefined,
|
||
});
|
||
```
|
||
|
||
Consumers supply compatible Vite and vite-plugin-cesium development dependencies.
|
||
The package's `node` export condition has no browser fallback. The boundary gate
|
||
builds this group for Node, with the declared build dependency external; its
|
||
owned module list is checked just like browser groups. Browser groups cannot
|
||
use build-only dependency exceptions.
|
||
|
||
`server/standalone/vite.config.js` loads the root environment and passes selected
|
||
browser keys, host/port and the ordered local provider plugins to this helper.
|
||
`server/providers/local.js` composes provider factories and re-exports existing
|
||
helpers for compatibility. Provider Settings lives in `server/standalone/key-setup.js`
|
||
and writes to the same root `.env` or Pinokio store as before. `vite.config.js`
|
||
preserves the default configuration and named provider exports for tools/tests.
|
||
|
||
## Aircraft and vessel providers
|
||
|
||
`server/providers/live.js` exports the existing Node middleware factories and
|
||
request helpers. `aircraft/` owns OpenSky state/fallback, military positions,
|
||
enrichment and track endpoints in separate files. `vessels/ais-live.js` owns
|
||
websocket setup and route responses; `vessels/ais-store.js` owns record ingestion,
|
||
static metadata and recent-track storage. Neither area imports globe rendering.
|
||
`common/http.js` owns capped reads/coalescing; `common/query.js` owns query values.
|
||
|
||
These plugins retain their existing process-scoped caches and server lifetime.
|
||
Importing the entry does not start acquisition. The AIS plugin disposes its
|
||
socket/watchdog on server close and re-reads configuration after restart.
|
||
The portable `gods-eye-view/sources/adsb-lol` export normalizes existing aircraft
|
||
records without importing Node middleware or a renderer. Browser layer/controller
|
||
separation is outside this server extraction.
|
||
|
||
## Place-search and routing providers
|
||
|
||
`gods-eye-view/server/providers/places` exports the Google nearby-place and
|
||
text-search plugin, OSRM route registration, and their shared Node helpers.
|
||
The existing Overpass plugin still mounts `/api/route` in its original order.
|
||
Google credentials are resolved on each request; the default uses the existing
|
||
server-key precedence, and callers may supply `resolveApiKey`.
|
||
|
||
`gods-eye-view/sources/places` exports portable response projections for Google
|
||
place results and OSRM route results/profile aliases. These functions own no
|
||
credentials, requests, caches, environment loading, or rendering. Callers retain
|
||
input validation and upstream-response acceptance. The boundary check builds
|
||
this entry independently and rejects Node imports.
|
||
|
||
The browser's direct geocoding, annotation rendering and full Overpass query
|
||
service remain in their existing modules.
|
||
|
||
## Satellite and launch providers
|
||
|
||
`gods-eye-view/server/providers/space` is a Node-only entry for the CelesTrak
|
||
and Launch Library 2 middleware. Separate files under `server/providers/space/`
|
||
own each feed's acquisition, memory/disk cache and error handling. The existing
|
||
local composition mounts them in the same order. Importing the entry performs
|
||
no acquisition; factory calls create independent cache state.
|
||
|
||
`gods-eye-view/sources/space` owns only fixed upstream URL construction: the
|
||
CelesTrak group/TLE query and Launch Library's recent 30-day detailed feed.
|
||
Callers supply the group or end date and own validation, credentials, transport,
|
||
response limits and cache policy. The boundary gate checks this portable entry
|
||
separately from the Node providers. Satellite rendering and launch replay remain
|
||
in their existing browser modules.
|
||
|
||
## Terrain, traffic, fires and bike-share providers
|
||
|
||
`gods-eye-view/server/providers/terrain`, `/traffic`, `/firms` and `/gbfs`
|
||
are separate Node-only entries. Each owns its existing middleware and
|
||
process-scoped cache or request handling. Standalone composition mounts them in
|
||
the original order; their imports do not start acquisition.
|
||
|
||
`gods-eye-view/sources/terrain` exports existing point-key, retry and cache
|
||
reconstruction mechanics with injectable acquisition dependencies.
|
||
`gods-eye-view/sources/traffic` exports tile math and budget calculations.
|
||
`gods-eye-view/sources/gbfs` exports host/path acceptance and cache-header rules.
|
||
These entries import no Node middleware, application configuration or rendering.
|
||
Callers retain their request admission and transport policy.
|
||
|
||
`gods-eye-view/sources/firms-csv` exports the existing CSV parser, header
|
||
recognition, acquisition-time conversion and trailing-day filter independently
|
||
of the Node middleware. It imports no Node, DOM, rendering or network code.
|
||
The Node provider continues using the same implementation; contract fixtures
|
||
cover malformed rows, acquisition times, empty feeds and the inclusive time
|
||
window. The boundary gate checks each entry independently.
|
||
|
||
Browser terrain sampling, traffic matching/drawing, fire overlays and bike-share
|
||
layer lifecycle remain in their current modules. This extraction changes no
|
||
source defaults, credentials, quotas, data interpretation or visual behavior.
|
||
|
||
## Local search, regional context, voice and setup
|
||
|
||
Node-only exports `server/providers/overpass`, `server/providers/military-installations`,
|
||
`server/providers/regional` and `server/providers/openai` own request handling
|
||
without importing the standalone configuration or browser rendering. Overpass
|
||
separates query admission, geometry simplification, cache and transport; military
|
||
search shares the bounded transport. Regional place/news/weather acquisition is
|
||
separate from briefing and weather-effect response caches. Voice handlers share
|
||
existing rate limits and request reading; schemas and instructions are separate.
|
||
|
||
`server/standalone/key-setup` is explicitly standalone Node functionality.
|
||
Its factory and the local voice factory accept `sourceRoot` for application-owned
|
||
configuration/log files; defaults resolve the repository root. Local voice also
|
||
accepts an optional `annotationGuidance` paragraph. Neither factory starts
|
||
acquisition on import. Setup retains its pre-environment-load provenance capture
|
||
and development-only registration. Package checks enumerate every owned module
|
||
and reject browser imports of these Node entries.
|
||
|
||
## Browser place search
|
||
|
||
`gods-eye-view/search` exports an explicit geocoding service and Google/Photon
|
||
adapters. The entry owns normalization, bounded caches, deadlines and fallback
|
||
sequencing. It imports no application state, environment configuration, rendering
|
||
or Node server code. Google transport is supplied by its caller.
|
||
|
||
`src/standalone/placeSearch.js` constructs the configured Google request and
|
||
keyless Photon fallback. The application passes this service to location
|
||
controls, annotation resolution and voice/radio actions. Those consumers retain
|
||
framing, landmark recovery, footprint matching and playback decisions. Existing
|
||
reverse geocoding and nearby/text-search routes remain separate.
|
||
|
||
## Panel controls
|
||
|
||
`gods-eye-view/ui/panels` owns collapse-button binding, nearest-panel Escape
|
||
handling, hover delays and delayed content-focus handoff. It accepts existing
|
||
DOM elements and callbacks; importing it creates no browser state. `destroy()`
|
||
removes owned listeners and cancels pending work without changing saved state
|
||
or moving focus. Call it before removing or replacing the controls.
|
||
|
||
`src/ui/applicationShell.js` retains panel layout, persistence, share restoration and application
|
||
reactions to state changes. Map Source selection and Location draft cleanup are
|
||
provided through callbacks. The component imports no globe, data, application
|
||
or server modules. Package checks and scoped formatting cover this entry.
|
||
|
||
## Surface keyboard handling
|
||
|
||
`gods-eye-view/ui/surfaces` exports `createSurfaceKeyboard` from
|
||
`src/ui/surfaceKeyboard.js`. It receives a root DOM node, an optional document,
|
||
an `isActive` predicate, an `onEscape` action and an optional return-focus fallback.
|
||
Construction is inert. `activate()` remembers the opener and installs one capture
|
||
listener; repeated activation is harmless. `deactivate({ restoreFocus: true })`
|
||
removes that listener and restores the opener when connected, otherwise invoking
|
||
the supplied fallback. Omit return focus when yielding to another surface.
|
||
`destroy()` permanently releases ownership without moving focus.
|
||
|
||
The welcome launcher and Provider Settings retain content, visibility, initial
|
||
focus, animation and screen-specific policy. Tab boundaries are read from the
|
||
current visible/enabled controls for each key; ordinary movement within those
|
||
boundaries remains native. The component honors already-handled keys and has no
|
||
app, server, storage or network dependencies. Its package boundary is checked
|
||
independently from the standalone screens that consume it.
|
||
|
||
## Panel rail layout
|
||
|
||
`gods-eye-view/ui/layout` exports synchronous `layoutLeftPanelRail` and
|
||
`layoutRightPanelRail` passes, `measurePanelNaturalHeight`, and the existing pure
|
||
corridor/allocation helpers. Separate modules own left placement, right placement,
|
||
DOM height measurement and rail geometry. They import no application, renderer,
|
||
server, storage or network modules; package checks build this entry independently.
|
||
|
||
Callers supply rail/obstacle DOM nodes, the viewport, HUD state, the preferred
|
||
panel, disclosure/retry callbacks and the left measurement cache. Right layout
|
||
reads the caller's Display scroll value at measurement time and restores it
|
||
within the resulting scroll range. The left pass notifies its caller after
|
||
alignment so the right pass can follow. Neither pass installs listeners, timers
|
||
or observers; construction/import does no work. Scheduling, preference writes,
|
||
share restoration and movement of controls between containers remain caller-owned.
|
||
Existing helper imports from `cockpitMath.js` and `rightRailPolicy.js` remain
|
||
compatible through re-exports.
|
||
|
||
### Adding a right-rail readout panel
|
||
|
||
Add the shell in `src/ui/views/ContextView.vue` inside `#right-context-rail`:
|
||
a `.panel-collapsible` with a stable `id` and matching `data-panel-id`, the
|
||
existing `.panel-header`, collapse button and a dedicated body. Register it
|
||
with the existing panel chrome/layout owners; do not allocate rail space in
|
||
the body renderer. Set `hidden` while empty so the allocator ignores it, and
|
||
expand through the existing collapse button only on first appearance per page
|
||
session, and only when the chrome marked the restored state as a default
|
||
(`data-collapsed-preference`), never over a stored or shared choice. Preserve
|
||
the user's later collapse choice, including body remounts. Mark the body
|
||
`data-rail-scroller` when it scrolls: the rail's measuring pass lifts its
|
||
`max-height` and puts the scroll offset back afterwards. Panel bodies only
|
||
scroll on an open-card change, with one write, never on a refresh.
|
||
|
||
Compose `createRailCards({ container, document, onParams, onOpen })` and
|
||
`createRailTimeline({ container, document, onCommit, onPreview, onStep,
|
||
onLatest, onPlay })`. Cards reconcile `{ id, title, badge, open, compact,
|
||
compactStatus, blocks }` in place. Their full-width native button headers expose
|
||
`aria-expanded` and `aria-controls`; articles expose `data-open`. The feature
|
||
adapter owns accordion state. Generic cards do not select data or enable layers.
|
||
|
||
`blocks` is an ordered array of loose, optional `{ id, type, ... }` descriptors,
|
||
rendered by `rail/RailCardBlocks.vue`. There are no per-section disclosures:
|
||
|
||
- `summary`: `text`, a single summary line.
|
||
- `list`: `list: { ariaLabel, items }`, keyed by `rail/RailRowList.vue`.
|
||
- `lines`: keyed `lines: [{ id, text, muted? }]` for details and status.
|
||
- `settings`: `settings: [{ id, label, chips }]`; each labelled row has a 56 px
|
||
label column and wrapping keyed chips from `rail/RailChips.vue`.
|
||
- `legend`: `legend: { colors, labels, units?, zeroIndex?, categorical? }` for a
|
||
ramp/scale (including a physical freezing anchor) or separate keyed swatches.
|
||
- `actions`: keyed `actions: [{ id, label, params?, href?, onClick?, disabled?,
|
||
hint? }]` in a footer, using buttons or safe new-tab links.
|
||
- `result`: `label`, keyed `lines`, and optional `clear: { params | onClick }`;
|
||
its accessible × button sits beside the title.
|
||
|
||
Every block and control has a stable id. Lists, settings, actions and results
|
||
can appear in any requested order, including a scene panel's rectangle action,
|
||
results list, then selected-scene details. Chip/list/action `params` dispatch
|
||
through `onParams(cardId, params)`; the feature adapter supplies
|
||
`setLayerParams(id, params, { origin: 'user' })`. Current descriptors and disabled
|
||
state are read at dispatch. Identical updates do not move nodes or write DOM;
|
||
focused controls survive feed refreshes.
|
||
|
||
Weather descriptors retain top-level `chips`, `list` and `legend` for non-DOM
|
||
consumers. They expose `summary.settings`, `summary.actions` and optional
|
||
`summary.result`; wind also retains its raw captured `summary.reading`.
|
||
`readout: true` layer rows render only the toggle and source/meta line; their
|
||
subscriptions still refresh the cards. Cards own configuration and readings.
|
||
|
||
Weather orders cyclones, wind, then a bordered Observed history group containing
|
||
the timeline and active radar, satellite and lightning cards. The group heading
|
||
and scope name its active products. The timeline stays visible whenever any
|
||
observed product is enabled; fewer than two ticks disables transport. Pass
|
||
`heading: false` to the timeline when the containing group owns the heading.
|
||
Exactly one active card is open. Header clicks and newly enabled ids choose it
|
||
(the last new entry wins a batch); refreshes and clock ticks retain it. First
|
||
appearance uses cyclones with storms, otherwise the first card. Disabling the
|
||
open layer falls back to the first remaining card. A WeakMap per document keeps
|
||
explicit choices through body remounts without adding share state. Card opening,
|
||
storm selection and layer enabling remain independent.
|
||
|
||
Optional card/badge/slider class names provide feature styling. Card titles use
|
||
`.data-name` typography; meta/time/badges use `.data-toggle-meta` typography;
|
||
setting/result labels use `.panel-title`; chips retain `.data-toggle-chip`.
|
||
Reserve one status line, even without a legend. Use app tokens. Wind's footer
|
||
reads the map center into a result after the action. The captured location stays
|
||
fixed until another read; model changes resample that location, units reformat
|
||
it, and × clears both reading and map marker.
|
||
|
||
The timeline shows endpoint times and receives ticks, index, mode, playing,
|
||
readout and disabled state. Its preview callback receives the tick and index and
|
||
may return readout text; commits receive the same values after a 150 ms coalesced
|
||
drag or final change. Feature adapters own data mapping and service subscriptions;
|
||
generic modules own DOM/listeners/timers and release them in `destroy()`.
|
||
|
||
Keep persistence with panel chrome: collapse uses
|
||
`godsEyeView.v6.panelCollapsed.<panelId>`, positions are
|
||
not stored (`godsEyeView.v8.panelPos.<panelId>` stays reserved), and share state uses the registered panel id.
|
||
Do not rename existing
|
||
ids or reset persistence versions when adding a body. The WEATHER adapter is
|
||
`src/ui/weatherPanel.js`; its observed-history selection remains transient.
|
||
|
||
## Visual input
|
||
|
||
`gods-eye-view/ui/input` exports `bindApplicationShortcuts` and
|
||
`createStyleParameters`. The shortcut binder owns one bubbling keydown listener
|
||
and receives the document, editing target and explicit action callbacks.
|
||
Parameter controls own only the supplied container's generated rows/listeners;
|
||
uniform metadata and read/write/change operations come from the caller.
|
||
Clearing permits reuse; destruction is final. Neither module imports the app,
|
||
renderer, persistence or services. The facade retains panel visibility, share
|
||
restore claims and render scheduling. Both controls are destroyed before the
|
||
facade's asynchronous teardown can yield.
|
||
|
||
## Ordinary action buttons
|
||
|
||
The scene panels view and the CCTV panel draw their action buttons with the shared
|
||
`gev-action-button` classes in `src/ui/styles/action-button.css`. Feature
|
||
controllers own action dispatch, state, persistence and cleanup, and the views
|
||
preserve IDs and layout hooks.
|
||
|
||
## Display controls
|
||
|
||
`ui/display` owns Display button, selector and slider subscriptions. It receives
|
||
DOM elements and explicit actions, imports no application or effect singleton,
|
||
and releases every listener on destruction. Settings and rendering remain with
|
||
the caller.
|
||
|
||
## Visual effects
|
||
|
||
`ui/effects` exports the effects controller and existing preset definitions.
|
||
It owns shader stages and their clock, with explicit render ownership callbacks.
|
||
Construction installs no stages or frame callbacks. Stop animation before
|
||
releasing UI consumers, then destroy to remove owned stages and restore the
|
||
borrowed bloom state. `ui/effects/bloom` exposes the pure intensity/version helpers
|
||
without loading the renderer. UI presentation and product-action coordination
|
||
remain in their callers.
|
||
|
||
## Map Source controls
|
||
|
||
`ui/maps` owns source-chip presentation, selection feedback and its subscription
|
||
lifetime. It receives the existing controller and explicit state/action callbacks;
|
||
it imports no renderer or application. Source construction and availability policy
|
||
remain with the map controller. The dock renders the chips; rebuilding controls
|
||
drops their previous subscription, and destruction suppresses late completions
|
||
without owning or destroying the supplied controller.
|
||
|
||
## Layer panel
|
||
|
||
`ui/layers` exports the Layers panel and clear-control binding. Callers supply
|
||
snapshots, row descriptors, subscriptions and actions; the component imports no
|
||
layer implementation or application bootstrap. Layer transactions remain with
|
||
the caller. Hidden-page refresh scheduling remains an explicit callback.
|
||
|
||
`ui/layers/feedback` exposes the existing pure loading/notice reducers separately
|
||
from DOM controls. Scheduling and presentation stay with their callers.
|
||
|
||
## Location controls
|
||
|
||
`ui/location` exports Location controls, the cancellable lookup controller and
|
||
the existing location-status formatter. Callers supply city data, search and
|
||
navigation operations. The component owns DOM listeners and pending expansion;
|
||
it imports no geocoder, camera engine, layer or application bootstrap. Existing
|
||
camera authority and search providers remain supplied by the application.
|
||
|
||
### Radio controls
|
||
|
||
`ui/radio` owns Radio input, disclosures, tuner state and presentation. It
|
||
receives the existing Radio port and explicit layer/layout actions, without
|
||
importing the renderer or station providers. Pure tuner calculations retain
|
||
compatibility exports from the data layer. Disposal revokes DOM listeners and
|
||
subscriptions before ending the active tuning interaction.
|
||
|
||
### Camera panel controls
|
||
|
||
`ui/cctv` composes camera controls, frame loading, calibration editing and status
|
||
presentation. It receives DOM elements, the existing camera port and explicit
|
||
application actions; it imports no provider, layer or camera engine. Selection,
|
||
placement, navigation and storage policy remain outside the component family.
|
||
|
||
### Context coordination
|
||
|
||
`ui/context` owns mode controls, transactions, session restoration and manager
|
||
subscriptions. Composition supplies the manager, installations search and
|
||
explicit visual/panel actions. `ui/context/policy` exposes the existing pure
|
||
mode and restoration rules. No source transport or renderer is imported by
|
||
these components; initial state and action results retain their existing shape.
|
||
|
||
## Cockpit controls
|
||
|
||
`ui/cockpit` supplies the Cockpit controller and Display portal. Camera updates,
|
||
instruments, Context readouts, briefings, signals, layout and input have separate
|
||
modules. Composition supplies the existing aircraft/awareness operations, terrain
|
||
cache and sampling operations, continuous-render owner and regional briefing
|
||
service. Pure math, utility layout and vision helpers have explicit exports.
|
||
Disposal releases subscriptions and pending work; portal moves preserve the
|
||
original Display groups, independent scroll positions and current focus owner.
|
||
|
||
## Scene controls
|
||
|
||
`ui/scenes` owns Scene prompts, panel input, project/shot rows, playback button and runtime
|
||
presentation. It receives project reads and explicit actions, with no imports of
|
||
the director, source modules, camera engine or storage. Replacement and disposal
|
||
release listeners; pending action feedback is limited to its current owner.
|
||
|
||
## UI assembly and styles
|
||
|
||
`ui/shell` assembles controls from supplied existing layer, navigation, terrain,
|
||
rendering, HUD and share operations. `src/standalone/controls.js` provides the running
|
||
application's instances. The shell
|
||
imports no standalone bootstrap or concrete live layer implementation.
|
||
Panel layout, position/drag, notices, recording and deferred UI work have separate
|
||
owners with synchronous cleanup. Existing scene, share and HUD engines retain
|
||
their entry points. `ui/styles` loads the ordered stylesheet entry; component
|
||
files retain the original cascade, including responsive and dock refinements.
|
||
|
||
## UI state and Scene actions
|
||
|
||
`StyleManager.subscribeShareState(listener)` supplies the current shareable
|
||
visual preferences and subsequent settings changes. The built-in share manager
|
||
consumes the same updates. `subscribeLocationSearch(listener)` follows the
|
||
current lookup owner across control replacement. `LocationSearch.subscribe`
|
||
provides the corresponding per-owner contract. Changes identify `started`,
|
||
`found`, `missing`, `failed`, `settled`, and the shell's `reset`; request IDs
|
||
belong to their lookup owner. Only current requests publish accepted results.
|
||
|
||
`gods-eye-view/scenes` exports `SceneDirector`. Its `subscribe(listener)` supplies
|
||
small playback snapshots plus editing outcomes. Scene controls consume these
|
||
updates to render the affected presentation; progress does not copy the project
|
||
or rebuild shot rows. Project import/export outcomes include the project;
|
||
shot editing outcomes include the affected shot and its index before deletion.
|
||
Camera, layer sequencing, storage and run-file download retain their existing
|
||
owners. Cesium remains an external dependency supplied by the application.
|
||
|
||
Each listener receives `{ state, change, revision, initial }` and subscriptions
|
||
return an unsubscribe function. Initial state is emitted by default; pass
|
||
`{ emitCurrent: false }` to receive only changes. Snapshots and outcomes are
|
||
immutable plain data. Reentrant publications retain delivery order; removing a
|
||
listener or destroying its owner prevents further queued delivery. These APIs
|
||
perform no network requests and discover no additional modules.
|
||
|
||
## Maps
|
||
|
||
`maps/controller` coordinates scene changes and lifetimes. `maps/imagery`,
|
||
`maps/terrain` and `maps/3d` supply constructors; `maps/defaults` selects the
|
||
standard sources and their setup/fallback policy. The standalone facade wires
|
||
these to the application's render governor.
|
||
|
||
A registry supplies `sources`, `defaultId`, `unknownId` and optional `recoveryId`.
|
||
Each source has a user-facing `descriptor`, availability/reason, and either an
|
||
`imagery({ signal })` factory or a supplied `tileset`/`createTileset({ signal })`.
|
||
Imagery sources can share a terrain definition with a stable `id` and
|
||
`create({ signal })` returning `{ provider }` or `{ terrain }`. Cache IDs must
|
||
identify the same source for the lifetime of that registry. Sources may supply
|
||
trusted credit markup and construction/tile-error fallback policy. Provider
|
||
configuration stays in factories; descriptor values are the presentation API.
|
||
|
||
Factories should honor cancellation where their SDK supports it. The controller
|
||
also checks scene ownership after asynchronous work, so late results cannot
|
||
replace a newer selection. Supplied tilesets are caller-owned; factory-created
|
||
tilesets and provider caches are controller-owned. Construct a fresh controller
|
||
for a new viewer or configuration lifetime.
|
||
|
||
The application-components group assembles the existing page-scoped catalog and
|
||
its engines. Its explicit module graph includes the smaller layer/UI groups;
|
||
those independent groups retain their narrower gates. Source adapters and
|
||
request services enter through construction, without replacing global fetch.
|
||
The Node build group also owns the allowlisted static HTML template assembler.
|
||
|
||
## Application catalog
|
||
|
||
`gods-eye-view/application/catalog` captures caller-supplied layer instances and
|
||
matching registration metadata. `application/data` registers that catalog, attaches
|
||
coordinators after registration and seals it before controls start restoration.
|
||
`application/controls` binds its layer services from the same catalog. The existing
|
||
control surface and v2 sharing codec retain their established layer IDs; changing
|
||
that schema requires a corresponding codec change.
|
||
|
||
`standalone/catalog` selects the existing page-scoped default instances and metadata.
|
||
Reusable data setup imports no standalone layer defaults. The current compatibility
|
||
source setters remain available while callers migrate to instance construction.
|
||
|
||
### Layer construction
|
||
|
||
`application/layers` constructs the current catalog from explicit source objects
|
||
and an application AbortSignal. Small `src/app/layers` modules wire existing scene
|
||
services into each family factory. Standalone provider selection lives in
|
||
`src/standalone/layerSources.js`. The construction export has its own checked
|
||
dependency graph, excluding standalone setup and compatibility layer instances.
|
||
|
||
Both aircraft layers share the catalog's classification registry; launches use
|
||
its satellites and Contacts uses its aircraft, vessels and installations. Data
|
||
registration, controls and voice actions read those same instances. Destruction
|
||
remains the manager's responsibility; classification also observes application
|
||
abort when startup has not reached registration. Scene engines remain page-owned,
|
||
so this change does not introduce multiple simultaneous viewers.
|
||
|
||
Direct `src/data` compatibility entries retain their old defaults and testing
|
||
exports. Browser regression probes use the registered instance's testing surface
|
||
to avoid accidentally inspecting an unused compatibility instance. Existing source
|
||
setters apply only to compatibility instances; the normal application supplies
|
||
its sources at construction.
|
||
|
||
### Application operations
|
||
|
||
`application/operations` accepts request-service instances and an application
|
||
lifetime. It constructs terrain resolution, coarse floor/mesh caches and an
|
||
annotation resolver without selecting upstream providers. Its checked graph is
|
||
separate from standalone setup. Scene construction returns these operations; the
|
||
catalog and controls use the same surface owner. Layers still own their individual
|
||
ground-snap caches and model resources.
|
||
|
||
Terrain cancellation rejects late replies before caching, clears floor queues and
|
||
removes the map-stack listener. Annotation lookup caches are instance-owned and
|
||
cleared on cancellation. Geometry selection and floor policies are unchanged.
|
||
HUD and weather controllers accept their respective service; regional lookup and
|
||
location framing use the supplied operations. Voice shares the same boundary and
|
||
floor services, with analyst memory scoped to the runner. Direct compatibility
|
||
entrypoints retain default services; normal assembly does not configure their
|
||
source slots.
|
||
|
||
## Layer lifecycle and presentation
|
||
|
||
`data/lifecycle` owns registrations, visibility intent, refresh transactions,
|
||
parameters and teardown. Its package group contains one module and no external
|
||
imports. Adding a panel, renderer or application dependency fails the boundary
|
||
build, including unused imports.
|
||
|
||
`app/layerPresentation` mounts the toggle panel and turns lifecycle activity into
|
||
render requests and detection invalidation. It owns hidden-panel refresh and
|
||
listener cleanup. Application data assembly constructs both owners explicitly;
|
||
`data/manager` is the compatibility facade for direct callers. The ordinary
|
||
state subscriptions retain their existing event contract.
|
||
|
||
## UI state owners
|
||
|
||
- `ui/navigation` owns navigation generations, pending search presentation and
|
||
tracking handoff. It reads Cockpit admission and uses supplied tracking operations.
|
||
- `ui/share-restoration` owns the initial restore transaction, layer coordinator,
|
||
status notices and gesture/timer cleanup.
|
||
- `share/view-codec` is the share-link codec (`decodeShareView`,
|
||
`encodeShareView`). It is pure (no DOM, no Cesium), so a host's server can
|
||
read a `/share/<code>` link, for example to describe it in link previews.
|
||
`share/link-path` reads and builds the `/share/<code>` address itself.
|
||
- `ui/visual-settings` owns style preferences, detection overrides, display inputs
|
||
and IR cleanup. Its engine services and panel operations are explicit.
|
||
- `ui/panel-chrome` owns disclosure, docking, collapse preferences and temporary
|
||
Cockpit panel snapshots, composing the existing positioning/layout controllers.
|
||
|
||
These package groups contain their own dependencies and exclude application
|
||
assembly. `applicationShell` retains composition and compatibility methods;
|
||
those methods delegate to the state owner. Source-based regression checks inspect
|
||
that implementation owner, and browser acceptance exercises the assembled UI.
|
||
|
||
## Civil-flight records and acquisition
|
||
|
||
`layers/flights/records` owns metadata, sticky observations, geoid values and
|
||
missing-poll admission. `layers/flights/ingestion` owns the source and request
|
||
lifetime, backoff and freshness state. Both are portable package groups with no
|
||
Cesium, viewer, billboard, model or application imports.
|
||
|
||
The layer composes these with `snapshotRenderer`, which applies record changes
|
||
to Cesium history and primitives and coordinates existing follow operations.
|
||
Occlusion points live with rendering state. Eviction still releases tracking
|
||
before deleting records; incomplete snapshots retain recent contacts for the
|
||
existing bounded interval. The renderer retains its existing per-frame scratch
|
||
objects; reconciliation occurs on source refresh, not on each frame.
|
||
|
||
`layers/military/records` and `layers/military/ingestion` have the same portable
|
||
ownership boundary. Military observations retain their aviation-foot readout,
|
||
source-time fallback and model-owned ground policy. The renderer supplies that
|
||
ownership fact and handles stale-ground lifting, Cesium history and primitives;
|
||
record reconciliation does not import the engine or application.
|
||
|
||
`layers/vessels/records` owns plain AIS metadata, stable MMSI identity and bounded
|
||
retention. `layers/vessels/ingestion` owns source requests and feed state through
|
||
explicit operations. Both exports exclude Cesium, DOM and application assembly.
|
||
The snapshot renderer applies record changes; rendering owns a weak map of
|
||
geometry and billboard resources used by cards, picking and trails.
|
||
|
||
`gods-eye-view/sources/reference` constructs fresh earthquake, GNSS integrity and bundled cable
|
||
source instances independently of standalone setup. Individual sources remain
|
||
available through their `layers/<family>/source` exports, including `layers/gnss/source`.
|
||
The latter retains the bundled dataset’s attribution and licensing requirements.
|
||
|
||
## Geocoding and feature-query providers
|
||
|
||
`createDefaultPlaceSearch` accepts an explicit Nominatim selection:
|
||
|
||
```js
|
||
const places = createDefaultPlaceSearch({
|
||
geocoding: {
|
||
provider: 'nominatim',
|
||
searchEndpoint: '/places/search',
|
||
reverseEndpoint: '/places/reverse',
|
||
},
|
||
fetchImpl,
|
||
signal,
|
||
});
|
||
```
|
||
|
||
The endpoints must return Nominatim JSONv2. They are supplied by application
|
||
composition; no instance is selected automatically and this does not install
|
||
those routes. For a remote instance, configure its full URLs and transport
|
||
requirements. The caller owns request scheduling, identifying headers and any
|
||
instance-specific usage policy. The existing public fallback retains its shared
|
||
queue, pacing and cache. `endpoints.nominatim` still names the legacy
|
||
Google-shaped `/api/geocode` fallback; it is not a raw Nominatim endpoint.
|
||
|
||
Coordinates and supplied presets remain offline. Explicit Nominatim selection
|
||
replaces the network forward-geocoder chain; it does not silently fall back to
|
||
another instance. Reverse geocoding is available only when a reverse endpoint
|
||
is configured. Other operations (Places text/nearby search and routing) retain
|
||
their independent providers. For custom compositions, `createNominatimProvider`
|
||
from `./search/nominatim` can be passed to `createPlaceSearch` and
|
||
`createGeospatialServices`; it exposes no route or nearby-search capability.
|
||
An empty search array is a definitive miss. HTTP failures, malformed results
|
||
and oversized responses remain retryable. Attribution identifies OpenStreetMap /
|
||
Nominatim.
|
||
|
||
Vector tile sources supply traffic roads, ALPR records and keyless military
|
||
areas. Operator-configured Overpass supplies named installations and annotation geometry (administrative boundaries,
|
||
neighborhoods, streets, building/grounds outlines and monument candidates).
|
||
Nominatim forward/reverse lookup does not replace those queries. Layer source
|
||
interfaces select traffic, camera and installation ingestion separately;
|
||
annotation and camera-framing consumers use the feature operations documented
|
||
below. The Overpass adapter translates those operations and normalizes records;
|
||
an alternate backend implements that source interface. Rendering and geometry
|
||
selection remain consumers of those results.
|
||
|
||
`./sources/nominatim` exports the lower-level JSONv2 client and normalizers for
|
||
server adapters without importing search composition.
|
||
|
||
`./sources/http-body` exports bounded text/JSON readers using web primitives;
|
||
`./sources/overpass` exports the quoted-string/comment lexer. The lexer alone is
|
||
not a query validator: spatial bounds, timeouts and other policy remain in the
|
||
server sanitizer. Existing server imports keep their compatibility exports.
|
||
|
||
Runtime formatting discovers tracked and new non-ignored `.js`, `.mjs` and `.cjs`
|
||
files under the configured owned roots. Tests retain explicit adoption. Git and
|
||
Prettier exclusions keep local/generated data out; resolved paths are validated
|
||
before any writes. New runtime modules do not need another scope-list entry.
|
||
|
||
## Map-feature sources
|
||
|
||
Application request services expose `features`. Callers may supply another source
|
||
with the same operations; the default is `createOverpassFeatureSource` from
|
||
`sources/map-features`. Legacy boundary-query configuration remains supported.
|
||
Search and annotation code request candidates and rank them without constructing
|
||
query-language strings or decoding backend tags and relation members.
|
||
|
||
| Operation | Result used by the caller |
|
||
| --------------------------------------------------------------------- | ------------------------------------------------------- |
|
||
| `getAdministrativeAreas(point, options)` | Named administrative candidates and geometry references |
|
||
| `getAreaGeometry(id, options)` | Geometry for one selected administrative reference |
|
||
| `getNeighborhoodAreas(point, options)` | Neighborhood polygon candidates |
|
||
| `getStreetAreas(point, options)` / `getStreetLines(point, options)` | Named areas and road lines for street annotations |
|
||
| `getFootprints(point, options)` / `getEnclosingAreas(point, options)` | Building and surrounding-ground candidates |
|
||
| `getMonuments(point, options)` | Named point candidates |
|
||
| `getFocusFootprints(point, options)` | Building/landmark candidates for camera framing |
|
||
|
||
Points use `{lat, lon}`. Options carry `signal`. A successful array, including an
|
||
empty array, is definitive; `null` means a transient failure;
|
||
`{rateLimited: true, retryAfterMs}` retains a provider's retry delay.
|
||
`{unavailable:true, code:'OVERPASS_NOT_CONFIGURED', retryable:false}` is a
|
||
capability miss that stops retries while preserving pins and offline geometry. Candidates
|
||
carry `id`, `names` (`primary`, `english`, `official`, `alternate`, `short`),
|
||
`coordinates` (objects with `lat` and `lon`), `building` and optional `heightM`,
|
||
`center` and `point`. Administrative candidates use `category: 'administrative'`
|
||
and a numeric `level`. Provenance may retain compatibility metadata, but ranking
|
||
does not use backend tags. The Overpass implementation retains its existing
|
||
operation-specific query radii and deadlines.
|
||
|
||
Traffic's source response decodes to `{roads}`. Each road supplies longitude/latitude
|
||
`coordinates`, a road-class `type` and `oneway` (`-1`, `0` or `1`). Scene construction
|
||
still owns thinning, terrain sampling and Cartesian waypoints. Installation
|
||
sources supply `{records, droppedCount, status, saturated}`; viewport filtering,
|
||
exact-bound retry and rendering stay in the layer. Legacy cache saturation is
|
||
decoded in the source. Source and geometry modules remain independent of Cesium,
|
||
DOM and platform middleware.
|
||
|
||
### Native form fields
|
||
|
||
Native numeric inputs are rendered by the views that own them; the CCTV pose
|
||
chip renders its inline input in `src/ui/cctv/CctvCalValue.vue`. Static
|
||
selects and number inputs use the same `gev-field` surface, with explicit
|
||
compact and inline densities. Feature owners retain
|
||
option identity/order, bounds, parsing, draft values, input/change timing and
|
||
teardown. CCTV effective-pose conversion and tuner/device operations remain
|
||
feature responsibilities.
|
||
|
||
The shared stylesheet owns field surfaces and disabled opacity; feature and theme
|
||
palettes use `--gev-field-background`, `--gev-field-border-color`,
|
||
`--gev-field-color` and `--gev-field-disabled-opacity`. Radio retains its own
|
||
compact density and arrow space. CCTV owns calibration editor width in
|
||
`cctv.css`; the shared inline density does not impose a feature-specific width.
|
||
Cyber supplies a shared-field palette explicitly and keeps its legacy native
|
||
field rules separate, so Radio's palette remains an intentional exception.
|
||
|
||
### Read-only status badges
|
||
|
||
Views draw read-only badges with the `gev-status-badge` classes, without
|
||
listeners, status inference or live-region policy. Appearance variants share
|
||
CSS rather than mapping machine states to universal severity. CCTV owns
|
||
frame/source and calibration rules and their data attributes, while Weather
|
||
owns coverage labels. The rail card keeps node identity, header focus,
|
||
disclosure and teardown, and does not announce every card update.
|