refactor: expose portable FIRMS CSV helpers

This commit is contained in:
Sameh Khamis committed 2026-09-14 12:58:57 -07:00
1 parent 191edb7c5e
commit fb8f9e1c49
7 files changed
+83 -4

No files matched your search

+2
View File
@@ -91,6 +91,8 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md
## [Unreleased]
- Expose existing FIRMS CSV parsing and UTC time-window helpers through a portable package export, with shared contract fixtures.
- Separate map source factories from switching and resource ownership; retain current source IDs, attribution and fallbacks.
- Separate radio directory loading, station selection, globe presentation and playback into composed components with an explicit metadata source.
+8 -3
View File
@@ -144,9 +144,14 @@ 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. FIRMS CSV parsing
remains an owned dependency of the FIRMS Node provider. The boundary gate
checks each entry independently.
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
+4
View File
@@ -1,5 +1,9 @@
# God's Eye View Current State
The `sources/firms-csv` package export exposes existing FIRMS CSV parsing and
UTC acquisition-window helpers without Node middleware or rendering dependencies.
The standalone FIRMS provider, source defaults and parsing behavior are unchanged.
CLI tools and development launchers accept `GEV_PROJECT_ROOT` to select the project environment, dependencies and output directory. Their default remains this checkout; bundled tool resources and source checks stay relative to the script installation. The setup doctor also accepts an explicit `rootDir`.
Application composition now uses shared scene/control/catalog/tool constructors and allowlisted HTML component templates. The standalone entry supplies settings and the default sources. Terrain, boundaries, weather, regional context and summaries use configurable services; renderer/action owners remain page-scoped. Annotation proximity guards remain on by default and allow distant targets only for explicit navigation.
+1
View File
@@ -148,6 +148,7 @@
"./aircraft": "./src/layers/aircraft/index.js",
"./layers/vessels": "./src/layers/vessels/index.js",
"./layers/earthquakes": "./src/layers/earthquakes/index.js",
"./sources/firms-csv": "./src/data/firmsCsv.js",
"./layers/firms": "./src/layers/firms/index.js",
"./layers/satellites": "./src/layers/satellites/index.js",
"./layers/launches": "./src/layers/launches/index.js",
+5
View File
@@ -115,6 +115,11 @@
"modules": ["src/data/tomtomTiles.js"],
"external": []
},
"firms-csv": {
"exports": ["./sources/firms-csv"],
"modules": ["src/data/firmsCsv.js"],
"external": []
},
"firms-provider": {
"runtime": "node",
"exports": ["./server/providers/firms"],
+19 -1
View File
@@ -9,7 +9,7 @@ import {
filterTrailing24h,
isLikelyCsv,
parseFirmsCsv,
} from './firmsCsv.js';
} from 'gods-eye-view/sources/firms-csv';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const FIXTURE = fs.readFileSync(
@@ -144,3 +144,21 @@ test('filterTrailing24h on the fixture keeps everything for a same-night now', (
const kept = filterTrailing24h(records, Date.UTC(2026, 6, 17, 2, 0));
assert.equal(kept.length, records.length);
});
const contractCases = JSON.parse(
fs.readFileSync(
path.join(__dirname, 'fixtures', 'firms-csv-cases.json'),
'utf8',
),
);
for (const fixture of contractCases) {
test(`portable FIRMS CSV contract: ${fixture.name}`, () => {
const records = parseFirmsCsv(fixture.csv);
assert.equal(records === null ? null : records.length, fixture.parsedCount);
const recent = filterTrailing24h(records, Date.parse(fixture.now));
assert.deepEqual(
recent.map((record) => record.acqTime),
fixture.recentTimes,
);
});
}
+44
View File
@@ -0,0 +1,44 @@
[
{
"name": "categorical confidence and unpadded midnight time",
"csv": "latitude,longitude,acq_date,acq_time,confidence,frp\n30,-97,2026-07-16,45,n,12\n",
"now": "2026-07-16T12:00:00Z",
"parsedCount": 1,
"recentTimes": ["45"]
},
{
"name": "truncated rows are omitted",
"csv": "latitude,longitude,acq_date,acq_time,confidence,frp\n30,-97,2026-07-16,1200\n",
"now": "2026-07-16T12:00:00Z",
"parsedCount": 0,
"recentTimes": []
},
{
"name": "invalid acquisition hour does not roll into tomorrow",
"csv": "latitude,longitude,acq_date,acq_time,confidence,frp\n30,-97,2026-07-15,2400,n,12\n",
"now": "2026-07-16T12:00:00Z",
"parsedCount": 1,
"recentTimes": []
},
{
"name": "inclusive trailing day and two-hour forward slack",
"csv": "latitude,longitude,acq_date,acq_time,confidence,frp\n30,-97,2026-07-15,1200,n,12\n30,-97,2026-07-15,1159,n,12\n30,-97,2026-07-16,1400,h,12\n30,-97,2026-07-16,1401,l,12\n",
"now": "2026-07-16T12:00:00Z",
"parsedCount": 4,
"recentTimes": ["1200", "1400"]
},
{
"name": "upstream error is different from an empty catalog",
"csv": "Invalid MAP_KEY",
"now": "2026-07-16T12:00:00Z",
"parsedCount": null,
"recentTimes": []
},
{
"name": "header-only catalog is successful and empty",
"csv": "latitude,longitude,acq_date,acq_time,confidence,frp\n",
"now": "2026-07-16T12:00:00Z",
"parsedCount": 0,
"recentTimes": []
}
]