@basemaps/lambda-tiler 6.29.0 → 6.30.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.
Files changed (144) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/build/__tests__/config.data.d.ts +6 -0
  3. package/build/__tests__/config.data.d.ts.map +1 -0
  4. package/build/__tests__/config.data.js +81 -0
  5. package/build/__tests__/config.data.js.map +1 -0
  6. package/build/__tests__/index.test.js +4 -3
  7. package/build/__tests__/index.test.js.map +1 -0
  8. package/build/__tests__/route.test.js +1 -0
  9. package/build/__tests__/route.test.js.map +1 -0
  10. package/build/__tests__/tiff.cache.test.js +1 -0
  11. package/build/__tests__/tiff.cache.test.js.map +1 -0
  12. package/build/__tests__/tile.cache.key.test.js +1 -0
  13. package/build/__tests__/tile.cache.key.test.js.map +1 -0
  14. package/build/__tests__/tile.set.cache.test.js +2 -53
  15. package/build/__tests__/tile.set.cache.test.js.map +1 -0
  16. package/build/__tests__/tile.set.test.js +1 -0
  17. package/build/__tests__/tile.set.test.js.map +1 -0
  18. package/build/__tests__/tile.style.json.test.js +1 -0
  19. package/build/__tests__/tile.style.json.test.js.map +1 -0
  20. package/build/__tests__/wmts.capability.test.d.ts +1 -1
  21. package/build/__tests__/wmts.capability.test.d.ts.map +1 -1
  22. package/build/__tests__/wmts.capability.test.js +207 -128
  23. package/build/__tests__/wmts.capability.test.js.map +1 -0
  24. package/build/__tests__/xyz.test.js +6 -37
  25. package/build/__tests__/xyz.test.js.map +1 -0
  26. package/build/__tests__/xyz.util.d.ts +0 -2
  27. package/build/__tests__/xyz.util.d.ts.map +1 -1
  28. package/build/__tests__/xyz.util.js +7 -29
  29. package/build/__tests__/xyz.util.js.map +1 -0
  30. package/build/api.key.js +1 -0
  31. package/build/api.key.js.map +1 -0
  32. package/build/cli/dump.js +1 -0
  33. package/build/cli/dump.js.map +1 -0
  34. package/build/cli/tile.set.local.js +1 -0
  35. package/build/cli/tile.set.local.js.map +1 -0
  36. package/build/cotar.cache.d.ts +25 -0
  37. package/build/cotar.cache.d.ts.map +1 -0
  38. package/build/cotar.cache.js +50 -0
  39. package/build/cotar.cache.js.map +1 -0
  40. package/build/index.d.ts.map +1 -1
  41. package/build/index.js +31 -35
  42. package/build/index.js.map +1 -0
  43. package/build/router.js +1 -0
  44. package/build/router.js.map +1 -0
  45. package/build/routes/__tests__/attribution.test.js +5 -3
  46. package/build/routes/__tests__/attribution.test.js.map +1 -0
  47. package/build/routes/__tests__/fonts.test.js +9 -1
  48. package/build/routes/__tests__/fonts.test.js.map +1 -0
  49. package/build/routes/__tests__/health.test.js +1 -0
  50. package/build/routes/__tests__/health.test.js.map +1 -0
  51. package/build/routes/__tests__/imagery.test.js +1 -0
  52. package/build/routes/__tests__/imagery.test.js.map +1 -0
  53. package/build/routes/__tests__/memory.fs.js +1 -0
  54. package/build/routes/__tests__/memory.fs.js.map +1 -0
  55. package/build/routes/__tests__/sprites.test.js +1 -0
  56. package/build/routes/__tests__/sprites.test.js.map +1 -0
  57. package/build/routes/__tests__/wmts.test.js +59 -10
  58. package/build/routes/__tests__/wmts.test.js.map +1 -0
  59. package/build/routes/api.d.ts +0 -1
  60. package/build/routes/api.d.ts.map +1 -1
  61. package/build/routes/api.js +1 -3
  62. package/build/routes/api.js.map +1 -0
  63. package/build/routes/attribution.js +1 -0
  64. package/build/routes/attribution.js.map +1 -0
  65. package/build/routes/esri/rest.js +1 -0
  66. package/build/routes/esri/rest.js.map +1 -0
  67. package/build/routes/fonts.d.ts.map +1 -1
  68. package/build/routes/fonts.js +9 -1
  69. package/build/routes/fonts.js.map +1 -0
  70. package/build/routes/health.js +1 -0
  71. package/build/routes/health.js.map +1 -0
  72. package/build/routes/imagery.d.ts +8 -1
  73. package/build/routes/imagery.d.ts.map +1 -1
  74. package/build/routes/imagery.js +6 -7
  75. package/build/routes/imagery.js.map +1 -0
  76. package/build/routes/response.js +1 -0
  77. package/build/routes/response.js.map +1 -0
  78. package/build/routes/sprites.d.ts.map +1 -1
  79. package/build/routes/sprites.js +8 -14
  80. package/build/routes/sprites.js.map +1 -0
  81. package/build/routes/tile.etag.js +1 -0
  82. package/build/routes/tile.etag.js.map +1 -0
  83. package/build/routes/tile.js +1 -0
  84. package/build/routes/tile.js.map +1 -0
  85. package/build/routes/tile.json.d.ts.map +1 -1
  86. package/build/routes/tile.json.js +2 -2
  87. package/build/routes/tile.json.js.map +1 -0
  88. package/build/routes/tile.style.json.js +1 -0
  89. package/build/routes/tile.style.json.js.map +1 -0
  90. package/build/routes/tile.wmts.d.ts.map +1 -1
  91. package/build/routes/tile.wmts.js +19 -23
  92. package/build/routes/tile.wmts.js.map +1 -0
  93. package/build/routes/tile.xyz.js +1 -0
  94. package/build/routes/tile.xyz.js.map +1 -0
  95. package/build/source.tracer.js +1 -0
  96. package/build/source.tracer.js.map +1 -0
  97. package/build/tiff.cache.js +1 -0
  98. package/build/tiff.cache.js.map +1 -0
  99. package/build/tile.set.cache.d.ts +0 -1
  100. package/build/tile.set.cache.d.ts.map +1 -1
  101. package/build/tile.set.cache.js +1 -29
  102. package/build/tile.set.cache.js.map +1 -0
  103. package/build/tile.set.js +1 -0
  104. package/build/tile.set.js.map +1 -0
  105. package/build/tile.set.raster.d.ts.map +1 -1
  106. package/build/tile.set.raster.js +6 -3
  107. package/build/tile.set.raster.js.map +1 -0
  108. package/build/tile.set.vector.d.ts +0 -7
  109. package/build/tile.set.vector.d.ts.map +1 -1
  110. package/build/tile.set.vector.js +3 -20
  111. package/build/tile.set.vector.js.map +1 -0
  112. package/build/validate.js +1 -0
  113. package/build/validate.js.map +1 -0
  114. package/build/wmts.capability.d.ts +26 -12
  115. package/build/wmts.capability.d.ts.map +1 -1
  116. package/build/wmts.capability.js +136 -51
  117. package/build/wmts.capability.js.map +1 -0
  118. package/dist/index.js +86 -72
  119. package/dist/node_modules/.package-lock.json +1 -1
  120. package/dist/package-lock.json +2 -2
  121. package/dist/package.json +1 -1
  122. package/package.json +7 -7
  123. package/src/__tests__/config.data.ts +82 -0
  124. package/src/__tests__/index.test.ts +3 -3
  125. package/src/__tests__/tile.set.cache.test.ts +1 -67
  126. package/src/__tests__/wmts.capability.test.ts +224 -154
  127. package/src/__tests__/xyz.test.ts +5 -49
  128. package/src/__tests__/xyz.util.ts +6 -31
  129. package/src/cotar.cache.ts +54 -0
  130. package/src/index.ts +30 -33
  131. package/src/routes/__tests__/attribution.test.ts +4 -4
  132. package/src/routes/__tests__/fonts.test.ts +10 -1
  133. package/src/routes/__tests__/wmts.test.ts +75 -15
  134. package/src/routes/api.ts +0 -4
  135. package/src/routes/fonts.ts +9 -1
  136. package/src/routes/imagery.ts +9 -7
  137. package/src/routes/sprites.ts +7 -15
  138. package/src/routes/tile.json.ts +1 -2
  139. package/src/routes/tile.wmts.ts +20 -22
  140. package/src/tile.set.cache.ts +1 -28
  141. package/src/tile.set.raster.ts +4 -2
  142. package/src/tile.set.vector.ts +3 -21
  143. package/src/wmts.capability.ts +143 -58
  144. package/tsconfig.tsbuildinfo +1 -1
@@ -1,8 +1,9 @@
1
- import { Bounds, ImageFormat, Nztm2000QuadTms, TileMatrixSet, WmtsProvider } from '@basemaps/geo';
1
+ import { Config, ConfigImagery, ConfigLayer, ConfigTileSet, standardizeLayerName } from '@basemaps/config';
2
+ import { Bounds, GoogleTms, ImageFormat, TileMatrixSet, WmtsProvider } from '@basemaps/geo';
2
3
  import { Projection, V, VNodeElement } from '@basemaps/shared';
3
4
  import { ImageFormatOrder } from '@basemaps/tiler';
5
+ import { BoundingBox } from '@cogeotiff/core';
4
6
  import { BBox, Wgs84 } from '@linzjs/geojson';
5
- import { TileSetRaster } from './tile.set.raster.js';
6
7
 
7
8
  const CapabilitiesAttrs = {
8
9
  xmlns: 'http://www.opengis.net/wmts/1.0',
@@ -15,65 +16,74 @@ const CapabilitiesAttrs = {
15
16
  version: '1.0.0',
16
17
  };
17
18
 
18
- function wgs84Extent(layer: TileSetRaster): BBox {
19
- return Projection.get(layer.tileMatrix).boundsToWgs84BoundingBox(layer.extent);
20
- }
21
-
22
- /**
23
- * Default the tile matrix id to the projection of the TileMatrixSet
24
- */
25
- export function getTileMatrixId(tileMatrix: TileMatrixSet): string {
26
- // TODO this should really change everything to identifier
27
- if (tileMatrix.identifier === Nztm2000QuadTms.identifier) return Nztm2000QuadTms.identifier;
28
- return tileMatrix.projection.toEpsgString();
19
+ function wgs84Extent(tileMatrix: TileMatrixSet, bbox: BoundingBox): BBox {
20
+ return Projection.get(tileMatrix).boundsToWgs84BoundingBox(bbox);
29
21
  }
30
22
 
31
23
  export interface WmtsCapabilitiesParams {
24
+ /** Base URL for tile server */
32
25
  httpBase: string;
33
26
  provider?: WmtsProvider;
34
- layers: TileSetRaster[];
27
+ /** Tileset to export into WMTS */
28
+ tileSet: ConfigTileSet;
29
+ /** List of tile matrixes to output */
30
+ tileMatrix: TileMatrixSet[];
31
+ /** Should WMTS Layers be created for each imagery set inside this tileSet */
32
+ isIndividualLayers: boolean;
33
+ /** All the imagery used by the tileSet and tileMatrixes */
34
+ imagery: Map<string, ConfigImagery>;
35
+ /** API key to append to all resource urls */
35
36
  apiKey?: string;
37
+ /** Limit the output to the following image formats other wise @see ImageFormatOrder */
36
38
  formats?: ImageFormat[];
37
39
  }
38
40
 
39
41
  export class WmtsCapabilities {
40
42
  httpBase: string;
41
43
  provider?: WmtsProvider;
42
-
43
- layers: Map<string, TileSetRaster[]> = new Map();
44
-
44
+ tileSet: ConfigTileSet;
45
45
  apiKey?: string;
46
46
  tileMatrixSets = new Map<string, TileMatrixSet>();
47
+ imagery: Map<string, ConfigImagery>;
47
48
  formats: ImageFormat[];
49
+ isIndividualLayers = false;
48
50
 
49
51
  constructor(params: WmtsCapabilitiesParams) {
50
52
  this.httpBase = params.httpBase;
51
53
  this.provider = params.provider;
54
+ this.tileSet = params.tileSet;
55
+ this.isIndividualLayers = params.isIndividualLayers;
56
+ for (const tms of params.tileMatrix) this.tileMatrixSets.set(tms.identifier, tms);
57
+ this.apiKey = params.apiKey;
58
+ this.formats = params.formats ?? ImageFormatOrder;
59
+ this.imagery = params.imagery;
60
+ }
52
61
 
53
- for (const layer of params.layers) {
54
- // TODO is grouping by name the best option
55
- let existing = this.layers.get(layer.fullName);
56
- if (existing == null) {
57
- existing = [];
58
- this.layers.set(layer.fullName, existing);
62
+ async loadImagery(): Promise<void> {
63
+ const ids = new Set<string>();
64
+ for (const tms of this.tileMatrixSets.values()) {
65
+ for (const layer of this.tileSet.layers) {
66
+ const layerId = layer[tms.projection.code];
67
+ if (layerId != null) ids.add(layerId);
59
68
  }
60
- // TODO should a error be thrown here if the projection is invalid
61
- existing.push(layer);
62
-
63
- this.tileMatrixSets.set(layer.tileMatrix.identifier, layer.tileMatrix);
64
69
  }
65
- this.apiKey = params.apiKey;
66
- this.formats = params.formats ?? ImageFormatOrder;
70
+ this.imagery = await Config.Imagery.getAll(ids);
67
71
  }
68
72
 
69
- buildWgs84BoundingBox(layers: TileSetRaster[], tagName = 'ows:WGS84BoundingBox'): VNodeElement {
70
- let bbox = wgs84Extent(layers[0]);
71
- for (let i = 1; i < layers.length; ++i) {
72
- bbox = Wgs84.union(bbox, wgs84Extent(layers[i]));
73
+ buildWgs84BoundingBox(tms: TileMatrixSet, layers: Bounds[]): VNodeElement {
74
+ let bbox: BBox;
75
+ if (layers.length > 0) {
76
+ bbox = wgs84Extent(tms, layers[0]);
77
+ for (let i = 1; i < layers.length; i++) {
78
+ bbox = Wgs84.union(bbox, wgs84Extent(tms, layers[i]));
79
+ }
80
+ } else {
81
+ // No layers provided assume extent is the size of the tile matrix set :shrug: ?
82
+ bbox = wgs84Extent(tms, tms.extent);
73
83
  }
74
84
 
75
85
  return V(
76
- tagName,
86
+ 'ows:WGS84BoundingBox',
77
87
  { crs: 'urn:ogc:def:crs:OGC:2:84' },
78
88
  bbox[2] > 180
79
89
  ? [V('ows:LowerCorner', `-180 -90`), V('ows:UpperCorner', `180 90`)]
@@ -81,8 +91,20 @@ export class WmtsCapabilities {
81
91
  );
82
92
  }
83
93
 
84
- buildBoundingBox(tms: TileMatrixSet, extent: Bounds): VNodeElement {
85
- const bbox = extent.toBbox();
94
+ /** Combine all the bounds of the imagery inside the layers into a extent for the imagery set */
95
+ buildBoundingBoxFromImagery(tms: TileMatrixSet, layers: ConfigLayer[]): VNodeElement | null {
96
+ let bounds;
97
+ for (const layer of layers) {
98
+ const imgId = layer[tms.projection.code];
99
+ if (imgId == null) continue;
100
+ const img = this.imagery.get(imgId);
101
+ if (img == null) continue;
102
+ if (bounds == null) bounds = Bounds.fromJson(img.bounds);
103
+ else bounds = bounds.union(Bounds.fromJson(img.bounds));
104
+ }
105
+ if (bounds == null) return null;
106
+
107
+ const bbox = bounds.toBbox();
86
108
  return V('ows:BoundingBox', { crs: tms.projection.toUrn() }, [
87
109
  V('ows:LowerCorner', `${bbox[tms.indexX]} ${bbox[tms.indexY]}`),
88
110
  V('ows:UpperCorner', `${bbox[tms.indexX + 2]} ${bbox[tms.indexY + 2]}`),
@@ -124,13 +146,13 @@ export class WmtsCapabilities {
124
146
  ];
125
147
  }
126
148
 
127
- buildTileUrl(tileSet: TileSetRaster, suffix: string): string {
149
+ buildTileUrl(tileSetId: string, suffix: string): string {
128
150
  const apiSuffix = this.apiKey ? `?api=${this.apiKey}` : '';
129
151
  return [
130
152
  this.httpBase,
131
153
  'v1',
132
154
  'tiles',
133
- tileSet.fullName,
155
+ tileSetId,
134
156
  '{TileMatrixSet}',
135
157
  '{TileMatrix}',
136
158
  '{TileCol}',
@@ -138,37 +160,91 @@ export class WmtsCapabilities {
138
160
  ].join('/');
139
161
  }
140
162
 
141
- buildResourceUrl(tileSet: TileSetRaster, suffix: string): VNodeElement {
163
+ buildResourceUrl(tileSetId: string, suffix: string): VNodeElement {
142
164
  return V('ResourceURL', {
143
165
  format: 'image/' + suffix,
144
166
  resourceType: 'tile',
145
- template: this.buildTileUrl(tileSet, suffix),
167
+ template: this.buildTileUrl(tileSetId, suffix),
146
168
  });
147
169
  }
148
170
 
149
- buildLayer(layers: TileSetRaster[]): VNodeElement {
150
- const matrixSets = new Set<string>();
171
+ buildLayerFromImagery(layer: ConfigLayer): VNodeElement | null {
172
+ const matrixSets = new Set<TileMatrixSet>();
151
173
  const matrixSetNodes: VNodeElement[] = [];
152
- for (const layer of layers) {
153
- if (matrixSets.has(layer.tileMatrix.identifier)) continue;
154
- matrixSets.add(layer.tileMatrix.identifier);
155
- matrixSetNodes.push(V('TileMatrixSetLink', [V('TileMatrixSet', getTileMatrixId(layer.tileMatrix))]));
174
+ for (const tms of this.tileMatrixSets.values()) {
175
+ const imdIg = layer[tms.projection.code];
176
+ if (imdIg == null) continue;
177
+ const img = this.imagery.get(imdIg);
178
+ if (img == null) continue;
179
+ matrixSetNodes.push(V('TileMatrixSetLink', [V('TileMatrixSet', tms.identifier)]));
180
+ matrixSets.add(tms);
181
+ }
182
+
183
+ const layerNameId = standardizeLayerName(layer.name);
184
+ const matrixSetList = [...matrixSets.values()];
185
+ const firstMatrix = matrixSetList[0];
186
+ if (firstMatrix == null) return null;
187
+ const firstImg = this.imagery.get(layer[firstMatrix.projection.code] ?? '');
188
+ if (firstImg == null) return null;
189
+
190
+ return V('Layer', [
191
+ V('ows:Title', layer.title ?? layerNameId),
192
+ V('ows:Abstract', ''),
193
+ V('ows:Identifier', layerNameId),
194
+ this.buildKeywords(firstImg),
195
+ ...matrixSetList.map((tms) => {
196
+ return this.buildBoundingBoxFromImagery(tms, [layer]);
197
+ }),
198
+ this.buildWgs84BoundingBox(firstMatrix, [Bounds.fromJson(firstImg.bounds)]),
199
+ this.buildStyle(),
200
+ ...this.formats.map((fmt) => V('Format', 'image/' + fmt)),
201
+ ...matrixSetNodes,
202
+ ...this.formats.map((fmt) => this.buildResourceUrl(layerNameId, fmt)),
203
+ ]);
204
+ }
205
+
206
+ buildLayer(layer: ConfigTileSet): VNodeElement {
207
+ const matrixSets = new Set<TileMatrixSet>();
208
+ const matrixSetNodes: VNodeElement[] = [];
209
+ for (const tms of this.tileMatrixSets.values()) {
210
+ if (layer.layers.find((f) => f[tms.projection.code] != null)) {
211
+ matrixSetNodes.push(V('TileMatrixSetLink', [V('TileMatrixSet', tms.identifier)]));
212
+ matrixSets.add(tms);
213
+ }
214
+ }
215
+ const layerNameId = standardizeLayerName(layer.name);
216
+ const matrixSetList = [...matrixSets.values()];
217
+ const firstMatrix = matrixSetList[0];
218
+ if (firstMatrix == null) throw new Error('No matrix sets found for layer ' + layer.name);
219
+
220
+ // Prefer using the web mercator tms for bounds
221
+ const webMercatorOrFirst = matrixSetList.find((f) => f.identifier === GoogleTms.identifier) ?? firstMatrix;
222
+ const bounds: Bounds[] = [];
223
+ for (const l of layer.layers) {
224
+ const img = this.imagery.get(l[webMercatorOrFirst.projection.code] ?? '');
225
+ if (img == null) continue;
226
+ bounds.push(Bounds.fromJson(img.bounds));
156
227
  }
157
228
 
158
- const [firstLayer] = layers;
159
229
  return V('Layer', [
160
- V('ows:Title', firstLayer.title),
161
- V('ows:Abstract', firstLayer.description),
162
- V('ows:Identifier', firstLayer.fullName),
163
- ...layers.map((layer) => this.buildBoundingBox(layer.tileMatrix, layer.extent)),
164
- this.buildWgs84BoundingBox(layers),
230
+ V('ows:Title', layer.title ?? layerNameId),
231
+ V('ows:Abstract', layer.description ?? ''),
232
+ V('ows:Identifier', layerNameId),
233
+ this.buildKeywords(layer),
234
+ ...[...matrixSets.values()].map((tms) => this.buildBoundingBoxFromImagery(tms, layer.layers)),
235
+ this.buildWgs84BoundingBox(webMercatorOrFirst, bounds),
165
236
  this.buildStyle(),
166
237
  ...this.formats.map((fmt) => V('Format', 'image/' + fmt)),
167
238
  ...matrixSetNodes,
168
- ...this.formats.map((fmt) => this.buildResourceUrl(firstLayer, fmt)),
239
+ ...this.formats.map((fmt) => this.buildResourceUrl(layerNameId, fmt)),
169
240
  ]);
170
241
  }
171
242
 
243
+ buildKeywords(tileSet: { category?: string }): VNodeElement {
244
+ if (tileSet.category == null) return V('ows:Keywords');
245
+ return V('ows:Keywords', [V('ows:Keyword', tileSet.category)]);
246
+ }
247
+
172
248
  buildStyle(): VNodeElement {
173
249
  return V('Style', { isDefault: 'true' }, [V('ows:Title', 'Default Style'), V('ows:Identifier', 'default')]);
174
250
  }
@@ -177,7 +253,7 @@ export class WmtsCapabilities {
177
253
  return V('TileMatrixSet', [
178
254
  V('ows:Title', tms.def.title),
179
255
  tms.def.abstract ? V('ows:Abstract', tms.def.abstract) : null,
180
- V('ows:Identifier', getTileMatrixId(tms)),
256
+ V('ows:Identifier', tms.identifier),
181
257
  V('ows:SupportedCRS', tms.projection.toUrn()),
182
258
  tms.def.wellKnownScaleSet ? V('WellKnownScaleSet', tms.def.wellKnownScaleSet) : null,
183
259
  ...tms.def.tileMatrix.map((c) => {
@@ -194,16 +270,25 @@ export class WmtsCapabilities {
194
270
  ]);
195
271
  }
196
272
  toVNode(): VNodeElement {
197
- const layers: VNodeElement[] = [];
198
- for (const tileSets of this.layers.values()) {
199
- layers.push(this.buildLayer(tileSets));
273
+ const layers: (VNodeElement | null)[] = [];
274
+ layers.push(this.buildLayer(this.tileSet));
275
+
276
+ if (this.isIndividualLayers) {
277
+ const layerByName = new Map<string, ConfigLayer>();
278
+ // Dedupe the layers by unique name
279
+ for (const img of this.tileSet.layers) layerByName.set(standardizeLayerName(img.name), img);
280
+ const orderedLayers = Array.from(layerByName.values()).sort((a, b) =>
281
+ (a.title ?? a.name).localeCompare(b.title ?? b.name),
282
+ );
283
+ for (const img of orderedLayers) layers.push(this.buildLayerFromImagery(img));
200
284
  }
285
+
201
286
  for (const tms of this.tileMatrixSets.values()) layers.push(this.buildTileMatrixSet(tms));
202
287
 
203
288
  return V('Capabilities', CapabilitiesAttrs, [...this.buildProvider(), V('Contents', layers)]);
204
289
  }
205
290
 
206
291
  toXml(): string {
207
- return '<?xml version="1.0"?>\n' + this.toVNode().toString();
292
+ return '<?xml version="1.0" encoding="utf-8"?>\n' + this.toVNode().toString();
208
293
  }
209
294
  }