@basemaps/lambda-tiler 7.3.0 → 7.5.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 (91) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/build/__tests__/config.data.d.ts +2 -0
  3. package/build/__tests__/config.data.js +24 -1
  4. package/build/__tests__/config.data.js.map +1 -1
  5. package/build/__tests__/index.test.js +1 -2
  6. package/build/__tests__/index.test.js.map +1 -1
  7. package/build/__tests__/tile.style.json.test.js +71 -16
  8. package/build/__tests__/tile.style.json.test.js.map +1 -1
  9. package/build/__tests__/wmts.capability.test.js +5 -2
  10. package/build/__tests__/wmts.capability.test.js.map +1 -1
  11. package/build/__tests__/xyz.util.js.map +1 -1
  12. package/build/cli/render.preview.js +5 -2
  13. package/build/cli/render.preview.js.map +1 -1
  14. package/build/cli/render.tile.js +1 -1
  15. package/build/cli/render.tile.js.map +1 -1
  16. package/build/index.js +1 -1
  17. package/build/index.js.map +1 -1
  18. package/build/routes/__tests__/attribution.test.js +1 -1
  19. package/build/routes/__tests__/attribution.test.js.map +1 -1
  20. package/build/routes/__tests__/health.test.js +1 -1
  21. package/build/routes/__tests__/health.test.js.map +1 -1
  22. package/build/routes/__tests__/imagery.test.js.map +1 -1
  23. package/build/routes/__tests__/memory.fs.js +1 -1
  24. package/build/routes/__tests__/memory.fs.js.map +1 -1
  25. package/build/routes/__tests__/preview.index.test.js +1 -1
  26. package/build/routes/__tests__/preview.index.test.js.map +1 -1
  27. package/build/routes/__tests__/tile.json.test.js.map +1 -1
  28. package/build/routes/__tests__/tile.style.json.test.js +144 -11
  29. package/build/routes/__tests__/tile.style.json.test.js.map +1 -1
  30. package/build/routes/__tests__/wmts.test.js +18 -2
  31. package/build/routes/__tests__/wmts.test.js.map +1 -1
  32. package/build/routes/config.js +1 -1
  33. package/build/routes/config.js.map +1 -1
  34. package/build/routes/ping.js +2 -2
  35. package/build/routes/ping.js.map +1 -1
  36. package/build/routes/preview.index.js +2 -1
  37. package/build/routes/preview.index.js.map +1 -1
  38. package/build/routes/preview.js +3 -1
  39. package/build/routes/preview.js.map +1 -1
  40. package/build/routes/sprites.js.map +1 -1
  41. package/build/routes/tile.style.json.d.ts +5 -4
  42. package/build/routes/tile.style.json.js +78 -24
  43. package/build/routes/tile.style.json.js.map +1 -1
  44. package/build/routes/tile.wmts.js +1 -0
  45. package/build/routes/tile.wmts.js.map +1 -1
  46. package/build/routes/tile.xyz.raster.js +6 -5
  47. package/build/routes/tile.xyz.raster.js.map +1 -1
  48. package/build/routes/version.js +2 -2
  49. package/build/routes/version.js.map +1 -1
  50. package/build/util/__test__/config.loader.test.js +12 -12
  51. package/build/util/__test__/config.loader.test.js.map +1 -1
  52. package/build/util/config.cache.js.map +1 -1
  53. package/build/util/source.cache.js +5 -4
  54. package/build/util/source.cache.js.map +1 -1
  55. package/build/util/validate.js +1 -1
  56. package/build/util/validate.js.map +1 -1
  57. package/build/wmts.capability.d.ts +8 -4
  58. package/build/wmts.capability.js +18 -8
  59. package/build/wmts.capability.js.map +1 -1
  60. package/package.json +10 -10
  61. package/src/__tests__/config.data.ts +31 -2
  62. package/src/__tests__/index.test.ts +2 -3
  63. package/src/__tests__/tile.style.json.test.ts +89 -16
  64. package/src/__tests__/wmts.capability.test.ts +13 -10
  65. package/src/__tests__/xyz.util.ts +4 -4
  66. package/src/cli/render.preview.ts +5 -2
  67. package/src/cli/render.tile.ts +1 -1
  68. package/src/routes/__tests__/attribution.test.ts +7 -7
  69. package/src/routes/__tests__/health.test.ts +3 -3
  70. package/src/routes/__tests__/imagery.test.ts +1 -1
  71. package/src/routes/__tests__/memory.fs.ts +2 -2
  72. package/src/routes/__tests__/preview.index.test.ts +3 -3
  73. package/src/routes/__tests__/tile.json.test.ts +1 -1
  74. package/src/routes/__tests__/tile.style.json.test.ts +175 -15
  75. package/src/routes/__tests__/wmts.test.ts +23 -3
  76. package/src/routes/config.ts +1 -1
  77. package/src/routes/ping.ts +2 -2
  78. package/src/routes/preview.index.ts +2 -1
  79. package/src/routes/preview.ts +4 -2
  80. package/src/routes/sprites.ts +1 -1
  81. package/src/routes/tile.style.json.ts +103 -24
  82. package/src/routes/tile.wmts.ts +1 -0
  83. package/src/routes/tile.xyz.raster.ts +7 -5
  84. package/src/routes/version.ts +2 -2
  85. package/src/util/__test__/config.loader.test.ts +17 -20
  86. package/src/util/config.cache.ts +2 -1
  87. package/src/util/source.cache.ts +6 -4
  88. package/src/util/validate.ts +1 -1
  89. package/src/wmts.capability.ts +17 -9
  90. package/tsconfig.json +10 -10
  91. package/tsconfig.tsbuildinfo +1 -1
@@ -3,7 +3,7 @@ import { afterEach, beforeEach, describe, it } from 'node:test';
3
3
 
4
4
  import { Attribution } from '@basemaps/attribution';
5
5
  import { ConfigProviderMemory } from '@basemaps/config';
6
- import { GoogleTms, Nztm2000QuadTms, Projection } from '@basemaps/geo';
6
+ import { AttributionStac, GoogleTms, Nztm2000QuadTms, Projection } from '@basemaps/geo';
7
7
  import { LogConfig } from '@basemaps/shared';
8
8
  import { BBox } from '@linzjs/geojson';
9
9
  import { HttpHeader } from '@linzjs/lambda';
@@ -328,7 +328,7 @@ describe('/v1/attribution', () => {
328
328
  const res = await handler.router.handle(request);
329
329
  assert.equal(res.status, 200);
330
330
 
331
- const json = JSON.parse(res.body);
331
+ const json = JSON.parse(res.body) as AttributionStac;
332
332
 
333
333
  const attr = Attribution.fromStac(json);
334
334
  assert.equal(attr.attributions.length, 1);
@@ -351,7 +351,7 @@ describe('/v1/attribution', () => {
351
351
  const res = await handler.router.handle(req);
352
352
  assert.equal(res.status, 200);
353
353
 
354
- const output = JSON.parse(res.body);
354
+ const output = JSON.parse(res.body) as AttributionStac;
355
355
  assert.equal(output.title, ts.title);
356
356
  assert.deepEqual(output.collections[0].summaries['linz:zoom'], { min: 5, max: 11 });
357
357
  });
@@ -361,7 +361,7 @@ describe('/v1/attribution', () => {
361
361
  const res = await handler.router.handle(req);
362
362
  assert.equal(res.status, 200);
363
363
 
364
- const output = JSON.parse(res.body);
364
+ const output = JSON.parse(res.body) as AttributionStac;
365
365
  assert.equal(output.title, ts.title);
366
366
  assert.deepEqual(output.collections[0].summaries['linz:zoom'], { min: 7, max: 14 });
367
367
  });
@@ -374,7 +374,7 @@ describe('/v1/attribution', () => {
374
374
  const res = await handler.router.handle(req);
375
375
  assert.equal(res.status, 200);
376
376
 
377
- const output = JSON.parse(res.body);
377
+ const output = JSON.parse(res.body) as AttributionStac;
378
378
  assert.equal(output.title, ts.title);
379
379
  assert.deepEqual(output.collections[0].summaries['linz:zoom'], { min: 0, max: 13 });
380
380
  });
@@ -387,13 +387,13 @@ describe('/v1/attribution', () => {
387
387
  const res = await handler.router.handle(req);
388
388
  assert.equal(res.status, 200);
389
389
 
390
- const output = JSON.parse(res.body);
390
+ const output = JSON.parse(res.body) as AttributionStac;
391
391
  assert.equal(output.title, ts.title);
392
392
  assert.deepEqual(output.collections[0].summaries['linz:zoom'], { min: 0, max: Nztm2000QuadTms.maxZoom });
393
393
  });
394
394
  });
395
395
 
396
- it('should create valid coordinates', async () => {
396
+ it('should create valid coordinates', () => {
397
397
  //bbox: BBox, files: NamedBounds[], proj: Projection
398
398
  const bbox = [174.79248047, -38.21228805, 175.25939941, -37.99616268] as BBox;
399
399
  const proj = Projection.get(GoogleTms);
@@ -4,7 +4,7 @@ import { afterEach, before, beforeEach, describe, it } from 'node:test';
4
4
  import { ConfigProviderMemory } from '@basemaps/config';
5
5
  import { LogConfig } from '@basemaps/shared';
6
6
  import { LambdaAlbRequest, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
7
- import { Context } from 'aws-lambda';
7
+ import { ALBEventRequestContext, Context } from 'aws-lambda';
8
8
  import sinon from 'sinon';
9
9
 
10
10
  import { FakeData } from '../../__tests__/config.data.js';
@@ -14,7 +14,7 @@ import { TileXyzRaster } from '../tile.xyz.raster.js';
14
14
 
15
15
  const ctx: LambdaHttpRequest = new LambdaAlbRequest(
16
16
  {
17
- requestContext: null as any,
17
+ requestContext: null as unknown as ALBEventRequestContext,
18
18
  httpMethod: 'get',
19
19
  path: '/v1/tiles/health',
20
20
  body: null,
@@ -24,7 +24,7 @@ const ctx: LambdaHttpRequest = new LambdaAlbRequest(
24
24
  LogConfig.get(),
25
25
  );
26
26
 
27
- describe('/v1/health', async () => {
27
+ describe('/v1/health', () => {
28
28
  const sandbox = sinon.createSandbox();
29
29
  const config = new ConfigProviderMemory();
30
30
 
@@ -10,6 +10,6 @@ describe('ImageryRoute', () => {
10
10
  assert.equal(isAllowedFile('foo.tiff'), false);
11
11
  assert.equal(isAllowedFile('foo'), false);
12
12
  assert.equal(isAllowedFile(''), false);
13
- assert.equal(isAllowedFile(null as any), false);
13
+ assert.equal(isAllowedFile(null as unknown as string), false);
14
14
  });
15
15
  });
@@ -4,9 +4,9 @@ export async function toBuffer(stream: Readable): Promise<Buffer> {
4
4
  return new Promise<Buffer>((resolve, reject) => {
5
5
  const buf: Buffer[] = [];
6
6
 
7
- stream.on('data', (chunk) => buf.push(chunk));
7
+ stream.on('data', (chunk: Buffer) => buf.push(chunk));
8
8
  stream.on('end', () => resolve(Buffer.concat(buf)));
9
- stream.on('error', (err) => reject(`error converting stream - ${err}`));
9
+ stream.on('error', (err) => reject(`error converting stream - ${String(err)}`));
10
10
  });
11
11
  }
12
12
  export function toReadable(r: string | Buffer | Readable): Readable {
@@ -5,16 +5,16 @@ import { ConfigProviderMemory, DefaultColorRampOutput, DefaultTerrainRgbOutput }
5
5
  import { LocationUrl } from '@basemaps/geo';
6
6
  import { Env, fsa, FsMemory, LogConfig, V } from '@basemaps/shared';
7
7
  import { LambdaAlbRequest, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
8
- import { ALBEvent, Context } from 'aws-lambda';
8
+ import { ALBEvent, ALBEventRequestContext, Context } from 'aws-lambda';
9
9
 
10
10
  import { FakeData } from '../../__tests__/config.data.js';
11
11
  import { CachedConfig } from '../../util/config.cache.js';
12
12
  import { loadAndServeIndexHtml, PreviewIndexGet, previewIndexGet } from '../preview.index.js';
13
13
 
14
- describe('/@*', async () => {
14
+ describe('/@*', () => {
15
15
  // o.specTimeout(1000);
16
16
  const baseRequest: ALBEvent = {
17
- requestContext: null as any,
17
+ requestContext: null as unknown as ALBEventRequestContext,
18
18
  httpMethod: 'get',
19
19
  path: '/@-41.8900012,174.0492432,z5',
20
20
  body: null,
@@ -149,7 +149,7 @@ describe('/v1/tiles/:tileSet/:tileMatrix/tile.json', () => {
149
149
  const res = await handler.router.handle(request);
150
150
  assert.equal(res.status, 200);
151
151
 
152
- const body = JSON.parse(Buffer.from(res.body, 'base64').toString());
152
+ const body = JSON.parse(Buffer.from(res.body, 'base64').toString()) as { tiles: string[] };
153
153
  assert.equal(body.tiles[0].includes(`config=${configLocation}`), true);
154
154
  });
155
155
 
@@ -1,11 +1,12 @@
1
1
  import assert from 'node:assert';
2
2
  import { afterEach, before, beforeEach, describe, it } from 'node:test';
3
3
 
4
- import { ConfigProviderMemory, StyleJson } from '@basemaps/config';
4
+ import { ConfigProviderMemory, SourceRaster, StyleJson } from '@basemaps/config';
5
+ import { Terrain } from '@basemaps/config/src/config/vector.style.js';
5
6
  import { Env } from '@basemaps/shared';
6
7
  import { createSandbox } from 'sinon';
7
8
 
8
- import { FakeData } from '../../__tests__/config.data.js';
9
+ import { FakeData, TileSetAerial, TileSetElevation } from '../../__tests__/config.data.js';
9
10
  import { Api, mockRequest, mockUrlRequest } from '../../__tests__/xyz.util.js';
10
11
  import { handler } from '../../index.js';
11
12
  import { ConfigLoader } from '../../util/config.loader.js';
@@ -48,6 +49,10 @@ describe('/v1/styles', () => {
48
49
  type: 'raster',
49
50
  tiles: [`/raster/{z}/{x}/{y}.webp`], // Shouldn't encode the {}
50
51
  },
52
+ basemaps_terrain: {
53
+ type: 'raster-dem',
54
+ tiles: [`/elevation/{z}/{x}/{y}.png?pipeline=terrain-rgb`],
55
+ },
51
56
  test_vector: {
52
57
  type: 'vector',
53
58
  url: 'vector.url.co.nz',
@@ -127,6 +132,11 @@ describe('/v1/styles', () => {
127
132
  tiles: [`${host}/raster/{z}/{x}/{y}.webp?api=${Api.key}`],
128
133
  };
129
134
 
135
+ fakeStyle.sources['basemaps_terrain'] = {
136
+ type: 'raster-dem',
137
+ tiles: [`${host}/elevation/{z}/{x}/{y}.png?pipeline=terrain-rgb&api=${Api.key}`],
138
+ };
139
+
130
140
  fakeStyle.sprite = `${host}/sprite`;
131
141
  fakeStyle.glyphs = `${host}/glyphs`;
132
142
 
@@ -174,14 +184,16 @@ describe('/v1/styles', () => {
174
184
  const res = await handler.router.handle(request);
175
185
  assert.equal(res.status, 200, res.statusDescription);
176
186
 
177
- const body = JSON.parse(Buffer.from(res.body, 'base64').toString());
187
+ const body = JSON.parse(Buffer.from(res.body, 'base64').toString()) as StyleJson;
178
188
 
179
189
  assert.equal(body.version, 8);
180
- assert.deepEqual(body.sources['basemaps-aerial'].type, 'raster');
181
- assert.deepEqual(body.sources['basemaps-aerial'].tiles, [
190
+
191
+ const aerialSource = body.sources['basemaps-aerial'] as SourceRaster;
192
+ assert.deepEqual(aerialSource.type, 'raster');
193
+ assert.deepEqual(aerialSource.tiles, [
182
194
  `https://tiles.test/v1/tiles/aerial/WebMercatorQuad/{z}/{x}/{y}.webp?api=${Api.key}`,
183
195
  ]);
184
- assert.deepEqual(body.sources['basemaps-aerial'].tileSize, 256);
196
+ assert.deepEqual(aerialSource.tileSize, 256);
185
197
  assert.deepEqual(body.layers, [{ id: 'basemaps-aerial', type: 'raster', source: 'basemaps-aerial' }]);
186
198
  });
187
199
 
@@ -192,14 +204,16 @@ describe('/v1/styles', () => {
192
204
  const res = await handler.router.handle(request);
193
205
  assert.equal(res.status, 200, res.statusDescription);
194
206
 
195
- const body = JSON.parse(Buffer.from(res.body, 'base64').toString());
207
+ const body = JSON.parse(Buffer.from(res.body, 'base64').toString()) as StyleJson;
196
208
 
197
209
  assert.equal(body.version, 8);
198
- assert.deepEqual(body.sources['basemaps-aerial'].type, 'raster');
199
- assert.deepEqual(body.sources['basemaps-aerial'].tiles, [
210
+ const aerialSource = body.sources['basemaps-aerial'] as unknown as SourceRaster;
211
+
212
+ assert.deepEqual(aerialSource.type, 'raster');
213
+ assert.deepEqual(aerialSource.tiles, [
200
214
  `https://tiles.test/v1/tiles/aerial/NZTM2000Quad/{z}/{x}/{y}.jpeg?api=${Api.key}`,
201
215
  ]);
202
- assert.deepEqual(body.sources['basemaps-aerial'].tileSize, 256);
216
+ assert.deepEqual(aerialSource.tileSize, 256);
203
217
  assert.deepEqual(body.layers, [{ id: 'basemaps-aerial', type: 'raster', source: 'basemaps-aerial' }]);
204
218
  });
205
219
 
@@ -210,14 +224,160 @@ describe('/v1/styles', () => {
210
224
  const res = await handler.router.handle(request);
211
225
  assert.equal(res.status, 200, res.statusDescription);
212
226
 
213
- const body = JSON.parse(Buffer.from(res.body, 'base64').toString());
227
+ const body = JSON.parse(Buffer.from(res.body, 'base64').toString()) as StyleJson;
228
+ body.sources['basemaps-aerial'];
229
+ body.sources['basemaps-aerial'];
230
+ body.sources['basemaps-aerial'];
231
+ const aerialSource = body.sources['basemaps-aerial'] as unknown as SourceRaster;
214
232
 
215
- assert.equal(body.version, 8);
216
- assert.deepEqual(body.sources['basemaps-aerial'].type, 'raster');
217
- assert.deepEqual(body.sources['basemaps-aerial'].tiles, [
233
+ assert.deepEqual(aerialSource.type, 'raster');
234
+ assert.deepEqual(aerialSource.tiles, [
218
235
  `https://tiles.test/v1/tiles/aerial/WebMercatorQuad/{z}/{x}/{y}.webp?api=${Api.key}&config=${configId}`,
219
236
  ]);
220
- assert.deepEqual(body.sources['basemaps-aerial'].tileSize, 256);
237
+ assert.deepEqual(aerialSource.tileSize, 256);
221
238
  assert.deepEqual(body.layers, [{ id: 'basemaps-aerial', type: 'raster', source: 'basemaps-aerial' }]);
222
239
  });
240
+
241
+ it('should create individual raster styles with terrain', async () => {
242
+ const configId = FakeData.bundle([FakeData.tileSetRaster('christchurch-urban-2020-2021-0.075m'), TileSetElevation]);
243
+ const request = mockUrlRequest(
244
+ '/v1/styles/christchurch-urban-2020-2021-0.075m.json',
245
+ `?config=${configId}`,
246
+ Api.header,
247
+ );
248
+
249
+ const res = await handler.router.handle(request);
250
+ assert.equal(res.status, 200, res.statusDescription);
251
+
252
+ const body = JSON.parse(Buffer.from(res.body, 'base64').toString()) as StyleJson;
253
+
254
+ assert.equal(body.version, 8);
255
+ const rasterSource = body.sources['basemaps-christchurch-urban-2020-2021-0.075m'] as unknown as SourceRaster;
256
+
257
+ assert.deepEqual(rasterSource.type, 'raster');
258
+ assert.deepEqual(rasterSource.tiles, [
259
+ `https://tiles.test/v1/tiles/christchurch-urban-2020-2021-0.075m/WebMercatorQuad/{z}/{x}/{y}.webp?api=${Api.key}&config=${configId}`,
260
+ ]);
261
+ assert.deepEqual(rasterSource.tileSize, 256);
262
+ assert.deepEqual(body.layers, [
263
+ {
264
+ id: 'basemaps-christchurch-urban-2020-2021-0.075m',
265
+ type: 'raster',
266
+ source: 'basemaps-christchurch-urban-2020-2021-0.075m',
267
+ },
268
+ ]);
269
+
270
+ const rasterDemSource = body.sources['LINZ-Terrain'] as unknown as SourceRaster;
271
+
272
+ assert.deepEqual(rasterDemSource.type, 'raster-dem');
273
+ assert.deepEqual(rasterDemSource.tiles, [
274
+ `https://tiles.test/v1/tiles/elevation/WebMercatorQuad/{z}/{x}/{y}.png?api=${Api.key}&config=${configId}&pipeline=terrain-rgb`,
275
+ ]);
276
+ });
277
+
278
+ const fakeVectorStyleConfig = {
279
+ id: 'test',
280
+ name: 'test',
281
+ sources: {
282
+ basemaps_vector: {
283
+ type: 'vector',
284
+ url: `/vector`,
285
+ },
286
+ },
287
+ layers: [
288
+ {
289
+ layout: {
290
+ visibility: 'visible',
291
+ },
292
+ paint: {
293
+ 'background-color': 'rgba(206, 229, 242, 1)',
294
+ },
295
+ id: 'Background1',
296
+ type: 'background',
297
+ minzoom: 0,
298
+ },
299
+ ],
300
+ };
301
+
302
+ const fakeVectorRecord = {
303
+ id: 'st_topolite',
304
+ name: 'topolite',
305
+ style: fakeVectorStyleConfig,
306
+ };
307
+
308
+ it('should ensure terrain for all style config', async () => {
309
+ const request = mockUrlRequest('/v1/styles/topolite.json', '?terrain=LINZ-Terrain', Api.header);
310
+ config.put(fakeVectorRecord);
311
+ config.put(TileSetElevation);
312
+
313
+ const res = await handler.router.handle(request);
314
+ assert.equal(res.status, 200, res.statusDescription);
315
+
316
+ const body = JSON.parse(Buffer.from(res.body, 'base64').toString()) as StyleJson;
317
+ const rasterDemSource = body.sources['LINZ-Terrain'] as unknown as SourceRaster;
318
+
319
+ assert.deepEqual(rasterDemSource.type, 'raster-dem');
320
+ assert.deepEqual(rasterDemSource.tiles, [
321
+ `https://tiles.test/v1/tiles/elevation/WebMercatorQuad/{z}/{x}/{y}.png?api=${Api.key}&pipeline=terrain-rgb`,
322
+ ]);
323
+ });
324
+
325
+ const fakeAerialStyleConfig = {
326
+ id: 'test',
327
+ name: 'test',
328
+ sources: {
329
+ basemaps_raster: {
330
+ type: 'raster',
331
+ tiles: [`/raster/{z}/{x}/{y}.webp`],
332
+ },
333
+ basemaps_terrain: {
334
+ type: 'raster-dem',
335
+ tiles: [`/elevation/{z}/{x}/{y}.png?pipeline=terrain-rgb`],
336
+ },
337
+ },
338
+ layers: [
339
+ {
340
+ layout: {
341
+ visibility: 'visible',
342
+ },
343
+ paint: {
344
+ 'background-color': 'rgba(206, 229, 242, 1)',
345
+ },
346
+ id: 'Background1',
347
+ type: 'background',
348
+ minzoom: 0,
349
+ },
350
+ ],
351
+ };
352
+
353
+ const fakeAerialRecord = {
354
+ id: 'st_aerial',
355
+ name: 'aerial',
356
+ style: fakeAerialStyleConfig,
357
+ };
358
+
359
+ it('should set terrain via parameter for style config', async () => {
360
+ const request = mockUrlRequest('/v1/styles/aerial.json', '?terrain=basemaps_terrain', Api.header);
361
+ config.put(fakeAerialRecord);
362
+ const res = await handler.router.handle(request);
363
+ assert.equal(res.status, 200, res.statusDescription);
364
+
365
+ const body = JSON.parse(Buffer.from(res.body, 'base64').toString()) as StyleJson;
366
+ const terrain = body.terrain as unknown as Terrain;
367
+ assert.deepEqual(terrain.source, 'basemaps_terrain');
368
+ assert.deepEqual(terrain.exaggeration, 1.2);
369
+ });
370
+
371
+ it('should set terrain via parameter for tileSet config', async () => {
372
+ config.put(TileSetAerial);
373
+ config.put(TileSetElevation);
374
+ const request = mockUrlRequest('/v1/styles/aerial.json', `?terrain=LINZ-Terrain`, Api.header);
375
+ const res = await handler.router.handle(request);
376
+ assert.equal(res.status, 200, res.statusDescription);
377
+
378
+ const body = JSON.parse(Buffer.from(res.body, 'base64').toString()) as StyleJson;
379
+ const terrain = body.terrain as unknown as Terrain;
380
+ assert.deepEqual(terrain.source, 'LINZ-Terrain');
381
+ assert.deepEqual(terrain.exaggeration, 1.2);
382
+ });
223
383
  });
@@ -4,7 +4,7 @@ import { afterEach, beforeEach, describe, it } from 'node:test';
4
4
  import { ConfigProviderMemory, ConfigTileSetRaster } from '@basemaps/config';
5
5
  import { Env } from '@basemaps/shared';
6
6
 
7
- import { Imagery2193, Imagery3857, Provider, TileSetAerial } from '../../__tests__/config.data.js';
7
+ import { Imagery2193, Imagery3857, Provider, TileSetAerial, TileSetElevation } from '../../__tests__/config.data.js';
8
8
  import { Api, mockUrlRequest } from '../../__tests__/xyz.util.js';
9
9
  import { handler } from '../../index.js';
10
10
  import { ConfigLoader } from '../../util/config.loader.js';
@@ -27,6 +27,28 @@ describe('WMTSRouting', () => {
27
27
  config.objects.clear();
28
28
  });
29
29
 
30
+ it('should support pipeline', async (t) => {
31
+ t.mock.method(Env, 'get', (arg: string) => {
32
+ if (arg === Env.PublicUrlBase) return 'https://tiles.test';
33
+ return process.env[arg];
34
+ });
35
+ config.put(TileSetElevation);
36
+ t.mock.method(ConfigLoader, 'load', () => Promise.resolve(config));
37
+ const req = mockUrlRequest(
38
+ '/v1/tiles/elevation/WebMercatorQuad/WMTSCapabilities.xml',
39
+ `tileFormat=png&api=${Api.key}&config=s3://linz-basemaps/config.json&pipeline=terrain-rgb`,
40
+ );
41
+ const res = await handler.router.handle(req);
42
+
43
+ assert.equal(res.status, 200);
44
+ const lines = Buffer.from(res.body, 'base64').toString().split('\n');
45
+ const resourceUrl = lines.find((f) => f.includes('ResourceURL'))?.trim();
46
+
47
+ assert.ok(resourceUrl);
48
+ assert.ok(resourceUrl.includes('amp;pipeline=terrain-rgb'), `includes pipeline=terrain-rgb in ${resourceUrl}`);
49
+ assert.ok(resourceUrl.includes('.png'), `includes .png in ${resourceUrl}`);
50
+ });
51
+
30
52
  it('should default to the aerial layer', async (t) => {
31
53
  t.mock.method(Env, 'get', (arg: string) => {
32
54
  if (arg === Env.PublicUrlBase) return 'https://tiles.test';
@@ -68,8 +90,6 @@ describe('WMTSRouting', () => {
68
90
 
69
91
  config.put({ ...TileSetAerial, id: 'ts_all', name: 'all', layers: [] } as ConfigTileSetRaster);
70
92
 
71
- config.createVirtualTileSets;
72
-
73
93
  const req = mockUrlRequest(
74
94
  '/v1/tiles/all/WMTSCapabilities.xml',
75
95
  `format=png&api=${Api.key}&config=s3://linz-basemaps/config.json`,
@@ -6,7 +6,7 @@ import { ConfigLoader } from '../util/config.loader.js';
6
6
  import { Etag } from '../util/etag.js';
7
7
  import { NotFound, NotModified } from '../util/response.js';
8
8
 
9
- async function sendJson(req: LambdaHttpRequest, toSend: unknown): Promise<LambdaHttpResponse> {
9
+ function sendJson(req: LambdaHttpRequest, toSend: unknown): LambdaHttpResponse {
10
10
  const data = Buffer.from(JSON.stringify(toSend));
11
11
 
12
12
  const cacheKey = Etag.key(data);
@@ -3,6 +3,6 @@ import { HttpHeader, LambdaHttpResponse } from '@linzjs/lambda';
3
3
  const OkResponse = new LambdaHttpResponse(200, 'ok');
4
4
  OkResponse.header(HttpHeader.CacheControl, 'no-store');
5
5
 
6
- export async function pingGet(): Promise<LambdaHttpResponse> {
7
- return OkResponse;
6
+ export function pingGet(): Promise<LambdaHttpResponse> {
7
+ return Promise.resolve(OkResponse);
8
8
  }
@@ -1,6 +1,7 @@
1
1
  import { promisify } from 'node:util';
2
2
  import { gunzip } from 'node:zlib';
3
3
 
4
+ import { TileSetType } from '@basemaps/config';
4
5
  import { GoogleTms, LocationUrl, LonLatZoom, TileMatrixSets } from '@basemaps/geo';
5
6
  import { Env, fsa, getPreviewQuery } from '@basemaps/shared';
6
7
  import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
@@ -95,7 +96,7 @@ export async function previewIndexGet(req: LambdaHttpRequest<PreviewIndexGet>):
95
96
  const tileSet = await config.TileSet.get(config.TileSet.id(query.style));
96
97
  req.timer.end('tileset:load');
97
98
  if (tileSet == null) return loadAndServeIndexHtml(req, loc);
98
- if (tileSet.type !== 'raster') return loadAndServeIndexHtml(req, loc);
99
+ if (tileSet.type !== TileSetType.Raster) return loadAndServeIndexHtml(req, loc);
99
100
 
100
101
  let tileMatrix = TileMatrixSets.find(query.tileMatrix);
101
102
  if (tileMatrix == null) tileMatrix = GoogleTms;
@@ -1,4 +1,4 @@
1
- import { ConfigTileSetRaster, ConfigTileSetRasterOutput } from '@basemaps/config';
1
+ import { ConfigTileSetRaster, ConfigTileSetRasterOutput, TileSetType } from '@basemaps/config';
2
2
  import { Bounds, LatLon, Projection, TileMatrixSet } from '@basemaps/geo';
3
3
  import { CompositionTiff, TileMakerContext, Tiler } from '@basemaps/tiler';
4
4
  import { SharpOverlay, TileMakerSharp } from '@basemaps/tiler-sharp';
@@ -62,7 +62,7 @@ export async function tilePreviewGet(req: LambdaHttpRequest<PreviewGet>): Promis
62
62
  req.timer.end('tileset:load');
63
63
  if (tileSet == null) return new LambdaHttpResponse(404, 'Tileset not found');
64
64
  // Only raster previews are supported
65
- if (tileSet.type !== 'raster') return new LambdaHttpResponse(404, 'Preview invalid tile set type');
65
+ if (tileSet.type !== TileSetType.Raster) return new LambdaHttpResponse(404, 'Preview invalid tile set type');
66
66
 
67
67
  const pipeline = req.query.get('pipeline');
68
68
 
@@ -161,6 +161,8 @@ export async function renderPreview(req: LambdaHttpRequest, ctx: PreviewRenderCo
161
161
 
162
162
  // Load all the tiff tiles and resize/them into the correct locations
163
163
  req.timer.start('compose:overlay');
164
+ // Remove with typescript >=5.5.0
165
+
164
166
  const overlays = (await Promise.all(
165
167
  compositions.map((comp) => {
166
168
  if (tileContext.pipeline) return TilerSharp.composeTilePipeline(comp, tileContext);
@@ -10,7 +10,7 @@ interface SpriteGet {
10
10
  };
11
11
  }
12
12
 
13
- const Extensions = new Map();
13
+ const Extensions = new Map<string, string>();
14
14
  Extensions.set('.png', 'image/png');
15
15
  Extensions.set('.json', 'application/json');
16
16