@basemaps/lambda-tiler 8.11.0 → 8.12.2
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/CHANGELOG.md +54 -0
- package/build/__tests__/config.data.d.ts +2 -0
- package/build/__tests__/config.data.js +38 -2
- package/build/__tests__/config.data.js.map +1 -1
- package/build/__tests__/wmts.capability.test.js +29 -4
- package/build/__tests__/wmts.capability.test.js.map +1 -1
- package/build/routes/__tests__/tile.style.json.test.js +56 -0
- package/build/routes/__tests__/tile.style.json.test.js.map +1 -1
- package/build/routes/__tests__/wmts.test.js +6 -3
- package/build/routes/__tests__/wmts.test.js.map +1 -1
- package/build/routes/__tests__/xyz.test.js +1 -1
- package/build/routes/__tests__/xyz.test.js.map +1 -1
- package/build/routes/preview.js +4 -14
- package/build/routes/preview.js.map +1 -1
- package/build/routes/tile.style.json.js +20 -14
- package/build/routes/tile.style.json.js.map +1 -1
- package/build/routes/tile.xyz.raster.js +7 -12
- package/build/routes/tile.xyz.raster.js.map +1 -1
- package/build/util/validate.d.ts +13 -2
- package/build/util/validate.js +53 -35
- package/build/util/validate.js.map +1 -1
- package/build/wmts.capability.d.ts +6 -6
- package/build/wmts.capability.js +45 -22
- package/build/wmts.capability.js.map +1 -1
- package/package.json +8 -8
- package/src/__tests__/config.data.ts +40 -2
- package/src/__tests__/wmts.capability.test.ts +57 -4
- package/src/routes/__tests__/tile.style.json.test.ts +76 -0
- package/src/routes/__tests__/wmts.test.ts +14 -3
- package/src/routes/__tests__/xyz.test.ts +1 -1
- package/src/routes/preview.ts +4 -16
- package/src/routes/tile.style.json.ts +23 -14
- package/src/routes/tile.xyz.raster.ts +7 -11
- package/src/util/validate.ts +60 -34
- package/src/wmts.capability.ts +57 -24
- package/tsconfig.tsbuildinfo +1 -1
package/src/util/validate.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface TileXyz {
|
|
|
16
16
|
/** Output tile format */
|
|
17
17
|
tileType: string;
|
|
18
18
|
/** Optional processing pipeline to use */
|
|
19
|
-
pipeline?: string
|
|
19
|
+
pipeline?: string;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export interface TileMatrixRequest {
|
|
@@ -118,15 +118,15 @@ export const Validate = {
|
|
|
118
118
|
if (isNaN(x) || x < 0 || x > zoom.matrixWidth) throw new LambdaHttpResponse(404, `X not found: ${x}`);
|
|
119
119
|
if (isNaN(y) || y < 0 || y > zoom.matrixHeight) throw new LambdaHttpResponse(404, `Y not found: ${y}`);
|
|
120
120
|
|
|
121
|
-
const pipeline = req.query.get('pipeline');
|
|
122
|
-
|
|
121
|
+
const pipeline = req.query.get('pipeline') ?? undefined;
|
|
122
|
+
req.set('pipeline', pipeline);
|
|
123
123
|
|
|
124
124
|
const xyzData = {
|
|
125
125
|
tile: { x, y, z },
|
|
126
126
|
tileSet: req.params.tileSet,
|
|
127
127
|
tileMatrix,
|
|
128
128
|
tileType: req.params.tileType,
|
|
129
|
-
pipeline
|
|
129
|
+
pipeline,
|
|
130
130
|
};
|
|
131
131
|
req.set('xyz', xyzData.tile);
|
|
132
132
|
|
|
@@ -137,42 +137,68 @@ export const Validate = {
|
|
|
137
137
|
},
|
|
138
138
|
|
|
139
139
|
/**
|
|
140
|
-
*
|
|
140
|
+
* Get the pipeline to use for a imagery set
|
|
141
141
|
*
|
|
142
|
-
*
|
|
142
|
+
* @param tileSet
|
|
143
|
+
* @param pipeline pipeline parameter if it exists
|
|
144
|
+
* @returns 'rgba' for any pipeline without outputs, otherwise the provided pipeline or default output
|
|
143
145
|
*/
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (tileSet.outputs == null) throw new LambdaHttpResponse(404, 'TileSet has no pipelines');
|
|
150
|
-
const output = tileSet.outputs.find((f) => f.name === pipeline);
|
|
151
|
-
if (output == null) throw new LambdaHttpResponse(404, `TileSet has no pipeline named "${pipeline}"`);
|
|
152
|
-
|
|
153
|
-
const validFormats = output.format ?? ['webp', 'png', 'jpeg', 'avif'];
|
|
154
|
-
if (!validFormats.includes(tileType as ImageFormat)) {
|
|
155
|
-
throw new LambdaHttpResponse(400, `TileSet pipeline "${pipeline}" cannot be output as ${tileType}`);
|
|
156
|
-
}
|
|
157
|
-
return output;
|
|
158
|
-
}
|
|
146
|
+
pipelineName(tileSet: ConfigTileSetRaster, pipeline?: string | null): ConfigTileSetRasterOutput {
|
|
147
|
+
if (pipeline == null && tileSet.outputs) {
|
|
148
|
+
// If no pipeline is specified find the default pipeline
|
|
149
|
+
const defaultOutput = tileSet.outputs.find((f) => f.default === true);
|
|
150
|
+
if (defaultOutput) return defaultOutput;
|
|
159
151
|
|
|
160
|
-
|
|
161
|
-
|
|
152
|
+
// If there is only one pipeline force the use of it
|
|
153
|
+
if (tileSet.outputs.length === 1) return tileSet.outputs[0];
|
|
154
|
+
|
|
155
|
+
// No default pipeline, and multiple pipelines exist one must be chosen
|
|
162
156
|
throw new LambdaHttpResponse(404, 'TileSet needs pipeline: ' + tileSet.outputs.map((f) => f.name).join(', '));
|
|
163
157
|
}
|
|
164
158
|
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
name: 'rgba',
|
|
171
|
-
output: {
|
|
172
|
-
type: [img],
|
|
173
|
-
lossless: img === 'png' ? true : false,
|
|
159
|
+
// No pipeline and no outputs default is RGBA
|
|
160
|
+
if (pipeline == null || pipeline === 'rgba') {
|
|
161
|
+
return {
|
|
162
|
+
title: `RGBA`,
|
|
163
|
+
name: 'rgba',
|
|
174
164
|
background: tileSet.background,
|
|
175
|
-
}
|
|
176
|
-
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Pipeline defined and pipeline not found
|
|
169
|
+
if (tileSet.outputs == null) throw new LambdaHttpResponse(404, `TileSet has no pipeline named "${pipeline}"`);
|
|
170
|
+
|
|
171
|
+
const output = tileSet.outputs.find((f) => f.name === pipeline);
|
|
172
|
+
if (output == null) throw new LambdaHttpResponse(404, `TileSet has no pipeline named "${pipeline}"`);
|
|
173
|
+
return output;
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Lookup the raster configuration pipeline for a output tile type
|
|
178
|
+
*
|
|
179
|
+
* Defaults to standard image format output if no outputs are defined on the tileset
|
|
180
|
+
*/
|
|
181
|
+
pipeline(
|
|
182
|
+
tileSet: ConfigTileSetRaster,
|
|
183
|
+
imageFormat?: string | null,
|
|
184
|
+
pipelineName?: string | null,
|
|
185
|
+
): { output: ConfigTileSetRasterOutput; format: ImageFormat } {
|
|
186
|
+
const output = Validate.pipelineName(tileSet, pipelineName);
|
|
187
|
+
|
|
188
|
+
// Failed to parse the chosen image format
|
|
189
|
+
const chosenFormat = getImageFormat(imageFormat);
|
|
190
|
+
if (imageFormat != null && chosenFormat == null) {
|
|
191
|
+
throw new LambdaHttpResponse(400, `TileSet pipeline "${output.name}" cannot be output as ${imageFormat}`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// No requirement on image formats
|
|
195
|
+
if (output.format == null) return { output, format: chosenFormat ?? 'webp' };
|
|
196
|
+
if (chosenFormat == null) return { output, format: output.format[0] };
|
|
197
|
+
|
|
198
|
+
// Validate selected format works as expected
|
|
199
|
+
if (!output.format.includes(chosenFormat)) {
|
|
200
|
+
throw new LambdaHttpResponse(400, `TileSet pipeline "${output.name}" cannot be output as ${imageFormat}`);
|
|
201
|
+
}
|
|
202
|
+
return { output, format: chosenFormat };
|
|
177
203
|
},
|
|
178
204
|
};
|
package/src/wmts.capability.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ConfigImagery,
|
|
3
|
+
ConfigLayer,
|
|
4
|
+
ConfigTileSet,
|
|
5
|
+
ConfigTileSetRasterOutput,
|
|
6
|
+
standardizeLayerName,
|
|
7
|
+
TileSetType,
|
|
8
|
+
} from '@basemaps/config';
|
|
2
9
|
import { BoundingBox, Bounds, GoogleTms, ImageFormat, Projection, TileMatrixSet, WmtsProvider } from '@basemaps/geo';
|
|
3
10
|
import { toQueryString, V, VNodeElement } from '@basemaps/shared';
|
|
4
11
|
import { ImageFormatOrder } from '@basemaps/tiler';
|
|
@@ -74,7 +81,13 @@ export class WmtsBuilder {
|
|
|
74
81
|
for (const format of formats) this.formats.push(format);
|
|
75
82
|
}
|
|
76
83
|
|
|
77
|
-
getFormats(): ImageFormat[] {
|
|
84
|
+
getFormats(restrictTo?: ImageFormat[]): ImageFormat[] {
|
|
85
|
+
if (restrictTo) {
|
|
86
|
+
if (this.formats.length === 0) return restrictTo;
|
|
87
|
+
const filtered = this.formats.filter((f) => restrictTo.includes(f));
|
|
88
|
+
if (filtered.length === 0) return restrictTo;
|
|
89
|
+
return filtered;
|
|
90
|
+
}
|
|
78
91
|
if (this.formats.length) return this.formats;
|
|
79
92
|
return ImageFormatOrder;
|
|
80
93
|
}
|
|
@@ -154,17 +167,17 @@ export class WmtsBuilder {
|
|
|
154
167
|
return V('Style', { isDefault: 'true' }, [V('ows:Title', 'Default Style'), V('ows:Identifier', 'default')]);
|
|
155
168
|
}
|
|
156
169
|
|
|
157
|
-
buildResourceUrl(tileSetId: string, suffix: string): VNodeElement {
|
|
170
|
+
buildResourceUrl(tileSetId: string, suffix: string, pipeline?: string): VNodeElement {
|
|
158
171
|
return V('ResourceURL', {
|
|
159
172
|
format: 'image/' + suffix,
|
|
160
173
|
resourceType: 'tile',
|
|
161
|
-
template: this.buildTileUrl(tileSetId, suffix),
|
|
174
|
+
template: this.buildTileUrl(tileSetId, suffix, pipeline),
|
|
162
175
|
});
|
|
163
176
|
}
|
|
164
177
|
|
|
165
|
-
buildTileUrl(tileSetId: string, suffix: string): string {
|
|
178
|
+
buildTileUrl(tileSetId: string, suffix: string, pipeline?: string): string {
|
|
166
179
|
// TODO this should restrict the output formats to supported formats in pipelines
|
|
167
|
-
const query = { api: this.apiKey, config: this.config, pipeline
|
|
180
|
+
const query = { api: this.apiKey, config: this.config, pipeline };
|
|
168
181
|
|
|
169
182
|
return [
|
|
170
183
|
this.httpBase,
|
|
@@ -178,10 +191,6 @@ export class WmtsBuilder {
|
|
|
178
191
|
].join('/');
|
|
179
192
|
}
|
|
180
193
|
|
|
181
|
-
buildFormats(): VNodeElement[] {
|
|
182
|
-
return this.getFormats().map((fmt) => V('Format', 'image/' + fmt));
|
|
183
|
-
}
|
|
184
|
-
|
|
185
194
|
buildTileMatrixLink(tileSet: ConfigTileSet): VNodeElement[] {
|
|
186
195
|
const matrixSetNodes: VNodeElement[] = [];
|
|
187
196
|
for (const tms of this.tileMatrixSets.values()) {
|
|
@@ -319,7 +328,7 @@ export class WmtsCapabilities extends WmtsBuilder {
|
|
|
319
328
|
];
|
|
320
329
|
}
|
|
321
330
|
|
|
322
|
-
toLayerVNode(tileSet: ConfigTileSet): VNodeElement {
|
|
331
|
+
toLayerVNode(tileSet: ConfigTileSet): VNodeElement[] {
|
|
323
332
|
const matrixSets = this.getMatrixSets(tileSet);
|
|
324
333
|
const matrixSetList = [...matrixSets.values()];
|
|
325
334
|
const firstMatrix = matrixSetList[0];
|
|
@@ -334,19 +343,43 @@ export class WmtsCapabilities extends WmtsBuilder {
|
|
|
334
343
|
bounds.push(Bounds.fromJson(img.bounds));
|
|
335
344
|
}
|
|
336
345
|
|
|
346
|
+
const layers: VNodeElement[] = [];
|
|
347
|
+
|
|
348
|
+
const pipelines = this.getPipelines(tileSet, this.pipeline);
|
|
349
|
+
|
|
337
350
|
const layerNameId = standardizeLayerName(tileSet.name);
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
351
|
+
|
|
352
|
+
for (const pipeline of pipelines) {
|
|
353
|
+
const formats = this.getFormats(pipeline.format);
|
|
354
|
+
const layerId = pipeline.default ? layerNameId : `${layerNameId}_${pipeline.name}`;
|
|
355
|
+
const layerTitle = pipeline.default ? tileSet.title : `${tileSet.title} ${pipeline.title}`;
|
|
356
|
+
|
|
357
|
+
const layer = V('Layer', [
|
|
358
|
+
V('ows:Title', layerTitle),
|
|
359
|
+
V('ows:Abstract', tileSet.description ?? ''),
|
|
360
|
+
V('ows:Identifier', layerId),
|
|
361
|
+
this.buildKeywords(tileSet),
|
|
362
|
+
...[...matrixSets.values()].map((tms) => this.buildBoundingBoxFromImagery(tms, tileSet.layers)),
|
|
363
|
+
this.buildWgs84BoundingBox(webMercatorOrFirst, bounds),
|
|
364
|
+
this.buildStyle(),
|
|
365
|
+
...formats.map((fmt) => V('Format', 'image/' + fmt)),
|
|
366
|
+
...this.buildTileMatrixLink(tileSet),
|
|
367
|
+
...formats.map((fmt) => this.buildResourceUrl(layerNameId, fmt, pipeline.default ? undefined : pipeline.name)),
|
|
368
|
+
]);
|
|
369
|
+
layers.push(layer);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return layers;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
getPipelines(tileSet: ConfigTileSet, pipeline?: string): ConfigTileSetRasterOutput[] {
|
|
376
|
+
if (tileSet.type !== TileSetType.Raster) return [];
|
|
377
|
+
|
|
378
|
+
if (tileSet.outputs == null) return [{ name: 'rgba', title: 'RGBA', default: true }];
|
|
379
|
+
|
|
380
|
+
if (pipeline) return tileSet.outputs.filter((f) => f.name === pipeline);
|
|
381
|
+
|
|
382
|
+
return tileSet.outputs;
|
|
350
383
|
}
|
|
351
384
|
|
|
352
385
|
toAllImageryLayersVNode(configLayers?: ConfigLayer[]): VNodeElement[] {
|
|
@@ -393,7 +426,7 @@ export class WmtsCapabilities extends WmtsBuilder {
|
|
|
393
426
|
|
|
394
427
|
// Build TileSet Layer VNodes
|
|
395
428
|
const layers: VNodeElement[] = [];
|
|
396
|
-
layers.push(this.toLayerVNode(this.tileSet));
|
|
429
|
+
layers.push(...this.toLayerVNode(this.tileSet));
|
|
397
430
|
const contents = layers.concat(this.toAllImageryLayersVNode(this.configLayers));
|
|
398
431
|
|
|
399
432
|
// Build TileMatrix Sets vNodes
|