@basemaps/lambda-tiler 7.7.0 → 7.10.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 (51) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/build/__tests__/config.data.js +3 -3
  3. package/build/__tests__/config.data.js.map +1 -1
  4. package/build/__tests__/tile.style.json.test.js +13 -12
  5. package/build/__tests__/tile.style.json.test.js.map +1 -1
  6. package/build/routes/__tests__/health.test.js +40 -20
  7. package/build/routes/__tests__/health.test.js.map +1 -1
  8. package/build/routes/__tests__/tile.style.json.test.js +81 -0
  9. package/build/routes/__tests__/tile.style.json.test.js.map +1 -1
  10. package/build/routes/__tests__/xyz.test.js +13 -0
  11. package/build/routes/__tests__/xyz.test.js.map +1 -1
  12. package/build/routes/health.d.ts +17 -0
  13. package/build/routes/health.js +119 -21
  14. package/build/routes/health.js.map +1 -1
  15. package/build/routes/tile.style.json.d.ts +36 -8
  16. package/build/routes/tile.style.json.js +144 -128
  17. package/build/routes/tile.style.json.js.map +1 -1
  18. package/build/routes/tile.xyz.raster.js.map +1 -1
  19. package/build/routes/tile.xyz.vector.js +9 -9
  20. package/build/routes/tile.xyz.vector.js.map +1 -1
  21. package/build/util/__test__/cache.test.d.ts +1 -0
  22. package/build/util/__test__/cache.test.js +29 -0
  23. package/build/util/__test__/cache.test.js.map +1 -0
  24. package/build/util/__test__/nztm.style.test.d.ts +1 -0
  25. package/build/util/__test__/nztm.style.test.js +87 -0
  26. package/build/util/__test__/nztm.style.test.js.map +1 -0
  27. package/build/util/nztm.style.d.ts +12 -0
  28. package/build/util/nztm.style.js +45 -0
  29. package/build/util/nztm.style.js.map +1 -0
  30. package/build/util/source.cache.d.ts +2 -8
  31. package/build/util/source.cache.js +6 -24
  32. package/build/util/source.cache.js.map +1 -1
  33. package/build/util/swapping.lru.d.ts +1 -0
  34. package/build/util/swapping.lru.js +4 -0
  35. package/build/util/swapping.lru.js.map +1 -1
  36. package/package.json +7 -6
  37. package/src/__tests__/config.data.ts +3 -3
  38. package/src/__tests__/tile.style.json.test.ts +16 -14
  39. package/src/routes/__tests__/health.test.ts +46 -22
  40. package/src/routes/__tests__/tile.style.json.test.ts +91 -0
  41. package/src/routes/__tests__/xyz.test.ts +18 -0
  42. package/src/routes/health.ts +129 -21
  43. package/src/routes/tile.style.json.ts +172 -149
  44. package/src/routes/tile.xyz.raster.ts +0 -1
  45. package/src/routes/tile.xyz.vector.ts +10 -6
  46. package/src/util/__test__/cache.test.ts +36 -0
  47. package/src/util/__test__/nztm.style.test.ts +100 -0
  48. package/src/util/nztm.style.ts +44 -0
  49. package/src/util/source.cache.ts +10 -20
  50. package/src/util/swapping.lru.ts +5 -0
  51. package/tsconfig.tsbuildinfo +1 -1
@@ -4,13 +4,15 @@ 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 { VectorTile, VectorTileFeature, VectorTileLayer } from '@mapbox/vector-tile';
7
8
  import { ALBEventRequestContext, Context } from 'aws-lambda';
8
9
  import sinon from 'sinon';
9
10
 
10
11
  import { FakeData } from '../../__tests__/config.data.js';
11
12
  import { ConfigLoader } from '../../util/config.loader.js';
12
- import { getTestBuffer, healthGet, TestTiles } from '../health.js';
13
+ import { getTestBuffer, healthGet, TestFeature, TestTiles, VectorTileProvider } from '../health.js';
13
14
  import { TileXyzRaster } from '../tile.xyz.raster.js';
15
+ import { tileXyzVector } from '../tile.xyz.vector.js';
14
16
 
15
17
  const ctx: LambdaHttpRequest = new LambdaAlbRequest(
16
18
  {
@@ -24,15 +26,38 @@ const ctx: LambdaHttpRequest = new LambdaAlbRequest(
24
26
  LogConfig.get(),
25
27
  );
26
28
 
29
+ // Function to create a vector tile with specific properties for testing
30
+ function createTestTile(testFeatures: TestFeature[]): VectorTile {
31
+ const layers: Record<string, VectorTileLayer> = {};
32
+ for (const testFeature of testFeatures) {
33
+ const layer = {
34
+ features: [{ properties: { [testFeature.key]: testFeature.value } }],
35
+
36
+ feature(i: number): VectorTileFeature {
37
+ return this.features[i] as VectorTileFeature;
38
+ },
39
+
40
+ get length(): number {
41
+ return this.features.length;
42
+ },
43
+ };
44
+
45
+ layers[testFeature.layer] = layer as unknown as VectorTileLayer;
46
+ }
47
+ return { layers } as unknown as VectorTile;
48
+ }
49
+
27
50
  describe('/v1/health', () => {
28
51
  const sandbox = sinon.createSandbox();
29
52
  const config = new ConfigProviderMemory();
30
53
 
31
- const fakeTileSet = FakeData.tileSetRaster('health');
54
+ const fakeTileSetRaster = FakeData.tileSetRaster('health');
55
+ const fakeTileSetVector = FakeData.tileSetVector('topographic');
32
56
  beforeEach(() => {
33
57
  config.objects.clear();
34
58
  sandbox.stub(ConfigLoader, 'getDefaultConfig').resolves(config);
35
- config.put(fakeTileSet);
59
+ config.put(fakeTileSetRaster);
60
+ config.put(fakeTileSetVector);
36
61
  });
37
62
 
38
63
  afterEach(() => {
@@ -40,17 +65,14 @@ describe('/v1/health', () => {
40
65
  sandbox.restore();
41
66
  });
42
67
 
43
- it('Should return bad response', async () => {
68
+ it('Should return bad response', () => {
44
69
  // Given ... a bad get tile response
45
70
  const BadResponse = new LambdaHttpResponse(500, 'Can not get Tile Set.');
46
71
  sandbox.stub(TileXyzRaster, 'tile').resolves(BadResponse);
72
+ sandbox.stub(tileXyzVector, 'tile').resolves(BadResponse);
47
73
 
48
- // When ...
49
- const res = await healthGet(ctx);
50
-
51
- // Then ...
52
- assert.equal(res.status, 500);
53
- assert.equal(res.statusDescription, 'Can not get Tile Set.');
74
+ // When ...Then ...
75
+ assert.rejects(() => healthGet(ctx), BadResponse);
54
76
  });
55
77
 
56
78
  const Response1 = new LambdaHttpResponse(200, 'ok');
@@ -66,9 +88,15 @@ describe('/v1/health', () => {
66
88
 
67
89
  it('Should give a 200 response', async () => {
68
90
  // Given ... a series good get tile response
69
- const callback = sandbox.stub(TileXyzRaster, 'tile');
70
- callback.onCall(0).resolves(Response1);
71
- callback.onCall(1).resolves(Response2);
91
+ const callbackRaster = sandbox.stub(TileXyzRaster, 'tile');
92
+
93
+ callbackRaster.onCall(0).resolves(Response1);
94
+ callbackRaster.onCall(1).resolves(Response2);
95
+ const callbackVectorTile = sandbox.stub(VectorTileProvider, 'getVectorTile');
96
+ const testVectorTile1 = createTestTile(TestTiles[2].testFeatures!);
97
+ const testVectorTile2 = createTestTile(TestTiles[3].testFeatures!);
98
+ callbackVectorTile.onCall(0).resolves(testVectorTile1);
99
+ callbackVectorTile.onCall(1).resolves(testVectorTile2);
72
100
 
73
101
  // When ...
74
102
  const res = await healthGet(ctx);
@@ -78,17 +106,13 @@ describe('/v1/health', () => {
78
106
  assert.equal(res.statusDescription, 'ok');
79
107
  });
80
108
 
81
- it('Should return mis-match tile response', async () => {
109
+ it('Should return mis-match tile response', () => {
82
110
  // Given ... a bad get tile response for second get tile
83
111
  const callback = sandbox.stub(TileXyzRaster, 'tile');
84
- callback.onCall(0).resolves(Response1);
85
- callback.onCall(1).resolves(Response1);
112
+ callback.onCall(0).resolves(Response2);
86
113
 
87
- // When ...
88
- const res = await healthGet(ctx);
89
-
90
- // Then ...
91
- assert.equal(res.status, 500);
92
- assert.equal(res.statusDescription, 'TileSet does not match.');
114
+ // When ... Then ...
115
+ const BadResponse = new LambdaHttpResponse(500, 'TileSet does not match.');
116
+ assert.rejects(() => healthGet(ctx), BadResponse);
93
117
  });
94
118
  });
@@ -380,4 +380,95 @@ describe('/v1/styles', () => {
380
380
  assert.deepEqual(terrain.source, 'LINZ-Terrain');
381
381
  assert.deepEqual(terrain.exaggeration, 1.2);
382
382
  });
383
+
384
+ it('should set labels via parameter', async () => {
385
+ config.put(TileSetAerial);
386
+ config.put(TileSetElevation);
387
+
388
+ const fakeStyle = { id: 'st_labels', name: 'labels', style: fakeVectorStyleConfig };
389
+ config.put(fakeStyle);
390
+
391
+ const request = mockUrlRequest('/v1/styles/aerial.json', `?terrain=LINZ-Terrain&labels=true`, Api.header);
392
+ const res = await handler.router.handle(request);
393
+ assert.equal(res.status, 200, res.statusDescription);
394
+
395
+ const body = JSON.parse(Buffer.from(res.body, 'base64').toString()) as StyleJson;
396
+ const terrain = body.terrain as unknown as Terrain;
397
+ assert.deepEqual(terrain.source, 'LINZ-Terrain');
398
+ assert.deepEqual(terrain.exaggeration, 1.2);
399
+
400
+ assert.equal(body.sources['basemaps_vector']?.type, 'vector');
401
+ assert.equal(body.layers.length, 2);
402
+ });
403
+
404
+ it('should error when joining layers with duplicate ids', async () => {
405
+ const fakeStyle = { id: 'st_labels', name: 'labels', style: fakeVectorStyleConfig };
406
+ config.put(fakeStyle);
407
+ config.put(TileSetAerial);
408
+
409
+ const request = mockUrlRequest('/v1/styles/labels.json', `?labels=true`, Api.header);
410
+ const res = await handler.router.handle(request);
411
+ assert.equal(res.status, 400, res.statusDescription);
412
+ assert.equal(res.statusDescription.includes('Background1'), true);
413
+ });
414
+
415
+ it('should convert NZTM2000Quad styles', async () => {
416
+ const fakeStyle = {
417
+ id: 'st_labels',
418
+ name: 'source',
419
+ style: {
420
+ layers: [
421
+ {
422
+ minzoom: 5,
423
+ maxzoom: 5,
424
+ layout: {
425
+ 'line-width': {
426
+ stops: [
427
+ [16, 0.75],
428
+ [24, 1.5],
429
+ ],
430
+ },
431
+ },
432
+
433
+ paint: {
434
+ 'line-width': {
435
+ stops: [
436
+ [16, 0.75],
437
+ [24, 1.5],
438
+ ],
439
+ },
440
+ },
441
+ },
442
+ ],
443
+ terrain: {
444
+ exaggeration: 1.1,
445
+ },
446
+ },
447
+ };
448
+ config.put(fakeStyle);
449
+
450
+ const request = mockUrlRequest('/v1/styles/labels.json', `?tileMatrix=NZTM2000Quad`, Api.header);
451
+ const res = await handler.router.handle(request);
452
+ assert.equal(res.status, 200, res.statusDescription);
453
+ const style = JSON.parse(Buffer.from(res.body, 'base64').toString()) as StyleJson;
454
+ assert.equal(style.layers[0].minzoom, 3);
455
+ assert.equal(style.layers[0].maxzoom, 3);
456
+ assert.equal(style.terrain?.exaggeration, 4.4);
457
+ assert.deepEqual(style.layers[0].layout, {
458
+ 'line-width': {
459
+ stops: [
460
+ [14, 0.75],
461
+ [22, 1.5],
462
+ ],
463
+ },
464
+ });
465
+ assert.deepEqual(style.layers[0].paint, {
466
+ 'line-width': {
467
+ stops: [
468
+ [14, 0.75],
469
+ [22, 1.5],
470
+ ],
471
+ },
472
+ });
473
+ });
383
474
  });
@@ -10,6 +10,7 @@ import { Api, mockRequest, mockUrlRequest } from '../../__tests__/xyz.util.js';
10
10
  import { handler } from '../../index.js';
11
11
  import { ConfigLoader } from '../../util/config.loader.js';
12
12
  import { Etag } from '../../util/etag.js';
13
+ import { CoSources } from '../../util/source.cache.js';
13
14
 
14
15
  const TileSetNames = ['aerial', 'aerial:ōtorohanga_urban_2021_0-1m_RGB', '01FYWKAJ86W9P7RWM1VB62KD0H'];
15
16
  describe('/v1/tiles', () => {
@@ -197,4 +198,21 @@ describe('/v1/tiles', () => {
197
198
  );
198
199
  assert.equal(resZz.status, 400, resZz.statusDescription);
199
200
  });
201
+
202
+ it('should support NZTM2000Quad vector tiles', async (t) => {
203
+ t.mock.method(ConfigLoader, 'getDefaultConfig', () => Promise.resolve(config));
204
+
205
+ // Force resolve a basic tile
206
+ const mockGetTile = t.mock.fn(() => Promise.resolve(Buffer.from('ABC123')));
207
+ t.mock.method(CoSources, 'getCotar', () => Promise.resolve({ get: mockGetTile }));
208
+
209
+ const topographic = FakeData.tileSetVector('topographic');
210
+ topographic.layers[0][2193] = 'memory://fake-tiles.tar.co';
211
+ config.put(topographic);
212
+ const resPbf = await handler.router.handle(
213
+ mockUrlRequest('/v1/tiles/topographic/NZTM2000Quad/11/2022/1283.pbf', 'get', Api.header),
214
+ );
215
+ assert.equal(resPbf.status, 200);
216
+ assert.equal(resPbf.body, Buffer.from('ABC123').toString('base64'));
217
+ });
200
218
  });
@@ -1,23 +1,67 @@
1
1
  import * as fs from 'node:fs';
2
2
 
3
- import { ConfigTileSetRaster } from '@basemaps/config';
3
+ import { ConfigTileSetRaster, ConfigTileSetVector, TileSetType } from '@basemaps/config';
4
4
  import { GoogleTms, Nztm2000QuadTms } from '@basemaps/geo';
5
5
  import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
6
+ import { VectorTile } from '@mapbox/vector-tile';
7
+ import Protobuf from 'pbf';
6
8
  import PixelMatch from 'pixelmatch';
7
9
  import Sharp from 'sharp';
10
+ import { gunzipSync } from 'zlib';
8
11
 
9
12
  import { ConfigLoader } from '../util/config.loader.js';
13
+ import { isGzip } from '../util/cotar.serve.js';
10
14
  import { TileXyz } from '../util/validate.js';
11
15
  import { TileXyzRaster } from './tile.xyz.raster.js';
16
+ import { tileXyzVector } from './tile.xyz.vector.js';
17
+
18
+ /**
19
+ * Vector feature that need to check existence
20
+ */
21
+ export interface TestFeature {
22
+ layer: string;
23
+ key: string;
24
+ value: string;
25
+ }
12
26
 
13
27
  interface TestTile extends TileXyz {
14
28
  buf?: Buffer;
29
+ testFeatures?: TestFeature[];
15
30
  }
16
31
 
17
32
  export const TestTiles: TestTile[] = [
18
33
  { tileSet: 'health', tileMatrix: GoogleTms, tileType: 'png', tile: { x: 252, y: 156, z: 8 } },
19
34
  { tileSet: 'health', tileMatrix: Nztm2000QuadTms, tileType: 'png', tile: { x: 30, y: 33, z: 6 } },
35
+ {
36
+ tileSet: 'topographic',
37
+ tileMatrix: GoogleTms,
38
+ tileType: 'pbf',
39
+ tile: { x: 1009, y: 641, z: 10 },
40
+ testFeatures: [
41
+ { layer: 'aeroway', key: 'name', value: 'Wellington Airport' },
42
+ { layer: 'place', key: 'name', value: 'Wellington' },
43
+ { layer: 'coastline', key: 'class', value: 'coastline' },
44
+ { layer: 'landcover', key: 'class', value: 'grass' },
45
+ { layer: 'poi', key: 'name', value: 'Seatoun Wharf' },
46
+ { layer: 'transportation', key: 'name', value: 'Mt Victoria Tunnel' },
47
+ ],
48
+ },
49
+ {
50
+ tileSet: 'topographic',
51
+ tileMatrix: GoogleTms,
52
+ tileType: 'pbf',
53
+ tile: { x: 62, y: 40, z: 6 },
54
+ testFeatures: [
55
+ { layer: 'landuse', key: 'name', value: 'Queenstown' },
56
+ { layer: 'place', key: 'name', value: 'Christchurch' },
57
+ { layer: 'water', key: 'name', value: 'Tasman Lake' },
58
+ { layer: 'coastline', key: 'class', value: 'coastline' },
59
+ { layer: 'landcover', key: 'class', value: 'wood' },
60
+ { layer: 'transportation', key: 'name', value: 'STATE HIGHWAY 6' },
61
+ ],
62
+ },
20
63
  ];
64
+
21
65
  const TileSize = 256;
22
66
 
23
67
  export async function getTestBuffer(test: TestTile): Promise<Buffer> {
@@ -40,6 +84,82 @@ export async function updateExpectedTile(test: TestTile, newTileData: Buffer, di
40
84
  await fs.promises.writeFile(`${expectedFileName}.diff.png`, imgPng);
41
85
  }
42
86
 
87
+ /**
88
+ * Compare and validate the raster test tile from server with pixel match
89
+ */
90
+ async function validateRasterTile(tileSet: ConfigTileSetRaster, test: TestTile, req: LambdaHttpRequest): Promise<void> {
91
+ // Get the parse response tile to raw buffer
92
+ const response = await TileXyzRaster.tile(req, tileSet, test);
93
+ if (response.status !== 200) throw new LambdaHttpResponse(500, response.statusDescription);
94
+ if (!Buffer.isBuffer(response._body)) throw new LambdaHttpResponse(500, 'Not a Buffer response content.');
95
+ const resImgBuffer = await Sharp(response._body).raw().toBuffer();
96
+
97
+ // Get test tile to compare
98
+ const testBuffer = await getTestBuffer(test);
99
+ test.buf = testBuffer;
100
+ const testImgBuffer = await Sharp(testBuffer).raw().toBuffer();
101
+
102
+ const outputBuffer = Buffer.alloc(testImgBuffer.length);
103
+ const missMatchedPixels = PixelMatch(testImgBuffer, resImgBuffer, outputBuffer, TileSize, TileSize);
104
+ if (missMatchedPixels) {
105
+ /** Uncomment this to overwite the expected files */
106
+ // await updateExpectedTile(test, response._body as Buffer, outputBuffer);
107
+ req.log.error({ missMatchedPixels, projection: test.tileMatrix.identifier, xyz: test.tile }, 'Health:MissMatch');
108
+ throw new LambdaHttpResponse(500, 'TileSet does not match.');
109
+ }
110
+ }
111
+
112
+ function checkFeatureExists(tile: VectorTile, testFeature: TestFeature): boolean {
113
+ const layer = tile.layers[testFeature.layer];
114
+ for (let i = 0; i < layer.length; i++) {
115
+ const feature = layer.feature(i);
116
+ if (feature.properties[testFeature.key] === testFeature.value) return true;
117
+ }
118
+ return false;
119
+ }
120
+
121
+ /**
122
+ * Fetch vector tile and decode into mapbox VectorTile
123
+ */
124
+ export const VectorTileProvider = {
125
+ async getVectorTile(tileSet: ConfigTileSetVector, test: TestTile, req: LambdaHttpRequest): Promise<VectorTile> {
126
+ // Get the parse response tile to raw buffer
127
+ const response = await tileXyzVector.tile(req, tileSet, test);
128
+ if (response.status !== 200) throw new LambdaHttpResponse(500, response.statusDescription);
129
+ if (!Buffer.isBuffer(response._body)) throw new LambdaHttpResponse(500, 'Not a Buffer response content.');
130
+ const buffer = isGzip(response._body) ? gunzipSync(response._body) : response._body;
131
+ return new VectorTile(new Protobuf(buffer));
132
+ },
133
+ };
134
+
135
+ /**
136
+ * Check the existence of a feature property in side the vector tile
137
+ *
138
+ * @throws LambdaHttpResponse if any test feature not found from vector tile
139
+ */
140
+ function featureCheck(tile: VectorTile, testTile: TestTile): void {
141
+ const testTileName = `${testTile.tileSet}-${testTile.tile.x}/${testTile.tile.y}/z${testTile.tile.z}`;
142
+ if (testTile.testFeatures == null) {
143
+ throw new LambdaHttpResponse(500, `No test feature found from testTile: ${testTileName}`);
144
+ }
145
+ for (const testFeature of testTile.testFeatures) {
146
+ if (!checkFeatureExists(tile, testFeature)) {
147
+ throw new LambdaHttpResponse(500, `Failed to validate tile: ${testTileName} for layer: ${testFeature.layer}.`);
148
+ }
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Health check the test vector tiles that contains all the expected features.
154
+ *
155
+ * @throws LambdaHttpResponse if test tiles not returned or features not exists
156
+ */
157
+ async function validateVectorTile(tileSet: ConfigTileSetVector, test: TestTile, req: LambdaHttpRequest): Promise<void> {
158
+ // Get the parse response tile to raw buffer
159
+ const tile = await VectorTileProvider.getVectorTile(tileSet, test, req);
160
+ featureCheck(tile, test);
161
+ }
162
+
43
163
  /**
44
164
  * Health request get health TileSets and validate with test TileSets
45
165
  * - Valid response from get heath tile request
@@ -49,27 +169,15 @@ export async function updateExpectedTile(test: TestTile, newTileData: Buffer, di
49
169
  */
50
170
  export async function healthGet(req: LambdaHttpRequest): Promise<LambdaHttpResponse> {
51
171
  const config = await ConfigLoader.load(req);
52
- const tileSet = await config.TileSet.get(config.TileSet.id('health'));
53
- if (tileSet == null) throw new LambdaHttpResponse(500, 'TileSet: "health" not found');
54
172
  for (const test of TestTiles) {
55
- // Get the parse response tile to raw buffer
56
- const response = await TileXyzRaster.tile(req, tileSet as ConfigTileSetRaster, test);
57
- if (response.status !== 200) return new LambdaHttpResponse(500, response.statusDescription);
58
- if (!Buffer.isBuffer(response._body)) throw new LambdaHttpResponse(500, 'Not a Buffer response content.');
59
- const resImgBuffer = await Sharp(response._body).raw().toBuffer();
60
-
61
- // Get test tile to compare
62
- const testBuffer = await getTestBuffer(test);
63
- test.buf = testBuffer;
64
- const testImgBuffer = await Sharp(testBuffer).raw().toBuffer();
65
-
66
- const outputBuffer = Buffer.alloc(testImgBuffer.length);
67
- const missMatchedPixels = PixelMatch(testImgBuffer, resImgBuffer, outputBuffer, TileSize, TileSize);
68
- if (missMatchedPixels) {
69
- /** Uncomment this to overwite the expected files */
70
- // await updateExpectedTile(test, response._body as Buffer, outputBuffer);
71
- req.log.error({ missMatchedPixels, projection: test.tileMatrix.identifier, xyz: test.tile }, 'Health:MissMatch');
72
- return new LambdaHttpResponse(500, 'TileSet does not match.');
173
+ const tileSet = await config.TileSet.get(config.TileSet.id(test.tileSet));
174
+ if (tileSet == null) throw new LambdaHttpResponse(500, `TileSet: ${test.tileSet} not found`);
175
+ if (tileSet.type === TileSetType.Raster) {
176
+ await validateRasterTile(tileSet, test, req);
177
+ } else if (tileSet.type === TileSetType.Vector) {
178
+ await validateVectorTile(tileSet, test, req);
179
+ } else {
180
+ throw new LambdaHttpResponse(500, `Invalid TileSet type for tileSet ${test.tileSet}`);
73
181
  }
74
182
  }
75
183