@basemaps/lambda-tiler 8.12.2 → 8.13.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.
@@ -298,9 +298,51 @@ export interface StyleGet {
298
298
  };
299
299
  }
300
300
 
301
+ /**
302
+ * Join styles together
303
+ *
304
+ * Returns a new style json with sources and layers merged together
305
+ *
306
+ * @throws if there are any duplicate layerIds between the styles
307
+ * @param styles styles to merge together, the first style in the array will be used as the base style and urls will be merged into this style
308
+ * @returns
309
+ */
310
+ function mergeStyles(styles: StyleJson[]): StyleJson {
311
+ const target = structuredClone(styles[0]);
312
+ if (styles.length === 1) return target;
313
+
314
+ const layerId = new Map<string, string>();
315
+ for (const l of target.layers) layerId.set(l.id, target.id);
316
+
317
+ for (const st of styles.slice(1)) {
318
+ for (const newLayers of st.layers) {
319
+ if (layerId.has(newLayers.id)) {
320
+ const prev = layerId.get(newLayers.id);
321
+ throw new LambdaHttpResponse(
322
+ 400,
323
+ `Cannot merge styles with duplicate layerIds! styles: "${prev}" "${st.id}" layer: ${newLayers.id}`,
324
+ );
325
+ }
326
+ layerId.set(newLayers.id, st.id);
327
+ }
328
+
329
+ if (target.glyphs == null) target.glyphs = st.glyphs;
330
+ if (target.sprite == null) target.sprite = st.sprite;
331
+ if (target.sky == null) target.sky = st.sky;
332
+
333
+ Object.assign(target.sources, st.sources);
334
+ target.layers.push(...st.layers);
335
+ target.name = target.name + '_' + st.name;
336
+ target.id = target.id + '_' + st.id;
337
+ }
338
+
339
+ return target;
340
+ }
341
+
301
342
  export async function styleJsonGet(req: LambdaHttpRequest<StyleGet>): Promise<LambdaHttpResponse> {
302
343
  const apiKey = Validate.apiKey(req);
303
- const styleName = req.params.styleName;
344
+ const styleNames = req.params.styleName.split(',').filter((f) => f.trim().length > 0);
345
+ if (styleNames.length > 9) throw new LambdaHttpResponse(400, 'Too many styles requested, max 10');
304
346
 
305
347
  const tileMatrix = TileMatrixSets.find(req.query.get('tileMatrix') ?? GoogleTms.identifier);
306
348
  if (tileMatrix == null) return new LambdaHttpResponse(400, 'Invalid tile matrix');
@@ -311,23 +353,32 @@ export async function styleJsonGet(req: LambdaHttpRequest<StyleGet>): Promise<La
311
353
  if (excluded.size > 0) req.set('excludedLayers', [...excluded]);
312
354
 
313
355
  /**
314
- * Configuration options used for the landing page:
315
- * "terrain" - force add a terrain layer
316
- * "labels" - merge the labels style with the current style
356
+ * Force add a terrain layer
317
357
  *
318
- * TODO: (2024-08) this is not a very scalable way of configuring styles, it would be good to provide a styleJSON merge
358
+ * @deprecated 2026-02: use "/aerial,terrain-v2.json"
319
359
  */
320
360
  const terrain = req.query.get('terrain') ?? undefined;
361
+ /**
362
+ * Merge the labels style with the current style
363
+ *
364
+ * @deprecated 2026-02: use "/aerial,labels-v2.json"
365
+ */
321
366
  const labels = Boolean(req.query.get('labels') ?? false);
322
- req.set('styleConfig', { terrain, labels });
367
+ req.set('styleConfig', { terrain, labels, styles: styleNames });
323
368
 
324
369
  // Get style Config from db
325
370
  const config = await ConfigLoader.load(req);
326
- const styleConfig = await config.Style.get(styleName);
327
- const styleSource =
328
- styleConfig?.style ?? (await generateStyleFromTileSet(req, config, styleName, tileMatrix, apiKey));
329
371
 
330
- const targetStyle = structuredClone(styleSource);
372
+ const styles = await Promise.all(
373
+ styleNames.map(async (styleName) => {
374
+ const styleConfig = await config.Style.get(styleName);
375
+ if (styleConfig?.style != null) return styleConfig.style;
376
+ return generateStyleFromTileSet(req, config, styleName, tileMatrix, apiKey);
377
+ }),
378
+ );
379
+
380
+ const targetStyle = mergeStyles(styles);
381
+
331
382
  // Ensure elevation for style json config
332
383
  // TODO: We should remove this after adding terrain source into style configs. PR-916
333
384
  await ensureTerrain(req, tileMatrix, apiKey, targetStyle);