@basemaps/lambda-tiler 7.7.0 → 7.9.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.
- package/CHANGELOG.md +19 -0
- package/build/__tests__/config.data.js +3 -3
- package/build/__tests__/config.data.js.map +1 -1
- package/build/__tests__/tile.style.json.test.js +0 -5
- package/build/__tests__/tile.style.json.test.js.map +1 -1
- package/build/routes/__tests__/tile.style.json.test.js +24 -0
- package/build/routes/__tests__/tile.style.json.test.js.map +1 -1
- package/build/routes/tile.style.json.d.ts +8 -2
- package/build/routes/tile.style.json.js +55 -24
- package/build/routes/tile.style.json.js.map +1 -1
- package/build/routes/tile.xyz.raster.js.map +1 -1
- package/build/util/__test__/cache.test.d.ts +1 -0
- package/build/util/__test__/cache.test.js +29 -0
- package/build/util/__test__/cache.test.js.map +1 -0
- package/build/util/source.cache.d.ts +2 -8
- package/build/util/source.cache.js +6 -24
- package/build/util/source.cache.js.map +1 -1
- package/build/util/swapping.lru.d.ts +1 -0
- package/build/util/swapping.lru.js +4 -0
- package/build/util/swapping.lru.js.map +1 -1
- package/package.json +4 -4
- package/src/__tests__/config.data.ts +3 -3
- package/src/__tests__/tile.style.json.test.ts +0 -7
- package/src/routes/__tests__/tile.style.json.test.ts +31 -0
- package/src/routes/tile.style.json.ts +59 -22
- package/src/routes/tile.xyz.raster.ts +0 -1
- package/src/util/__test__/cache.test.ts +36 -0
- package/src/util/source.cache.ts +10 -20
- package/src/util/swapping.lru.ts +5 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"swapping.lru.js","sourceRoot":"","sources":["../../src/util/swapping.lru.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,WAAW;IAYtB,YAAY,OAAe;QAX3B;;;;mBAAyB,IAAI,GAAG,EAAE;WAAC;QACnC;;;;mBAAyB,IAAI,GAAG,EAAE;WAAC;QACnC;;;;;WAAgB;QAEhB;;;;mBAAO,CAAC;WAAC;QACT;;;;mBAAS,CAAC;WAAC;QACX;;;;mBAAS,CAAC;WAAC;QACX;;;;mBAAS,CAAC;WAAC;QAEX;;;;mBAAiB,CAAC,CAAC;WAAC;QAGlB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,0DAA0D;QAC1D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,sBAAsB;IACtB,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,GAAG,CAAC,EAAU,EAAE,IAAO;QACrB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAED,sDAAsD;IACtD,KAAK;QACH,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC;YAAE,OAAO;QAC9B,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,qFAAqF;QACrF,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YAChB,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;IAC1B,CAAC;IAED,6DAA6D;IAC7D,IAAI,WAAW;QACb,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YAAE,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;QAC7D,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"swapping.lru.js","sourceRoot":"","sources":["../../src/util/swapping.lru.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,WAAW;IAYtB,YAAY,OAAe;QAX3B;;;;mBAAyB,IAAI,GAAG,EAAE;WAAC;QACnC;;;;mBAAyB,IAAI,GAAG,EAAE;WAAC;QACnC;;;;;WAAgB;QAEhB;;;;mBAAO,CAAC;WAAC;QACT;;;;mBAAS,CAAC;WAAC;QACX;;;;mBAAS,CAAC;WAAC;QACX;;;;mBAAS,CAAC;WAAC;QAEX;;;;mBAAiB,CAAC,CAAC;WAAC;QAGlB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnC,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,0DAA0D;QAC1D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,sBAAsB;IACtB,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,EAAU;QACf,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACvB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACzB,CAAC;IAED,GAAG,CAAC,EAAU,EAAE,IAAO;QACrB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAED,sDAAsD;IACtD,KAAK;QACH,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC;YAAE,OAAO;QAC9B,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QAC7C,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,qFAAqF;QACrF,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YAChB,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;IAC1B,CAAC;IAED,6DAA6D;IAC7D,IAAI,WAAW;QACb,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YAAE,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC;QAC7D,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basemaps/lambda-tiler",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.9.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/linz/basemaps.git",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@basemaps/config": "^7.7.0",
|
|
26
|
-
"@basemaps/config-loader": "^7.
|
|
26
|
+
"@basemaps/config-loader": "^7.9.0",
|
|
27
27
|
"@basemaps/geo": "^7.5.0",
|
|
28
|
-
"@basemaps/shared": "^7.
|
|
28
|
+
"@basemaps/shared": "^7.9.0",
|
|
29
29
|
"@basemaps/tiler": "^7.5.0",
|
|
30
30
|
"@basemaps/tiler-sharp": "^7.7.0",
|
|
31
31
|
"@linzjs/geojson": "^7.5.0",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"@types/pixelmatch": "^5.0.0",
|
|
56
56
|
"pretty-json-log": "^1.0.0"
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "5dc4332d74563f6ca6ac644258728eb64ceacf6a"
|
|
59
59
|
}
|
|
@@ -33,9 +33,9 @@ export const TileSetAerial: ConfigTileSetRaster = {
|
|
|
33
33
|
export const TileSetVector: ConfigTileSetVector = {
|
|
34
34
|
id: 'ts_topographic',
|
|
35
35
|
type: TileSetType.Vector,
|
|
36
|
-
name: '
|
|
37
|
-
description: '
|
|
38
|
-
title: '
|
|
36
|
+
name: 'topographic',
|
|
37
|
+
description: 'topographic__description',
|
|
38
|
+
title: 'topographic Imagery',
|
|
39
39
|
category: 'Basemap',
|
|
40
40
|
layers: [
|
|
41
41
|
{
|
|
@@ -4,7 +4,6 @@ import { afterEach, beforeEach, describe, it } from 'node:test';
|
|
|
4
4
|
import { StyleJson } from '@basemaps/config';
|
|
5
5
|
import { GoogleTms, Nztm2000QuadTms } from '@basemaps/geo';
|
|
6
6
|
import { Env } from '@basemaps/shared';
|
|
7
|
-
import { LambdaHttpResponse } from '@linzjs/lambda';
|
|
8
7
|
|
|
9
8
|
import { convertRelativeUrl, convertStyleJson } from '../routes/tile.style.json.js';
|
|
10
9
|
|
|
@@ -153,12 +152,6 @@ describe('TileStyleJson', () => {
|
|
|
153
152
|
});
|
|
154
153
|
});
|
|
155
154
|
|
|
156
|
-
it('should thrown error for NZTM2000Quad with vector source', () => {
|
|
157
|
-
const converted = (): StyleJson => convertStyleJson(baseStyleJson, Nztm2000QuadTms, 'abc123', null);
|
|
158
|
-
|
|
159
|
-
assert.throws(converted, LambdaHttpResponse);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
155
|
it('should convert relative glyphs and sprites', () => {
|
|
163
156
|
const apiKey = '0x9f9f';
|
|
164
157
|
const converted = convertStyleJson(baseStyleJson, GoogleTms, apiKey, null);
|
|
@@ -380,4 +380,35 @@ 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
|
+
});
|
|
383
414
|
});
|
|
@@ -48,9 +48,6 @@ export function convertStyleJson(
|
|
|
48
48
|
const sources = JSON.parse(JSON.stringify(style.sources)) as Sources;
|
|
49
49
|
for (const [key, value] of Object.entries(sources)) {
|
|
50
50
|
if (value.type === 'vector') {
|
|
51
|
-
if (tileMatrix !== GoogleTms) {
|
|
52
|
-
throw new LambdaHttpResponse(400, `TileMatrix is not supported for the vector source ${value.url}.`);
|
|
53
|
-
}
|
|
54
51
|
value.url = convertRelativeUrl(value.url, tileMatrix, apiKey, config);
|
|
55
52
|
} else if ((value.type === 'raster' || value.type === 'raster-dem') && Array.isArray(value.tiles)) {
|
|
56
53
|
for (let i = 0; i < value.tiles.length; i++) {
|
|
@@ -72,6 +69,7 @@ export function convertStyleJson(
|
|
|
72
69
|
if (style.glyphs) styleJson.glyphs = convertRelativeUrl(style.glyphs, undefined, undefined, config);
|
|
73
70
|
if (style.sprite) styleJson.sprite = convertRelativeUrl(style.sprite, undefined, undefined, config);
|
|
74
71
|
if (style.sky) styleJson.sky = style.sky;
|
|
72
|
+
if (style.terrain) styleJson.terrain = style.terrain;
|
|
75
73
|
|
|
76
74
|
return styleJson;
|
|
77
75
|
}
|
|
@@ -82,6 +80,13 @@ export interface StyleGet {
|
|
|
82
80
|
};
|
|
83
81
|
}
|
|
84
82
|
|
|
83
|
+
export interface StyleConfig {
|
|
84
|
+
/** Name of the terrain layer */
|
|
85
|
+
terrain?: string | null;
|
|
86
|
+
/** Combine layer with the labels layer */
|
|
87
|
+
labels: boolean;
|
|
88
|
+
}
|
|
89
|
+
|
|
85
90
|
function setStyleTerrain(style: StyleJson, terrain: string, tileMatrix: TileMatrixSet): void {
|
|
86
91
|
const source = Object.keys(style.sources).find((s) => s === terrain);
|
|
87
92
|
if (source == null) throw new LambdaHttpResponse(400, `Terrain: ${terrain} is not exists in the style source.`);
|
|
@@ -91,6 +96,32 @@ function setStyleTerrain(style: StyleJson, terrain: string, tileMatrix: TileMatr
|
|
|
91
96
|
};
|
|
92
97
|
}
|
|
93
98
|
|
|
99
|
+
async function setStyleLabels(req: LambdaHttpRequest<StyleGet>, style: StyleJson): Promise<void> {
|
|
100
|
+
const config = await ConfigLoader.load(req);
|
|
101
|
+
const labels = await config.Style.get('labels');
|
|
102
|
+
|
|
103
|
+
if (labels == null) {
|
|
104
|
+
req.log.warn('LabelsStyle:Missing');
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const layerId = new Set<string>();
|
|
109
|
+
for (const l of style.layers) layerId.add(l.id);
|
|
110
|
+
|
|
111
|
+
for (const newLayers of labels.style.layers) {
|
|
112
|
+
if (layerId.has(newLayers.id)) {
|
|
113
|
+
throw new LambdaHttpResponse(400, 'Cannot merge styles with duplicate layerIds: ' + newLayers.id);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (style.glyphs == null) style.glyphs = labels.style.glyphs;
|
|
118
|
+
if (style.sprite == null) style.sprite = labels.style.sprite;
|
|
119
|
+
if (style.sky == null) style.sky = labels.style.sky;
|
|
120
|
+
|
|
121
|
+
Object.assign(style.sources, labels.style.sources);
|
|
122
|
+
style.layers = style.layers.concat(labels.style.layers);
|
|
123
|
+
}
|
|
124
|
+
|
|
94
125
|
async function ensureTerrain(
|
|
95
126
|
req: LambdaHttpRequest<StyleGet>,
|
|
96
127
|
tileMatrix: TileMatrixSet,
|
|
@@ -98,17 +129,16 @@ async function ensureTerrain(
|
|
|
98
129
|
style: StyleJson,
|
|
99
130
|
): Promise<void> {
|
|
100
131
|
const config = await ConfigLoader.load(req);
|
|
101
|
-
const terrain = await config.TileSet.get('
|
|
102
|
-
if (terrain)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
132
|
+
const terrain = await config.TileSet.get('elevation');
|
|
133
|
+
if (terrain == null) return;
|
|
134
|
+
const configLocation = ConfigLoader.extract(req);
|
|
135
|
+
const elevationQuery = toQueryString({ config: configLocation, api: apiKey, pipeline: 'terrain-rgb' });
|
|
136
|
+
style.sources['LINZ-Terrain'] = {
|
|
137
|
+
type: 'raster-dem',
|
|
138
|
+
tileSize: 256,
|
|
139
|
+
maxzoom: 18,
|
|
140
|
+
tiles: [convertRelativeUrl(`/v1/tiles/elevation/${tileMatrix.identifier}/{z}/{x}/{y}.png${elevationQuery}`)],
|
|
141
|
+
};
|
|
112
142
|
}
|
|
113
143
|
|
|
114
144
|
export async function tileSetToStyle(
|
|
@@ -116,7 +146,7 @@ export async function tileSetToStyle(
|
|
|
116
146
|
tileSet: ConfigTileSetRaster,
|
|
117
147
|
tileMatrix: TileMatrixSet,
|
|
118
148
|
apiKey: string,
|
|
119
|
-
|
|
149
|
+
cfg: StyleConfig,
|
|
120
150
|
): Promise<LambdaHttpResponse> {
|
|
121
151
|
const [tileFormat] = Validate.getRequestedFormats(req) ?? ['webp'];
|
|
122
152
|
if (tileFormat == null) return new LambdaHttpResponse(400, 'Invalid image format');
|
|
@@ -144,9 +174,10 @@ export async function tileSetToStyle(
|
|
|
144
174
|
await ensureTerrain(req, tileMatrix, apiKey, style);
|
|
145
175
|
|
|
146
176
|
// Add terrain in style
|
|
147
|
-
if (terrain) setStyleTerrain(style, terrain, tileMatrix);
|
|
177
|
+
if (cfg.terrain) setStyleTerrain(style, cfg.terrain, tileMatrix);
|
|
178
|
+
if (cfg.labels) await setStyleLabels(req, style);
|
|
148
179
|
|
|
149
|
-
const data = Buffer.from(JSON.stringify(style));
|
|
180
|
+
const data = Buffer.from(JSON.stringify(convertStyleJson(style, tileMatrix, apiKey, configLocation)));
|
|
150
181
|
|
|
151
182
|
const cacheKey = Etag.key(data);
|
|
152
183
|
if (Etag.isNotModified(req, cacheKey)) return NotModified();
|
|
@@ -164,7 +195,7 @@ export async function tileSetOutputToStyle(
|
|
|
164
195
|
tileSet: ConfigTileSetRaster,
|
|
165
196
|
tileMatrix: TileMatrixSet,
|
|
166
197
|
apiKey: string,
|
|
167
|
-
|
|
198
|
+
cfg: StyleConfig,
|
|
168
199
|
): Promise<LambdaHttpResponse> {
|
|
169
200
|
const configLocation = ConfigLoader.extract(req);
|
|
170
201
|
const query = toQueryString({ config: configLocation, api: apiKey });
|
|
@@ -227,9 +258,10 @@ export async function tileSetOutputToStyle(
|
|
|
227
258
|
await ensureTerrain(req, tileMatrix, apiKey, style);
|
|
228
259
|
|
|
229
260
|
// Add terrain in style
|
|
230
|
-
if (terrain) setStyleTerrain(style, terrain, tileMatrix);
|
|
261
|
+
if (cfg.terrain) setStyleTerrain(style, cfg.terrain, tileMatrix);
|
|
262
|
+
if (cfg.labels) await setStyleLabels(req, style);
|
|
231
263
|
|
|
232
|
-
const data = Buffer.from(JSON.stringify(style));
|
|
264
|
+
const data = Buffer.from(JSON.stringify(convertStyleJson(style, tileMatrix, apiKey, configLocation)));
|
|
233
265
|
|
|
234
266
|
const cacheKey = Etag.key(data);
|
|
235
267
|
if (Etag.isNotModified(req, cacheKey)) return Promise.resolve(NotModified());
|
|
@@ -250,18 +282,22 @@ export async function styleJsonGet(req: LambdaHttpRequest<StyleGet>): Promise<La
|
|
|
250
282
|
const tileMatrix = TileMatrixSets.find(req.query.get('tileMatrix') ?? GoogleTms.identifier);
|
|
251
283
|
if (tileMatrix == null) return new LambdaHttpResponse(400, 'Invalid tile matrix');
|
|
252
284
|
const terrain = req.query.get('terrain') ?? undefined;
|
|
285
|
+
const labels = Boolean(req.query.get('labels') ?? false);
|
|
253
286
|
|
|
254
287
|
// Get style Config from db
|
|
255
288
|
const config = await ConfigLoader.load(req);
|
|
256
289
|
const dbId = config.Style.id(styleName);
|
|
257
290
|
const styleConfig = await config.Style.get(dbId);
|
|
291
|
+
|
|
292
|
+
req.set('styleConfig', { terrain, labels });
|
|
293
|
+
|
|
258
294
|
if (styleConfig == null) {
|
|
259
295
|
// Were we given a tileset name instead, generated
|
|
260
296
|
const tileSet = await config.TileSet.get(config.TileSet.id(styleName));
|
|
261
297
|
if (tileSet == null) return NotFound();
|
|
262
298
|
if (tileSet.type !== TileSetType.Raster) return NotFound();
|
|
263
|
-
if (tileSet.outputs) return await tileSetOutputToStyle(req, tileSet, tileMatrix, apiKey, terrain);
|
|
264
|
-
else return await tileSetToStyle(req, tileSet, tileMatrix, apiKey, terrain);
|
|
299
|
+
if (tileSet.outputs) return await tileSetOutputToStyle(req, tileSet, tileMatrix, apiKey, { terrain, labels });
|
|
300
|
+
else return await tileSetToStyle(req, tileSet, tileMatrix, apiKey, { terrain, labels });
|
|
265
301
|
}
|
|
266
302
|
|
|
267
303
|
// Prepare sources and add linz source
|
|
@@ -279,6 +315,7 @@ export async function styleJsonGet(req: LambdaHttpRequest<StyleGet>): Promise<La
|
|
|
279
315
|
|
|
280
316
|
// Add terrain in style
|
|
281
317
|
if (terrain) setStyleTerrain(style, terrain, tileMatrix);
|
|
318
|
+
if (labels) await setStyleLabels(req, style);
|
|
282
319
|
|
|
283
320
|
const data = Buffer.from(JSON.stringify(style));
|
|
284
321
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
|
|
4
|
+
import { fsa, FsMemory } from '@chunkd/fs';
|
|
5
|
+
|
|
6
|
+
import { SourceCache } from '../source.cache.js';
|
|
7
|
+
|
|
8
|
+
describe('CoSourceCache', () => {
|
|
9
|
+
it('should not exit if a promise rejection happens for tiff', async () => {
|
|
10
|
+
const cache = new SourceCache(5);
|
|
11
|
+
|
|
12
|
+
const mem = new FsMemory();
|
|
13
|
+
const tiffLoc = new URL('memory://foo/bar.tiff');
|
|
14
|
+
await mem.write(tiffLoc, Buffer.from('ABC123'));
|
|
15
|
+
fsa.register('memory://', mem);
|
|
16
|
+
|
|
17
|
+
let failCount = 0;
|
|
18
|
+
await cache.getCog(tiffLoc).catch(() => failCount++);
|
|
19
|
+
assert.equal(cache.cache.currentSize, 0);
|
|
20
|
+
assert.equal(failCount, 1);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should not exit if a promise rejection happens for tar', async () => {
|
|
24
|
+
const cache = new SourceCache(5);
|
|
25
|
+
|
|
26
|
+
const mem = new FsMemory();
|
|
27
|
+
const tiffLoc = new URL('memory://foo/bar.tar');
|
|
28
|
+
await mem.write(tiffLoc, Buffer.from('ABC123'));
|
|
29
|
+
fsa.register('memory://', mem);
|
|
30
|
+
|
|
31
|
+
let failCount = 0;
|
|
32
|
+
await cache.getCotar(tiffLoc).catch(() => failCount++);
|
|
33
|
+
assert.equal(cache.cache.currentSize, 0);
|
|
34
|
+
assert.equal(failCount, 1);
|
|
35
|
+
});
|
|
36
|
+
});
|
package/src/util/source.cache.ts
CHANGED
|
@@ -7,54 +7,44 @@ export type LruStrut = LruStrutCotar | LruStrutCog;
|
|
|
7
7
|
export interface LruStrutCotar {
|
|
8
8
|
type: 'cotar';
|
|
9
9
|
value: Promise<Cotar>;
|
|
10
|
-
|
|
10
|
+
size: number;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface LruStrutCog {
|
|
14
14
|
type: 'cog';
|
|
15
15
|
value: Promise<Tiff>;
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
class LruStrutObj<T extends LruStrut> {
|
|
20
|
-
ob: T;
|
|
21
|
-
constructor(ob: T) {
|
|
22
|
-
this.ob = ob;
|
|
23
|
-
if (this.ob._value == null) {
|
|
24
|
-
void this.ob.value.then((c) => (this.ob._value = c));
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
size = 1;
|
|
16
|
+
size: number;
|
|
29
17
|
}
|
|
30
18
|
|
|
31
19
|
export class SourceCache {
|
|
32
|
-
cache: SwappingLru<
|
|
20
|
+
cache: SwappingLru<LruStrut>;
|
|
33
21
|
constructor(maxSize: number) {
|
|
34
|
-
this.cache = new SwappingLru<
|
|
22
|
+
this.cache = new SwappingLru<LruStrut>(maxSize);
|
|
35
23
|
}
|
|
36
24
|
|
|
37
25
|
getCog(location: URL): Promise<Tiff> {
|
|
38
|
-
const existing = this.cache.get(location.href)
|
|
26
|
+
const existing = this.cache.get(location.href);
|
|
39
27
|
|
|
40
28
|
if (existing != null) {
|
|
41
29
|
if (existing.type === 'cog') return existing.value;
|
|
42
30
|
throw new Error(`Existing object of type: ${existing.type} made for location: ${location.href}`);
|
|
43
31
|
}
|
|
44
32
|
const value = Tiff.create(fsa.source(location));
|
|
45
|
-
this.cache.set(location.href,
|
|
33
|
+
this.cache.set(location.href, { type: 'cog', value, size: 1 });
|
|
34
|
+
value.catch(() => this.cache.delete(location.href));
|
|
46
35
|
return value;
|
|
47
36
|
}
|
|
48
37
|
|
|
49
38
|
getCotar(location: URL): Promise<Cotar> {
|
|
50
|
-
const existing = this.cache.get(location.href)
|
|
39
|
+
const existing = this.cache.get(location.href);
|
|
51
40
|
|
|
52
41
|
if (existing != null) {
|
|
53
42
|
if (existing.type === 'cotar') return existing.value;
|
|
54
43
|
throw new Error(`Existing object of type: ${existing.type} made for location: ${location.href}`);
|
|
55
44
|
}
|
|
56
45
|
const value = Cotar.fromTar(fsa.source(location));
|
|
57
|
-
this.cache.set(location.href,
|
|
46
|
+
this.cache.set(location.href, { type: 'cotar', value, size: 1 });
|
|
47
|
+
value.catch(() => this.cache.delete(location.href));
|
|
58
48
|
return value;
|
|
59
49
|
}
|
|
60
50
|
}
|
package/src/util/swapping.lru.ts
CHANGED
|
@@ -41,6 +41,11 @@ export class SwappingLru<T extends { size: number }> {
|
|
|
41
41
|
this.clears++;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
delete(id: string): void {
|
|
45
|
+
this.cacheA.delete(id);
|
|
46
|
+
this.cacheB.delete(id);
|
|
47
|
+
}
|
|
48
|
+
|
|
44
49
|
set(id: string, tiff: T): void {
|
|
45
50
|
this.cacheA.set(id, tiff);
|
|
46
51
|
this.check();
|