From 4879e3419f7d70ef179e7359ddf1c47af075f086 Mon Sep 17 00:00:00 2001 From: neodescis Date: Thu, 10 Aug 2023 22:41:52 -0600 Subject: [PATCH] Fix addLayer() typing to allow adding a source with a layer (#2966) * Update check-for-support example to document failIfMajorPerformanceCaveat * Fix map and style addLayer typing to allow for full source specification * Fix failing test * Code review updates * Update CHANGELOG * Fix lint warnings --------- Co-authored-by: neodescis --- CHANGELOG.md | 1 + src/style/style.ts | 18 ++++++++++++------ src/ui/map.test.ts | 15 ++++++++++++++- src/ui/map.ts | 8 +++----- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 468e1a3d85..976a70946e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### 🐞 Bug fixes - Correct declared return type of `Map.getLayer()` and `Style.getLayer()` to be `StyleLayer | undefined` to match the documentation. +- Correct type of `Map.addLayer()` and `Style.addLayer()` to allow adding a layer with an embedded source, matching the documentation. - _...Add new stuff here..._ ## 3.3.0 diff --git a/src/style/style.ts b/src/style/style.ts index 9b7e4ef180..9e5fb825c9 100644 --- a/src/style/style.ts +++ b/src/style/style.ts @@ -191,6 +191,12 @@ export type StyleSwapOptions = { transformStyle?: TransformStyleFunction; } +/** + * Specifies a layer to be added to a {@link Style}. In addition to a standard {@link LayerSpecification} + * or a {@link CustomLayerInterface}, a {@link LayerSpecification} with an embedded {@link SourceSpecification} can also be provided. + */ +export type AddLayerObject = LayerSpecification | (Omit & {source: SourceSpecification}) | CustomLayerInterface; + /** * The Style base class */ @@ -848,7 +854,7 @@ export class Style extends Evented { * @param options - Style setter options. * @returns `this`. */ - addLayer(layerObject: LayerSpecification | CustomLayerInterface, before?: string, options: StyleSetterOptions = {}): this { + addLayer(layerObject: AddLayerObject, before?: string, options: StyleSetterOptions = {}): this { this._checkLoaded(); const id = layerObject.id; @@ -858,7 +864,7 @@ export class Style extends Evented { return; } - let layer; + let layer: ReturnType; if (layerObject.type === 'custom') { if (emitValidationErrors(this, validateCustomStyleLayer(layerObject))) return; @@ -866,17 +872,17 @@ export class Style extends Evented { layer = createStyleLayer(layerObject); } else { - if (typeof (layerObject as any).source === 'object') { - this.addSource(id, (layerObject as any).source); + if ('source' in layerObject && typeof layerObject.source === 'object') { + this.addSource(id, layerObject.source); layerObject = clone(layerObject); - layerObject = (extend(layerObject, {source: id}) as any); + layerObject = extend(layerObject, {source: id}); } // this layer is not in the style.layers array, so we pass an impossible array index if (this._validate(validateStyle.layer, `layers.${id}`, layerObject, {arrayIndex: -1}, options)) return; - layer = createStyleLayer(layerObject); + layer = createStyleLayer(layerObject as LayerSpecification | CustomLayerInterface); this._validateLayer(layer); layer.setEventedParent(this, {layer: {id}}); diff --git a/src/ui/map.test.ts b/src/ui/map.test.ts index e5bc256b7e..955fbb2766 100755 --- a/src/ui/map.test.ts +++ b/src/ui/map.test.ts @@ -6,7 +6,7 @@ import {OverscaledTileID} from '../source/tile_id'; import {Event, ErrorEvent} from '../util/evented'; import simulate from '../../test/unit/lib/simulate_interaction'; import {fixedLngLat, fixedNum} from '../../test/unit/lib/fixed'; -import {LayerSpecification, SourceSpecification, StyleSpecification} from '@maplibre/maplibre-gl-style-spec'; +import {GeoJSONSourceSpecification, LayerSpecification, SourceSpecification, StyleSpecification} from '@maplibre/maplibre-gl-style-spec'; import {RequestTransformFunction} from '../util/request_manager'; import {extend} from '../util/util'; import {LngLatBoundsLike} from '../geo/lng_lat_bounds'; @@ -675,6 +675,19 @@ describe('Map', () => { map.addSource('fill', source); }); + test('a layer can be added with an embedded source specification', () => { + const map = createMap({deleteStyle: true}); + const source: GeoJSONSourceSpecification = { + type: 'geojson', + data: {type: 'Point', coordinates: [0, 0]} + }; + map.addLayer({ + id: 'foo', + type: 'symbol', + source + }); + }); + test('returns the style with added source and layer', done => { const style = createStyle(); const map = createMap({style}); diff --git a/src/ui/map.ts b/src/ui/map.ts index d9e51276c1..e967bf950b 100644 --- a/src/ui/map.ts +++ b/src/ui/map.ts @@ -33,9 +33,8 @@ import {StyleLayer} from '../style/style_layer'; import type {RequestTransformFunction} from '../util/request_manager'; import type {LngLatLike} from '../geo/lng_lat'; import type {LngLatBoundsLike} from '../geo/lng_lat_bounds'; -import type {FeatureIdentifier, StyleOptions, StyleSetterOptions} from '../style/style'; +import type {AddLayerObject, FeatureIdentifier, StyleOptions, StyleSetterOptions} from '../style/style'; import type {MapDataEvent} from './events'; -import type {CustomLayerInterface} from '../style/style_layer/custom_style_layer'; import type {StyleImage, StyleImageInterface, StyleImageMetadata} from '../style/style_image'; import type {PointLike} from './camera'; import type {ScrollZoomHandler} from './handler/scroll_zoom'; @@ -51,7 +50,6 @@ import {defaultLocale} from './default_locale'; import type {TaskID} from '../util/task_queue'; import type {Cancelable} from '../types/cancelable'; import type { - LayerSpecification, FilterSpecification, StyleSpecification, LightSpecification, @@ -2346,7 +2344,7 @@ export class Map extends Camera { * * @param layer - The layer to add, * conforming to either the MapLibre Style Specification's [layer definition](https://maplibre.org/maplibre-style-spec/layers) or, - * less commonly, the {@link CustomLayerInterface} specification. + * less commonly, the {@link CustomLayerInterface} specification. Can also be a layer definition with an embedded source definition. * The MapLibre Style Specification's layer definition is appropriate for most layers. * * @param beforeId - The ID of an existing layer to insert the new layer before, @@ -2418,7 +2416,7 @@ export class Map extends Camera { * @see [Add a vector tile source](https://maplibre.org/maplibre-gl-js/docs/examples/vector-source/) * @see [Add a WMS source](https://maplibre.org/maplibre-gl-js/docs/examples/wms/) */ - addLayer(layer: (LayerSpecification & {source?: string | SourceSpecification}) | CustomLayerInterface, beforeId?: string) { + addLayer(layer: AddLayerObject, beforeId?: string) { this._lazyInitEmptyStyle(); this.style.addLayer(layer, beforeId); return this._update(true);