@geolibre/core 3.1.0 → 3.2.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.d.mts CHANGED
@@ -1947,6 +1947,12 @@ export interface RuntimeEnvironmentVariable {
1947
1947
  key: string;
1948
1948
  value: string;
1949
1949
  enabled: boolean;
1950
+ /**
1951
+ * Absent or `true`: the value is a secret (desktop keeps it in the OS
1952
+ * keychain; every egress removes it). `false`: an ordinary value saved in the
1953
+ * project and kept on share/export.
1954
+ */
1955
+ secret?: boolean;
1950
1956
  }
1951
1957
  declare global {
1952
1958
  interface Window {
@@ -2532,8 +2538,32 @@ export interface GeoLibreProject {
2532
2538
  styleLibrary?: StyleLibraryEntry[];
2533
2539
  /** Anchored review comments on map points or features (issue #1518). */
2534
2540
  comments?: ProjectComment[];
2541
+ /**
2542
+ * Interaction state applied when the project opens: the Identify target and
2543
+ * which map controls and toolbar panels start shown (issue #2688). Written by
2544
+ * the Python `geolibre` package from `set_identify` / `show_control`, so a
2545
+ * saved or HTML-exported notebook map opens the way it was set up. Omitted
2546
+ * by default; the app keeps what it loaded and writes it back unchanged.
2547
+ */
2548
+ interaction?: ProjectInteraction;
2535
2549
  metadata: Record<string, unknown>;
2536
2550
  }
2551
+ /**
2552
+ * Startup interaction state carried by a project (see
2553
+ * {@link GeoLibreProject.interaction}).
2554
+ */
2555
+ export interface ProjectInteraction {
2556
+ /**
2557
+ * Identify target on open: a layer id, `"all"` for every visible queryable
2558
+ * layer, a list of layer ids to identify only those, or `null` for off.
2559
+ */
2560
+ identify?: string | string[] | null;
2561
+ /**
2562
+ * Map control or toolbar panel name (`"search"`, `"bookmark"`, `"globe"`,
2563
+ * ...) to whether it starts shown. Unknown names are ignored on open.
2564
+ */
2565
+ controls?: Record<string, boolean>;
2566
+ }
2537
2567
  export type CommentAnchor = {
2538
2568
  type: "point";
2539
2569
  lngLat: [number, number];
@@ -4259,6 +4289,47 @@ export declare function inferFieldTypes(features: ReadonlyArray<{
4259
4289
  properties?: Record<string, unknown> | null;
4260
4290
  }>, names: string[]): Record<string, ExpressionFieldType>;
4261
4291
  //#endregion
4292
+ //#region src/style-layer-evaluator.d.ts
4293
+ /** The geometry kinds a MapLibre style expression tells apart (`["geometry-type"]`). */
4294
+ export type StyleGeometryKind = "Point" | "LineString" | "Polygon";
4295
+ /** A feature as a style layer's expressions read it. */
4296
+ export interface StyleFeatureInput {
4297
+ id?: string | number;
4298
+ properties: Record<string, unknown> | null | undefined;
4299
+ kind: StyleGeometryKind;
4300
+ }
4301
+ /** A style layer's filter and property values, evaluated as MapLibre would. */
4302
+ export interface StyleLayerEvaluator {
4303
+ /** Whether the layer's `filter` keeps the feature at `zoom`. */
4304
+ passes: (zoom: number, feature: StyleFeatureInput) => boolean;
4305
+ /**
4306
+ * A paint or layout property's value for a feature at `zoom`: the layer's
4307
+ * value (a literal, a legacy function or an expression) or the spec's
4308
+ * default. A color comes back as `[r, g, b, a]` with channels 0-255 and
4309
+ * alpha 0-1; formatted text as its plain string. `undefined` for a property
4310
+ * the spec does not know or an expression that does not compile.
4311
+ */
4312
+ value: (group: "paint" | "layout", name: string, zoom: number, feature: StyleFeatureInput) => unknown;
4313
+ }
4314
+ interface StyleLayerInput {
4315
+ id?: string;
4316
+ type: string;
4317
+ filter?: unknown;
4318
+ paint?: Record<string, unknown>;
4319
+ layout?: Record<string, unknown>;
4320
+ }
4321
+ /**
4322
+ * Compile a MapLibre style layer's filter and properties for evaluation
4323
+ * outside MapLibre, for a renderer that draws the layer itself (the ArcGIS
4324
+ * renderer drawing a plugin's own GeoJSON overlay, say). Uses the style spec's
4325
+ * own evaluator, so data-driven and zoom expressions, legacy functions and
4326
+ * defaults behave as they do on MapLibre. Each property compiles once.
4327
+ *
4328
+ * @param layer - The style layer (its `type`, `filter`, `paint`, `layout`).
4329
+ * @returns The layer's evaluator.
4330
+ */
4331
+ export declare function createStyleLayerEvaluator(layer: StyleLayerInput): StyleLayerEvaluator;
4332
+ //#endregion
4262
4333
  //#region src/document-locale.d.ts
4263
4334
  /**
4264
4335
  * The document language, so formatted numbers and dates follow the UI locale.
@@ -4447,6 +4518,21 @@ export declare function supportsBridgedOpacity(layerId: string): boolean;
4447
4518
  export declare function rendererAppliesOpacity(layer: {
4448
4519
  type: string;
4449
4520
  }, renderer: string | undefined): boolean;
4521
+ /**
4522
+ * Whether `layer` is an Add Vector Layer layer GeoLibre adopted
4523
+ * (`maplibre-gl-vector-adopted`, ADOPTED_VECTOR_SOURCE_KIND in
4524
+ * @geolibre/plugins) that has no features yet. A project saves a URL- or
4525
+ * path-backed adopted layer without them, and the vector control reads them
4526
+ * again on reopen. Until then its `source.url` may name GeoParquet or
4527
+ * GeoPackage, so a renderer must wait rather than load that URL as GeoJSON.
4528
+ *
4529
+ * @param layer - A store layer.
4530
+ * @returns True while the adopted layer awaits its features.
4531
+ */
4532
+ export declare function isAdoptedVectorAwaitingFeatures(layer: {
4533
+ metadata: Record<string, unknown>;
4534
+ geojson?: unknown;
4535
+ }): boolean;
4450
4536
  //#endregion
4451
4537
  //#region src/attribute-form.d.ts
4452
4538
  /** Options threaded to expression evaluation (constraints, visibility). */
@@ -5141,14 +5227,23 @@ export declare class ElevationFetchError extends Error {
5141
5227
  }
5142
5228
  /** A `fetch`-compatible function, so tests can inject a stub. */
5143
5229
  export type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;
5230
+ /**
5231
+ * Normalize longitude into [-180, 180] degrees (handles unwrapped coordinates
5232
+ * from antimeridian cross-overs and world-copy pannings).
5233
+ */
5234
+ export declare function normalizeLongitude(lng: number): number;
5235
+ /**
5236
+ * Clamp latitude into [-90, 90] degrees.
5237
+ */
5238
+ export declare function clampLatitude(lat: number): number;
5144
5239
  /**
5145
5240
  * Fetch elevations (in meters) for an ordered list of coordinates.
5146
5241
  *
5147
5242
  * @param points - Coordinates as `[lng, lat]`, at most {@link MAX_POINTS_PER_REQUEST}
5148
5243
  * @param fetchImpl - Optional `fetch` implementation; defaults to the global `fetch`
5149
5244
  * @returns The elevation in meters for each input coordinate, in the same order
5150
- * @throws {ElevationFetchError} On too many points, a network error, a non-2xx
5151
- * response, a malformed body, or a length mismatch
5245
+ * @throws {ElevationFetchError} On too many points, a non-finite coordinate, a
5246
+ * network error, a non-2xx response, a malformed body, or a length mismatch
5152
5247
  */
5153
5248
  export declare function fetchElevations(points: LngLat[], fetchImpl?: FetchLike): Promise<number[]>;
5154
5249
  /** The slice of the MapLibre map the terrain sampler needs (stubbed in tests). */
@@ -5426,6 +5521,18 @@ export declare function normalizeWidgets(value: unknown): DashboardWidget[] | nu
5426
5521
  * @returns An integer column count within [MIN, MAX].
5427
5522
  */
5428
5523
  export declare function normalizeDashboardColumns(value: unknown): number;
5524
+ /**
5525
+ * Coerce an untrusted `interaction` block into a {@link ProjectInteraction}.
5526
+ *
5527
+ * Layer ids are kept even when no such layer exists: the block is replayed
5528
+ * against whatever layers the project has when it opens, and the loader drops
5529
+ * the ones it cannot find. Control names are kept as written for the same
5530
+ * reason; the app ignores names it does not know.
5531
+ *
5532
+ * @param value - Raw `interaction` value from the project JSON or the store.
5533
+ * @returns The normalized block, or null when it carries nothing to apply.
5534
+ */
5535
+ export declare function normalizeProjectInteraction(value: unknown): ProjectInteraction | null;
5429
5536
  export declare function isAllowedPluginManifestUrl(url: string): boolean;
5430
5537
  export declare function normalizeProjectComments(rawComments: unknown): ProjectComment[];
5431
5538
  export declare function projectFromStore(state: {
@@ -5454,6 +5561,8 @@ export declare function projectFromStore(state: {
5454
5561
  /** Project-scoped Style Manager entries (the store's `projectStyleLibrary`). */
5455
5562
  styleLibrary?: StyleLibraryEntry[] | null;
5456
5563
  comments?: ProjectComment[] | null;
5564
+ /** Startup interaction state loaded with the project, written back as-is. */
5565
+ interaction?: ProjectInteraction | null;
5457
5566
  metadata: Record<string, unknown>;
5458
5567
  }): GeoLibreProject;
5459
5568
  /**
@@ -5490,6 +5599,7 @@ export declare function applyProjectToStore(project: GeoLibreProject): {
5490
5599
  primaryRenderer: MapRendererKind;
5491
5600
  projectStyleLibrary: StyleLibraryEntry[];
5492
5601
  comments: ProjectComment[];
5602
+ projectInteraction: ProjectInteraction | null;
5493
5603
  metadata: Record<string, unknown>;
5494
5604
  };
5495
5605
  /**
@@ -6032,6 +6142,101 @@ export declare function extractCopiedLayerStyle(layer: GeoLibreLayer): CopiedLay
6032
6142
  */
6033
6143
  export declare function applyCopiedLayerStyle(target: GeoLibreLayer, copied: CopiedLayerStyle): Partial<GeoLibreLayer> | null;
6034
6144
  //#endregion
6145
+ //#region src/layer-style-file.d.ts
6146
+ /** `type` tag identifying a layer styles file. */
6147
+ export declare const LAYER_STYLES_FILE_TYPE = "geolibre-layer-styles";
6148
+ /** Format version written by {@link serializeLayerStylesFile}. */
6149
+ export declare const LAYER_STYLES_FILE_VERSION = 1;
6150
+ /** One layer's style in a layer styles file, keyed by the layer's name. */
6151
+ export type LayerStyleFileEntry = {
6152
+ /** Name of the layer the style was exported from; the match key. */
6153
+ layerName: string;
6154
+ kind: "vector";
6155
+ /** The full vector {@link LayerStyle} bag. */
6156
+ style: LayerStyle;
6157
+ } | {
6158
+ layerName: string;
6159
+ kind: "raster";
6160
+ /** Raster visualization state (`metadata.rasterState`). */
6161
+ rasterState?: Record<string, unknown>;
6162
+ /** Raster classification symbology (`metadata.rasterSymbology`). */
6163
+ rasterSymbology?: Record<string, unknown>;
6164
+ };
6165
+ /** The on-disk layer styles document. */
6166
+ export interface LayerStylesFile {
6167
+ type: typeof LAYER_STYLES_FILE_TYPE;
6168
+ version: typeof LAYER_STYLES_FILE_VERSION;
6169
+ styles: LayerStyleFileEntry[];
6170
+ }
6171
+ /**
6172
+ * Capture the style of every layer that has one. Layers without copyable
6173
+ * symbology (basemap tiles, 3D tiles, ...) are skipped. Layers that share a
6174
+ * name are all written, in stack order; the first one wins when the file is
6175
+ * applied (see {@link findLayerStyleEntryIndex}).
6176
+ *
6177
+ * @param layers - The layers to export, in store (bottom-to-top) order.
6178
+ * @returns The style entries.
6179
+ */
6180
+ export declare function extractLayerStyleEntries(layers: readonly GeoLibreLayer[]): LayerStyleFileEntry[];
6181
+ /**
6182
+ * Serialize style entries into the JSON written by Export Layer Styles.
6183
+ *
6184
+ * @param entries - The entries to write.
6185
+ * @returns Pretty-printed file content.
6186
+ */
6187
+ export declare function serializeLayerStylesFile(entries: readonly LayerStyleFileEntry[]): string;
6188
+ /**
6189
+ * Coerce untrusted entries (a hand-edited file, or a copy kept in settings)
6190
+ * into clean ones. An entry without a name or a known kind is dropped; a
6191
+ * vector style is sanitized and completed against the default style, and a
6192
+ * raster state keeps only well-typed appearance keys, so applying an entry
6193
+ * never hands a renderer an unknown, missing or wrong-typed field.
6194
+ *
6195
+ * @param value - The raw `styles` array.
6196
+ * @returns The usable entries.
6197
+ */
6198
+ export declare function normalizeLayerStyleEntries(value: unknown): LayerStyleFileEntry[];
6199
+ /**
6200
+ * Parse a file written by {@link serializeLayerStylesFile}.
6201
+ *
6202
+ * @param json - The file content.
6203
+ * @returns The normalized entries.
6204
+ * @throws Error when the content is not a layer styles file, comes from a
6205
+ * newer format version, or holds no usable entries.
6206
+ */
6207
+ export declare function parseLayerStylesFile(json: string): LayerStyleFileEntry[];
6208
+ /**
6209
+ * Find the entry for a layer name: an exact match first, then one that differs
6210
+ * only in case or surrounding whitespace, so `Roads` still picks up a style
6211
+ * saved for `roads`. The first match in file order wins.
6212
+ *
6213
+ * @param entries - The style entries.
6214
+ * @param layerName - The layer name to look up.
6215
+ * @param kind - When given, only entries of this style family are considered,
6216
+ * so a raster style saved under a shared name does not shadow the vector one.
6217
+ * @returns The matching entry's index in `entries`, or -1.
6218
+ */
6219
+ export declare function findLayerStyleEntryIndex(entries: readonly LayerStyleFileEntry[], layerName: string, kind?: LayerStyleClipboardKind): number;
6220
+ /** A layer restyled from a style entry, and the entry it took. */
6221
+ export interface LayerStyleMatch {
6222
+ /** Index of the applied entry in the entries array. */
6223
+ entryIndex: number;
6224
+ /** The patch that applies it. */
6225
+ patch: Partial<GeoLibreLayer>;
6226
+ }
6227
+ /**
6228
+ * Build the patch that restyles a layer from the entry matching its name, with
6229
+ * the same semantics as pasting a copied style: a vector style replaces the
6230
+ * whole style bag, a raster style merges its appearance keys and keeps the
6231
+ * layer's own band selection, and layer opacity is left alone.
6232
+ *
6233
+ * @param layer - The layer to restyle.
6234
+ * @param entries - The style entries.
6235
+ * @returns The matched entry and patch, or `null` when no entry of the layer's
6236
+ * style family matches its name (or the layer has no stylable symbology).
6237
+ */
6238
+ export declare function matchLayerStyleEntry(layer: GeoLibreLayer, entries: readonly LayerStyleFileEntry[]): LayerStyleMatch | null;
6239
+ //#endregion
6035
6240
  //#region src/layer-groups.d.ts
6036
6241
  /** Opacity a freshly created {@link LayerGroup} starts at (fully opaque). */
6037
6242
  export declare const DEFAULT_LAYER_GROUP_OPACITY = 1;
@@ -6323,6 +6528,236 @@ export declare function layerGroupSortability(layers: GeoLibreLayer[], groups: L
6323
6528
  */
6324
6529
  export declare function formatPixelValue(value: number): string;
6325
6530
  //#endregion
6531
+ //#region src/s3.d.ts
6532
+ /**
6533
+ * Amazon S3 (and S3-compatible) object URLs: parsing, public HTTPS mapping,
6534
+ * SigV4 query-string presigning, and the registry the app uses to plug
6535
+ * credentialed signing into every reader.
6536
+ *
6537
+ * Readers in GeoLibre take a plain HTTPS URL (geotiff.js, cog-tiler-wasm,
6538
+ * pmtiles, DuckDB-WASM's HTTP reader, the vector control). A presigned URL is
6539
+ * the one form of authenticated S3 access all of them accept without a custom
6540
+ * fetch hook, so private objects are read by signing the URL first and handing
6541
+ * the reader the result. Layers keep the unsigned source URL (`s3://…` or the
6542
+ * plain object URL); the signed one is minted again on every load, so a saved
6543
+ * project never carries a signature or a session token.
6544
+ */
6545
+ /** A bucket and object key, with the endpoint the URL named, if any. */
6546
+ export interface S3ObjectLocation {
6547
+ bucket: string;
6548
+ /** The raw (decoded) object key, without a leading slash. */
6549
+ key: string;
6550
+ /** The region an AWS HTTPS URL named in its host, when it named one. */
6551
+ region?: string;
6552
+ }
6553
+ /** Where and how a bucket is addressed. */
6554
+ export interface S3EndpointConfig {
6555
+ /** Signing region, e.g. `us-east-1`. S3-compatible stores often accept `auto`. */
6556
+ region: string;
6557
+ /**
6558
+ * Custom endpoint origin for S3-compatible stores (MinIO, Cloudflare R2,
6559
+ * Wasabi, Ceph), e.g. `https://minio.example.com:9000`. Empty for AWS.
6560
+ */
6561
+ endpoint?: string;
6562
+ /** Address the bucket in the path instead of the host name. */
6563
+ pathStyle?: boolean;
6564
+ }
6565
+ /** AWS credentials used to sign a request. */
6566
+ export interface S3Credentials {
6567
+ accessKeyId: string;
6568
+ secretAccessKey: string;
6569
+ sessionToken?: string;
6570
+ /** Epoch milliseconds at which temporary credentials stop working. */
6571
+ expiresAt?: number;
6572
+ }
6573
+ /** A presigned URL and the moment it stops working. */
6574
+ export interface S3SignedUrl {
6575
+ href: string;
6576
+ /** Epoch milliseconds. */
6577
+ expiresAt: number;
6578
+ }
6579
+ /** SigV4 allows a presigned URL to live at most seven days. */
6580
+ export declare const S3_MAX_PRESIGN_SECONDS: number;
6581
+ /**
6582
+ * Parses an `s3://bucket/key` URI or an AWS S3 HTTPS object URL
6583
+ * (virtual-hosted or path-style, any region) into its bucket and key.
6584
+ * Query strings and fragments are ignored, so a presigned URL parses to the
6585
+ * object it signs.
6586
+ *
6587
+ * @param url The URL to parse.
6588
+ * @returns The bucket and key, or null when the URL is not an S3 object URL.
6589
+ */
6590
+ export declare function parseS3Url(url: string): S3ObjectLocation | null;
6591
+ /** Whether `url` is an `s3://` URI (as opposed to an HTTPS object URL). */
6592
+ export declare function isS3Uri(url: string): boolean;
6593
+ /** Formats a location as an `s3://bucket/key` URI. */
6594
+ export declare function formatS3Uri(location: S3ObjectLocation): string;
6595
+ /**
6596
+ * URI-encodes a key the way SigV4 canonicalizes an S3 path: every byte except
6597
+ * the unreserved set and `/` is percent-encoded, once.
6598
+ */
6599
+ export declare function encodeS3Key(key: string): string;
6600
+ /**
6601
+ * Builds the HTTPS URL of an object.
6602
+ *
6603
+ * AWS buckets whose name contains a dot are addressed path-style, since the
6604
+ * `*.s3.amazonaws.com` wildcard certificate covers one label only.
6605
+ *
6606
+ * @param location The bucket and key.
6607
+ * @param config The endpoint; without one the global AWS endpoint is used.
6608
+ * @returns The unsigned object URL.
6609
+ */
6610
+ export declare function s3ObjectHttpsUrl(location: S3ObjectLocation, config?: Partial<S3EndpointConfig>): string;
6611
+ export interface PresignS3Options {
6612
+ /** The unsigned HTTPS object URL (see {@link s3ObjectHttpsUrl}). */
6613
+ url: string;
6614
+ region: string;
6615
+ credentials: S3Credentials;
6616
+ /** Lifetime in seconds, clamped to 1…{@link S3_MAX_PRESIGN_SECONDS}. */
6617
+ expiresIn: number;
6618
+ /** HTTP method the URL authorizes. Defaults to GET. */
6619
+ method?: string;
6620
+ /** Signing time; defaults to now. Exposed for tests. */
6621
+ now?: Date;
6622
+ }
6623
+ /**
6624
+ * Presigns an S3 request with AWS Signature Version 4 in the query string.
6625
+ * Runs on WebCrypto, so it works in the browser, the Tauri webview, and Node.
6626
+ *
6627
+ * The URL authorizes exactly one method: a GET URL cannot answer a HEAD, so
6628
+ * readers that probe with HEAD need a GET range request instead.
6629
+ *
6630
+ * @param options The object URL, region, credentials, and lifetime.
6631
+ * @returns The presigned URL.
6632
+ */
6633
+ export declare function presignS3Url(options: PresignS3Options): Promise<string>;
6634
+ /** One signed S3 GET: an object read, or a bucket-level call such as ListObjectsV2. */
6635
+ export interface S3PresignRequest {
6636
+ bucket: string;
6637
+ /** Object key; empty for a bucket-level request. */
6638
+ key: string;
6639
+ /** Extra query parameters to sign (e.g. `list-type=2`). */
6640
+ query?: Record<string, string>;
6641
+ /** Region an AWS URL named, used ahead of the connection's default. */
6642
+ region?: string;
6643
+ /**
6644
+ * Sign with this connection instead of the one matched by bucket name (the
6645
+ * S3 browser listing a chosen connection's buckets, where `bucket` is empty).
6646
+ */
6647
+ connectionId?: string;
6648
+ }
6649
+ /** A configured connection, as the S3 browser lists it. No secrets. */
6650
+ export interface S3ConnectionSummary {
6651
+ id: string;
6652
+ name: string;
6653
+ /** Bucket patterns the connection covers; empty means every bucket. */
6654
+ buckets: string[];
6655
+ }
6656
+ /**
6657
+ * Presigns S3 requests with the app's configured credentials. `presign`
6658
+ * resolves to null when no configured connection covers the bucket, in which
6659
+ * case the object is read anonymously.
6660
+ */
6661
+ export interface S3UrlSigner {
6662
+ /** Whether a configured connection covers `bucket`. Must be synchronous. */
6663
+ covers(bucket: string): boolean;
6664
+ /** Presigns a GET; rejects when the connection's credentials cannot be resolved. */
6665
+ presign(request: S3PresignRequest, signal?: AbortSignal): Promise<S3SignedUrl | null>;
6666
+ /** The configured connections, for pickers. */
6667
+ connections(): S3ConnectionSummary[];
6668
+ /**
6669
+ * Fetches a presigned bucket-level URL (listing). The desktop app routes it
6670
+ * through its native HTTP client, which needs no bucket CORS rule.
6671
+ */
6672
+ fetchText?(url: string, signal?: AbortSignal): Promise<{
6673
+ status: number;
6674
+ body: string;
6675
+ }>;
6676
+ /** The persisted location (`s3://bucket/prefix/`) the S3 browser opens at, or "". */
6677
+ defaultLocation?(): string;
6678
+ /** Persists the S3 browser's default location; "" clears it. */
6679
+ setDefaultLocation?(location: string): void;
6680
+ }
6681
+ /** Installs (or with null, removes) the app's S3 signer. */
6682
+ export declare function registerS3UrlSigner(signer: S3UrlSigner | null): void;
6683
+ /**
6684
+ * Whether reading `url` needs the S3 signer: it names an S3 object in a bucket
6685
+ * a configured connection covers.
6686
+ */
6687
+ export declare function isCredentialedS3Url(url: string): boolean;
6688
+ /**
6689
+ * The unsigned URL a presigned one was minted for by
6690
+ * {@link resolveReadableUrl}, or `url` itself. Layer sync runs every URL a
6691
+ * control reports through this, so the store (and a saved project) keeps the
6692
+ * `s3://` source rather than an expiring signature.
6693
+ */
6694
+ export declare function unsignedSourceUrl(url: string): string;
6695
+ export declare function unsignedSourceUrl(url: string | undefined): string | undefined;
6696
+ /**
6697
+ * Resolves a data URL into one a plain HTTP reader can fetch:
6698
+ *
6699
+ * - an S3 object in a bucket a configured connection covers → a presigned URL;
6700
+ * - any other `s3://` URI → the public HTTPS object URL (anonymous read);
6701
+ * - anything else → unchanged.
6702
+ *
6703
+ * @param url The URL a layer or query names.
6704
+ * @param signal Aborts a pending credential lookup.
6705
+ * @returns The URL to hand the reader.
6706
+ * @throws When the bucket is covered but its credentials cannot be resolved.
6707
+ */
6708
+ export declare function resolveReadableUrl(url: string, signal?: AbortSignal): Promise<string>;
6709
+ /** The installed signer, for the S3 browser. */
6710
+ export declare function getS3UrlSigner(): S3UrlSigner | null;
6711
+ /** One page of a ListObjectsV2 response. */
6712
+ export interface S3ListPage {
6713
+ /** Common prefixes ("folders") under the requested prefix. */
6714
+ prefixes: string[];
6715
+ objects: Array<{
6716
+ key: string;
6717
+ size: number;
6718
+ lastModified?: string;
6719
+ }>;
6720
+ /** Present when more results follow. */
6721
+ nextContinuationToken?: string;
6722
+ }
6723
+ /**
6724
+ * Parses a ListObjectsV2 XML body. S3's listing XML is flat and predictable,
6725
+ * so this reads it with patterns rather than an XML DOM, which keeps it usable
6726
+ * in workers and Node tests.
6727
+ */
6728
+ export declare function parseS3ListObjects(xml: string): S3ListPage;
6729
+ /** The error code and message of an S3 XML error body, when it is one. */
6730
+ export declare function parseS3Error(xml: string): {
6731
+ code: string;
6732
+ message: string;
6733
+ region?: string;
6734
+ } | null;
6735
+ /** Bucket names from a ListBuckets (`GET /` on the service) XML body. */
6736
+ export declare function parseS3BucketList(xml: string): string[];
6737
+ /** A read the bucket's CORS configuration blocked. */
6738
+ export declare class S3CorsError extends Error {
6739
+ readonly bucket: string;
6740
+ readonly origin: string;
6741
+ constructor(message: string, bucket: string, origin: string, cause: unknown);
6742
+ }
6743
+ /** Translates `key`, falling back to `defaultValue` (an app API's `translate`). */
6744
+ export type S3ErrorTranslate = (key: string, defaultValue: string, params?: Record<string, string | number>) => string;
6745
+ /**
6746
+ * Explains why reading an S3 object failed when the browser only said
6747
+ * "Failed to fetch". A browser reports a request the bucket's CORS rules
6748
+ * blocked exactly like a network outage, so this repeats the request twice:
6749
+ * normally, where success means the failure was transient; then in `no-cors`
6750
+ * mode, which CORS cannot block. Only when the first fails and the second gets
6751
+ * an answer is the bucket's CORS configuration the cause.
6752
+ *
6753
+ * @param url The `s3://` URI or object URL that was being read.
6754
+ * @param error What the reader threw.
6755
+ * @param translate Turns the message into the UI language.
6756
+ * @returns An {@link S3CorsError} naming the bucket and the origin to allow,
6757
+ * or `error` unchanged when it is not a CORS refusal of an S3 read.
6758
+ */
6759
+ export declare function explainS3ReadError(url: string, error: unknown, translate?: S3ErrorTranslate): Promise<unknown>;
6760
+ //#endregion
6326
6761
  //#region src/storymap-sample.d.ts
6327
6762
  /**
6328
6763
  * Build a ready-to-play sample story map.
@@ -6566,6 +7001,22 @@ interface LayersSlice {
6566
7001
  * style was applied, so callers can skip the confirmation on a no-op.
6567
7002
  */
6568
7003
  pasteLayerStyle: (id: string) => boolean;
7004
+ /**
7005
+ * Restyle layers from layer styles file entries matched by layer name
7006
+ * (Import Layer Styles, and the Startup setting's auto-apply). Each matched
7007
+ * layer is patched the way {@link pasteLayerStyle} would patch it, all in a
7008
+ * single store update so the import is one undo step.
7009
+ *
7010
+ * @param entries - The parsed style entries.
7011
+ * @param layerIds - Restrict the restyle to these layers; every layer when
7012
+ * omitted.
7013
+ * @returns Each restyled layer's id with the index of the entry it took, in
7014
+ * stack order.
7015
+ */
7016
+ applyLayerStyleEntries: (entries: readonly LayerStyleFileEntry[], layerIds?: readonly string[]) => {
7017
+ layerId: string;
7018
+ entryIndex: number;
7019
+ }[];
6569
7020
  /**
6570
7021
  * Replace a layer's persistent attribute joins and immediately re-derive its
6571
7022
  * joined columns (strip what the previous joins added, apply the new list).
@@ -6827,6 +7278,12 @@ interface ProjectContentSlice {
6827
7278
  dashboardColumns: number;
6828
7279
  /** Anchored review comments on map points or features (issue #1518). */
6829
7280
  comments: ProjectComment[];
7281
+ /**
7282
+ * The loaded project's startup `interaction` block (issue #2688). Applied
7283
+ * once on load and written back unchanged on save; live Identify and control
7284
+ * changes do not edit it.
7285
+ */
7286
+ projectInteraction: ProjectInteraction | null;
6830
7287
  /** Append a new dashboard widget. */
6831
7288
  addWidget: (widget: DashboardWidget) => void;
6832
7289
  /** Patch an existing dashboard widget by id (no-op if absent). Merges, so an
@@ -6915,7 +7372,45 @@ interface GpsStatusFix {
6915
7372
  }
6916
7373
  /** Reserved Identify target for querying every visible queryable layer at once. */
6917
7374
  export declare const IDENTIFY_ALL_LAYERS_ID = "__geolibre_identify_all_layers__";
7375
+ /** The Identify fields of the store, as set together by an Identify change. */
7376
+ interface IdentifyState {
7377
+ identifyLayerId: string | null;
7378
+ identifyLayerIds: string[] | null;
7379
+ }
7380
+ /**
7381
+ * Resolve an Identify target against the layers that exist.
7382
+ *
7383
+ * Shared by the scripting `setIdentify` command and by project load, which
7384
+ * applies a project's saved `interaction.identify` (issue #2688).
7385
+ *
7386
+ * @param target - A layer id, `"all"`, a list of layer ids, or null/undefined.
7387
+ * @param layerIds - Ids of the layers currently in the project.
7388
+ * @returns The store fields to set. Ids that name no layer are dropped; a list
7389
+ * that keeps one id becomes a single-layer target, and one that keeps several
7390
+ * becomes the all-layers mode restricted to those ids.
7391
+ */
7392
+ export declare function resolveIdentifyTarget(target: string | readonly string[] | null | undefined, layerIds: Iterable<string>): IdentifyState;
7393
+ /**
7394
+ * Whether the all-layers Identify mode may query a layer.
7395
+ *
7396
+ * @param layerId - The candidate layer's id.
7397
+ * @param identifyLayerIds - The store's `identifyLayerIds` restriction.
7398
+ * @returns True when there is no restriction or the layer is in it.
7399
+ */
7400
+ export declare function identifyAllIncludes(layerId: string, identifyLayerIds: readonly string[] | null | undefined): boolean;
7401
+ /**
7402
+ * Drop removed layers from the Identify state.
7403
+ *
7404
+ * @param state - The current Identify fields.
7405
+ * @param removed - Ids of the layers being removed.
7406
+ * @returns The Identify fields with those layers gone. A restricted all-layers
7407
+ * mode left with one layer narrows to it, and with none turns Identify off.
7408
+ */
7409
+ export declare function identifyStateWithoutLayers(state: IdentifyState, removed: ReadonlySet<string>): IdentifyState;
6918
7410
  interface SessionSlice {
7411
+ /** Local viewing switch; saved layer popup settings are left untouched. */
7412
+ hoverTooltipsEnabled: boolean;
7413
+ setHoverTooltipsEnabled: (enabled: boolean) => void;
6919
7414
  selectedLayerId: string | null;
6920
7415
  selectedFeatureId: string | null;
6921
7416
  /**
@@ -6932,6 +7427,14 @@ interface SessionSlice {
6932
7427
  * DuckDB query, WMS, COG, NetCDF image and time-slider raster alike.
6933
7428
  */
6934
7429
  identifyLayerId: string | null;
7430
+ /**
7431
+ * Layers the all-layers Identify mode is limited to, or null for every
7432
+ * visible queryable layer. Set only alongside {@link IDENTIFY_ALL_LAYERS_ID},
7433
+ * by a script or project that names several layers (issue #2688), and
7434
+ * cleared by every `setIdentifyLayer` call so the in-app buttons keep their
7435
+ * plain meaning.
7436
+ */
7437
+ identifyLayerIds: string[] | null;
6935
7438
  pointerCoords: [number, number] | null;
6936
7439
  /**
6937
7440
  * Ground elevation in true metres under the pointer, for the status bar
@@ -6965,6 +7468,8 @@ interface SessionSlice {
6965
7468
  */
6966
7469
  selectFeatures: (ids: string[], anchorId?: string | null) => void;
6967
7470
  setIdentifyLayer: (id: string | null) => void;
7471
+ /** Set both Identify fields at once (see {@link resolveIdentifyTarget}). */
7472
+ setIdentifyState: (state: IdentifyState) => void;
6968
7473
  setAttributeFilter: (filter: string) => void;
6969
7474
  }
6970
7475
  //#endregion
@@ -7944,6 +8449,89 @@ export declare function resolveThreeDTilesRequestHeaders(url: string, headers: R
7944
8449
  */
7945
8450
  export declare function persistedThreeDTilesRequestHeaders(url: string, headers: Record<string, string> | undefined): Record<string, string> | undefined;
7946
8451
  //#endregion
8452
+ //#region src/project-credential-refs.d.ts
8453
+ export declare function geocodingApiKeyAccount(providerId: string): string;
8454
+ export declare function environmentVariableAccount(key: string): string;
8455
+ /** Rows are secret unless explicitly marked `secret: false`. */
8456
+ export declare function isSecretEnvironmentVariable(variable: RuntimeEnvironmentVariable): boolean;
8457
+ type ProjectCredentialLookup = (account: string) => string | undefined;
8458
+ /** Install (or clear, with `null`) the source of stored project credentials. */
8459
+ export declare function setProjectCredentialLookup(lookup: ProjectCredentialLookup | null): void;
8460
+ /** The stored value for `account`, or `undefined` when none (or no lookup). */
8461
+ export declare function lookupProjectCredential(account: string): string | undefined;
8462
+ /** Fill empty geocoding API keys from the stored ones. */
8463
+ export declare function overlayStoredGeocodingApiKeys(geocoding: GeocodingPreferences): GeocodingPreferences;
8464
+ /** Fill empty secret environment variable values from the stored ones. */
8465
+ export declare function overlayStoredEnvironmentVariables(variables: RuntimeEnvironmentVariable[]): RuntimeEnvironmentVariable[];
8466
+ /** Preferences with every empty stored credential filled in. */
8467
+ export declare function overlayStoredPreferenceCredentials(preferences: ProjectPreferences): ProjectPreferences;
8468
+ /**
8469
+ * The credential changes an edited Settings draft makes, keyed by account
8470
+ * (`""` deletes).
8471
+ *
8472
+ * - `seeded`: the overlaid preferences the dialog opened with.
8473
+ * - `next`: the normalized draft being saved.
8474
+ *
8475
+ * Only values the user changed are returned, so an untouched session override
8476
+ * (plaintext from the opened file) stays out of the keychain and opening a
8477
+ * file never writes it. Removing, renaming, or un-secreting a variable never
8478
+ * deletes its stored value: names are shared by every project on the device.
8479
+ * Clearing a field deletes the stored value only when the field showed that
8480
+ * stored value; clearing a file override that differed from it just drops the
8481
+ * override, so the shared value applies again and other projects keep it.
8482
+ */
8483
+ export declare function changedPreferenceCredentials(seeded: ProjectPreferences, next: ProjectPreferences): Record<string, string>;
8484
+ /**
8485
+ * Move unambiguous geocoding API keys and secret environment variable values
8486
+ * out of `project` (a copy; the input is untouched) into `secrets`, keyed by
8487
+ * account. Secret environment rows that have no unique name remain in the
8488
+ * project for an explicit keep/strip choice. Layers pass through: their
8489
+ * request headers reference variables as `${NAME}` rather than holding
8490
+ * secrets that need moving.
8491
+ */
8492
+ export declare function splitProjectCredentials(project: GeoLibreProject): {
8493
+ project: GeoLibreProject;
8494
+ secrets: Record<string, string>;
8495
+ };
8496
+ /**
8497
+ * `headers` with every `${NAME}` resolved from the project's enabled
8498
+ * Environment Variables (stored secret values filled in). Only those rows
8499
+ * count, not the OS environment or build-time values that share the runtime
8500
+ * env. A header referencing an unset variable is dropped.
8501
+ */
8502
+ export declare function resolveProjectHeaderReferences(headers: Record<string, string> | undefined): Record<string, string> | undefined;
8503
+ //#endregion
8504
+ //#region src/header-references.d.ts
8505
+ /**
8506
+ * `${NAME}` references in request header values.
8507
+ *
8508
+ * A header such as `Authorization: Bearer ${TILES_TOKEN}` is saved as typed
8509
+ * and resolved from the project's Environment Variables when a request is
8510
+ * made, so the secret itself never sits on the layer. This module is pure (no
8511
+ * store import): `credentials.ts` depends on it, and the store depends on
8512
+ * `credentials.ts`.
8513
+ */
8514
+ export declare function hasHeaderReferences(headers: Record<string, string> | undefined): boolean;
8515
+ /**
8516
+ * Whether `value` carries no secret of its own: at most a scheme word such as
8517
+ * `Bearer` followed by a single `${NAME}`. Redaction keeps such values.
8518
+ */
8519
+ export declare function isHeaderReferenceOnly(value: string): boolean;
8520
+ /**
8521
+ * Whether credential-bearing request headers may be sent to `url`: HTTPS, or
8522
+ * plain HTTP to loopback so a local dev server still works. The scheme is read
8523
+ * off a parsed URL, so an unusually cased `HTTPS://` is not misread as
8524
+ * plaintext; a relative or unparseable URL is refused.
8525
+ */
8526
+ export declare function allowsCredentialHeaders(url: string): boolean;
8527
+ /**
8528
+ * `headers` with every `${NAME}` replaced by `values[NAME]`. A header that
8529
+ * references an unset (or empty) variable is omitted rather than sent with a
8530
+ * hole in it. Returns the input unchanged when nothing references a variable,
8531
+ * and `undefined` when no header remains.
8532
+ */
8533
+ export declare function resolveHeaderReferences(headers: Record<string, string> | undefined, values: Readonly<Record<string, string>>): Record<string, string> | undefined;
8534
+ //#endregion
7947
8535
  //#region src/credentials.d.ts
7948
8536
  /**
7949
8537
  * Project fields whose values are credentials. Keep this registry as the
@@ -8189,5 +8777,5 @@ export declare function localFileName(path: string): string;
8189
8777
  /** Keep imported layers distinguishable, including within a multi-file import. */
8190
8778
  export declare function uniqueImportedLayerName(name: string, names: Iterable<string>): string;
8191
8779
  //#endregion
8192
- export type { AppState, CesiumIonAssetKind, CesiumIonLayerOptions, CesiumIonQuickPick, CesiumIonQuickPickGroup, CesiumKmlLayerOptions, ConversionToolKind, CredentialRedactionResult, CzmlDocument, CzmlLayerOptions, CzmlPacket, CzmlSource, GeocodeMatch, GeocodeRequest, GeocodeStatus, GeocoderConfig, GeocodingPreferenceInput, GeocodingProvider, GeocodingProviderId, GpsStatusFix, LayerSummary, NetworkToolKind, NominatimForwardResult, NominatimReverseResult, RasterToolKind, ReverseGeocodeDisplay, StatisticsToolKind, VectorToolKind };
8780
+ export type { AppState, CesiumIonAssetKind, CesiumIonLayerOptions, CesiumIonQuickPick, CesiumIonQuickPickGroup, CesiumKmlLayerOptions, ConversionToolKind, CredentialRedactionResult, CzmlDocument, CzmlLayerOptions, CzmlPacket, CzmlSource, GeocodeMatch, GeocodeRequest, GeocodeStatus, GeocoderConfig, GeocodingPreferenceInput, GeocodingProvider, GeocodingProviderId, GpsStatusFix, IdentifyState, LayerSummary, NetworkToolKind, NominatimForwardResult, NominatimReverseResult, ProjectCredentialLookup, RasterToolKind, ReverseGeocodeDisplay, StatisticsToolKind, VectorToolKind };
8193
8781
  //# sourceMappingURL=index.d.mts.map