@geolibre/core 3.4.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as isHeaderReferenceOnly, $n as geoJSONToPolylineStr, $r as MAX_DASHBOARD_COLUMNS, $t as layerGroupSortability, A as normalizeSecondaryMapViews, An as metadataDateToRfc3339, Ar as getActiveEllipsoid, At as normalizeStyleLibraryEntries, B as storyMapHasContent, Bn as isStyleSpecColor, Br as DEFAULT_BASEMAP, Bt as scrubPrintLayoutForRemovedLayers, C as normalizeModelGraph, Cn as stripVirtualFieldColumns, Cr as PLANETARY_BASEMAP_GROUPS, Ct as RAMP_STYLE_KEYS, D as normalizeProcessingHistory, Dn as isValidMetadataDate, Dr as earthAreaToBody, Dt as createStyleLibraryEntryId, E as normalizePrimaryRenderer, En as buildLayerStacItem, Er as bodyLengthToEarth, Et as SYMBOL_STYLE_KEYS, F as projectFromStore, Fn as EXPRESSION_FUNCTION_CATEGORIES, Fr as getPlanetaryBasemapByStyleUrl, Ft as createDefaultPrintLayout, G as isCredentialUrlParam, Gn as SELECTION_MODES, Gr as DEFAULT_MAP_GRID_LAYOUT, Gt as DEFAULT_LAYER_GROUP_OPACITY, H as PROJECT_CREDENTIAL_FIELDS, Hn as removeTrailingJsonCommas, Hr as DEFAULT_DASHBOARD_COLUMNS, Ht as scrubCommentsForRemovedLayers, I as resolveMapGrid, In as compileFeatureExpression, Ir as meanRadiusMeters, It as isDefaultPrintLayout, J as redactProjectCredentials, Jn as invertSelection, Jr as DEFAULT_STORY_MAP, Jt as buildLayerTree, K as redactConfigurationCredentials, Kn as applySelectionMode, Kr as DEFAULT_PRIMARY_RENDERER, Kt as applyGroupEffects, L as serializeProject, Ln as evaluateMapExpression, Lr as setActiveEllipsoidId, Lt as normalizePrintLayoutConfig, M as normalizeWidgets, Mn as parseMetadataKeywords, Mr as getActiveSemiMajorAxisMeters, Mt as sanitizeLayerStylePatch, N as parseProject, Nn as stacAssetMediaType, Nr as getEllipsoid, Nt as serializeStyleLibrary, O as normalizeProjectComments, On as isValidMetadataEmail, Or as earthLengthToBody, Ot as extractStyleLibraryStyle, P as portableWmsTileUrl, Pn as validateLayerDescriptiveMetadata, Pr as getPlanetaryBasemapById, Pt as DEFAULT_PRINT_LAYOUT, Q as hasHeaderReferences, Qn as encodePolyline, Qr as LAYER_TYPES, Qt as layerGroupMoveability, R as serializeProjectWithLayerCache, Rn as formatExpressionPreviewValue, Rr as BLANK_BASEMAP, Rt as printLayoutConfigsEqual, S as normalizeMapViewState, Sn as applyLayerVirtualFields, Sr as PLANETARY_BASEMAPS, St as BUILT_IN_STYLE_PRESETS, T as normalizeObiaWorkbench, Tn as STAC_VERSION, Tr as PLANET_SWITCHER_OPTIONS, Tt as STYLE_LIBRARY_BUNDLE_VERSION, U as PUBLISHABLE_PLUGIN_SETTINGS, Un as substituteExpressionVariables, Ur as DEFAULT_LAYER_STYLE, Ut as scrubLegendForRemovedLayers, V as MAX_REDACT_DEPTH, Vn as matchFeaturesByExpression, Vr as DEFAULT_BLEND_MODE, Vt as removedLayerIdSet, W as isCredentialFieldName, Wn as validateMapExpression, Wr as DEFAULT_LEGEND_CONFIG, Wt as scrubWidgetsForRemovedLayers, X as setRegistryPublishableSettings, Xn as decodePolyline, Xr as DUCKDB_VECTOR_ROUTE_BYTES, Xt as groupMemberIndices, Y as redactUrlCredentials, Yn as batchDecodePolylines, Yr as DUCKDB_VECTOR_FEATURE_WARN_COUNT, Yt as effectiveLayerRenderState, Z as allowsCredentialHeaders, Zn as decodePolylineDetailed, Zr as LARGE_VECTOR_FEATURE_THRESHOLD, Zt as layerGroupDepth, _ as normalizeBookmarkGroups, _n as cascadeLayerJoinRefresh, _r as getRegionalBasemapByStyleUrl, _t as CZML_SOURCE_KIND, a as DEFAULT_PROJECT_NAME, ai as PROJECT_VERSION, an as ROLE_PRIVILEGES, ar as ARCGIS_PROJECTION_PRESETS, at as CESIUM_OSM_BUILDINGS_ASSET_ID, b as normalizeLegendConfig, bn as reapplyLayerJoins, br as EARTH_MEAN_RADIUS_METERS, bt as isCzmlLayer, c as createDefaultMapView, ci as detectNonGeographicCoordinates, cn as hasAppPrivilege, cr as availableCesiumBasemap, ct as createCesiumIonLayer, d as createProjectTemplate, di as styleValue, dn as normalizeAppPrivileges, dr as sameCesiumImagery, dt as parseCesiumIonAssetId, ei as MAX_MAP_GRID_DIM, en as layerPanelGroupHeaders, er as polylineStrToGeoJSON, et as resolveHeaderReferences, f as detachProjectCopy, fn as normalizeLayerCapabilities, fr as CHINA_BASEMAPS, ft as CESIUM_KML_SOURCE_KIND, g as normalizeBlankBackgroundColor, gn as applyLayerJoins, gr as getRegionalBasemapById, gt as CZML_QUICK_PICKS, h as isSessionOnlyLayer, hn as applyJoinsToLayer, hr as REGIONAL_BASEMAP_SENTINEL_PREFIX, ht as isCesiumKmlLayer, i as previewValue, ii as OPENFREEMAP_BASEMAPS, in as ALL_APP_PRIVILEGES, ir as transformGeojsonElevation, it as CESIUM_ION_SOURCE_KIND, j as normalizeStoryMap, jn as normalizeLayerDescriptiveMetadata, jr as getActiveMeanRadiusMeters, jt as parseStyleLibrary, k as normalizeProjectInteraction, kn as isValidMetadataUrl, kr as getActiveBodyRadiusRatio, kt as isStyleLibraryTargetLayer, l as createEmptyProject, li as isDuckDBQueryLayer, ln as inferLayerCapabilities, lr as basemapToCesiumImagery, lt as isCesiumIonLayer, m as isAllowedPluginManifestUrl, mn as resolveRolePrivileges, mr as REGIONAL_BASEMAP_GROUPS, mt as createCesiumKmlLayer, n as diffProjects, ni as MIN_DASHBOARD_COLUMNS, nn as reorderLayerGroupInPanel, nr as geojsonHasZCoordinates, nt as CESIUM_GOOGLE_PHOTOREALISTIC_ASSET_ID, o as MAX_PROJECT_BOOKMARKS, oi as PROTOMAPS_BASEMAPS, on as appPrivilegeReason, or as normalizeArcgisWkid, ot as cesiumIonAssetId, p as hydrateProjectLayer, pn as resolveLayerCapabilities, pr as REGIONAL_BASEMAPS, pt as cesiumKmlSource, q as redactCredentials, qn as featureSelectionId, qr as DEFAULT_PROJECT_PREFERENCES, qt as buildLayerPanelUnits, r as jsonValuesEqual, ri as NETCDF_IMAGE_SOURCE_KIND, rn as sortLayerGroupInPanel, rr as horizontalBbox, rt as CESIUM_ION_QUICK_PICKS, s as applyProjectToStore, si as SQL_QUERY_SOURCE_KIND, sn as createDefaultAppCapabilities, sr as CESIUM_BASEMAPS, st as cesiumIonAssetKind, t as diffFeatureCollections, ti as MAX_PROCESSING_HISTORY, tn as normalizeGroupContiguity, tr as unescapePolyline, tt as CESIUM_BING_AERIAL_ASSET_ID, u as createProjectLayerSerializationCache, ui as shouldUseTiledRendering, un as intersectPrivileges, ur as normalizeCesiumBasemap, ut as isCesiumOnlyLayer, v as normalizeBookmarks, vn as collectTransitiveJoinSourceIds, vr as isRegionalBasemapSentinel, vt as createCzmlLayer, w as normalizeModels, wn as STAC_PROCESSING_EXTENSION, wr as PLANETARY_BASEMAP_SENTINEL_PREFIX, wt as STYLE_LIBRARY_BUNDLE_TYPE, x as normalizeMapLayout, xn as stripJoinFields, xr as ELLIPSOIDS, xt as parseCzml, y as normalizeDashboardColumns, yn as layerJoinKey, yr as DEFAULT_ELLIPSOID_ID, yt as czmlSource, z as serializeProjectWithLayerCacheAsync, zn as inferFieldTypes, zr as BLEND_MODES, zt as scrubPrintLayoutForLayers } from "./project-diff-Bua7fBME.mjs";
1
+ import { $ as GEOCODING_PROVIDERS, $i as getPlanetaryBasemapByStyleUrl, $n as groupMemberIndices, $r as getBuildEnvironment, $t as CESIUM_BING_AERIAL_ASSET_ID, A as normalizeSecondaryMapViews, Ai as CHINA_BASEMAPS, An as createStyleLibraryEntryId, Ar as isValidMetadataDate, At as selectedGeocodingLocator, B as storyMapHasContent, Bi as PLANETARY_BASEMAPS, Bn as normalizePrintLayoutConfig, Br as evaluateMapExpression, Bt as PROJECT_CREDENTIAL_FIELDS, C as normalizeModelGraph, Ca as PROJECT_VERSION, Ci as ARCGIS_PROJECTION_PRESETS, Cn as isGeoArrowBatch, Cr as reapplyLayerJoins, Ct as normalizeArcGISLocatorUrl, D as normalizeProcessingHistory, Da as isDuckDBQueryLayer, Di as basemapToCesiumImagery, Dn as STYLE_LIBRARY_BUNDLE_TYPE, Dr as STAC_PROCESSING_EXTENSION, Dt as parseArcGISSuggestions, E as normalizePrimaryRenderer, Ea as detectNonGeographicCoordinates, Ei as availableCesiumBasemap, En as RAMP_STYLE_KEYS, Er as stripVirtualFieldColumns, Et as parseArcGISLocatorInfo, F as projectFromStore, Fi as getRegionalBasemapByStyleUrl, Fn as sanitizeLayerStylePatch, Fr as parseMetadataKeywords, Ft as DEFAULT_STORY_CHAPTER_DURATION_SECONDS, G as DEFAULT_REVERSE_GEOCODE_ENDPOINT, Gi as earthAreaToBody, Gn as scrubCommentsForRemovedLayers, Gr as removeTrailingJsonCommas, Gt as redactCredentials, H as CARTOCIUDAD_PUBLIC_HOST, Hi as PLANETARY_BASEMAP_SENTINEL_PREFIX, Hn as scrubPrintLayoutForLayers, Hr as inferFieldTypes, Ht as isCredentialFieldName, I as resolveMapGrid, Ii as isRegionalBasemapSentinel, In as serializeStyleLibrary, Ir as stacAssetMediaType, It as MAX_STORY_CHAPTER_DURATION_SECONDS, J as GEOCODE_LAT_KEY, Ji as getActiveEllipsoid, Jn as DEFAULT_LAYER_GROUP_OPACITY, Jr as SELECTION_MODES, Jt as setRegistryPublishableSettings, K as GEOCODE_ATTRIBUTE_PREFIX, Ki as earthLengthToBody, Kn as scrubLegendForRemovedLayers, Kr as substituteExpressionVariables, Kt as redactProjectCredentials, L as serializeProject, Li as DEFAULT_ELLIPSOID_ID, Ln as DEFAULT_PRINT_LAYOUT, Lr as validateLayerDescriptiveMetadata, Lt as MIN_STORY_CHAPTER_DURATION_SECONDS, M as normalizeWidgets, Mi as REGIONAL_BASEMAP_GROUPS, Mn as isStyleLibraryTargetLayer, Mr as isValidMetadataUrl, Mt as setGeocodingTokenProvider, N as parseProject, Ni as REGIONAL_BASEMAP_SENTINEL_PREFIX, Nn as normalizeStyleLibraryEntries, Nr as metadataDateToRfc3339, Nt as shouldThrottle, O as normalizeProjectComments, Oa as shouldUseTiledRendering, Oi as normalizeCesiumBasemap, On as STYLE_LIBRARY_BUNDLE_VERSION, Or as STAC_VERSION, Ot as resolveGeocoderConfig, P as portableWmsTileUrl, Pi as getRegionalBasemapById, Pn as parseStyleLibrary, Pr as normalizeLayerDescriptiveMetadata, Pt as unmatchedGeocodeFeature, Q as GEOCODE_STATUS_KEY, Qi as getPlanetaryBasemapById, Qn as effectiveLayerRenderState, Qr as getArcgisApiKey, Qt as resolveHeaderReferences, R as serializeProjectWithLayerCache, Ri as EARTH_MEAN_RADIUS_METERS, Rn as createDefaultPrintLayout, Rr as EXPRESSION_FUNCTION_CATEGORIES, Rt as normalizeStoryChapterDurationSeconds, S as normalizeMapViewState, Sa as OPENFREEMAP_BASEMAPS, Si as parseMapCrsEpsgCode, Sn as geoArrowToFeatureCollection, Sr as layerJoinKey, St as nominatimReverseResultToDisplay, T as normalizeObiaWorkbench, Ta as SQL_QUERY_SOURCE_KIND, Ti as CESIUM_BASEMAPS, Tn as BUILT_IN_STYLE_PRESETS, Tr as applyLayerVirtualFields, Tt as normalizeGeocodingProviderId, U as DEFAULT_FORWARD_GEOCODE_ENDPOINT, Ui as PLANET_SWITCHER_OPTIONS, Un as scrubPrintLayoutForRemovedLayers, Ur as isStyleSpecColor, Ut as isCredentialUrlParam, V as CARTOCIUDAD_MIN_INTERVAL_MS, Vi as PLANETARY_BASEMAP_GROUPS, Vn as printLayoutConfigsEqual, Vr as formatExpressionPreviewValue, Vt as PUBLISHABLE_PLUGIN_SETTINGS, W as DEFAULT_GEOCODING_PROVIDER_ID, Wi as bodyLengthToEarth, Wn as removedLayerIdSet, Wr as matchFeaturesByExpression, Wt as redactConfigurationCredentials, X as GEOCODE_PROVIDER_KEY, Xi as getActiveSemiMajorAxisMeters, Xn as buildLayerPanelUnits, Xr as featureSelectionId, Xt as hasHeaderReferences, Y as GEOCODE_LON_KEY, Yi as getActiveMeanRadiusMeters, Yn as applyGroupEffects, Yr as applySelectionMode, Yt as allowsCredentialHeaders, Z as GEOCODE_SCORE_KEY, Zi as getEllipsoid, Zn as buildLayerTree, Zr as invertSelection, Zt as isHeaderReferenceOnly, _ as normalizeBookmarkGroups, _a as MAX_DASHBOARD_COLUMNS, _i as MAP_CRS_PRESETS, _n as czmlSource, _r as resolveRolePrivileges, _t as geocoderSupportsSuggest, a as DEFAULT_PROJECT_NAME, aa as DEFAULT_BLEND_MODE, ai as getRuntimeEnvironment, an as cesiumIonAssetKind, ar as reorderLayerGroupInPanel, at as arcgisLocatorInputField, b as normalizeLegendConfig, ba as MIN_DASHBOARD_COLUMNS, bi as getMapCrsPreset, bn as computeGeoArrowBBox, br as cascadeLayerJoinRefresh, bt as nextDelayMs, c as createDefaultMapView, ca as DEFAULT_LEGEND_CONFIG, ci as decodePolyline, cn as isCesiumOnlyLayer, cr as ROLE_PRIVILEGES, ct as csvRowsToGeocodeRequests, d as createProjectTemplate, da as DEFAULT_PROJECT_PREFERENCES, di as geoJSONToPolylineStr, dn as cesiumKmlSource, dr as hasAppPrivilege, dt as geocodeMatchToFeature, ea as meanRadiusMeters, ei as getCesiumIonToken, en as CESIUM_GOOGLE_PHOTOREALISTIC_ASSET_ID, er as layerGroupDepth, et as GeocoderServiceError, f as detachProjectCopy, fa as DEFAULT_STORY_MAP, fi as polylineStrToGeoJSON, fn as createCesiumKmlLayer, fr as inferLayerCapabilities, ft as geocodeReverse, g as normalizeBlankBackgroundColor, ga as LAYER_TYPES, gi as transformGeojsonElevation, gn as createCzmlLayer, gr as resolveLayerCapabilities, gt as geocoderSupportsReverse, h as isSessionOnlyLayer, ha as LARGE_VECTOR_FEATURE_THRESHOLD, hi as horizontalBbox, hn as CZML_SOURCE_KIND, hr as normalizeLayerCapabilities, ht as geocoderNeedsApiKey, i as previewValue, ia as DEFAULT_BASEMAP, ii as getProtomapsStyleUrl, in as cesiumIonAssetId, ir as normalizeGroupContiguity, it as PUBLIC_GEOCODE_ROW_CAP, j as normalizeStoryMap, ji as REGIONAL_BASEMAPS, jn as extractStyleLibraryStyle, jr as isValidMetadataEmail, jt as setGeocodingFetch, k as normalizeProjectInteraction, ka as styleValue, ki as sameCesiumImagery, kn as SYMBOL_STYLE_KEYS, kr as buildLayerStacItem, kt as rowCap, l as createEmptyProject, la as DEFAULT_MAP_GRID_LAYOUT, li as decodePolylineDetailed, ln as parseCesiumIonAssetId, lr as appPrivilegeReason, lt as fetchArcGISLocatorInfo, m as isAllowedPluginManifestUrl, ma as DUCKDB_VECTOR_ROUTE_BYTES, mi as geojsonHasZCoordinates, mn as CZML_QUICK_PICKS, mr as normalizeAppPrivileges, mt as geocoderMinIntervalMs, n as diffProjects, na as BLANK_BASEMAP, ni as getMapboxAccessToken, nn as CESIUM_ION_SOURCE_KIND, nr as layerGroupSortability, nt as NOMINATIM_MIN_INTERVAL_MS, o as MAX_PROJECT_BOOKMARKS, oa as DEFAULT_DASHBOARD_COLUMNS, oi as getSpatialExtensionPath, on as createCesiumIonLayer, or as sortLayerGroupInPanel, ot as buildForwardGeocodeUrl, p as hydrateProjectLayer, pa as DUCKDB_VECTOR_FEATURE_WARN_COUNT, pi as unescapePolyline, pn as isCesiumKmlLayer, pr as intersectPrivileges, pt as geocodeSuggest, q as GEOCODE_DISPLAY_NAME_KEY, qi as getActiveBodyRadiusRatio, qn as scrubWidgetsForRemovedLayers, qr as validateMapExpression, qt as redactUrlCredentials, r as jsonValuesEqual, ra as BLEND_MODES, ri as getProtomapsApiKey, rn as CESIUM_OSM_BUILDINGS_ASSET_ID, rr as layerPanelGroupHeaders, rt as NOMINATIM_PUBLIC_HOST, s as applyProjectToStore, sa as DEFAULT_LAYER_STYLE, si as batchDecodePolylines, sn as isCesiumIonLayer, sr as ALL_APP_PRIVILEGES, st as buildReverseGeocodeUrl, t as diffFeatureCollections, ta as setActiveEllipsoidId, ti as getGoogleMapsApiKey, tn as CESIUM_ION_QUICK_PICKS, tr as layerGroupMoveability, tt as GeocoderUnsupportedError, u as createProjectLayerSerializationCache, ua as DEFAULT_PRIMARY_RENDERER, ui as encodePolyline, un as CESIUM_KML_SOURCE_KIND, ur as createDefaultAppCapabilities, ut as geocodeForward, v as normalizeBookmarks, va as MAX_MAP_GRID_DIM, vi as adaptBboxTemplateToCrs, vn as isCzmlLayer, vr as applyJoinsToLayer, vt as getGeocoderConfig, w as normalizeModels, wa as PROTOMAPS_BASEMAPS, wi as normalizeArcgisWkid, wn as withRasterSourceDefaults, wr as stripJoinFields, wt as normalizeGeocodingLocator, x as normalizeMapLayout, xa as NETCDF_IMAGE_SOURCE_KIND, xi as normalizeMapCrs, xn as featureCollectionToGeoArrow, xr as collectTransitiveJoinSourceIds, xt as nominatimResultToFeature, y as normalizeDashboardColumns, ya as MAX_PROCESSING_HISTORY, yi as deriveTileMatrixSet, yn as parseCzml, yr as applyLayerJoins, yt as getGeocodingProvider, z as serializeProjectWithLayerCacheAsync, zi as ELLIPSOIDS, zn as isDefaultPrintLayout, zr as compileFeatureExpression, zt as MAX_REDACT_DEPTH } from "./project-diff-CPb5ZXb_.mjs";
2
2
  import { Color, featureFilter, latest, normalizePropertyExpression } from "@maplibre/maplibre-gl-style-spec";
3
3
  import { create } from "zustand";
4
4
  import { temporal } from "zundo";
@@ -976,176 +976,6 @@ function isAbsoluteFilesystemPath(path) {
976
976
  return path.startsWith("/") || /^[a-z]:[\\/]/i.test(path);
977
977
  }
978
978
  //#endregion
979
- //#region src/runtime-env.ts
980
- const buildEnv = typeof __GEOLIBRE_BUILD_ENV__ === "undefined" ? {} : __GEOLIBRE_BUILD_ENV__;
981
- /**
982
- * The allowlisted build-time environment, with no runtime overlay.
983
- *
984
- * For settings that must be fixed by the build and NOT overridable by a
985
- * `.geolibre.json` a user opened — the auth gate, the deployment profile, the
986
- * embed origin allowlist. Routing those through {@link getRuntimeEnvironment}
987
- * would let project-supplied `__GEOLIBRE_RUNTIME_ENV__` values relax them.
988
- *
989
- * Callers should prefer this over reading `import.meta.env` directly: a
990
- * whole-object read defeats Vite's per-key replacement and inlines every
991
- * `VITE_` var on the build machine into the chunk.
992
- *
993
- * @returns The build-time environment record.
994
- */
995
- function getBuildEnvironment() {
996
- return buildEnv;
997
- }
998
- /**
999
- * Merges build-time env with project runtime env (the latter wins). Falls back
1000
- * to build-time env alone outside a browser (e.g. in tests).
1001
- *
1002
- * @returns The resolved environment variables.
1003
- */
1004
- function getRuntimeEnvironment() {
1005
- if (typeof window === "undefined") return buildEnv;
1006
- return {
1007
- ...buildEnv,
1008
- ...window.__GEOLIBRE_RUNTIME_ENV__ ?? {}
1009
- };
1010
- }
1011
- /**
1012
- * Resolves a local DuckDB spatial extension path from the runtime environment.
1013
- *
1014
- * When `VITE_DUCKDB_SPATIAL_EXTENSION_PATH` is set, DuckDB consumers (the
1015
- * desktop app's own loader and the Add Vector panel's maplibre-gl-vector
1016
- * control) load the spatial extension from this path with `LOAD '<path>'`
1017
- * instead of installing it from the remote repository, which hangs in
1018
- * sandboxed or firewalled environments. Lives in `@geolibre/core` so every
1019
- * consumer shares one implementation.
1020
- *
1021
- * @param env - Environment record (defaults to the runtime environment);
1022
- * injectable for testing.
1023
- * @returns The trimmed extension path, or undefined when unset.
1024
- */
1025
- function getSpatialExtensionPath(env) {
1026
- return (env ?? getRuntimeEnvironment()).VITE_DUCKDB_SPATIAL_EXTENSION_PATH?.trim() || void 0;
1027
- }
1028
- /**
1029
- * Resolves the Protomaps API key from the runtime environment.
1030
- *
1031
- * Protomaps' hosted styles require an API key embedded in the style URL. The
1032
- * key is supplied via `VITE_PROTOMAPS_API_KEY` (baked in at build time for the
1033
- * web demo; see the deploy workflow). When unset, the Protomaps basemaps are
1034
- * unavailable and should be hidden from the UI.
1035
- *
1036
- * @param env - Environment record (defaults to the runtime environment);
1037
- * injectable for testing.
1038
- * @returns The trimmed API key, or undefined when unset.
1039
- */
1040
- function getProtomapsApiKey(env) {
1041
- return (env ?? getRuntimeEnvironment()).VITE_PROTOMAPS_API_KEY?.trim() || void 0;
1042
- }
1043
- /**
1044
- * Resolves the Google Maps API key from the runtime environment.
1045
- *
1046
- * GeoLibre's browser-facing builds normally use `VITE_GOOGLE_MAPS_API_KEY`.
1047
- * The bare `GOOGLE_MAPS_API_KEY` fallback is reached two ways: (1) the desktop
1048
- * Vite config copies it to `VITE_GOOGLE_MAPS_API_KEY` at build time for local
1049
- * shell testing (`vite.config.ts`'s `envPrefix` does not include the bare
1050
- * name), and (2) a project's own runtime environment variables
1051
- * (`window.__GEOLIBRE_RUNTIME_ENV__`), which are not subject to Vite's
1052
- * envPrefix allowlist at all.
1053
- *
1054
- * @param env - Environment record (defaults to the runtime environment);
1055
- * injectable for testing.
1056
- * @returns The trimmed API key, or undefined when unset.
1057
- */
1058
- function getGoogleMapsApiKey(env) {
1059
- const runtimeEnv = env ?? getRuntimeEnvironment();
1060
- return runtimeEnv.VITE_GOOGLE_MAPS_API_KEY?.trim() || runtimeEnv.GOOGLE_MAPS_API_KEY?.trim() || void 0;
1061
- }
1062
- /**
1063
- * Resolves the Mapbox access token from the runtime environment.
1064
- *
1065
- * The basemap control's Mapbox styles authenticate with the user's own token.
1066
- * It is supplied via `VITE_MAPBOX_ACCESS_TOKEN` (baked in at build time from the
1067
- * bare `MAPBOX_TOKEN` env var, which `vite.config.ts` copies into the prefixed
1068
- * name — the spelling Mapbox's own tooling uses) or set at runtime through
1069
- * Settings → Environment variables (`window.__GEOLIBRE_RUNTIME_ENV__`, which
1070
- * bypasses Vite's envPrefix allowlist, so a bare `MAPBOX_TOKEN` entry works
1071
- * there too). When unset, the Mapbox basemaps prompt for a token in the basemap
1072
- * panel's API keys view instead.
1073
- *
1074
- * Note the precedence, shared with {@link getGoogleMapsApiKey} and
1075
- * {@link getCesiumIonToken}: the prefixed name always wins over the bare one,
1076
- * and `getRuntimeEnvironment` merges build-time and runtime vars into one
1077
- * record. So a build that baked in `VITE_MAPBOX_ACCESS_TOKEN` is overridden at
1078
- * runtime by a Settings entry under that *same* prefixed name; a bare
1079
- * `MAPBOX_TOKEN` entry is a fallback for when nothing was baked in, not a way
1080
- * to override a baked token.
1081
- *
1082
- * @param env - Environment record (defaults to the runtime environment);
1083
- * injectable for testing.
1084
- * @returns The trimmed token, or undefined when unset.
1085
- */
1086
- function getMapboxAccessToken(env) {
1087
- const runtimeEnv = env ?? getRuntimeEnvironment();
1088
- return runtimeEnv.VITE_MAPBOX_ACCESS_TOKEN?.trim() || runtimeEnv.MAPBOX_TOKEN?.trim() || void 0;
1089
- }
1090
- /**
1091
- * Resolves the ArcGIS API key from the runtime environment.
1092
- *
1093
- * The ArcGIS renderer draws the translated project basemap and non-Esri layers
1094
- * without a key; Esri's basemap styles and location services require one
1095
- * (an ArcGIS Location Platform or ArcGIS Online API key credential). It is
1096
- * supplied via `VITE_ARCGIS_API_KEY` (baked in at build time from the bare
1097
- * `ARCGIS_API_KEY` env var, which `vite.config.ts` copies into the prefixed
1098
- * name) or set at runtime through Settings → Environment variables
1099
- * (`window.__GEOLIBRE_RUNTIME_ENV__`, so a bare `ARCGIS_API_KEY` entry works
1100
- * there too). Same precedence as {@link getMapboxAccessToken}.
1101
- *
1102
- * @param env - Environment record (defaults to the runtime environment);
1103
- * injectable for testing.
1104
- * @returns The trimmed key, or undefined when unset.
1105
- */
1106
- function getArcgisApiKey(env) {
1107
- const runtimeEnv = env ?? getRuntimeEnvironment();
1108
- return runtimeEnv.VITE_ARCGIS_API_KEY?.trim() || runtimeEnv.ARCGIS_API_KEY?.trim() || void 0;
1109
- }
1110
- /**
1111
- * Resolves the Cesium Ion access token from the runtime environment.
1112
- *
1113
- * Cesium World Terrain and Ion World Imagery need a Cesium Ion token. It is
1114
- * supplied via `VITE_CESIUM_TOKEN` (baked in at build time from the bare
1115
- * `CESIUM_TOKEN` env var, which `vite.config.ts` copies into the prefixed name)
1116
- * or set at runtime through Settings → Environment variables
1117
- * (`window.__GEOLIBRE_RUNTIME_ENV__`, which bypasses Vite's envPrefix allowlist,
1118
- * so a bare `CESIUM_TOKEN` entry works there too).
1119
- *
1120
- * The 3D-globe view itself does **not** need one: it draws the project basemap
1121
- * as its base imagery whenever that basemap has a raster form (see
1122
- * {@link basemapToCesiumImagery}), and falls back to Ion World Imagery — or, with
1123
- * no token, to OpenStreetMap — for the ones that do not. So an absent token
1124
- * costs terrain and the quality of that fallback, not the view.
1125
- *
1126
- * @param env - Environment record (defaults to the runtime environment);
1127
- * injectable for testing.
1128
- * @returns The trimmed token, or undefined when unset.
1129
- */
1130
- function getCesiumIonToken(env) {
1131
- const runtimeEnv = env ?? getRuntimeEnvironment();
1132
- return runtimeEnv.VITE_CESIUM_TOKEN?.trim() || runtimeEnv.CESIUM_TOKEN?.trim() || void 0;
1133
- }
1134
- /**
1135
- * Builds a full Protomaps v5 style URL for a flavor, injecting the API key.
1136
- *
1137
- * @param flavor - The Protomaps flavor name (e.g. `light`, `dark`, `white`,
1138
- * `grayscale`, `black`).
1139
- * @param env - Environment record (defaults to the runtime environment);
1140
- * injectable for testing.
1141
- * @returns The resolved style URL, or undefined when no API key is configured.
1142
- */
1143
- function getProtomapsStyleUrl(flavor, env) {
1144
- const key = getProtomapsApiKey(env);
1145
- if (!key) return void 0;
1146
- return `https://api.protomaps.com/styles/v5/${encodeURIComponent(flavor)}/en.json?key=${encodeURIComponent(key)}`;
1147
- }
1148
- //#endregion
1149
979
  //#region src/routing.ts
1150
980
  /**
1151
981
  * Routing / network-analysis client and pure helpers backing the Processing →
@@ -4612,7 +4442,8 @@ const RASTER_TILE_LAYER_TYPES = /* @__PURE__ */ new Set([
4612
4442
  const createLayersSlice = (set, get) => ({
4613
4443
  layers: [],
4614
4444
  copiedLayerStyle: null,
4615
- addLayer: (layer, beforeLayerId = null) => set((s) => {
4445
+ addLayer: (inputLayer, beforeLayerId = null) => set((s) => {
4446
+ let layer = withRasterSourceDefaults(inputLayer);
4616
4447
  const layers = [...s.layers];
4617
4448
  const { sourcePath } = layer;
4618
4449
  if (sourcePath && (!/^[a-z][a-z0-9+.-]*:\/\//i.test(sourcePath) || /^(content|file):\/\//i.test(sourcePath)) && isSourceDerivedLayerName(layer.name, sourcePath)) layer = {
@@ -4656,10 +4487,19 @@ const createLayersSlice = (set, get) => ({
4656
4487
  isDirty: true
4657
4488
  })),
4658
4489
  updateLayer: (id, patch) => set((s) => {
4659
- let layers = s.layers.map((l) => l.id === id ? {
4660
- ...l,
4661
- ...patch
4662
- } : l);
4490
+ let layers = s.layers.map((l) => {
4491
+ if (l.id !== id) return l;
4492
+ const updated = {
4493
+ ...l,
4494
+ ...patch
4495
+ };
4496
+ if (patch.geojson !== void 0 && !("geoarrow" in patch)) delete updated.geoarrow;
4497
+ else if ("geoarrow" in patch) {
4498
+ if (patch.geoarrow === null || patch.geoarrow === void 0) delete updated.geoarrow;
4499
+ else updated.geoarrow = patch.geoarrow;
4500
+ }
4501
+ return updated;
4502
+ });
4663
4503
  if (patch.geojson !== void 0) {
4664
4504
  if (patch.joins === void 0 && patch.virtualFields === void 0) layers = layers.map((l) => l.id === id && (l.joins?.length || l.virtualFields?.length) ? applyJoinsToLayer(l, layers) : l);
4665
4505
  layers = cascadeLayerJoinRefresh(layers, id);
@@ -4793,8 +4633,14 @@ const createLayersSlice = (set, get) => ({
4793
4633
  isDirty: true
4794
4634
  };
4795
4635
  }),
4796
- addGeoJsonLayer: (name, geojson, sourcePath, beforeLayerId = null) => {
4636
+ addGeoJsonLayer: (name, geojson, sourcePath, beforeLayerId = null, extra) => {
4797
4637
  const id = v4();
4638
+ let geoarrow = extra?.geoarrow;
4639
+ if (!geoarrow && shouldUseTiledRendering(geojson)) try {
4640
+ geoarrow = featureCollectionToGeoArrow(geojson) ?? void 0;
4641
+ } catch (err) {
4642
+ console.warn("[GeoLibre] GeoArrow batch conversion failed; falling back to GeoJSON", err);
4643
+ }
4798
4644
  const layer = {
4799
4645
  id,
4800
4646
  name,
@@ -4807,8 +4653,9 @@ const createLayersSlice = (set, get) => ({
4807
4653
  layers: get().layers,
4808
4654
  overrides: { simpleStyleEnabled: hasSimpleStyleProperties(geojson) }
4809
4655
  }),
4810
- metadata: {},
4656
+ metadata: { ...extra?.metadata },
4811
4657
  geojson,
4658
+ ...geoarrow ? { geoarrow } : {},
4812
4659
  sourcePath
4813
4660
  };
4814
4661
  get().addLayer(layer, beforeLayerId);
@@ -8062,7 +7909,8 @@ const CSV_HEADERS = [
8062
7909
  "mapAnimation",
8063
7910
  "rotateAnimation",
8064
7911
  "onChapterEnter",
8065
- "onChapterExit"
7912
+ "onChapterExit",
7913
+ "durationSeconds"
8066
7914
  ];
8067
7915
  /**
8068
7916
  * Serialize a story map's chapters to CSV (one row per chapter).
@@ -8090,7 +7938,8 @@ function serializeStoryMapCsv(storymap) {
8090
7938
  c.mapAnimation,
8091
7939
  String(c.rotateAnimation),
8092
7940
  JSON.stringify(c.onChapterEnter),
8093
- JSON.stringify(c.onChapterExit)
7941
+ JSON.stringify(c.onChapterExit),
7942
+ String(c.durationSeconds ?? "")
8094
7943
  ].map(csvEscape).join(","));
8095
7944
  return rows.join("\n") + "\n";
8096
7945
  }
@@ -8145,6 +7994,7 @@ function parseStoryMapCsv(text, base) {
8145
7994
  },
8146
7995
  mapAnimation: get("mapanimation").trim() || "flyTo",
8147
7996
  rotateAnimation: bool("rotateanimation"),
7997
+ durationSeconds: get("durationseconds").trim() ? Number(get("durationseconds")) : void 0,
8148
7998
  onChapterEnter: jsonArray("onchapterenter"),
8149
7999
  onChapterExit: jsonArray("onchapterexit")
8150
8000
  };
@@ -8337,814 +8187,6 @@ function useLayersWhen(active) {
8337
8187
  return useAppStore(selectLayersWhen(active));
8338
8188
  }
8339
8189
  //#endregion
8340
- //#region src/geocoding.ts
8341
- /**
8342
- * Geocoding client and pure helpers shared by the batch-geocode dialog and the
8343
- * reverse-geocode plugin.
8344
- *
8345
- * This module lives in `@geolibre/core` rather than `@geolibre/processing`
8346
- * because `@geolibre/plugins` depends on core but not on processing, and the
8347
- * reverse-geocode plugin needs the same client. The pure helpers (URL builders,
8348
- * result mappers, pacing) carry no React or MapLibre dependency so they can be
8349
- * unit-tested without a browser or network.
8350
- *
8351
- * Providers: geocoding is dispatched through a small {@link GeocodingProvider}
8352
- * registry so alternatives to Nominatim (ArcGIS World Geocoder, CartoCiudad, Mapbox,
8353
- * Pelias, Google) can be selected per project. Each provider builds its own request
8354
- * URLs and normalizes its response into a {@link GeocodeMatch} (forward) or a
8355
- * {@link ReverseGeocodeDisplay} (reverse), so the dialog and plugin stay
8356
- * provider-agnostic. Nominatim is the default.
8357
- *
8358
- * The 1 request/second throttle and the row cap are part of Nominatim's public
8359
- * usage policy and are therefore applied ONLY to the default public host; a
8360
- * self-hosted endpoint relaxes both, and keyed providers (Mapbox/ArcGIS/Google)
8361
- * are paced by their own quotas, not by us.
8362
- *
8363
- * Browser fetch cannot set `User-Agent`/`Referer`, so the app is identified to
8364
- * Nominatim via the optional `email` query parameter plus the automatically
8365
- * sent `Referer`. The desktop build overrides this with a native (Tauri) fetch
8366
- * via {@link setGeocodingFetch} — see the note there. See
8367
- * docs/user-guide/data-integrations.md#geocoding.
8368
- */
8369
- const DEFAULT_FORWARD_GEOCODE_ENDPOINT = "https://nominatim.openstreetmap.org/search";
8370
- const DEFAULT_REVERSE_GEOCODE_ENDPOINT = "https://nominatim.openstreetmap.org/reverse";
8371
- /** Host whose public usage policy (1 req/sec, bulk limits) we must respect. */
8372
- const NOMINATIM_PUBLIC_HOST = "nominatim.openstreetmap.org";
8373
- /** Minimum spacing between requests to the public Nominatim endpoint. */
8374
- const NOMINATIM_MIN_INTERVAL_MS = 1100;
8375
- /** Host of the free, unkeyed public CartoCiudad geocoder (IGN/CNIG). */
8376
- const CARTOCIUDAD_PUBLIC_HOST = "cartociudad.es";
8377
- /**
8378
- * Courtesy spacing (~5 req/sec) between requests to the public CartoCiudad
8379
- * endpoint. Unlike {@link NOMINATIM_MIN_INTERVAL_MS} this is not a published
8380
- * policy — IGN documents no rate limit — it is our own conservative default so
8381
- * a large batch does not burst at a free public government service. See
8382
- * {@link geocoderMinIntervalMs}.
8383
- */
8384
- const CARTOCIUDAD_MIN_INTERVAL_MS = 200;
8385
- /** Max rows a single batch run will geocode against the public endpoint. */
8386
- const PUBLIC_GEOCODE_ROW_CAP = 1e3;
8387
- /** Property keys added to each geocoded feature. */
8388
- const GEOCODE_LAT_KEY = "geocode_lat";
8389
- const GEOCODE_LON_KEY = "geocode_lon";
8390
- const GEOCODE_DISPLAY_NAME_KEY = "geocode_display_name";
8391
- const GEOCODE_SCORE_KEY = "geocode_importance";
8392
- /** Provider id that produced (or failed to produce) a match, when stamped. */
8393
- const GEOCODE_PROVIDER_KEY = "geocode_provider";
8394
- /** Whether a row matched, when stamped. See {@link GeocodeStatus}. */
8395
- const GEOCODE_STATUS_KEY = "geocode_status";
8396
- /** The provider used when none is configured. */
8397
- const DEFAULT_GEOCODING_PROVIDER_ID = "nominatim";
8398
- function coerceScore(value) {
8399
- if (value === void 0 || value === null || value === "") return null;
8400
- const num = Number(value);
8401
- return Number.isFinite(num) ? num : null;
8402
- }
8403
- /** Append `base` to `existing`, suffixing `_2`, `_3`, ... if the key collides. */
8404
- function uniqueKey(base, existing) {
8405
- if (!(base in existing)) return base;
8406
- let suffix = 2;
8407
- while (`${base}_${suffix}` in existing) suffix += 1;
8408
- return `${base}_${suffix}`;
8409
- }
8410
- /**
8411
- * Coerce an address-parts record to `Record<string, string>`. Provider address
8412
- * objects can carry numbers (ArcGIS `Score`/`X`/`Y`, Pelias coordinates), so
8413
- * values are stringified rather than unsafely cast; null/undefined are dropped.
8414
- */
8415
- function stringifyParts(obj) {
8416
- const parts = {};
8417
- for (const [key, value] of Object.entries(obj)) {
8418
- if (value === null || value === void 0) continue;
8419
- parts[key] = typeof value === "string" ? value : String(value);
8420
- }
8421
- return parts;
8422
- }
8423
- /** Read a string property off an unknown object, or undefined. */
8424
- function readString(obj, key) {
8425
- if (obj && typeof obj === "object" && key in obj) {
8426
- const value = obj[key];
8427
- if (typeof value === "string") return value;
8428
- if (typeof value === "number") return String(value);
8429
- }
8430
- }
8431
- /** Build a Nominatim forward-geocoding URL (jsonv2, address details on). */
8432
- function buildForwardGeocodeUrl(endpoint, query, options = {}) {
8433
- const url = new URL(endpoint);
8434
- url.searchParams.set("q", query);
8435
- url.searchParams.set("format", "jsonv2");
8436
- url.searchParams.set("addressdetails", "1");
8437
- url.searchParams.set("limit", String(options.limit ?? 1));
8438
- if (options.email) url.searchParams.set("email", options.email);
8439
- return url.toString();
8440
- }
8441
- /** Build a Nominatim reverse-geocoding URL (jsonv2, address details on). */
8442
- function buildReverseGeocodeUrl(endpoint, lon, lat, options = {}) {
8443
- const url = new URL(endpoint);
8444
- url.searchParams.set("lat", String(lat));
8445
- url.searchParams.set("lon", String(lon));
8446
- url.searchParams.set("format", "jsonv2");
8447
- url.searchParams.set("addressdetails", "1");
8448
- if (options.zoom !== void 0) url.searchParams.set("zoom", String(options.zoom));
8449
- if (options.email) url.searchParams.set("email", options.email);
8450
- return url.toString();
8451
- }
8452
- /** Map one Nominatim forward result onto a normalized match, or null. */
8453
- function nominatimForwardResultToMatch(result) {
8454
- const lat = Number(result.lat);
8455
- const lon = Number(result.lon);
8456
- if (!Number.isFinite(lat) || !Number.isFinite(lon)) return null;
8457
- return {
8458
- lat,
8459
- lon,
8460
- displayName: result.display_name ?? "",
8461
- score: coerceScore(result.importance)
8462
- };
8463
- }
8464
- /**
8465
- * Convert a normalized {@link GeocodeMatch} into a point Feature whose
8466
- * properties carry the original CSV row plus `geocode_lat`/`geocode_lon`/
8467
- * `geocode_display_name`/`geocode_importance`. The added keys are de-duplicated
8468
- * against the original columns so an existing `geocode_lat` is not clobbered.
8469
- * Geometry coordinates are `[lon, lat]`. Returns null when the match has no
8470
- * finite coordinates.
8471
- *
8472
- * `extra.providerId`, when passed, also stamps `geocode_provider` and
8473
- * `geocode_status: "matched"` (dropped when omitted, so the existing
8474
- * `GeocodeDialog` call site keeps its current output unchanged).
8475
- */
8476
- function geocodeMatchToFeature(match, originalRow = {}, extra) {
8477
- if (!Number.isFinite(match.lat) || !Number.isFinite(match.lon)) return null;
8478
- const properties = { ...originalRow };
8479
- const added = {
8480
- [GEOCODE_LAT_KEY]: match.lat,
8481
- [GEOCODE_LON_KEY]: match.lon,
8482
- [GEOCODE_DISPLAY_NAME_KEY]: match.displayName ?? "",
8483
- [GEOCODE_SCORE_KEY]: match.score
8484
- };
8485
- if (extra?.providerId) {
8486
- added[GEOCODE_PROVIDER_KEY] = extra.providerId;
8487
- added[GEOCODE_STATUS_KEY] = "matched";
8488
- }
8489
- for (const [key, value] of Object.entries(added)) properties[uniqueKey(key, properties)] = value;
8490
- return {
8491
- type: "Feature",
8492
- geometry: {
8493
- type: "Point",
8494
- coordinates: [match.lon, match.lat]
8495
- },
8496
- properties
8497
- };
8498
- }
8499
- /**
8500
- * Build a null-geometry Feature for a CSV row that could not be geocoded, so
8501
- * it is kept (not silently dropped) alongside the matched point features.
8502
- * Mirrors the null-geometry shape {@link parseDelimitedTextLayer} already uses
8503
- * for a non-spatial attribute table. Stamps `geocode_status: "unmatched"` and
8504
- * `geocode_provider`, de-duplicated against the original columns the same way
8505
- * {@link geocodeMatchToFeature} does.
8506
- */
8507
- function unmatchedGeocodeFeature(originalRow, providerId) {
8508
- const properties = { ...originalRow };
8509
- const added = {
8510
- [GEOCODE_STATUS_KEY]: "unmatched",
8511
- [GEOCODE_PROVIDER_KEY]: providerId
8512
- };
8513
- for (const [key, value] of Object.entries(added)) properties[uniqueKey(key, properties)] = value;
8514
- return {
8515
- type: "Feature",
8516
- geometry: null,
8517
- properties
8518
- };
8519
- }
8520
- /**
8521
- * Convert a Nominatim forward result into a point Feature. Retained as a thin
8522
- * wrapper over {@link geocodeMatchToFeature} for callers and tests that work
8523
- * directly with Nominatim results. Returns null when the result has no finite
8524
- * coordinates.
8525
- */
8526
- function nominatimResultToFeature(result, originalRow = {}) {
8527
- const match = nominatimForwardResultToMatch(result);
8528
- return match ? geocodeMatchToFeature(match, originalRow) : null;
8529
- }
8530
- /**
8531
- * Resolve a Nominatim reverse result to a display string and address parts, or
8532
- * null when the point could not be reverse-geocoded.
8533
- */
8534
- function nominatimReverseResultToDisplay(result) {
8535
- if (!result || result.error) return null;
8536
- const displayName = result.display_name?.trim();
8537
- if (!displayName) return null;
8538
- return {
8539
- displayName,
8540
- parts: result.address ?? {}
8541
- };
8542
- }
8543
- const nominatimProvider = {
8544
- id: "nominatim",
8545
- label: "Nominatim (OpenStreetMap)",
8546
- forward: true,
8547
- reverse: true,
8548
- requiresApiKey: false,
8549
- acceptsApiKey: false,
8550
- defaultForwardEndpoint: DEFAULT_FORWARD_GEOCODE_ENDPOINT,
8551
- defaultReverseEndpoint: DEFAULT_REVERSE_GEOCODE_ENDPOINT,
8552
- buildForwardUrl: (config, query, options) => buildForwardGeocodeUrl(config.forwardEndpoint, query, {
8553
- email: options.email,
8554
- limit: options.limit
8555
- }),
8556
- parseForward: (data) => Array.isArray(data) ? data.map(nominatimForwardResultToMatch).filter((m) => m !== null) : [],
8557
- buildReverseUrl: (config, lon, lat, options) => buildReverseGeocodeUrl(config.reverseEndpoint, lon, lat, {
8558
- email: options.email,
8559
- zoom: options.zoom
8560
- }),
8561
- parseReverse: (data) => nominatimReverseResultToDisplay(data && typeof data === "object" ? data : null)
8562
- };
8563
- /** Read a GeoJSON FeatureCollection's features array, or []. */
8564
- function geojsonFeatures(data) {
8565
- if (data && typeof data === "object" && Array.isArray(data.features)) return data.features.filter((f) => !!f && typeof f === "object");
8566
- return [];
8567
- }
8568
- /** Pull `[lon, lat]` from a GeoJSON Point geometry, or null. */
8569
- function pointCoords(feature) {
8570
- const coords = feature.geometry?.coordinates;
8571
- if (Array.isArray(coords) && coords.length >= 2) {
8572
- const lon = Number(coords[0]);
8573
- const lat = Number(coords[1]);
8574
- if (Number.isFinite(lon) && Number.isFinite(lat)) return [lon, lat];
8575
- }
8576
- return null;
8577
- }
8578
- const peliasProvider = {
8579
- id: "pelias",
8580
- label: "Pelias",
8581
- forward: true,
8582
- reverse: true,
8583
- requiresApiKey: false,
8584
- acceptsApiKey: true,
8585
- defaultForwardEndpoint: "https://api.geocode.earth/v1/search",
8586
- defaultReverseEndpoint: "https://api.geocode.earth/v1/reverse",
8587
- buildForwardUrl: (config, query, options) => {
8588
- const url = new URL(config.forwardEndpoint);
8589
- url.searchParams.set("text", query);
8590
- if (options.limit) url.searchParams.set("size", String(options.limit));
8591
- if (config.apiKey) url.searchParams.set("api_key", config.apiKey);
8592
- return url.toString();
8593
- },
8594
- parseForward: (data) => geojsonFeatures(data).map((feature) => {
8595
- const coords = pointCoords(feature);
8596
- if (!coords) return null;
8597
- const props = feature.properties ?? {};
8598
- return {
8599
- lon: coords[0],
8600
- lat: coords[1],
8601
- displayName: readString(props, "label") ?? "",
8602
- score: coerceScore(props.confidence)
8603
- };
8604
- }).filter((m) => m !== null),
8605
- buildReverseUrl: (config, lon, lat) => {
8606
- const url = new URL(config.reverseEndpoint);
8607
- url.searchParams.set("point.lat", String(lat));
8608
- url.searchParams.set("point.lon", String(lon));
8609
- if (config.apiKey) url.searchParams.set("api_key", config.apiKey);
8610
- return url.toString();
8611
- },
8612
- parseReverse: (data) => {
8613
- const feature = geojsonFeatures(data)[0];
8614
- if (!feature) return null;
8615
- const props = feature.properties ?? {};
8616
- const displayName = readString(props, "label")?.trim();
8617
- return displayName ? {
8618
- displayName,
8619
- parts: stringifyParts(props)
8620
- } : null;
8621
- }
8622
- };
8623
- const arcgisProvider = {
8624
- id: "arcgis",
8625
- label: "ArcGIS World Geocoder",
8626
- forward: true,
8627
- reverse: true,
8628
- requiresApiKey: true,
8629
- acceptsApiKey: true,
8630
- defaultForwardEndpoint: "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates",
8631
- defaultReverseEndpoint: "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode",
8632
- buildForwardUrl: (config, query, options) => {
8633
- const url = new URL(config.forwardEndpoint);
8634
- url.searchParams.set("SingleLine", query);
8635
- url.searchParams.set("f", "json");
8636
- url.searchParams.set("outFields", "Match_addr");
8637
- if (options.limit) url.searchParams.set("maxLocations", String(options.limit));
8638
- if (config.apiKey) url.searchParams.set("token", config.apiKey);
8639
- return url.toString();
8640
- },
8641
- parseForward: (data) => {
8642
- return (data && typeof data === "object" && Array.isArray(data.candidates) ? data.candidates : []).map((candidate) => {
8643
- const location = candidate.location;
8644
- const lon = Number(location?.x);
8645
- const lat = Number(location?.y);
8646
- if (!Number.isFinite(lon) || !Number.isFinite(lat)) return null;
8647
- return {
8648
- lon,
8649
- lat,
8650
- displayName: readString(candidate, "address") ?? "",
8651
- score: coerceScore(candidate.score)
8652
- };
8653
- }).filter((m) => m !== null);
8654
- },
8655
- buildReverseUrl: (config, lon, lat) => {
8656
- const url = new URL(config.reverseEndpoint);
8657
- url.searchParams.set("location", `${lon},${lat}`);
8658
- url.searchParams.set("f", "json");
8659
- if (config.apiKey) url.searchParams.set("token", config.apiKey);
8660
- return url.toString();
8661
- },
8662
- parseReverse: (data) => {
8663
- const address = data && typeof data === "object" ? data.address : void 0;
8664
- if (!address || typeof address !== "object") return null;
8665
- const displayName = (readString(address, "LongLabel") ?? readString(address, "Match_addr"))?.trim();
8666
- return displayName ? {
8667
- displayName,
8668
- parts: stringifyParts(address)
8669
- } : null;
8670
- }
8671
- };
8672
- const mapboxProvider = {
8673
- id: "mapbox",
8674
- label: "Mapbox",
8675
- forward: true,
8676
- reverse: true,
8677
- requiresApiKey: true,
8678
- acceptsApiKey: true,
8679
- defaultForwardEndpoint: "https://api.mapbox.com/geocoding/v5/mapbox.places",
8680
- defaultReverseEndpoint: "https://api.mapbox.com/geocoding/v5/mapbox.places",
8681
- buildForwardUrl: (config, query, options) => {
8682
- const base = config.forwardEndpoint.replace(/\/+$/, "");
8683
- const url = new URL(`${base}/${encodeURIComponent(query)}.json`);
8684
- if (options.limit) url.searchParams.set("limit", String(options.limit));
8685
- if (config.apiKey) url.searchParams.set("access_token", config.apiKey);
8686
- return url.toString();
8687
- },
8688
- parseForward: (data) => geojsonFeatures(data).map((feature) => {
8689
- const center = feature.center;
8690
- let coords = null;
8691
- if (Array.isArray(center) && center.length >= 2) {
8692
- const lon = Number(center[0]);
8693
- const lat = Number(center[1]);
8694
- if (Number.isFinite(lon) && Number.isFinite(lat)) coords = [lon, lat];
8695
- }
8696
- coords ??= pointCoords(feature);
8697
- if (!coords) return null;
8698
- return {
8699
- lon: coords[0],
8700
- lat: coords[1],
8701
- displayName: readString(feature, "place_name") ?? "",
8702
- score: coerceScore(feature.relevance)
8703
- };
8704
- }).filter((m) => m !== null),
8705
- buildReverseUrl: (config, lon, lat) => {
8706
- const base = config.reverseEndpoint.replace(/\/+$/, "");
8707
- const url = new URL(`${base}/${lon},${lat}.json`);
8708
- if (config.apiKey) url.searchParams.set("access_token", config.apiKey);
8709
- return url.toString();
8710
- },
8711
- parseReverse: (data) => {
8712
- const feature = geojsonFeatures(data)[0];
8713
- if (!feature) return null;
8714
- const displayName = readString(feature, "place_name")?.trim();
8715
- return displayName ? {
8716
- displayName,
8717
- parts: stringifyParts(feature.properties ?? {})
8718
- } : null;
8719
- }
8720
- };
8721
- /**
8722
- * Detect a Google Geocoding API error embedded in an HTTP 200 body. Google v3
8723
- * returns REQUEST_DENIED / OVER_QUERY_LIMIT / INVALID_REQUEST and friends with
8724
- * a 200 status and the failure only in the `status` field, so `response.ok`
8725
- * alone would silently turn those into empty results. Returns null for OK and
8726
- * ZERO_RESULTS (a successful empty match).
8727
- */
8728
- function googleErrorMessage(data) {
8729
- const status = readString(data, "status");
8730
- if (!status || status === "OK" || status === "ZERO_RESULTS") return null;
8731
- const detail = readString(data, "error_message");
8732
- return detail ? `Google geocoder error: ${status} - ${detail}` : `Google geocoder error: ${status}`;
8733
- }
8734
- const googleProvider = {
8735
- id: "google",
8736
- label: "Google",
8737
- forward: true,
8738
- reverse: true,
8739
- requiresApiKey: true,
8740
- acceptsApiKey: true,
8741
- browserCorsRestricted: true,
8742
- defaultForwardEndpoint: "https://maps.googleapis.com/maps/api/geocode/json",
8743
- defaultReverseEndpoint: "https://maps.googleapis.com/maps/api/geocode/json",
8744
- buildForwardUrl: (config, query) => {
8745
- const url = new URL(config.forwardEndpoint);
8746
- url.searchParams.set("address", query);
8747
- if (config.apiKey) url.searchParams.set("key", config.apiKey);
8748
- return url.toString();
8749
- },
8750
- parseForward: (data) => {
8751
- const error = googleErrorMessage(data);
8752
- if (error) throw new Error(error);
8753
- return parseGoogleResults(data);
8754
- },
8755
- buildReverseUrl: (config, lon, lat) => {
8756
- const url = new URL(config.reverseEndpoint);
8757
- url.searchParams.set("latlng", `${lat},${lon}`);
8758
- if (config.apiKey) url.searchParams.set("key", config.apiKey);
8759
- return url.toString();
8760
- },
8761
- parseReverse: (data) => {
8762
- const error = googleErrorMessage(data);
8763
- if (error) throw new Error(error);
8764
- const displayName = readString((data && typeof data === "object" && Array.isArray(data.results) ? data.results : [])[0], "formatted_address")?.trim();
8765
- return displayName ? {
8766
- displayName,
8767
- parts: {}
8768
- } : null;
8769
- }
8770
- };
8771
- /** Map a Google Geocoding API `results` array onto normalized matches. */
8772
- function parseGoogleResults(data) {
8773
- return (data && typeof data === "object" && Array.isArray(data.results) ? data.results : []).map((result) => {
8774
- const location = result.geometry?.location;
8775
- const lat = Number(location?.lat);
8776
- const lon = Number(location?.lng);
8777
- if (!Number.isFinite(lat) || !Number.isFinite(lon)) return null;
8778
- return {
8779
- lat,
8780
- lon,
8781
- displayName: readString(result, "formatted_address") ?? "",
8782
- score: null
8783
- };
8784
- }).filter((m) => m !== null);
8785
- }
8786
- /**
8787
- * Read a CartoCiudad `lat`/`lng` field as a finite number, or null when the
8788
- * field is absent, blank, or not numeric (`"NaN"` and `"invalid"` included).
8789
- * Guarding the raw value matters because `Number(null)` is 0, which would turn
8790
- * a coordinate-less response into a match in the Gulf of Guinea.
8791
- */
8792
- function cartociudadCoordinate(value) {
8793
- if (typeof value === "number") return Number.isFinite(value) ? value : null;
8794
- if (typeof value !== "string" || !value.trim()) return null;
8795
- const parsed = Number(value);
8796
- return Number.isFinite(parsed) ? parsed : null;
8797
- }
8798
- /** Validated WGS84 position for a result, or null when it carries none. */
8799
- function cartociudadCoords(r) {
8800
- const lat = cartociudadCoordinate(r.lat);
8801
- const lon = cartociudadCoordinate(r.lng);
8802
- if (lat === null || lon === null) return null;
8803
- if (lat < -90 || lat > 90 || lon < -180 || lon > 180) return null;
8804
- return {
8805
- lat,
8806
- lon
8807
- };
8808
- }
8809
- /** Default endpoints for the public CartoCiudad REST API (no auth required). */
8810
- const CARTOCIUDAD_FORWARD_ENDPOINT = "https://www.cartociudad.es/geocoder/api/geocoder/find";
8811
- const CARTOCIUDAD_REVERSE_ENDPOINT = "https://www.cartociudad.es/geocoder/api/geocoder/reverseGeocode";
8812
- /**
8813
- * Build a human-readable display name from CartoCiudad address fields.
8814
- * Format: "Tip Via Address Num, CP Poblacion (Province)"
8815
- */
8816
- function cartociudadDisplayName(r) {
8817
- const parts = [];
8818
- const streetParts = [r.tip_via, r.address].filter((s) => s && String(s).trim()).map((s) => String(s).trim());
8819
- if (streetParts.length) {
8820
- let street = streetParts.join(" ");
8821
- const portalNumber = r.portalNumber === void 0 || r.portalNumber === null ? "" : String(r.portalNumber).trim();
8822
- if (portalNumber) street += ` ${portalNumber}`;
8823
- parts.push(street);
8824
- }
8825
- const localityName = [r.poblacion, r.muni].find((s) => s && String(s).trim());
8826
- const locality = [r.postalCode, localityName].filter((s) => s && String(s).trim()).map((s) => String(s).trim()).join(" ");
8827
- if (locality) parts.push(locality);
8828
- const province = r.province ? String(r.province).trim() : "";
8829
- if (province) parts.push(`(${province})`);
8830
- return parts.join(", ") || r.address || r.poblacion || r.muni || "";
8831
- }
8832
- /** All selectable geocoding providers, Nominatim first (the default). */
8833
- const GEOCODING_PROVIDERS = [
8834
- nominatimProvider,
8835
- peliasProvider,
8836
- arcgisProvider,
8837
- mapboxProvider,
8838
- googleProvider,
8839
- {
8840
- id: "cartociudad",
8841
- label: "CartoCiudad (IGN España)",
8842
- forward: true,
8843
- reverse: true,
8844
- requiresApiKey: false,
8845
- acceptsApiKey: false,
8846
- defaultForwardEndpoint: CARTOCIUDAD_FORWARD_ENDPOINT,
8847
- defaultReverseEndpoint: CARTOCIUDAD_REVERSE_ENDPOINT,
8848
- buildForwardUrl: (config, query) => {
8849
- const url = new URL(config.forwardEndpoint);
8850
- url.searchParams.set("q", query);
8851
- return url.toString();
8852
- },
8853
- parseForward: (data) => {
8854
- if (!data || typeof data !== "object" || Array.isArray(data)) return [];
8855
- const r = data;
8856
- const coords = cartociudadCoords(r);
8857
- if (!coords) return [];
8858
- const displayName = cartociudadDisplayName(r).trim();
8859
- if (!displayName) return [];
8860
- return [{
8861
- lat: coords.lat,
8862
- lon: coords.lon,
8863
- displayName,
8864
- score: null
8865
- }];
8866
- },
8867
- buildReverseUrl: (config, lon, lat) => {
8868
- const url = new URL(config.reverseEndpoint);
8869
- url.searchParams.set("lat", String(lat));
8870
- url.searchParams.set("lon", String(lon));
8871
- return url.toString();
8872
- },
8873
- parseReverse: (data) => {
8874
- if (!data || typeof data !== "object" || Array.isArray(data)) return null;
8875
- const r = data;
8876
- if (!cartociudadCoords(r)) return null;
8877
- const displayName = cartociudadDisplayName(r).trim();
8878
- if (!displayName) return null;
8879
- const parts = {};
8880
- for (const [key, value] of Object.entries({
8881
- type: r.type,
8882
- tip_via: r.tip_via,
8883
- address: r.address,
8884
- portalNumber: r.portalNumber,
8885
- postalCode: r.postalCode,
8886
- poblacion: r.poblacion,
8887
- muni: r.muni,
8888
- province: r.province,
8889
- comunidadAutonoma: r.comunidadAutonoma,
8890
- refCatastral: r.refCatastral
8891
- })) if (value !== void 0 && value !== null && value !== "") parts[key] = String(value);
8892
- return {
8893
- displayName,
8894
- parts
8895
- };
8896
- }
8897
- }
8898
- ];
8899
- const PROVIDERS_BY_ID = new Map(GEOCODING_PROVIDERS.map((provider) => [provider.id, provider]));
8900
- /** Coerce an arbitrary string to a known provider id, defaulting to Nominatim. */
8901
- function normalizeGeocodingProviderId(value) {
8902
- const id = value?.trim();
8903
- return id && PROVIDERS_BY_ID.has(id) ? id : DEFAULT_GEOCODING_PROVIDER_ID;
8904
- }
8905
- /** Look up a provider by id, falling back to Nominatim for unknown ids. */
8906
- function getGeocodingProvider(id) {
8907
- return PROVIDERS_BY_ID.get(normalizeGeocodingProviderId(id)) ?? nominatimProvider;
8908
- }
8909
- /**
8910
- * Resolve the geocoder configuration from runtime env, falling back to the
8911
- * selected provider's default endpoints. `VITE_GEOCODER_PROVIDER` selects the
8912
- * backend; `VITE_GEOCODER_ENDPOINT`/`VITE_GEOCODER_REVERSE_ENDPOINT` override
8913
- * the endpoints; `VITE_GEOCODER_EMAIL` supplies the contact email; and
8914
- * `VITE_GEOCODER_API_KEY` supplies the API key for keyed providers.
8915
- */
8916
- function getGeocoderConfig() {
8917
- const env = getRuntimeEnvironment();
8918
- const provider = getGeocodingProvider(env.VITE_GEOCODER_PROVIDER);
8919
- return {
8920
- providerId: provider.id,
8921
- forwardEndpoint: env.VITE_GEOCODER_ENDPOINT?.trim() || provider.defaultForwardEndpoint,
8922
- reverseEndpoint: env.VITE_GEOCODER_REVERSE_ENDPOINT?.trim() || provider.defaultReverseEndpoint,
8923
- email: env.VITE_GEOCODER_EMAIL?.trim() || void 0,
8924
- apiKey: env.VITE_GEOCODER_API_KEY?.trim() || void 0
8925
- };
8926
- }
8927
- /**
8928
- * Build a {@link GeocoderConfig} from structured project preferences. Used by
8929
- * the geocode dialog so a per-run provider choice resolves the right endpoints
8930
- * and API key without round-tripping through runtime env.
8931
- */
8932
- function resolveGeocoderConfig(input) {
8933
- const provider = getGeocodingProvider(input.providerId);
8934
- return {
8935
- providerId: provider.id,
8936
- forwardEndpoint: input.forwardEndpoint?.trim() || provider.defaultForwardEndpoint,
8937
- reverseEndpoint: input.reverseEndpoint?.trim() || provider.defaultReverseEndpoint,
8938
- email: input.email?.trim() || void 0,
8939
- apiKey: input.apiKeys?.[provider.id]?.trim() || void 0
8940
- };
8941
- }
8942
- /** Hostname of `endpoint`, or null when it does not parse as a URL. */
8943
- function geocoderHostname(endpoint) {
8944
- try {
8945
- return new URL(endpoint).hostname;
8946
- } catch {
8947
- return null;
8948
- }
8949
- }
8950
- /** Whether `hostname` is the public CartoCiudad service or a subdomain of it. */
8951
- function isCartociudadHost(hostname) {
8952
- if (hostname === null) return false;
8953
- return hostname === "cartociudad.es" || hostname.endsWith(`.cartociudad.es`);
8954
- }
8955
- /**
8956
- * Whether requests to `endpoint` must be throttled AND row-capped. True for the
8957
- * public Nominatim host (its usage policy applies) and, defensively, for any
8958
- * endpoint that does not parse as a URL. Every other host (a self-hosted
8959
- * Nominatim or a keyed provider) returns false.
8960
- *
8961
- * Note this is the *Nominatim policy* gate, not "is this host paced at all" —
8962
- * see {@link geocoderMinIntervalMs}, which paces CartoCiudad more gently
8963
- * without capping its row count.
8964
- */
8965
- function shouldThrottle(endpoint) {
8966
- const hostname = geocoderHostname(endpoint);
8967
- return hostname === null || hostname === "nominatim.openstreetmap.org";
8968
- }
8969
- /**
8970
- * The row cap to apply for `endpoint`: a finite cap for the public Nominatim
8971
- * host, else Infinity. CartoCiudad is uncapped — IGN publishes no row limit and
8972
- * its own bulk address geocoder processes up to 60,000 records per run, so a
8973
- * cap here would be an invented constraint. It is still paced; see
8974
- * {@link geocoderMinIntervalMs}.
8975
- */
8976
- function rowCap(endpoint) {
8977
- return shouldThrottle(endpoint) ? PUBLIC_GEOCODE_ROW_CAP : Number.POSITIVE_INFINITY;
8978
- }
8979
- /**
8980
- * Minimum spacing (ms) between requests for `endpoint`. Gated on the hostname,
8981
- * not the selected provider, so pointing any provider at the public Nominatim
8982
- * host still honors its 1 req/sec policy.
8983
- *
8984
- * CartoCiudad gets a gentler pace of its own. IGN documents no rate limit for
8985
- * the single-lookup `find`/`reverseGeocode` endpoints either way, so the honest
8986
- * position is that unbounded bursting is unverified rather than sanctioned:
8987
- * a large CSV run against a free public government service with zero spacing
8988
- * risks getting the caller's IP throttled and degrading the service for
8989
- * everyone. Nominatim's 1 req/sec is that provider's published policy and is
8990
- * not borrowed here. Keyed providers and self-hosted endpoints are paced by
8991
- * their own quotas, not by us.
8992
- */
8993
- function geocoderMinIntervalMs(endpoint) {
8994
- if (shouldThrottle(endpoint)) return NOMINATIM_MIN_INTERVAL_MS;
8995
- return isCartociudadHost(geocoderHostname(endpoint)) ? 200 : 0;
8996
- }
8997
- /** Hosted Pelias service that rejects keyless requests. */
8998
- const GEOCODE_EARTH_HOST_SUFFIX = "geocode.earth";
8999
- /**
9000
- * Whether `config` cannot geocode without an API key. True for the keyed
9001
- * providers (ArcGIS, Mapbox, Google) and for Pelias only when it targets the
9002
- * hosted geocode.earth endpoint (a self-hosted Pelias needs no key). Drives the
9003
- * batch dialog's "missing key" warning and disabled run.
9004
- */
9005
- function geocoderNeedsApiKey(config) {
9006
- const provider = getGeocodingProvider(config.providerId);
9007
- if (provider.requiresApiKey) return true;
9008
- if (provider.id === "pelias") try {
9009
- const host = new URL(config.forwardEndpoint).hostname;
9010
- return host === GEOCODE_EARTH_HOST_SUFFIX || host.endsWith(`.${GEOCODE_EARTH_HOST_SUFFIX}`);
9011
- } catch {
9012
- return false;
9013
- }
9014
- return false;
9015
- }
9016
- /**
9017
- * Milliseconds to wait before starting the next request so consecutive
9018
- * requests are spaced at least `intervalMs` apart, measured from the previous
9019
- * request's start time (not its completion) so a slow network does not double
9020
- * the wait. Returns 0 for the first request or when enough time has elapsed.
9021
- */
9022
- function nextDelayMs(lastStartedAt, now, intervalMs) {
9023
- if (lastStartedAt === null) return 0;
9024
- return Math.max(0, intervalMs - (now - lastStartedAt));
9025
- }
9026
- /**
9027
- * Build geocoding requests from parsed CSV rows. The address for each row is
9028
- * the selected columns trimmed and joined with ", " (so multi-part addresses
9029
- * like street/city/country can be combined). Rows whose composed address is
9030
- * empty are skipped.
9031
- */
9032
- function csvRowsToGeocodeRequests(rows, addressColumns) {
9033
- const requests = [];
9034
- rows.forEach((row, index) => {
9035
- const address = addressColumns.map((column) => (row[column] ?? "").trim()).filter(Boolean).join(", ").trim();
9036
- if (!address) return;
9037
- requests.push({
9038
- index,
9039
- address,
9040
- row
9041
- });
9042
- });
9043
- return requests;
9044
- }
9045
- /**
9046
- * The fetch implementation used by {@link geocodeForward}/{@link geocodeReverse}.
9047
- * Null means "use the global browser `fetch`" (the default for the web and
9048
- * embedded builds).
9049
- */
9050
- let geocodingFetch = null;
9051
- /**
9052
- * Override the fetch used for geocoding requests, or pass null to restore the
9053
- * global browser `fetch`.
9054
- *
9055
- * The desktop shell sets this to Tauri's native HTTP fetch so geocoding requests
9056
- * are made from the Rust side, which:
9057
- * - bypasses the WebView's CORS enforcement. Public Nominatim's CDN
9058
- * intermittently omits the `Access-Control-Allow-Origin` header on cached
9059
- * responses, which the browser then rejects — surfacing to the user as
9060
- * "Search failed. Try again." (the symptom that failed Microsoft Store
9061
- * certification); and
9062
- * - can send a `User-Agent` identifying the app, as Nominatim's usage policy
9063
- * requires (browser fetch cannot set that header).
9064
- *
9065
- * Safe to call multiple times; only the most recent implementation is used.
9066
- */
9067
- function setGeocodingFetch(fetchImpl) {
9068
- geocodingFetch = fetchImpl;
9069
- }
9070
- /** The active geocoding fetch: the injected override, else the global fetch. */
9071
- function geocodeFetch() {
9072
- return geocodingFetch ?? fetch;
9073
- }
9074
- /**
9075
- * Read a geocoder response body as JSON, treating an empty one as "no results".
9076
- *
9077
- * CartoCiudad answers an unmatched query with HTTP 204 and an empty body rather
9078
- * than a JSON null (verified against the live `find` and `reverseGeocode`
9079
- * endpoints). `response.ok` is true for 204, so parsing unconditionally would
9080
- * throw a JSON syntax error and surface a nonsense address as "Search failed"
9081
- * instead of "no match". Returning undefined lets each provider's parser report
9082
- * no results the way it already does for a null body.
9083
- */
9084
- async function readGeocodeJson(response) {
9085
- if (response.status === 204) return void 0;
9086
- const text = await response.text();
9087
- if (!text.trim()) return void 0;
9088
- return JSON.parse(text);
9089
- }
9090
- /**
9091
- * Normalize a longitude into [-180, 180], or null when it is not finite.
9092
- *
9093
- * MapLibre reports `lngLat.lng` unwrapped once the map is zoomed out far enough
9094
- * to show repeated world copies, so a click on a non-primary copy arrives as
9095
- * e.g. 210 rather than -150. Rejecting those outright would silently drop a
9096
- * legitimate reverse-geocode click for every provider, so wrap instead.
9097
- *
9098
- * An in-range longitude returns untouched: the modulo round-trip is not exact
9099
- * in floating point (-3.7 comes back as -3.7000000000000455), and the common
9100
- * case should not be perturbed to handle the rare one.
9101
- */
9102
- function wrapLongitude(lon) {
9103
- if (!Number.isFinite(lon)) return null;
9104
- if (lon >= -180 && lon <= 180) return lon;
9105
- return ((lon + 180) % 360 + 360) % 360 - 180;
9106
- }
9107
- /**
9108
- * Forward-geocode a single query through the configured provider, returning
9109
- * normalized matches.
9110
- */
9111
- async function geocodeForward(query, options = {}) {
9112
- const config = options.config ?? getGeocoderConfig();
9113
- const provider = getGeocodingProvider(config.providerId);
9114
- const url = provider.buildForwardUrl(config, query, {
9115
- email: config.email,
9116
- limit: options.limit
9117
- });
9118
- const response = await geocodeFetch()(url, {
9119
- signal: options.signal,
9120
- headers: { Accept: "application/json" }
9121
- });
9122
- if (!response.ok) throw new Error(`Geocoder returned HTTP ${response.status}`);
9123
- const data = await readGeocodeJson(response);
9124
- return provider.parseForward(data);
9125
- }
9126
- /**
9127
- * Reverse-geocode a single point ([lon, lat]) through the configured provider,
9128
- * returning a normalized display result or null when no address was found.
9129
- */
9130
- async function geocodeReverse(lon, lat, options = {}) {
9131
- const wrappedLon = wrapLongitude(lon);
9132
- if (wrappedLon === null || !Number.isFinite(lat) || lat < -90 || lat > 90) return null;
9133
- const config = options.config ?? getGeocoderConfig();
9134
- const provider = getGeocodingProvider(config.providerId);
9135
- const url = provider.buildReverseUrl(config, wrappedLon, lat, {
9136
- email: config.email,
9137
- zoom: options.zoom
9138
- });
9139
- const response = await geocodeFetch()(url, {
9140
- signal: options.signal,
9141
- headers: { Accept: "application/json" }
9142
- });
9143
- if (!response.ok) throw new Error(`Geocoder returned HTTP ${response.status}`);
9144
- const data = await readGeocodeJson(response);
9145
- return provider.parseReverse(data);
9146
- }
9147
- //#endregion
9148
8190
  //#region src/platform.ts
9149
8191
  /**
9150
8192
  * Platform detection shared across the workspace. Carries no React/MapLibre
@@ -9450,8 +8492,9 @@ function excludeHiddenFieldsFromProject(project) {
9450
8492
  const strippedGeojson = excludeHiddenFieldsFromGeojson(layer.geojson, layer.fieldVisibility);
9451
8493
  if (strippedGeojson !== layer.geojson) {
9452
8494
  changed = true;
8495
+ const { geoarrow: _staleGeoarrow, ...rest } = updatedLayer;
9453
8496
  updatedLayer = {
9454
- ...updatedLayer,
8497
+ ...rest,
9455
8498
  geojson: strippedGeojson
9456
8499
  };
9457
8500
  }
@@ -9979,6 +9022,6 @@ function withJpegTablesPatch(module) {
9979
9022
  };
9980
9023
  }
9981
9024
  //#endregion
9982
- export { ALL_APP_PRIVILEGES, ALL_DEPLOYMENT_CAPABILITIES, ARCGIS_PROJECTION_PRESETS, BLANK_BASEMAP, BLEND_MODES, BUILT_IN_STYLE_PRESETS, CARTOCIUDAD_MIN_INTERVAL_MS, CARTOCIUDAD_PUBLIC_HOST, CESIUM_BASEMAPS, CESIUM_BING_AERIAL_ASSET_ID, CESIUM_GOOGLE_PHOTOREALISTIC_ASSET_ID, CESIUM_ION_QUICK_PICKS, CESIUM_ION_SOURCE_KIND, CESIUM_KML_SOURCE_KIND, CESIUM_OSM_BUILDINGS_ASSET_ID, CHINA_BASEMAPS, CZML_QUICK_PICKS, CZML_SOURCE_KIND, DEFAULT_BASEMAP, DEFAULT_BLEND_MODE, DEFAULT_COLLABORATION_STATE, DEFAULT_DASHBOARD_COLUMNS, DEFAULT_EDITOR_IDENTITY, DEFAULT_EDITOR_TRACKING_CONFIG, DEFAULT_ELLIPSOID_ID, DEFAULT_FORWARD_GEOCODE_ENDPOINT, DEFAULT_GEOCODING_PROVIDER_ID, DEFAULT_LAYER_GROUP_OPACITY, DEFAULT_LAYER_STYLE, DEFAULT_LEGEND_CONFIG, DEFAULT_MAP_GRID_LAYOUT, DEFAULT_PRIMARY_RENDERER, DEFAULT_PRINT_LAYOUT, DEFAULT_PROJECT_NAME, DEFAULT_PROJECT_PREFERENCES, DEFAULT_REVERSE_GEOCODE_ENDPOINT, DEFAULT_ROUTING_ENDPOINT, DEFAULT_STORY_MAP, DEPLOYMENT_CAPABILITIES, DUCKDB_VECTOR_FEATURE_WARN_COUNT, DUCKDB_VECTOR_ROUTE_BYTES, EARTH_MEAN_RADIUS_METERS, EDITOR_IDENTITY_STORAGE_KEY, ELEVATION_REQUEST_TIMEOUT_MS, ELLIPSOIDS, EXPRESSION_FUNCTION_CATEGORIES, ElevationFetchError, FEET_PER_METER, FEET_PER_MILE, GEOCODE_DISPLAY_NAME_KEY, GEOCODE_LAT_KEY, GEOCODE_LON_KEY, GEOCODE_PROVIDER_KEY, GEOCODE_SCORE_KEY, GEOCODE_STATUS_KEY, GEOCODING_PROVIDERS, GOOGLE_MAPS_API_KEY_HEADER, IDENTIFY_ALL_LAYERS_ID, LABEL_NUMBER_LOCALES, LABEL_NUMBER_SAMPLE, LARGE_VECTOR_FEATURE_THRESHOLD, LAYERS_FILE_TYPE, LAYERS_FILE_VERSION, LAYER_LIBRARY_BUNDLE_TYPE, LAYER_LIBRARY_BUNDLE_VERSION, LAYER_PALETTE, LAYER_STYLES_FILE_TYPE, LAYER_STYLES_FILE_VERSION, LAYER_TYPES, MAX_DASHBOARD_COLUMNS, MAX_DIAGRAM_FEATURES, MAX_DIAGRAM_SCAN_FEATURES, MAX_LAYERS_FILE_BYTES, MAX_LAYER_LIBRARY_ENTRIES, MAX_LAYER_LIBRARY_ENTRY_BYTES, MAX_MAP_GRID_DIM, MAX_POINTS_PER_REQUEST, MAX_PROCESSING_HISTORY, MAX_PROJECT_BOOKMARKS, MAX_REDACT_DEPTH, MERCATOR_METERS_PER_PIXEL_AT_ZOOM_0, METERS_PER_FOOT, METERS_PER_MILE, METERS_PER_NAUTICAL_MILE, MIN_DASHBOARD_COLUMNS, MIN_DIAGRAM_SIZE, NETCDF_IMAGE_SOURCE_KIND, NOMINATIM_MIN_INTERVAL_MS, NOMINATIM_PUBLIC_HOST, NO_DEPLOYMENT_CAPABILITIES, NO_LAYERS, OPENFREEMAP_BASEMAPS, PHOTO_FULL_PROPERTY, PHOTO_PROPERTY, PLANETARY_BASEMAPS, PLANETARY_BASEMAP_GROUPS, PLANETARY_BASEMAP_SENTINEL_PREFIX, PLANET_SWITCHER_OPTIONS, POINTER_ELEVATION_CACHE_LIMIT, POINTER_ELEVATION_DEBOUNCE_MS, POPUP_IMAGE_HEIGHT_RANGE, POPUP_MAX_WIDTH_RANGE, PROJECT_CREDENTIAL_FIELDS, PROJECT_VERSION, PROTOMAPS_BASEMAPS, PUBLIC_GEOCODE_ROW_CAP, PUBLISHABLE_PLUGIN_SETTINGS, RAMP_STYLE_KEYS, RASTER_APPEARANCE_STATE_KEYS, REGIONAL_BASEMAPS, REGIONAL_BASEMAP_GROUPS, REGIONAL_BASEMAP_SENTINEL_PREFIX, ROLE_PRIVILEGES, RoutingRequestError, S3CorsError, S3_MAX_PRESIGN_SECONDS, SELECTION_MODES, SQL_QUERY_SOURCE_KIND, STAC_PROCESSING_EXTENSION, STAC_VERSION, STYLE_LIBRARY_BUNDLE_TYPE, STYLE_LIBRARY_BUNDLE_VERSION, SYMBOL_STYLE_KEYS, VECTOR_COLOR_RAMPS, activeLayerFilterExpression, activeQuickFilters, addLayersToProject, allowsCredentialHeaders, appPrivilegeReason, applyCopiedLayerStyle, applyGroupEffects, applyJoinsToLayer, applyLayerJoins, applyLayerVirtualFields, applyMatchedSelection, applyProjectToStore, applySelectionMode, applyStoryLayerOpacity, attributeFormFieldLabel, attributeLinkUrl, availableCesiumBasemap, basemapToCesiumImagery, batchDecodePolylines, bodyLengthToEarth, buildForwardGeocodeUrl, buildIsochroneRequest, buildLayerPanelUnits, buildLayerStacItem, buildLayerTree, buildMatrixRequest, buildReverseGeocodeUrl, buildRouteRequest, canRedoProjectRestore, canSaveLayerToLibrary, canUndoProjectRestore, captureLayerLibraryEntry, cascadeLayerJoinRefresh, cesiumIonAssetId, cesiumIonAssetKind, cesiumKmlSource, changedPreferenceCredentials, circleRadiusValue, clampLabelDecimals, clampLatitude, clearExternalNativePaintBridge, clearHistory, clearQuickFilterValues, coerceAttributeFormValue, collectDiagramData, collectTransitiveJoinSourceIds, compareSequenceValues, compileFeatureExpression, compileLayerFilters, compileQuickFilter, compileQuickFilters, controlRendersLayer, convertTiffYCbCrToRgb, copyableLayerStyleKind, createCesiumIonLayer, createCesiumKmlLayer, createCzmlLayer, createDefaultAppCapabilities, createDefaultMapView, createDefaultPrintLayout, createEmptyProject, createEqualIntervalBreaks, createGraduatedClassBreaks, createLayerLibraryEntryId, createPointerElevationResolver, createProjectLayerSerializationCache, createProjectTemplate, createQuantileBreaks, createSampleStoryMap, createStyleLayerEvaluator, createStyleLibraryEntryId, csvRowsToGeocodeRequests, currentEditorIdentity, czmlSource, darkenHex, datumShiftFor, decodePolyline, decodePolylineDetailed, detachProjectCopy, detectNonGeographicCoordinates, diagramAnchor, diagramPixelSize, diagramsSuppressedByPointRenderer, diffFeatureCollections, diffProjects, documentLocale, dominantGeometry, drawMarkerPath, earthAreaToBody, earthLengthToBody, editorTrackingFieldNames, effectiveLayerRenderState, effectiveVectorRules, encodePolyline, encodeS3Key, ensureEditorTrackingFields, environmentVariableAccount, evaluateMapExpression, excludeHiddenFieldsFromGeojson, excludeHiddenFieldsFromProject, explainS3ReadError, extractCopiedLayerStyle, extractLayerStyleEntries, extractLayersFileContent, extractStyleLibraryStyle, extrusionColorValue, extrusionHeightValue, featureSelectionId, fetchElevations, findLayerStyleEntryIndex, formatCameraAltitude, formatExpressionPreviewValue, formatLabelNumber, formatLabelNumberSample, formatPixelValue, formatPopupValue, formatRoundNum, formatS3Uri, generatorCircleRadiusValue, generatorSizeRange, geoJSONToPolylineStr, geocodeForward, geocodeMatchToFeature, geocodeReverse, geocoderMinIntervalMs, geocoderNeedsApiKey, geocodingApiKeyAccount, geojsonHasZCoordinates, getActiveBodyRadiusRatio, getActiveEllipsoid, getActiveMeanRadiusMeters, getActiveSemiMajorAxisMeters, getArcgisApiKey, getAttributeFormField, getBuildEnvironment, getCesiumIonToken, getEllipsoid, getExternalNativePaintBridge, getGeocoderConfig, getGeocodingProvider, getGoogleMapsApiKey, getHistoryCoalesceMs, getMapboxAccessToken, getMaxHistoryFeatureCount, getPlanetaryBasemapById, getPlanetaryBasemapByStyleUrl, getProtomapsApiKey, getProtomapsStyleUrl, getRegionalBasemapById, getRegionalBasemapByStyleUrl, getRoundNum, getRoutingConfig, getRuntimeEnvironment, getS3UrlSigner, getSpatialExtensionPath, getVectorColorRamp, googleMapsApiKeyHeaderValue, groupMemberIndices, hasActiveLayerFilter, hasActiveQuickFilter, hasAppPrivilege, hasHeaderReferences, hasPathTraversal, hasRestorableLayerSource, hasSimpleStyleProperties, heatmapRampColors, horizontalBbox, hydrateProjectLayer, identifyAllIncludes, identifyStateWithoutLayers, inferFieldTypes, inferLayerCapabilities, initialLayerStyle, installCogTilerDatumShift, interpolateColors, interpolateHexColor, interpolateRampColors, intersectPrivileges, invertSelection, isAbbreviatedJpegCompression, isAbsoluteFilesystemPath, isAdoptedVectorAwaitingFeatures, isAllowedPluginManifestUrl, isAttributeFormFieldVisible, isCesiumIonLayer, isCesiumKmlLayer, isCesiumOnlyLayer, isCredentialFieldName, isCredentialUrlParam, isCredentialedS3Url, isCzmlLayer, isDefaultPrintLayout, isDeploymentCapability, isDiagramStyleEnabled, isDuckDBQueryLayer, isExternalNativeLayerRecord, isGooglePhotorealisticTilesetUrl, isHeaderReferenceOnly, isHexColor, isInitialLayerStyle, isInlineImageValue, isInternalPopupField, isIpadDesktopUserAgent, isMaintainedEditorTrackingField, isPopupClickEnabled, isPopupHoverEnabled, isRasterMarkerSource, isReferencedLayer, isRegionalBasemapSentinel, isS3Uri, isSafePopupUrl, isSecretEnvironmentVariable, isSessionOnlyLayer, isStoryHiddenLayer, isStyleLibraryTargetLayer, isStyleSpecColor, isSvgMarkerResponse, isValidMetadataDate, isValidMetadataEmail, isValidMetadataUrl, isVectorColorExpression, isochroneResponseToFeatures, jsonValuesEqual, labelFieldTextField, layerGroupDepth, layerGroupMoveability, layerGroupSortability, layerJoinKey, layerLibraryConfigPatch, layerLibraryEntryNeedsLocalFile, layerLocalPath, layerPanelGroupHeaders, lineWidthValue, localFileName, lookupProjectCredential, mapZoomStepOutputs, matchFeaturesByExpression, matchLayerStyleEntry, matrixResponseToFeatures, meanRadiusMeters, mercatorMetersPerPixelAtZoom0, mergeAttributeFormConfigs, metadataDateToRfc3339, metersWidthExpression, nextDelayMs, nextLayerPaletteColor, nominatimResultToFeature, nominatimReverseResultToDisplay, nonEmptyRecord, normalizeAppPrivileges, normalizeArcgisWkid, normalizeBlankBackgroundColor, normalizeBookmarkGroups, normalizeBookmarks, normalizeCesiumBasemap, normalizeDashboardColumns, normalizeGeocodingProviderId, normalizeGroupContiguity, normalizeHexColor, normalizeLayerCapabilities, normalizeLayerDescriptiveMetadata, normalizeLayerLibraryEntries, normalizeLayerStyleEntries, normalizeLayersFileContent, normalizeLegendConfig, normalizeLongitude, normalizeMapLayout, normalizeMapViewState, normalizeModelGraph, normalizeModels, normalizeObiaWorkbench, normalizePrimaryRenderer, normalizePrintLayoutConfig, normalizeProcessingHistory, normalizeProjectComments, normalizeProjectInteraction, normalizeSecondaryMapViews, normalizeStoryMap, normalizeStyleLibraryEntries, normalizeWidgets, overlayStoredEnvironmentVariables, overlayStoredGeocodingApiKeys, overlayStoredPreferenceCredentials, parseCesiumIonAssetId, parseContours, parseCzml, parseDeploymentCapabilities, parseHexColor, parseHexColorList, parseJsonExpression, parseLayerLibrary, parseLayerStylesFile, parseLayersFile, parseMetadataKeywords, parseProject, parseS3BucketList, parseS3Error, parseS3ListObjects, parseS3Url, parseStoryMapCsv, parseStoryMapJson, parseStyleLibrary, parseValueMapText, patchJpegCogSource, persistedThreeDTilesRequestHeaders, pickEditorIdentity, planLayerLibraryAdd, pluginOwnsPaint, polylineStrToGeoJSON, popupFieldLabel, portableWmsTileUrl, presignS3Url, previewValue, printLayoutConfigsEqual, projectFromStore, projectPathLabel, proportionalRadiusExpression, proportionalSizeRange, readStoredAuthorName, reapplyLayerJoins, redactConfigurationCredentials, redactCredentials, redactProjectCredentials, redactUrlCredentials, redo, registerProjectRestoreHistory, registerS3UrlSigner, removeTrailingJsonCommas, rendererAppliesOpacity, reorderLayerGroupInPanel, requestIsochrone, requestMatrix, requestNavigationRoute, requestRoute, resolveConfiguredPopupTitle, resolveEditorTrackingConfig, resolveGeocoderConfig, resolveHeaderReferences, resolveIdentifyTarget, resolveLabelNumberLocale, resolveLayerCapabilities, resolveMapGrid, resolvePopupBody, resolvePopupImageHeight, resolvePopupMaxWidth, resolvePopupRows, resolvePopupTitle, resolveProjectHeaderReferences, resolveReadableUrl, resolveRolePrivileges, resolveSvgSource, resolveThreeDTilesRequestHeaders, rgbToHex, routeResponseToFeatures, rowCap, ruleBasedColorExpression, ruleBasedVisibilityFilter, s3ObjectHttpsUrl, sameCesiumImagery, sampleMapTerrain, sampleMapTerrainPoint, sampleRemoteElevations, sanitizeLayerStylePatch, scaleAltitudeToActiveBody, scaleDenomination, scaleSpan, scrubCommentsForRemovedLayers, scrubLegendForRemovedLayers, scrubPrintLayoutForLayers, scrubPrintLayoutForRemovedLayers, scrubWidgetsForRemovedLayers, selectLayerById, selectLayerIds, selectLayerSummaries, selectLayersWhen, serializeLayerLibrary, serializeLayerStylesFile, serializeLayersFile, serializeProject, serializeProjectWithLayerCache, serializeProjectWithLayerCacheAsync, serializeStoryMapCsv, serializeStoryMapJson, serializeStyleLibrary, setActiveEllipsoidId, setExternalNativePaintBridge, setGeocodingFetch, setHistoryCoalesceMs, setMaxHistoryFeatureCount, setProjectCredentialLookup, setRegistryPublishableSettings, setStoredAuthorName, shouldThrottle, shouldUseTiledRendering, shouldZoomToNewLayers, simpleStyleNumberValue, sortLayerGroupInPanel, splitProjectCredentials, stacAssetMediaType, stampFeatureCollectionEditorTracking, stampFeatureEditorTracking, stampFeaturePropertiesEditorTracking, storyLayerOpacityFactor, storyLocationView, storyMapHasContent, storyVisibleLayers, stringifyPopupValue, stripGoogleMapsApiKeyHeader, stripJoinFields, stripVirtualFieldColumns, styleValue, subscribeProjectRestoreHistory, substituteExpressionVariables, supportsBridgedOpacity, transformGeojsonElevation, trimHistoryBySize, undo, unescapePolyline, uniqueImportedLayerName, unmatchedGeocodeFeature, unresolvedLayerLibraryJoins, unsignedSourceUrl, useAppCapability, useAppStore, useLayer, useLayerIds, useLayerSummaries, useLayersWhen, validateAttributeFormField, validateAttributeFormValues, validateLayerDescriptiveMetadata, validateMapExpression, valueMapLabelFor, valueMapToText, vectorCircleColorValue, vectorColorExpression, vectorFillColorValue, vectorFillOpacityValue, vectorLineColorValue, vectorOutlineColorValue, vectorStrokeWidthValue, visiblePopupFields, visiblePopupProperties, withDatumShift, withGeoKeysDatumShift, withJpegTablesPatch, withoutHistory };
9025
+ export { ALL_APP_PRIVILEGES, ALL_DEPLOYMENT_CAPABILITIES, ARCGIS_PROJECTION_PRESETS, BLANK_BASEMAP, BLEND_MODES, BUILT_IN_STYLE_PRESETS, CARTOCIUDAD_MIN_INTERVAL_MS, CARTOCIUDAD_PUBLIC_HOST, CESIUM_BASEMAPS, CESIUM_BING_AERIAL_ASSET_ID, CESIUM_GOOGLE_PHOTOREALISTIC_ASSET_ID, CESIUM_ION_QUICK_PICKS, CESIUM_ION_SOURCE_KIND, CESIUM_KML_SOURCE_KIND, CESIUM_OSM_BUILDINGS_ASSET_ID, CHINA_BASEMAPS, CZML_QUICK_PICKS, CZML_SOURCE_KIND, DEFAULT_BASEMAP, DEFAULT_BLEND_MODE, DEFAULT_COLLABORATION_STATE, DEFAULT_DASHBOARD_COLUMNS, DEFAULT_EDITOR_IDENTITY, DEFAULT_EDITOR_TRACKING_CONFIG, DEFAULT_ELLIPSOID_ID, DEFAULT_FORWARD_GEOCODE_ENDPOINT, DEFAULT_GEOCODING_PROVIDER_ID, DEFAULT_LAYER_GROUP_OPACITY, DEFAULT_LAYER_STYLE, DEFAULT_LEGEND_CONFIG, DEFAULT_MAP_GRID_LAYOUT, DEFAULT_PRIMARY_RENDERER, DEFAULT_PRINT_LAYOUT, DEFAULT_PROJECT_NAME, DEFAULT_PROJECT_PREFERENCES, DEFAULT_REVERSE_GEOCODE_ENDPOINT, DEFAULT_ROUTING_ENDPOINT, DEFAULT_STORY_CHAPTER_DURATION_SECONDS, DEFAULT_STORY_MAP, DEPLOYMENT_CAPABILITIES, DUCKDB_VECTOR_FEATURE_WARN_COUNT, DUCKDB_VECTOR_ROUTE_BYTES, EARTH_MEAN_RADIUS_METERS, EDITOR_IDENTITY_STORAGE_KEY, ELEVATION_REQUEST_TIMEOUT_MS, ELLIPSOIDS, EXPRESSION_FUNCTION_CATEGORIES, ElevationFetchError, FEET_PER_METER, FEET_PER_MILE, GEOCODE_ATTRIBUTE_PREFIX, GEOCODE_DISPLAY_NAME_KEY, GEOCODE_LAT_KEY, GEOCODE_LON_KEY, GEOCODE_PROVIDER_KEY, GEOCODE_SCORE_KEY, GEOCODE_STATUS_KEY, GEOCODING_PROVIDERS, GOOGLE_MAPS_API_KEY_HEADER, GeocoderServiceError, GeocoderUnsupportedError, IDENTIFY_ALL_LAYERS_ID, LABEL_NUMBER_LOCALES, LABEL_NUMBER_SAMPLE, LARGE_VECTOR_FEATURE_THRESHOLD, LAYERS_FILE_TYPE, LAYERS_FILE_VERSION, LAYER_LIBRARY_BUNDLE_TYPE, LAYER_LIBRARY_BUNDLE_VERSION, LAYER_PALETTE, LAYER_STYLES_FILE_TYPE, LAYER_STYLES_FILE_VERSION, LAYER_TYPES, MAP_CRS_PRESETS, MAX_DASHBOARD_COLUMNS, MAX_DIAGRAM_FEATURES, MAX_DIAGRAM_SCAN_FEATURES, MAX_LAYERS_FILE_BYTES, MAX_LAYER_LIBRARY_ENTRIES, MAX_LAYER_LIBRARY_ENTRY_BYTES, MAX_MAP_GRID_DIM, MAX_POINTS_PER_REQUEST, MAX_PROCESSING_HISTORY, MAX_PROJECT_BOOKMARKS, MAX_REDACT_DEPTH, MAX_STORY_CHAPTER_DURATION_SECONDS, MERCATOR_METERS_PER_PIXEL_AT_ZOOM_0, METERS_PER_FOOT, METERS_PER_MILE, METERS_PER_NAUTICAL_MILE, MIN_DASHBOARD_COLUMNS, MIN_DIAGRAM_SIZE, MIN_STORY_CHAPTER_DURATION_SECONDS, NETCDF_IMAGE_SOURCE_KIND, NOMINATIM_MIN_INTERVAL_MS, NOMINATIM_PUBLIC_HOST, NO_DEPLOYMENT_CAPABILITIES, NO_LAYERS, OPENFREEMAP_BASEMAPS, PHOTO_FULL_PROPERTY, PHOTO_PROPERTY, PLANETARY_BASEMAPS, PLANETARY_BASEMAP_GROUPS, PLANETARY_BASEMAP_SENTINEL_PREFIX, PLANET_SWITCHER_OPTIONS, POINTER_ELEVATION_CACHE_LIMIT, POINTER_ELEVATION_DEBOUNCE_MS, POPUP_IMAGE_HEIGHT_RANGE, POPUP_MAX_WIDTH_RANGE, PROJECT_CREDENTIAL_FIELDS, PROJECT_VERSION, PROTOMAPS_BASEMAPS, PUBLIC_GEOCODE_ROW_CAP, PUBLISHABLE_PLUGIN_SETTINGS, RAMP_STYLE_KEYS, RASTER_APPEARANCE_STATE_KEYS, REGIONAL_BASEMAPS, REGIONAL_BASEMAP_GROUPS, REGIONAL_BASEMAP_SENTINEL_PREFIX, ROLE_PRIVILEGES, RoutingRequestError, S3CorsError, S3_MAX_PRESIGN_SECONDS, SELECTION_MODES, SQL_QUERY_SOURCE_KIND, STAC_PROCESSING_EXTENSION, STAC_VERSION, STYLE_LIBRARY_BUNDLE_TYPE, STYLE_LIBRARY_BUNDLE_VERSION, SYMBOL_STYLE_KEYS, VECTOR_COLOR_RAMPS, activeLayerFilterExpression, activeQuickFilters, adaptBboxTemplateToCrs, addLayersToProject, allowsCredentialHeaders, appPrivilegeReason, applyCopiedLayerStyle, applyGroupEffects, applyJoinsToLayer, applyLayerJoins, applyLayerVirtualFields, applyMatchedSelection, applyProjectToStore, applySelectionMode, applyStoryLayerOpacity, arcgisLocatorInputField, attributeFormFieldLabel, attributeLinkUrl, availableCesiumBasemap, basemapToCesiumImagery, batchDecodePolylines, bodyLengthToEarth, buildForwardGeocodeUrl, buildIsochroneRequest, buildLayerPanelUnits, buildLayerStacItem, buildLayerTree, buildMatrixRequest, buildReverseGeocodeUrl, buildRouteRequest, canRedoProjectRestore, canSaveLayerToLibrary, canUndoProjectRestore, captureLayerLibraryEntry, cascadeLayerJoinRefresh, cesiumIonAssetId, cesiumIonAssetKind, cesiumKmlSource, changedPreferenceCredentials, circleRadiusValue, clampLabelDecimals, clampLatitude, clearExternalNativePaintBridge, clearHistory, clearQuickFilterValues, coerceAttributeFormValue, collectDiagramData, collectTransitiveJoinSourceIds, compareSequenceValues, compileFeatureExpression, compileLayerFilters, compileQuickFilter, compileQuickFilters, computeGeoArrowBBox, controlRendersLayer, convertTiffYCbCrToRgb, copyableLayerStyleKind, createCesiumIonLayer, createCesiumKmlLayer, createCzmlLayer, createDefaultAppCapabilities, createDefaultMapView, createDefaultPrintLayout, createEmptyProject, createEqualIntervalBreaks, createGraduatedClassBreaks, createLayerLibraryEntryId, createPointerElevationResolver, createProjectLayerSerializationCache, createProjectTemplate, createQuantileBreaks, createSampleStoryMap, createStyleLayerEvaluator, createStyleLibraryEntryId, csvRowsToGeocodeRequests, currentEditorIdentity, czmlSource, darkenHex, datumShiftFor, decodePolyline, decodePolylineDetailed, deriveTileMatrixSet, detachProjectCopy, detectNonGeographicCoordinates, diagramAnchor, diagramPixelSize, diagramsSuppressedByPointRenderer, diffFeatureCollections, diffProjects, documentLocale, dominantGeometry, drawMarkerPath, earthAreaToBody, earthLengthToBody, editorTrackingFieldNames, effectiveLayerRenderState, effectiveVectorRules, encodePolyline, encodeS3Key, ensureEditorTrackingFields, environmentVariableAccount, evaluateMapExpression, excludeHiddenFieldsFromGeojson, excludeHiddenFieldsFromProject, explainS3ReadError, extractCopiedLayerStyle, extractLayerStyleEntries, extractLayersFileContent, extractStyleLibraryStyle, extrusionColorValue, extrusionHeightValue, featureCollectionToGeoArrow, featureSelectionId, fetchArcGISLocatorInfo, fetchElevations, findLayerStyleEntryIndex, formatCameraAltitude, formatExpressionPreviewValue, formatLabelNumber, formatLabelNumberSample, formatPixelValue, formatPopupValue, formatRoundNum, formatS3Uri, generatorCircleRadiusValue, generatorSizeRange, geoArrowToFeatureCollection, geoJSONToPolylineStr, geocodeForward, geocodeMatchToFeature, geocodeReverse, geocodeSuggest, geocoderMinIntervalMs, geocoderNeedsApiKey, geocoderSupportsReverse, geocoderSupportsSuggest, geocodingApiKeyAccount, geojsonHasZCoordinates, getActiveBodyRadiusRatio, getActiveEllipsoid, getActiveMeanRadiusMeters, getActiveSemiMajorAxisMeters, getArcgisApiKey, getAttributeFormField, getBuildEnvironment, getCesiumIonToken, getEllipsoid, getExternalNativePaintBridge, getGeocoderConfig, getGeocodingProvider, getGoogleMapsApiKey, getHistoryCoalesceMs, getMapCrsPreset, getMapboxAccessToken, getMaxHistoryFeatureCount, getPlanetaryBasemapById, getPlanetaryBasemapByStyleUrl, getProtomapsApiKey, getProtomapsStyleUrl, getRegionalBasemapById, getRegionalBasemapByStyleUrl, getRoundNum, getRoutingConfig, getRuntimeEnvironment, getS3UrlSigner, getSpatialExtensionPath, getVectorColorRamp, googleMapsApiKeyHeaderValue, groupMemberIndices, hasActiveLayerFilter, hasActiveQuickFilter, hasAppPrivilege, hasHeaderReferences, hasPathTraversal, hasRestorableLayerSource, hasSimpleStyleProperties, heatmapRampColors, horizontalBbox, hydrateProjectLayer, identifyAllIncludes, identifyStateWithoutLayers, inferFieldTypes, inferLayerCapabilities, initialLayerStyle, installCogTilerDatumShift, interpolateColors, interpolateHexColor, interpolateRampColors, intersectPrivileges, invertSelection, isAbbreviatedJpegCompression, isAbsoluteFilesystemPath, isAdoptedVectorAwaitingFeatures, isAllowedPluginManifestUrl, isAttributeFormFieldVisible, isCesiumIonLayer, isCesiumKmlLayer, isCesiumOnlyLayer, isCredentialFieldName, isCredentialUrlParam, isCredentialedS3Url, isCzmlLayer, isDefaultPrintLayout, isDeploymentCapability, isDiagramStyleEnabled, isDuckDBQueryLayer, isExternalNativeLayerRecord, isGeoArrowBatch, isGooglePhotorealisticTilesetUrl, isHeaderReferenceOnly, isHexColor, isInitialLayerStyle, isInlineImageValue, isInternalPopupField, isIpadDesktopUserAgent, isMaintainedEditorTrackingField, isPopupClickEnabled, isPopupHoverEnabled, isRasterMarkerSource, isReferencedLayer, isRegionalBasemapSentinel, isS3Uri, isSafePopupUrl, isSecretEnvironmentVariable, isSessionOnlyLayer, isStoryHiddenLayer, isStyleLibraryTargetLayer, isStyleSpecColor, isSvgMarkerResponse, isValidMetadataDate, isValidMetadataEmail, isValidMetadataUrl, isVectorColorExpression, isochroneResponseToFeatures, jsonValuesEqual, labelFieldTextField, layerGroupDepth, layerGroupMoveability, layerGroupSortability, layerJoinKey, layerLibraryConfigPatch, layerLibraryEntryNeedsLocalFile, layerLocalPath, layerPanelGroupHeaders, lineWidthValue, localFileName, lookupProjectCredential, mapZoomStepOutputs, matchFeaturesByExpression, matchLayerStyleEntry, matrixResponseToFeatures, meanRadiusMeters, mercatorMetersPerPixelAtZoom0, mergeAttributeFormConfigs, metadataDateToRfc3339, metersWidthExpression, nextDelayMs, nextLayerPaletteColor, nominatimResultToFeature, nominatimReverseResultToDisplay, nonEmptyRecord, normalizeAppPrivileges, normalizeArcGISLocatorUrl, normalizeArcgisWkid, normalizeBlankBackgroundColor, normalizeBookmarkGroups, normalizeBookmarks, normalizeCesiumBasemap, normalizeDashboardColumns, normalizeGeocodingLocator, normalizeGeocodingProviderId, normalizeGroupContiguity, normalizeHexColor, normalizeLayerCapabilities, normalizeLayerDescriptiveMetadata, normalizeLayerLibraryEntries, normalizeLayerStyleEntries, normalizeLayersFileContent, normalizeLegendConfig, normalizeLongitude, normalizeMapCrs, normalizeMapLayout, normalizeMapViewState, normalizeModelGraph, normalizeModels, normalizeObiaWorkbench, normalizePrimaryRenderer, normalizePrintLayoutConfig, normalizeProcessingHistory, normalizeProjectComments, normalizeProjectInteraction, normalizeSecondaryMapViews, normalizeStoryChapterDurationSeconds, normalizeStoryMap, normalizeStyleLibraryEntries, normalizeWidgets, overlayStoredEnvironmentVariables, overlayStoredGeocodingApiKeys, overlayStoredPreferenceCredentials, parseArcGISLocatorInfo, parseArcGISSuggestions, parseCesiumIonAssetId, parseContours, parseCzml, parseDeploymentCapabilities, parseHexColor, parseHexColorList, parseJsonExpression, parseLayerLibrary, parseLayerStylesFile, parseLayersFile, parseMapCrsEpsgCode, parseMetadataKeywords, parseProject, parseS3BucketList, parseS3Error, parseS3ListObjects, parseS3Url, parseStoryMapCsv, parseStoryMapJson, parseStyleLibrary, parseValueMapText, patchJpegCogSource, persistedThreeDTilesRequestHeaders, pickEditorIdentity, planLayerLibraryAdd, pluginOwnsPaint, polylineStrToGeoJSON, popupFieldLabel, portableWmsTileUrl, presignS3Url, previewValue, printLayoutConfigsEqual, projectFromStore, projectPathLabel, proportionalRadiusExpression, proportionalSizeRange, readStoredAuthorName, reapplyLayerJoins, redactConfigurationCredentials, redactCredentials, redactProjectCredentials, redactUrlCredentials, redo, registerProjectRestoreHistory, registerS3UrlSigner, removeTrailingJsonCommas, rendererAppliesOpacity, reorderLayerGroupInPanel, requestIsochrone, requestMatrix, requestNavigationRoute, requestRoute, resolveConfiguredPopupTitle, resolveEditorTrackingConfig, resolveGeocoderConfig, resolveHeaderReferences, resolveIdentifyTarget, resolveLabelNumberLocale, resolveLayerCapabilities, resolveMapGrid, resolvePopupBody, resolvePopupImageHeight, resolvePopupMaxWidth, resolvePopupRows, resolvePopupTitle, resolveProjectHeaderReferences, resolveReadableUrl, resolveRolePrivileges, resolveSvgSource, resolveThreeDTilesRequestHeaders, rgbToHex, routeResponseToFeatures, rowCap, ruleBasedColorExpression, ruleBasedVisibilityFilter, s3ObjectHttpsUrl, sameCesiumImagery, sampleMapTerrain, sampleMapTerrainPoint, sampleRemoteElevations, sanitizeLayerStylePatch, scaleAltitudeToActiveBody, scaleDenomination, scaleSpan, scrubCommentsForRemovedLayers, scrubLegendForRemovedLayers, scrubPrintLayoutForLayers, scrubPrintLayoutForRemovedLayers, scrubWidgetsForRemovedLayers, selectLayerById, selectLayerIds, selectLayerSummaries, selectLayersWhen, selectedGeocodingLocator, serializeLayerLibrary, serializeLayerStylesFile, serializeLayersFile, serializeProject, serializeProjectWithLayerCache, serializeProjectWithLayerCacheAsync, serializeStoryMapCsv, serializeStoryMapJson, serializeStyleLibrary, setActiveEllipsoidId, setExternalNativePaintBridge, setGeocodingFetch, setGeocodingTokenProvider, setHistoryCoalesceMs, setMaxHistoryFeatureCount, setProjectCredentialLookup, setRegistryPublishableSettings, setStoredAuthorName, shouldThrottle, shouldUseTiledRendering, shouldZoomToNewLayers, simpleStyleNumberValue, sortLayerGroupInPanel, splitProjectCredentials, stacAssetMediaType, stampFeatureCollectionEditorTracking, stampFeatureEditorTracking, stampFeaturePropertiesEditorTracking, storyLayerOpacityFactor, storyLocationView, storyMapHasContent, storyVisibleLayers, stringifyPopupValue, stripGoogleMapsApiKeyHeader, stripJoinFields, stripVirtualFieldColumns, styleValue, subscribeProjectRestoreHistory, substituteExpressionVariables, supportsBridgedOpacity, transformGeojsonElevation, trimHistoryBySize, undo, unescapePolyline, uniqueImportedLayerName, unmatchedGeocodeFeature, unresolvedLayerLibraryJoins, unsignedSourceUrl, useAppCapability, useAppStore, useLayer, useLayerIds, useLayerSummaries, useLayersWhen, validateAttributeFormField, validateAttributeFormValues, validateLayerDescriptiveMetadata, validateMapExpression, valueMapLabelFor, valueMapToText, vectorCircleColorValue, vectorColorExpression, vectorFillColorValue, vectorFillOpacityValue, vectorLineColorValue, vectorOutlineColorValue, vectorStrokeWidthValue, visiblePopupFields, visiblePopupProperties, withDatumShift, withGeoKeysDatumShift, withJpegTablesPatch, withoutHistory };
9983
9026
 
9984
9027
  //# sourceMappingURL=index.mjs.map