Files
GeoLibre/scripts/plugin-reference.json
T
Qiusheng Wu b606f13441 feat(plugins): NASA Earthaccess plugin for CMR search and Earthdata download (#3085)
* feat(plugins): add NASA Earthaccess plugin for CMR search and download

Add a Web Services plugin that searches NASA's Common Metadata
Repository for datasets and granules over the map view and a date
range, draws granule footprints as a Layers-panel entry, and downloads
granules with an Earthdata Login token. ICESat-2 (ATL06, ATL08) and GEDI
(L2A, L2B, L4A) granules open straight into Add Data -> ICESat-2 / GEDI.

The DAACs send no CORS headers and refuse a preflighted Authorization
header, so downloads need a non-browser hop:

- Desktop: a new native download_remote_file command streams the file
  to disk (no 64 MiB cap, progress over a channel, cancellable), either
  to a path picked in a native save dialog or to the app cache, read
  back once by take_cached_download. JavaScript never names a write
  path. Exposed to plugins as app.downloadRemoteFile.
- Web: a new /earthdata/download route on the tiles Worker, origin
  gated, that accepts only NASA Earthdata data hosts, sends the bearer
  token to the first hop only, follows the presigned CloudFront/S3
  redirect, and streams the file back with CORS and no-store.

Desktop users can also sign in with a user name and password (via
nativeFetch, since the EDL token endpoint has no CORS); only the
returned token is kept, in the keychain through app.credentials.

Part of #3078 (Phase 2: granule search and authenticated download).

* fix(earthaccess): Earthdata Search details link, CI checks

CMR serves granule records only as metadata formats, so Details now
opens the granule in Earthdata Search. Also add the plugin to the
generated plugin reference, list downloadRemoteFile as a desktop-only
app API member, and typecheck the Worker proxy test with the Workers
types.

* Address Claude review feedback

- earthdata.ts: catch a malformed redirect Location and answer 502 with
  CORS instead of an uncaught 500, and narrow the redirect allowlist from
  all of amazonaws.com to S3 endpoints.
- remote_download.rs: request Accept-Encoding: identity (and keep callers
  from overriding it) so the Content-Length check compares like with like.
- remote_download.rs: reject a reused request ID before the save dialog
  opens, and never let a new cache entry orphan an earlier one's file.

* feat(earthaccess): multi-file download and NASA COG map layers

- Multi-file granules (an HLS scene has 15 files) get a collapsible file
  list with a Download per file, and Download all: the desktop app asks
  for a folder once (new pick_download_folder command; JavaScript holds
  only the folder's id, never a path), the browser saves each file.
- GeoTIFFs in the list get Add, which puts them on the map as COG
  layers. The COG readers fetch with the global fetch and take no
  headers, and the DAACs send no CORS headers, so a layer reads through
  the tiles Worker relay. Its saved URL carries no token; a fetch
  wrapper installed at boot adds the Earthdata Login token to requests
  for that exact route, so reopened projects keep working.
- The Worker caches presigned redirect targets (keyed by a hash of the
  token and URL, in memory and in the edge cache, 50 minutes), cutting a
  cached range request from about 1.9 s to about 0.1 s.
- File names in the list drop the shared granule prefix (B04.tif), and
  toggling the list no longer closes it by re-rendering the card.

* fix(earthaccess): refresh Add/Added when a COG layer is removed

The panel computed a file's Added state only when it re-rendered, so
removing the layer from the Layers panel left the button disabled. The
panel now re-renders when the set of Earthdata COG layers in the store
changes, and ignores unrelated layer edits.

* Address review feedback

- earthdata.ts: restrict the content-disposition file name to
  [A-Za-z0-9._-] so an odd URL path cannot make Headers.set throw, and
  request identity encoding upstream so Content-Length matches the body.
- spaceborne-lidar-handoff.ts: isolate listener failures so one bad
  listener cannot stop the others or reach the plugin.
- maplibre-earthaccess.ts: fill MultiPolygon footprints too (CMR reports
  several polygons or boxes for some granules).
- maplibre-earthaccess.ts: freeze the search's date range so Load more
  pages the same query after the date inputs are edited.
- maplibre-earthaccess.ts: give the token link an href so keyboard users
  can reach it.
- remote_download.rs: a folder download never replaces an existing file
  (adds " (n)"), and folder ids come from a counter.

* Address Claude review feedback

- maplibre-earthaccess.ts / earthdata-relay.ts: send the Earthdata
  token only to HTTPS NASA Earthdata data hosts (isEarthdataDataUrl).
  CMR data links are chosen by each provider, so a link on another host
  gets no token on desktop, has no Add, and opens in a new tab on the web
  (the relay serves Earthdata hosts only).
- remote_download.rs: accept only Authorization, Cookie and Accept
  headers (the ones reqwest strips on a cross-host redirect, plus
  Accept), and refuse to send them over plain HTTP; the module docs now
  say exactly which headers stay on the first host.
- earthdata-fetch-auth.ts: install the fetch wrapper through an explicit
  installEarthdataFetchAuth() call in main.tsx, placed right before
  installDiagnosticsCapture(), instead of an import side effect.

* Address review feedback

- remote_download.rs: requests that carry credentials use a client whose
  redirects must stay on HTTPS, since reqwest strips credentials only
  when the host changes (a same-host https -> http hop would resend them).
- remote_download.rs: a folder download reserves its destination with
  create_new before transferring (name, then "name (n)"), streams into a
  request-specific .part file, and removes the placeholder if it fails,
  so concurrent downloads of one name never collide or replace a file.
- types.ts / remote-download.ts: GeoLibreRemoteDownloadOptions is a
  discriminated union that requires folderId for "folder", and the host
  rejects a missing id at runtime.
- maplibre-earthaccess.ts: the browser's Download all reports that the
  downloads started and mentions the multiple-downloads prompt, instead
  of claiming every file was saved.
- earthdata.ts: edge-cache hits go through rememberPresigned so the
  in-memory cap applies.

* Address review feedback

- earthdata.ts: cache the first redirect only when it is a presigned
  target, not another Earthdata host that would fail the tokenless
  replay and be evicted on every request.
- remote_download.rs: report a panicked transfer task as a failure, not
  as "cancelled".
- remote_download.rs: create the folder placeholder's cleanup guard right
  after the reservation and move it into the task, so an abort before
  the task first runs still removes the empty file.
2026-10-09 23:58:30 -04:00

261 lines
11 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"maplibre-layer-control": {
"menu": "Controls → Layer Control",
"description": "The on-map layer list. On by default."
},
"maplibre-gl-geo-editor": {
"description": "Drawing, vertex editing, snapping, and deletion tools for GeoJSON layers."
},
"maplibre-gl-annotations": {
"description": "The map-annotation toolbar (text, arrows, highlights, pins, sticky notes, images) and the Elements panel.",
"docs": "map-controls.md#annotations-and-the-elements-panel"
},
"maplibre-gl-dimensions": {
"description": "CAD-style linear and angular dimension features with vertex snapping, stored in the project as a GeoJSON layer."
},
"maplibre-gl-fema-wms": {
"description": "FEMA National Flood Hazard Layer WMS layers.",
"docs": "web-services.md#fema-nfhl"
},
"maplibre-gl-nasa-earthdata": {
"description": "Over 1,100 pre-rendered global NASA GIBS imagery layers, by date.",
"docs": "web-services.md#nasa-earthdata"
},
"maplibre-gl-enviroatlas": {
"description": "US EPA environmental and ecosystem map services.",
"docs": "web-services.md#us-epa-enviroatlas"
},
"maplibre-gl-national-map": {
"description": "USGS topo, imagery, hydrography, elevation, and index services.",
"docs": "web-services.md#usgs-national-map"
},
"maplibre-usgs-nldi": {
"description": "Flowline tracing, hydrolocation, upstream basins, and network navigation.",
"docs": "usgs-nldi.md"
},
"maplibre-gl-usgs-dem": {
"description": "USGS 3DEP digital elevation models (1 m, 1/3 and 1 arc-second, and more).",
"docs": "web-services.md#usgs-3dep"
},
"maplibre-gl-usgs-lidar": {
"description": "Clip a USGS 3DEP point cloud to an area of interest and download the result as COPC."
},
"maplibre-gl-vantor": {
"description": "Vantor disaster-event satellite imagery (COG).",
"docs": "web-services.md#vantor-open-data"
},
"geolibre-planet-open-data": {
"description": "Planet's disaster data releases, through the STAC browser.",
"docs": "web-services.md#planet-open-data"
},
"geolibre-portolan": {
"description": "Browse the public Portolan Registry of catalogs, or connect to a publisher's catalog URL, and add assets through the STAC loaders."
},
"maplibre-gl-earthdata-gis": {
"description": "NASA EOSDIS ArcGIS image, map, and feature services, and published web maps.",
"docs": "web-services.md#earthdata-gis"
},
"geolibre-earthaccess": {
"description": "Search NASA Earthdata (CMR) for datasets and granules over the map view and download them with an Earthdata Login; ICESat-2 and GEDI granules open onto the map.",
"docs": "web-services.md#nasa-earthaccess"
},
"maplibre-gl-openaerialmap": {
"description": "Openly licensed drone and aerial imagery.",
"docs": "web-services.md#openaerialmap"
},
"geolibre-osm-downloader": {
"description": "Download OpenStreetMap buildings, roads, amenities, waterways, land use, or custom tags through Overpass.",
"docs": "web-services.md#osm-downloader"
},
"geolibre-ign-lidar-hd": {
"description": "Search France's IGN LiDAR HD tile coverage and download COPC point clouds."
},
"geolibre-arcgis-portal": {
"description": "Browse and add the content of your ArcGIS Online organization or ArcGIS Enterprise portal after signing in.",
"docs": "web-services.md#arcgis-portal"
},
"maplibre-gl-arcgis-hub": {
"description": "Public datasets published to ArcGIS Hub.",
"docs": "web-services.md#arcgis-hub"
},
"geolibre-tennessee-gis": {
"description": "The geodata.tn.gov open GIS data portal.",
"docs": "web-services.md#tennessee-gis"
},
"geolibre-us-federal-gis": {
"description": "The public GIS portals of 24 US federal agencies.",
"docs": "web-services.md#us-federal-gis"
},
"geolibre-us-state-gis": {
"description": "The public GIS data portals of all 50 states and DC.",
"docs": "web-services.md#us-state-gis"
},
"geolibre-us-local-gis": {
"description": "The GIS and open-data portals of about 150 large US cities, counties, and regional agencies.",
"docs": "web-services.md#us-local-gis"
},
"maplibre-gl-socrata": {
"description": "Search government Socrata open-data portals.",
"docs": "web-services.md#socrata"
},
"maplibre-gl-ckan": {
"description": "Humanitarian Data Exchange (CKAN) resources.",
"docs": "web-services.md#ckan"
},
"geolibre-stac-catalogs": {
"description": "Any STAC API or static catalog, via STAC Index.",
"docs": "web-services.md#stac-catalogs"
},
"maplibre-gl-source-coop": {
"description": "Cloud-native products (PMTiles, GeoParquet, COG) on Source Cooperative.",
"docs": "web-services.md#source-cooperative"
},
"geolibre-s3-browser": {
"description": "Browse any Amazon S3 or S3-compatible bucket, public or private, and add its files.",
"docs": "web-services.md#s3-browser"
},
"maplibre-gl-natural-earth": {
"description": "The Natural Earth vector and raster themes.",
"docs": "web-services.md#natural-earth"
},
"maplibre-gl-huggingface": {
"description": "Geospatial files in Hugging Face dataset repos, and uploads to them.",
"docs": "web-services.md#hugging-face"
},
"geolibre-satellite-embeddings": {
"description": "Pre-computed foundation-model embeddings such as AlphaEarth, Tessera, and Earth Index.",
"docs": "web-services.md#satellite-embeddings"
},
"geolibre-fields-of-the-world": {
"description": "Global agricultural field boundaries for 2017–2025, colored by model score.",
"docs": "web-services.md#fields-of-the-world"
},
"geolibre-sentinel2-explorer": {
"description": "Sentinel-2 imagery search and viewer over static STAC-GeoParquet, with no API.",
"docs": "web-services.md#sentinel-2-explorer"
},
"geolibre-ocean-data-platform": {
"description": "HUB Ocean's public ocean datasets: habitats, protected areas, fisheries, and observations.",
"docs": "web-services.md#ocean-data-platform"
},
"geolibre-dynamical": {
"description": "dynamical.org weather forecasts, ensembles and analyses (NOAA GFS, GEFS, HRRR and MRMS, ECMWF AIFS and IFS, DWD ICON-EU, ECCC HRDPS, NASA IMERG) as Zarr layers.",
"docs": "web-services.md#dynamical"
},
"maplibre-gl-geolens": {
"description": "A self-hosted GeoLens spatial catalog.",
"docs": "web-services.md#geolens"
},
"maplibre-gl-streetview": {
"description": "Google Street View panoramas at a clicked point."
},
"maplibre-gl-mapillary": {
"description": "Mapillary street-level imagery."
},
"maplibre-h3-grid": {
"description": "The H3 hexagonal grid over the current view; identify a cell and export the grid or selection."
},
"maplibre-s2-grid": {
"description": "The S2 cell grid over the current view; identify a cell and export the grid or selection."
},
"maplibre-a5-grid": {
"description": "The A5 pentagonal grid over the current view; identify a cell and export the grid or selection."
},
"maplibre-dggrid": {
"description": "DGGRID discrete global grids over the current view; identify a cell and export the grid or selection."
},
"maplibre-dggal": {
"description": "DGGAL discrete global grids over the current view; identify a cell and export the grid or selection."
},
"maplibre-olc": {
"description": "The Open Location Code (plus code) grid over the current view; identify a cell and export the grid or selection."
},
"maplibre-geohash": {
"description": "The Geohash grid over the current view; identify a cell and export the grid or selection."
},
"maplibre-tilecode": {
"description": "The web-map tile grid (z/x/y tile codes) over the current view; identify a cell and export the grid or selection."
},
"maplibre-gl-basemap-control": {
"description": "A basemap gallery for switching the background map, from the same catalog as the Change background dialog."
},
"maplibre-gl-esri-wayback": {
"description": "Browse historical aerial and satellite imagery (Esri World Imagery Wayback) for a location."
},
"maplibre-gl-time-slider": {
"description": "Filter a temporal layer by a date or number field, or step a time-enabled raster or Zarr cube through its time axis."
},
"geolibre-timelapse": {
"description": "Animate annual cloudless basemaps (EOX Sentinel-2, NASA GIBS Landsat/WELD and MODIS land cover) and record them to video."
},
"maplibre-gl-overture-maps": {
"description": "Browse and add Overture Maps themes."
},
"maplibre-gl-geoagent": {
"description": "An in-map AI agent panel."
},
"geolibre-elevation-profile": {
"description": "A terrain profile along a drawn line, or along the selected line features of a layer."
},
"maplibre-gl-swipe": {
"description": "A swipe bar comparing two layers."
},
"maplibre-gl-graticule": {
"menu": "Controls → Gridlines",
"description": "A coordinate grid with edge labels, including UTM easting/northing and MGRS/USNG modes."
},
"maplibre-gl-clouds": {
"menu": "Controls → Weather",
"description": "Near-realtime NASA cloud imagery, animated day by day."
},
"maplibre-gl-precipitation": {
"menu": "Controls → Weather",
"description": "RainViewer precipitation radar, animated over roughly the last two hours."
},
"maplibre-atmosphere-effects": {
"menu": "Controls → Atmospheric Effects",
"description": "A deep-space backdrop, starfield, comets, and an atmospheric halo at low zoom."
},
"geolibre-sun": {
"menu": "Controls → Sun",
"description": "The sun's position and the day/night terminator for any date and time."
},
"geolibre-route-animation": {
"menu": "Controls → Route Animation",
"description": "Animate a marker along a line layer with play/pause, speed, a trail, and camera follow."
},
"geolibre-flight-simulator": {
"menu": "Plugins; also Controls → Flight Simulator",
"description": "Fly over terrain and 3D layers with keyboard controls."
},
"gods-eye-view": {
"description": "Live earthquakes, satellite orbits, flights, transit, public cameras, and more on the Cesium globe.",
"docs": "#gods-eye-view"
},
"maplibre-samgeo": {
"description": "Segment imagery into vector features.",
"docs": "segmentation.md"
},
"geolibre-point-cloud-annotation": {
"description": "Select LiDAR points with a box or lasso, assign ASPRS classes, and export LAS 1.4 or a Segments.ai label.",
"docs": "point-cloud-annotation.md"
},
"maplibre-gl-directions": {
"menu": "Controls → Directions",
"description": "Click the map to add waypoints and get a route from the public OSRM demo server."
},
"maplibre-reverse-geocode": {
"menu": "Controls → Reverse Geocode",
"description": "Click the map to look up the address at that point through the configured geocoding provider."
},
"maplibre-deckgl-viz": {
"menu": "Add Data → Deck.gl Layer",
"description": "The deck.gl overlay that renders layers built in the Deck.gl Layer dialog."
},
"maplibre-gl-components": {
"menu": "Controls (Search, Legend, Measure, …)",
"description": "The component panels; each is toggled from the Controls menu rather than as one plugin.",
"docs": "map-controls.md#component-tools"
}
}