@basemaps/lambda-tiler 6.39.0 → 6.41.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 (140) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/build/__tests__/config.data.d.ts.map +1 -1
  3. package/build/__tests__/config.data.js +142 -1
  4. package/build/__tests__/config.data.js.map +1 -1
  5. package/build/__tests__/wmts.capability.test.js +105 -79
  6. package/build/__tests__/wmts.capability.test.js.map +1 -1
  7. package/build/__tests__/xyz.util.d.ts.map +1 -1
  8. package/build/__tests__/xyz.util.js +6 -2
  9. package/build/__tests__/xyz.util.js.map +1 -1
  10. package/build/cli/render.tile.d.ts +2 -0
  11. package/build/cli/render.tile.d.ts.map +1 -0
  12. package/build/cli/render.tile.js +36 -0
  13. package/build/cli/render.tile.js.map +1 -0
  14. package/build/routes/__tests__/attribution.test.js +62 -2
  15. package/build/routes/__tests__/attribution.test.js.map +1 -1
  16. package/build/routes/__tests__/wmts.test.js +50 -8
  17. package/build/routes/__tests__/wmts.test.js.map +1 -1
  18. package/build/routes/attribution.d.ts +11 -0
  19. package/build/routes/attribution.d.ts.map +1 -1
  20. package/build/routes/attribution.js +32 -28
  21. package/build/routes/attribution.js.map +1 -1
  22. package/build/routes/tile.json.d.ts.map +1 -1
  23. package/build/routes/tile.json.js +2 -1
  24. package/build/routes/tile.json.js.map +1 -1
  25. package/build/routes/tile.style.json.d.ts.map +1 -1
  26. package/build/routes/tile.style.json.js +2 -1
  27. package/build/routes/tile.style.json.js.map +1 -1
  28. package/build/routes/tile.wmts.d.ts.map +1 -1
  29. package/build/routes/tile.wmts.js +12 -7
  30. package/build/routes/tile.wmts.js.map +1 -1
  31. package/build/routes/tile.xyz.raster.d.ts.map +1 -1
  32. package/build/routes/tile.xyz.raster.js +5 -1
  33. package/build/routes/tile.xyz.raster.js.map +1 -1
  34. package/build/util/__test__/filter.test.d.ts +2 -0
  35. package/build/util/__test__/filter.test.d.ts.map +1 -0
  36. package/build/util/__test__/filter.test.js +64 -0
  37. package/build/util/__test__/filter.test.js.map +1 -0
  38. package/build/util/config.loader.d.ts.map +1 -1
  39. package/build/util/config.loader.js +2 -3
  40. package/build/util/config.loader.js.map +1 -1
  41. package/build/util/filter.d.ts +15 -0
  42. package/build/util/filter.d.ts.map +1 -0
  43. package/build/util/filter.js +59 -0
  44. package/build/util/filter.js.map +1 -0
  45. package/build/util/validate.d.ts.map +1 -1
  46. package/build/util/validate.js +4 -3
  47. package/build/util/validate.js.map +1 -1
  48. package/build/wmts.capability.d.ts +61 -28
  49. package/build/wmts.capability.d.ts.map +1 -1
  50. package/build/wmts.capability.js +175 -99
  51. package/build/wmts.capability.js.map +1 -1
  52. package/dist/index.js +110 -82
  53. package/dist/node_modules/.package-lock.json +17 -17
  54. package/dist/node_modules/detect-libc/README.md +4 -1
  55. package/dist/node_modules/detect-libc/index.d.ts +3 -0
  56. package/dist/node_modules/detect-libc/lib/detect-libc.js +105 -4
  57. package/dist/node_modules/detect-libc/lib/filesystem.js +41 -0
  58. package/dist/node_modules/detect-libc/lib/process.js +3 -0
  59. package/dist/node_modules/detect-libc/package.json +7 -3
  60. package/dist/node_modules/minimist/.eslintrc +25 -50
  61. package/dist/node_modules/minimist/CHANGELOG.md +87 -1
  62. package/dist/node_modules/minimist/README.md +14 -10
  63. package/dist/node_modules/minimist/example/parse.js +2 -0
  64. package/dist/node_modules/minimist/index.js +256 -242
  65. package/dist/node_modules/minimist/package.json +73 -73
  66. package/dist/node_modules/minimist/test/all_bool.js +26 -24
  67. package/dist/node_modules/minimist/test/bool.js +146 -147
  68. package/dist/node_modules/minimist/test/dash.js +33 -21
  69. package/dist/node_modules/minimist/test/default_bool.js +26 -24
  70. package/dist/node_modules/minimist/test/dotted.js +13 -11
  71. package/dist/node_modules/minimist/test/kv_short.js +26 -10
  72. package/dist/node_modules/minimist/test/long.js +28 -26
  73. package/dist/node_modules/minimist/test/num.js +30 -28
  74. package/dist/node_modules/minimist/test/parse.js +169 -157
  75. package/dist/node_modules/minimist/test/parse_modified.js +7 -5
  76. package/dist/node_modules/minimist/test/proto.js +41 -37
  77. package/dist/node_modules/minimist/test/short.js +57 -55
  78. package/dist/node_modules/minimist/test/stop_early.js +10 -8
  79. package/dist/node_modules/minimist/test/unknown.js +83 -81
  80. package/dist/node_modules/minimist/test/whitespace.js +6 -4
  81. package/dist/node_modules/node-abi/.circleci/config.yml +2 -2
  82. package/dist/node_modules/node-abi/.github/CODEOWNERS +1 -0
  83. package/dist/node_modules/node-abi/.github/workflows/semantic.yml +26 -0
  84. package/dist/node_modules/node-abi/.github/workflows/update-abi.yml +5 -4
  85. package/dist/node_modules/node-abi/README.md +5 -3
  86. package/dist/node_modules/node-abi/abi_registry.json +32 -1
  87. package/dist/node_modules/node-abi/package.json +4 -4
  88. package/dist/node_modules/node-abi/scripts/update-abi-registry.js +2 -2
  89. package/dist/node_modules/readable-stream/README.md +1 -1
  90. package/dist/node_modules/readable-stream/lib/_stream_duplex.js +12 -25
  91. package/dist/node_modules/readable-stream/lib/_stream_passthrough.js +2 -4
  92. package/dist/node_modules/readable-stream/lib/_stream_readable.js +176 -273
  93. package/dist/node_modules/readable-stream/lib/_stream_transform.js +26 -37
  94. package/dist/node_modules/readable-stream/lib/_stream_writable.js +118 -174
  95. package/dist/node_modules/readable-stream/lib/internal/streams/async_iterator.js +10 -37
  96. package/dist/node_modules/readable-stream/lib/internal/streams/buffer_list.js +20 -47
  97. package/dist/node_modules/readable-stream/lib/internal/streams/destroy.js +8 -17
  98. package/dist/node_modules/readable-stream/lib/internal/streams/end-of-stream.js +1 -19
  99. package/dist/node_modules/readable-stream/lib/internal/streams/from.js +12 -24
  100. package/dist/node_modules/readable-stream/lib/internal/streams/pipeline.js +5 -16
  101. package/dist/node_modules/readable-stream/lib/internal/streams/state.js +2 -7
  102. package/dist/node_modules/readable-stream/package.json +1 -1
  103. package/dist/node_modules/semver/README.md +70 -1
  104. package/dist/node_modules/semver/bin/semver.js +16 -2
  105. package/dist/node_modules/semver/classes/comparator.js +39 -34
  106. package/dist/node_modules/semver/classes/range.js +45 -28
  107. package/dist/node_modules/semver/classes/semver.js +32 -17
  108. package/dist/node_modules/semver/functions/coerce.js +1 -1
  109. package/dist/node_modules/semver/functions/diff.js +58 -16
  110. package/dist/node_modules/semver/functions/inc.js +3 -2
  111. package/dist/node_modules/semver/functions/parse.js +5 -22
  112. package/dist/node_modules/semver/index.js +1 -0
  113. package/dist/node_modules/semver/internal/constants.js +20 -2
  114. package/dist/node_modules/semver/internal/parse-options.js +14 -10
  115. package/dist/node_modules/semver/internal/re.js +34 -4
  116. package/dist/node_modules/semver/package.json +8 -7
  117. package/dist/node_modules/semver/ranges/intersects.js +1 -1
  118. package/dist/node_modules/semver/ranges/subset.js +6 -3
  119. package/dist/package-lock.json +18 -349
  120. package/dist/package.json +1 -2
  121. package/package.json +9 -10
  122. package/src/__tests__/config.data.ts +142 -1
  123. package/src/__tests__/wmts.capability.test.ts +117 -79
  124. package/src/__tests__/xyz.util.ts +6 -2
  125. package/src/cli/render.tile.ts +41 -0
  126. package/src/routes/__tests__/attribution.test.ts +64 -2
  127. package/src/routes/__tests__/wmts.test.ts +70 -9
  128. package/src/routes/attribution.ts +28 -28
  129. package/src/routes/tile.json.ts +2 -1
  130. package/src/routes/tile.style.json.ts +2 -1
  131. package/src/routes/tile.wmts.ts +13 -6
  132. package/src/routes/tile.xyz.raster.ts +4 -1
  133. package/src/util/__test__/filter.test.ts +80 -0
  134. package/src/util/config.loader.ts +1 -2
  135. package/src/util/filter.ts +60 -0
  136. package/src/util/validate.ts +4 -3
  137. package/src/wmts.capability.ts +216 -123
  138. package/tsconfig.tsbuildinfo +1 -1
  139. package/test-dump.js +0 -6
  140. package/test-imagery.js +0 -3
@@ -1,6 +1,6 @@
1
1
  import { ConfigImagery, ConfigLayer, ConfigTileSet, standardizeLayerName } from '@basemaps/config';
2
- import { Bounds, GoogleTms, ImageFormat, TileMatrixSet, WmtsProvider } from '@basemaps/geo';
3
- import { Projection, toQueryString, V, VNodeElement } from '@basemaps/shared';
2
+ import { Bounds, GoogleTms, ImageFormat, Projection, TileMatrixSet, WmtsProvider } from '@basemaps/geo';
3
+ import { toQueryString, V, VNodeElement } from '@basemaps/shared';
4
4
  import { ImageFormatOrder } from '@basemaps/tiler';
5
5
  import { BoundingBox } from '@cogeotiff/core';
6
6
  import { BBox } from '@linzjs/geojson';
@@ -20,26 +20,6 @@ function wgs84Extent(tileMatrix: TileMatrixSet, bbox: BoundingBox): BBox {
20
20
  return Projection.get(tileMatrix).boundsToWgs84BoundingBox(bbox);
21
21
  }
22
22
 
23
- export interface WmtsCapabilitiesParams {
24
- /** Base URL for tile server */
25
- httpBase: string;
26
- provider?: WmtsProvider;
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 */
36
- apiKey?: string;
37
- /** Limit the output to the following image formats other wise @see ImageFormatOrder */
38
- formats?: ImageFormat[] | null;
39
- /** Config location */
40
- config?: string | null;
41
- }
42
-
43
23
  /** Number of decimal places to use in lat lng */
44
24
  const LngLatPrecision = 6;
45
25
  const MeterPrecision = 4;
@@ -52,31 +32,66 @@ function formatCoords(x: number, precision: number): string {
52
32
  function formatBbox(x: number, y: number, precision: number): string {
53
33
  return `${formatCoords(x, precision)} ${formatCoords(y, precision)}`;
54
34
  }
35
+ export interface WmtsBuilderParams {
36
+ /** Base URL for tile server */
37
+ httpBase: string;
38
+ /** API key to append to all resource urls */
39
+ apiKey?: string;
40
+ /** Config location */
41
+ config?: string | null;
42
+ /** Specific DateRange filter for the wmts layers */
43
+ filters?: Record<string, string | undefined>;
44
+ }
55
45
 
56
- export class WmtsCapabilities {
46
+ export class WmtsBuilder {
57
47
  httpBase: string;
58
- provider?: WmtsProvider;
59
- tileSet: ConfigTileSet;
60
48
  apiKey?: string;
61
49
  config?: string | null;
62
- tileMatrixSets = new Map<string, TileMatrixSet>();
63
- imagery: Map<string, ConfigImagery>;
64
- formats: ImageFormat[];
65
- isIndividualLayers = false;
50
+ filters?: Record<string, string | undefined>;
66
51
 
67
- minZoom = 0;
68
- maxZoom = 32;
52
+ /** All the imagery used by the tileSet and tileMatrixes */
53
+ imagery: Map<string, ConfigImagery> = new Map();
54
+ formats: ImageFormat[] = [];
55
+
56
+ tileMatrixSets = new Map<string, TileMatrixSet>();
69
57
 
70
- constructor(params: WmtsCapabilitiesParams) {
58
+ constructor(params: WmtsBuilderParams) {
71
59
  this.httpBase = params.httpBase;
72
- this.provider = params.provider;
73
- this.tileSet = params.tileSet;
74
- this.config = params.config;
75
- this.isIndividualLayers = params.isIndividualLayers;
76
- for (const tms of params.tileMatrix) this.tileMatrixSets.set(tms.identifier, tms);
77
60
  this.apiKey = params.apiKey;
78
- this.formats = params.formats ?? ImageFormatOrder;
79
- this.imagery = params.imagery;
61
+ this.config = params.config;
62
+ this.filters = params.filters;
63
+ }
64
+
65
+ addImagery(...imagery: ConfigImagery[]): void {
66
+ for (const im of imagery) this.imagery.set(im.id, im);
67
+ }
68
+
69
+ addTileMatrix(...tileMatrix: TileMatrixSet[]): void {
70
+ for (const tms of tileMatrix) this.tileMatrixSets.set(tms.identifier, tms);
71
+ }
72
+
73
+ addFormats(...formats: ImageFormat[]): void {
74
+ for (const format of formats) this.formats.push(format);
75
+ }
76
+
77
+ getFormats(): ImageFormat[] {
78
+ if (this.formats.length) return this.formats;
79
+ return ImageFormatOrder;
80
+ }
81
+
82
+ getMatrixSets(tileSet: ConfigTileSet): Set<TileMatrixSet> {
83
+ const matrixSets = new Set<TileMatrixSet>();
84
+ for (const tms of this.tileMatrixSets.values()) {
85
+ if (tileSet.layers.find((f) => f[tms.projection.code] != null)) {
86
+ matrixSets.add(tms);
87
+ }
88
+ }
89
+ return matrixSets;
90
+ }
91
+
92
+ buildKeywords(tileSet: { category?: string }): VNodeElement {
93
+ if (tileSet.category == null) return V('ows:Keywords');
94
+ return V('ows:Keywords', [V('ows:Keyword', tileSet.category)]);
80
95
  }
81
96
 
82
97
  buildWgs84BoundingBox(tms: TileMatrixSet, layers: Bounds[]): VNodeElement {
@@ -124,43 +139,21 @@ export class WmtsCapabilities {
124
139
  ]);
125
140
  }
126
141
 
127
- buildProvider(): VNodeElement[] {
128
- if (this.provider == null) return [];
129
- const { serviceIdentification, serviceProvider } = this.provider;
130
- const { contact } = serviceProvider;
131
- return [
132
- V('ows:ServiceIdentification', [
133
- V('ows:Title', serviceIdentification.title),
134
- V('ows:Abstract', serviceIdentification.description),
135
- V('ows:ServiceType', 'OGC WMTS'),
136
- V('ows:ServiceTypeVersion', '1.0.0'),
137
- V('ows:Fees', serviceIdentification.fees),
138
- V('ows:AccessConstraints', serviceIdentification.accessConstraints),
139
- ]),
142
+ buildStyle(): VNodeElement {
143
+ return V('Style', { isDefault: 'true' }, [V('ows:Title', 'Default Style'), V('ows:Identifier', 'default')]);
144
+ }
140
145
 
141
- V('ows:ServiceProvider', [
142
- V('ows:ProviderName', serviceProvider.name),
143
- V('ows:ProviderSite', { 'xlink:href': serviceProvider.site }),
144
- V('ows:ServiceContact', [
145
- V('ows:IndividualName', contact.individualName),
146
- V('ows:PositionName', contact.position),
147
- V('ows:ContactInfo', [
148
- V('ows:Phone', [V('ows:Voice', contact.phone)]),
149
- V('ows:Address', [
150
- V('ows:DeliveryPoint', contact.address.deliveryPoint),
151
- V('ows:City', contact.address.city),
152
- V('ows:PostalCode', contact.address.postalCode),
153
- V('ows:Country', contact.address.country),
154
- V('ows:ElectronicMailAddress', contact.address.email),
155
- ]),
156
- ]),
157
- ]),
158
- ]),
159
- ];
146
+ buildResourceUrl(tileSetId: string, suffix: string, addFilter = false): VNodeElement {
147
+ return V('ResourceURL', {
148
+ format: 'image/' + suffix,
149
+ resourceType: 'tile',
150
+ template: this.buildTileUrl(tileSetId, suffix, addFilter),
151
+ });
160
152
  }
161
153
 
162
- buildTileUrl(tileSetId: string, suffix: string): string {
163
- const query = toQueryString({ api: this.apiKey, config: this.config });
154
+ buildTileUrl(tileSetId: string, suffix: string, addFilter = false): string {
155
+ let query = { api: this.apiKey, config: this.config };
156
+ if (addFilter) query = { api: this.apiKey, config: this.config, ...this.filters };
164
157
 
165
158
  return [
166
159
  this.httpBase,
@@ -170,16 +163,22 @@ export class WmtsCapabilities {
170
163
  '{TileMatrixSet}',
171
164
  '{TileMatrix}',
172
165
  '{TileCol}',
173
- `{TileRow}.${suffix}${query}`,
166
+ `{TileRow}.${suffix}${toQueryString(query)}`,
174
167
  ].join('/');
175
168
  }
176
169
 
177
- buildResourceUrl(tileSetId: string, suffix: string): VNodeElement {
178
- return V('ResourceURL', {
179
- format: 'image/' + suffix,
180
- resourceType: 'tile',
181
- template: this.buildTileUrl(tileSetId, suffix),
182
- });
170
+ buildFormats(): VNodeElement[] {
171
+ return this.getFormats().map((fmt) => V('Format', 'image/' + fmt));
172
+ }
173
+
174
+ buildTileMatrixLink(tileSet: ConfigTileSet): VNodeElement[] {
175
+ const matrixSetNodes: VNodeElement[] = [];
176
+ for (const tms of this.tileMatrixSets.values()) {
177
+ if (tileSet.layers.find((f) => f[tms.projection.code] != null)) {
178
+ matrixSetNodes.push(V('TileMatrixSetLink', [V('TileMatrixSet', tms.identifier)]));
179
+ }
180
+ }
181
+ return matrixSetNodes;
183
182
  }
184
183
 
185
184
  buildLayerFromImagery(layer: ConfigLayer): VNodeElement | null {
@@ -202,7 +201,7 @@ export class WmtsCapabilities {
202
201
  if (firstImg == null) return null;
203
202
 
204
203
  return V('Layer', [
205
- V('ows:Title', layer.title ?? layerNameId),
204
+ V('ows:Title', layer.title),
206
205
  V('ows:Abstract', ''),
207
206
  V('ows:Identifier', layerNameId),
208
207
  this.buildKeywords(firstImg),
@@ -211,56 +210,142 @@ export class WmtsCapabilities {
211
210
  }),
212
211
  this.buildWgs84BoundingBox(firstMatrix, [Bounds.fromJson(firstImg.bounds)]),
213
212
  this.buildStyle(),
214
- ...this.formats.map((fmt) => V('Format', 'image/' + fmt)),
213
+ ...this.getFormats().map((fmt) => V('Format', 'image/' + fmt)),
215
214
  ...matrixSetNodes,
216
- ...this.formats.map((fmt) => this.buildResourceUrl(layerNameId, fmt)),
215
+ ...this.getFormats().map((fmt) => this.buildResourceUrl(layerNameId, fmt)),
217
216
  ]);
218
217
  }
218
+ }
219
219
 
220
- buildLayer(layer: ConfigTileSet): VNodeElement {
221
- const matrixSets = new Set<TileMatrixSet>();
222
- const matrixSetNodes: VNodeElement[] = [];
223
- for (const tms of this.tileMatrixSets.values()) {
224
- if (layer.layers.find((f) => f[tms.projection.code] != null)) {
225
- matrixSetNodes.push(V('TileMatrixSetLink', [V('TileMatrixSet', tms.identifier)]));
226
- matrixSets.add(tms);
227
- }
228
- }
229
- const layerNameId = standardizeLayerName(layer.name);
220
+ export interface WmtsCapabilitiesParams {
221
+ provider?: WmtsProvider;
222
+ /** Tileset to export into WMTS */
223
+ tileSet: ConfigTileSet;
224
+ /** List of tile matrixes to output */
225
+ tileMatrix: TileMatrixSet[];
226
+ /** All the imagery used by the tileSet and tileMatrixes */
227
+ imagery: Map<string, ConfigImagery>;
228
+ /** Limit the output to the following image formats other wise @see ImageFormatOrder */
229
+ formats: ImageFormat[];
230
+ /** Specific layers to add to the WMTS */
231
+ layers?: ConfigLayer[];
232
+ }
233
+
234
+ /**
235
+ * WMTS Capabilities Builder
236
+ *
237
+ * /v1/tiles/:tileSet/:tileMatrix/WMTSCapabilities.xml
238
+ * /v1/tiles/:tileSet/WMTSCapabilities.xml
239
+ * /v1/tiles/WMTSCapabilities.xml
240
+ *
241
+ * @example
242
+ *
243
+ */
244
+ export class WmtsCapabilities extends WmtsBuilder {
245
+ minZoom = 0;
246
+ maxZoom = 32;
247
+ /** Wmts tileSet layer and imagery layers information */
248
+ tileSet: ConfigTileSet;
249
+ configLayers?: ConfigLayer[];
250
+
251
+ /** Wmts Provider information */
252
+ provider?: WmtsProvider;
253
+
254
+ constructor(params: WmtsBuilderParams) {
255
+ super(params);
256
+ }
257
+
258
+ addTileSet(tileSet: ConfigTileSet): void {
259
+ this.tileSet = tileSet;
260
+ }
261
+
262
+ addLayers(configLayers?: ConfigLayer[]): void {
263
+ this.configLayers = configLayers;
264
+ }
265
+
266
+ addProvider(provider?: WmtsProvider): void {
267
+ this.provider = provider;
268
+ }
269
+
270
+ toProviderVNode(provider?: WmtsProvider): VNodeElement[] | [] {
271
+ if (provider == null) return [];
272
+ const { serviceIdentification, serviceProvider } = provider;
273
+ const { contact } = serviceProvider;
274
+ return [
275
+ V('ows:ServiceIdentification', [
276
+ V('ows:Title', serviceIdentification.title),
277
+ V('ows:Abstract', serviceIdentification.description),
278
+ V('ows:ServiceType', 'OGC WMTS'),
279
+ V('ows:ServiceTypeVersion', '1.0.0'),
280
+ V('ows:Fees', serviceIdentification.fees),
281
+ V('ows:AccessConstraints', serviceIdentification.accessConstraints),
282
+ ]),
283
+
284
+ V('ows:ServiceProvider', [
285
+ V('ows:ProviderName', serviceProvider.name),
286
+ V('ows:ProviderSite', { 'xlink:href': serviceProvider.site }),
287
+ V('ows:ServiceContact', [
288
+ V('ows:IndividualName', contact.individualName),
289
+ V('ows:PositionName', contact.position),
290
+ V('ows:ContactInfo', [
291
+ V('ows:Phone', [V('ows:Voice', contact.phone)]),
292
+ V('ows:Address', [
293
+ V('ows:DeliveryPoint', contact.address.deliveryPoint),
294
+ V('ows:City', contact.address.city),
295
+ V('ows:PostalCode', contact.address.postalCode),
296
+ V('ows:Country', contact.address.country),
297
+ V('ows:ElectronicMailAddress', contact.address.email),
298
+ ]),
299
+ ]),
300
+ ]),
301
+ ]),
302
+ ];
303
+ }
304
+
305
+ toLayerVNode(tileSet: ConfigTileSet): VNodeElement {
306
+ const matrixSets = this.getMatrixSets(tileSet);
230
307
  const matrixSetList = [...matrixSets.values()];
231
308
  const firstMatrix = matrixSetList[0];
232
- if (firstMatrix == null) throw new Error('No matrix sets found for layer ' + layer.name);
309
+ if (firstMatrix == null) throw new Error('No matrix sets found for layer ' + tileSet.name);
233
310
 
234
311
  // Prefer using the web mercator tms for bounds
235
312
  const webMercatorOrFirst = matrixSetList.find((f) => f.identifier === GoogleTms.identifier) ?? firstMatrix;
236
313
  const bounds: Bounds[] = [];
237
- for (const l of layer.layers) {
314
+ for (const l of tileSet.layers) {
238
315
  const img = this.imagery.get(l[webMercatorOrFirst.projection.code] ?? '');
239
316
  if (img == null) continue;
240
317
  bounds.push(Bounds.fromJson(img.bounds));
241
318
  }
242
319
 
320
+ const layerNameId = standardizeLayerName(tileSet.name);
243
321
  return V('Layer', [
244
- V('ows:Title', layer.title ?? layerNameId),
245
- V('ows:Abstract', layer.description ?? ''),
322
+ V('ows:Title', tileSet.title),
323
+ V('ows:Abstract', tileSet.description ?? ''),
246
324
  V('ows:Identifier', layerNameId),
247
- this.buildKeywords(layer),
248
- ...[...matrixSets.values()].map((tms) => this.buildBoundingBoxFromImagery(tms, layer.layers)),
325
+ this.buildKeywords(tileSet),
326
+ ...[...matrixSets.values()].map((tms) => this.buildBoundingBoxFromImagery(tms, tileSet.layers)),
249
327
  this.buildWgs84BoundingBox(webMercatorOrFirst, bounds),
250
328
  this.buildStyle(),
251
- ...this.formats.map((fmt) => V('Format', 'image/' + fmt)),
252
- ...matrixSetNodes,
253
- ...this.formats.map((fmt) => this.buildResourceUrl(layerNameId, fmt)),
329
+ ...this.buildFormats(),
330
+ ...this.buildTileMatrixLink(tileSet),
331
+ ...this.getFormats().map((fmt) => this.buildResourceUrl(layerNameId, fmt, true)),
254
332
  ]);
255
333
  }
256
334
 
257
- buildKeywords(tileSet: { category?: string }): VNodeElement {
258
- if (tileSet.category == null) return V('ows:Keywords');
259
- return V('ows:Keywords', [V('ows:Keyword', tileSet.category)]);
260
- }
261
-
262
- buildStyle(): VNodeElement {
263
- return V('Style', { isDefault: 'true' }, [V('ows:Title', 'Default Style'), V('ows:Identifier', 'default')]);
335
+ toAllImageryLayersVNode(configLayers?: ConfigLayer[]): VNodeElement[] {
336
+ if (configLayers == null) return [];
337
+ const layersVNode: VNodeElement[] = [];
338
+ const layerByName = new Map<string, ConfigLayer>();
339
+ // Dedupe the layers by unique name
340
+ for (const img of configLayers) layerByName.set(standardizeLayerName(img.name), img);
341
+ const orderedLayers = Array.from(layerByName.values()).sort((a, b) =>
342
+ (a.title ?? a.name).localeCompare(b.title ?? b.name),
343
+ );
344
+ for (const img of orderedLayers) {
345
+ const layer = this.buildLayerFromImagery(img);
346
+ if (layer) layersVNode.push(layer);
347
+ }
348
+ return layersVNode;
264
349
  }
265
350
 
266
351
  buildTileMatrixSet(tms: TileMatrixSet): VNodeElement {
@@ -283,26 +368,34 @@ export class WmtsCapabilities {
283
368
  }),
284
369
  ]);
285
370
  }
371
+
286
372
  toVNode(): VNodeElement {
287
- const layers: (VNodeElement | null)[] = [];
288
- layers.push(this.buildLayer(this.tileSet));
289
-
290
- if (this.isIndividualLayers) {
291
- const layerByName = new Map<string, ConfigLayer>();
292
- // Dedupe the layers by unique name
293
- for (const img of this.tileSet.layers) layerByName.set(standardizeLayerName(img.name), img);
294
- const orderedLayers = Array.from(layerByName.values()).sort((a, b) =>
295
- (a.title ?? a.name).localeCompare(b.title ?? b.name),
296
- );
297
- for (const img of orderedLayers) layers.push(this.buildLayerFromImagery(img));
298
- }
373
+ // Prepare provider vNode if exists
374
+ const provider = this.toProviderVNode(this.provider);
375
+
376
+ // Build TileSet Layer VNodes
377
+ const layers: VNodeElement[] = [];
378
+ layers.push(this.toLayerVNode(this.tileSet));
379
+ const contents = layers.concat(this.toAllImageryLayersVNode(this.configLayers));
299
380
 
300
- for (const tms of this.tileMatrixSets.values()) layers.push(this.buildTileMatrixSet(tms));
381
+ // Build TileMatrix Sets vNodes
382
+ for (const tms of this.tileMatrixSets.values()) contents.push(this.buildTileMatrixSet(tms));
301
383
 
302
- return V('Capabilities', CapabilitiesAttrs, [...this.buildProvider(), V('Contents', layers)]);
384
+ return V('Capabilities', CapabilitiesAttrs, [...provider, V('Contents', contents)]);
303
385
  }
304
386
 
305
387
  toXml(): string {
306
388
  return '<?xml version="1.0" encoding="utf-8"?>\n' + this.toVNode().toString();
307
389
  }
390
+
391
+ fromParams(params: WmtsCapabilitiesParams): void {
392
+ for (const tileMatrix of params.tileMatrix) this.addTileMatrix(tileMatrix);
393
+ for (const im of params.imagery.values()) this.addImagery(im);
394
+ for (const format of params.formats) this.addFormats(format);
395
+
396
+ // Build wmts capabilities
397
+ this.addTileSet(params.tileSet);
398
+ this.addLayers(params.layers);
399
+ this.addProvider(params.provider);
400
+ }
308
401
  }