@basemaps/lambda-tiler 6.31.0 → 6.32.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 +21 -0
- package/build/__tests__/config.data.d.ts +6 -1
- package/build/__tests__/config.data.d.ts.map +1 -1
- package/build/__tests__/config.data.js +33 -2
- package/build/__tests__/config.data.js.map +1 -1
- package/build/__tests__/index.test.js +3 -13
- package/build/__tests__/index.test.js.map +1 -1
- package/build/__tests__/xyz.util.d.ts +7 -9
- package/build/__tests__/xyz.util.d.ts.map +1 -1
- package/build/__tests__/xyz.util.js +14 -20
- package/build/__tests__/xyz.util.js.map +1 -1
- package/build/index.d.ts +0 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +57 -26
- package/build/index.js.map +1 -1
- package/build/routes/__tests__/attribution.test.js +350 -400
- package/build/routes/__tests__/attribution.test.js.map +1 -1
- package/build/routes/__tests__/fonts.test.js +11 -5
- package/build/routes/__tests__/fonts.test.js.map +1 -1
- package/build/routes/__tests__/health.test.js +16 -13
- package/build/routes/__tests__/health.test.js.map +1 -1
- package/build/routes/__tests__/sprites.test.js +6 -0
- package/build/routes/__tests__/sprites.test.js.map +1 -1
- package/build/routes/__tests__/tile.json.test.d.ts +2 -0
- package/build/routes/__tests__/tile.json.test.d.ts.map +1 -0
- package/build/routes/__tests__/tile.json.test.js +124 -0
- package/build/routes/__tests__/tile.json.test.js.map +1 -0
- package/build/routes/__tests__/tile.style.json.test.d.ts +2 -0
- package/build/routes/__tests__/tile.style.json.test.d.ts.map +1 -0
- package/build/routes/__tests__/tile.style.json.test.js +95 -0
- package/build/routes/__tests__/tile.style.json.test.js.map +1 -0
- package/build/routes/__tests__/wmts.test.js +5 -44
- package/build/routes/__tests__/wmts.test.js.map +1 -1
- package/build/{__tests__ → routes/__tests__}/xyz.test.d.ts +0 -0
- package/build/routes/__tests__/xyz.test.d.ts.map +1 -0
- package/build/routes/__tests__/xyz.test.js +99 -0
- package/build/routes/__tests__/xyz.test.js.map +1 -0
- package/build/routes/attribution.d.ts +7 -5
- package/build/routes/attribution.d.ts.map +1 -1
- package/build/routes/attribution.js +43 -81
- package/build/routes/attribution.js.map +1 -1
- package/build/routes/fonts.d.ts +1 -1
- package/build/routes/fonts.d.ts.map +1 -1
- package/build/routes/fonts.js +30 -15
- package/build/routes/fonts.js.map +1 -1
- package/build/routes/health.d.ts +3 -3
- package/build/routes/health.d.ts.map +1 -1
- package/build/routes/health.js +15 -13
- package/build/routes/health.js.map +1 -1
- package/build/routes/imagery.d.ts.map +1 -1
- package/build/routes/imagery.js +11 -10
- package/build/routes/imagery.js.map +1 -1
- package/build/routes/ping.d.ts +3 -0
- package/build/routes/ping.d.ts.map +1 -0
- package/build/routes/ping.js +7 -0
- package/build/routes/ping.js.map +1 -0
- package/build/routes/sprites.d.ts.map +1 -1
- package/build/routes/sprites.js +16 -10
- package/build/routes/sprites.js.map +1 -1
- package/build/routes/tile.json.d.ts +7 -1
- package/build/routes/tile.json.d.ts.map +1 -1
- package/build/routes/tile.json.js +18 -21
- package/build/routes/tile.json.js.map +1 -1
- package/build/routes/tile.style.json.d.ts +6 -1
- package/build/routes/tile.style.json.d.ts.map +1 -1
- package/build/routes/tile.style.json.js +10 -13
- package/build/routes/tile.style.json.js.map +1 -1
- package/build/routes/tile.wmts.d.ts +9 -3
- package/build/routes/tile.wmts.d.ts.map +1 -1
- package/build/routes/tile.wmts.js +26 -35
- package/build/routes/tile.wmts.js.map +1 -1
- package/build/routes/tile.xyz.d.ts +14 -4
- package/build/routes/tile.xyz.d.ts.map +1 -1
- package/build/routes/tile.xyz.js +21 -17
- package/build/routes/tile.xyz.js.map +1 -1
- package/build/routes/tile.xyz.raster.d.ts +11 -0
- package/build/routes/tile.xyz.raster.d.ts.map +1 -0
- package/build/routes/tile.xyz.raster.js +90 -0
- package/build/routes/tile.xyz.raster.js.map +1 -0
- package/build/routes/tile.xyz.vector.d.ts +8 -0
- package/build/routes/tile.xyz.vector.d.ts.map +1 -0
- package/build/routes/tile.xyz.vector.js +46 -0
- package/build/routes/tile.xyz.vector.js.map +1 -0
- package/build/routes/version.d.ts +3 -0
- package/build/routes/version.d.ts.map +1 -0
- package/build/routes/version.js +9 -0
- package/build/routes/version.js.map +1 -0
- package/build/util/__test__/validate.test.d.ts +2 -0
- package/build/util/__test__/validate.test.d.ts.map +1 -0
- package/build/util/__test__/validate.test.js +66 -0
- package/build/util/__test__/validate.test.js.map +1 -0
- package/build/{cotar.cache.d.ts → util/cotar.serve.d.ts} +3 -8
- package/build/util/cotar.serve.d.ts.map +1 -0
- package/build/util/cotar.serve.js +41 -0
- package/build/util/cotar.serve.js.map +1 -0
- package/build/util/etag.d.ts +6 -0
- package/build/util/etag.d.ts.map +1 -0
- package/build/util/etag.js +20 -0
- package/build/util/etag.js.map +1 -0
- package/build/util/response.d.ts +4 -0
- package/build/util/response.d.ts.map +1 -0
- package/build/util/response.js +4 -0
- package/build/util/response.js.map +1 -0
- package/build/util/source.cache.d.ts +28 -0
- package/build/util/source.cache.d.ts.map +1 -0
- package/build/util/source.cache.js +53 -0
- package/build/util/source.cache.js.map +1 -0
- package/build/{source.tracer.d.ts → util/source.tracer.d.ts} +1 -0
- package/build/util/source.tracer.d.ts.map +1 -0
- package/build/{source.tracer.js → util/source.tracer.js} +3 -0
- package/build/util/source.tracer.js.map +1 -0
- package/build/util/swapping.lru.d.ts +21 -0
- package/build/util/swapping.lru.d.ts.map +1 -0
- package/build/util/swapping.lru.js +56 -0
- package/build/util/swapping.lru.js.map +1 -0
- package/build/util/validate.d.ts +46 -0
- package/build/util/validate.d.ts.map +1 -0
- package/build/util/validate.js +107 -0
- package/build/util/validate.js.map +1 -0
- package/build/wmts.capability.d.ts +1 -1
- package/build/wmts.capability.d.ts.map +1 -1
- package/dist/index.js +62 -60
- package/dist/node_modules/.package-lock.json +1 -1
- package/dist/package-lock.json +2 -2
- package/dist/package.json +1 -1
- package/package.json +6 -6
- package/src/__tests__/config.data.ts +41 -3
- package/src/__tests__/index.test.ts +3 -19
- package/src/__tests__/xyz.util.ts +18 -21
- package/src/index.ts +66 -29
- package/src/routes/__tests__/attribution.test.ts +356 -403
- package/src/routes/__tests__/fonts.test.ts +11 -5
- package/src/routes/__tests__/health.test.ts +17 -13
- package/src/routes/__tests__/sprites.test.ts +6 -1
- package/src/routes/__tests__/tile.json.test.ts +145 -0
- package/src/routes/__tests__/tile.style.json.test.ts +105 -0
- package/src/routes/__tests__/wmts.test.ts +5 -55
- package/src/routes/__tests__/xyz.test.ts +119 -0
- package/src/routes/attribution.ts +53 -99
- package/src/routes/fonts.ts +29 -15
- package/src/routes/health.ts +17 -16
- package/src/routes/imagery.ts +10 -9
- package/src/routes/ping.ts +8 -0
- package/src/routes/sprites.ts +16 -10
- package/src/routes/tile.json.ts +24 -18
- package/src/routes/tile.style.json.ts +15 -12
- package/src/routes/tile.wmts.ts +30 -31
- package/src/routes/tile.xyz.raster.ts +106 -0
- package/src/routes/tile.xyz.ts +31 -16
- package/src/routes/tile.xyz.vector.ts +47 -0
- package/src/routes/version.ts +8 -0
- package/src/util/__test__/validate.test.ts +74 -0
- package/src/util/cotar.serve.ts +46 -0
- package/src/util/etag.ts +20 -0
- package/src/util/response.ts +4 -0
- package/src/util/source.cache.ts +71 -0
- package/src/{source.tracer.ts → util/source.tracer.ts} +4 -0
- package/src/util/swapping.lru.ts +63 -0
- package/src/util/validate.ts +126 -0
- package/src/wmts.capability.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/build/__tests__/route.test.d.ts +0 -2
- package/build/__tests__/route.test.d.ts.map +0 -1
- package/build/__tests__/route.test.js +0 -21
- package/build/__tests__/route.test.js.map +0 -1
- package/build/__tests__/tiff.cache.test.d.ts +0 -2
- package/build/__tests__/tiff.cache.test.d.ts.map +0 -1
- package/build/__tests__/tiff.cache.test.js +0 -59
- package/build/__tests__/tiff.cache.test.js.map +0 -1
- package/build/__tests__/tile.cache.key.test.d.ts +0 -2
- package/build/__tests__/tile.cache.key.test.d.ts.map +0 -1
- package/build/__tests__/tile.cache.key.test.js +0 -49
- package/build/__tests__/tile.cache.key.test.js.map +0 -1
- package/build/__tests__/tile.set.cache.test.d.ts +0 -2
- package/build/__tests__/tile.set.cache.test.d.ts.map +0 -1
- package/build/__tests__/tile.set.cache.test.js +0 -72
- package/build/__tests__/tile.set.cache.test.js.map +0 -1
- package/build/__tests__/tile.set.test.d.ts +0 -2
- package/build/__tests__/tile.set.test.d.ts.map +0 -1
- package/build/__tests__/tile.set.test.js +0 -12
- package/build/__tests__/tile.set.test.js.map +0 -1
- package/build/__tests__/xyz.test.d.ts.map +0 -1
- package/build/__tests__/xyz.test.js +0 -275
- package/build/__tests__/xyz.test.js.map +0 -1
- package/build/api.key.d.ts +0 -2
- package/build/api.key.d.ts.map +0 -1
- package/build/api.key.js +0 -24
- package/build/api.key.js.map +0 -1
- package/build/cli/dump.d.ts +0 -2
- package/build/cli/dump.d.ts.map +0 -1
- package/build/cli/dump.js +0 -48
- package/build/cli/dump.js.map +0 -1
- package/build/cli/tile.set.local.d.ts +0 -12
- package/build/cli/tile.set.local.d.ts.map +0 -1
- package/build/cli/tile.set.local.js +0 -40
- package/build/cli/tile.set.local.js.map +0 -1
- package/build/cotar.cache.d.ts.map +0 -1
- package/build/cotar.cache.js +0 -50
- package/build/cotar.cache.js.map +0 -1
- package/build/router.d.ts +0 -15
- package/build/router.d.ts.map +0 -1
- package/build/router.js +0 -50
- package/build/router.js.map +0 -1
- package/build/routes/api.d.ts +0 -4
- package/build/routes/api.d.ts.map +0 -1
- package/build/routes/api.js +0 -14
- package/build/routes/api.js.map +0 -1
- package/build/routes/esri/rest.d.ts +0 -10
- package/build/routes/esri/rest.d.ts.map +0 -1
- package/build/routes/esri/rest.js +0 -88
- package/build/routes/esri/rest.js.map +0 -1
- package/build/routes/response.d.ts +0 -4
- package/build/routes/response.d.ts.map +0 -1
- package/build/routes/response.js +0 -4
- package/build/routes/response.js.map +0 -1
- package/build/routes/tile.d.ts +0 -3
- package/build/routes/tile.d.ts.map +0 -1
- package/build/routes/tile.etag.d.ts +0 -11
- package/build/routes/tile.etag.d.ts.map +0 -1
- package/build/routes/tile.etag.js +0 -30
- package/build/routes/tile.etag.js.map +0 -1
- package/build/routes/tile.js +0 -28
- package/build/routes/tile.js.map +0 -1
- package/build/source.tracer.d.ts.map +0 -1
- package/build/source.tracer.js.map +0 -1
- package/build/tiff.cache.d.ts +0 -17
- package/build/tiff.cache.d.ts.map +0 -1
- package/build/tiff.cache.js +0 -46
- package/build/tiff.cache.js.map +0 -1
- package/build/tile.set.cache.d.ts +0 -20
- package/build/tile.set.cache.d.ts.map +0 -1
- package/build/tile.set.cache.js +0 -72
- package/build/tile.set.cache.js.map +0 -1
- package/build/tile.set.d.ts +0 -4
- package/build/tile.set.d.ts.map +0 -1
- package/build/tile.set.js +0 -2
- package/build/tile.set.js.map +0 -1
- package/build/tile.set.raster.d.ts +0 -49
- package/build/tile.set.raster.d.ts.map +0 -1
- package/build/tile.set.raster.js +0 -189
- package/build/tile.set.raster.js.map +0 -1
- package/build/tile.set.vector.d.ts +0 -18
- package/build/tile.set.vector.d.ts.map +0 -1
- package/build/tile.set.vector.js +0 -54
- package/build/tile.set.vector.js.map +0 -1
- package/build/validate.d.ts +0 -16
- package/build/validate.d.ts.map +0 -1
- package/build/validate.js +0 -32
- package/build/validate.js.map +0 -1
- package/src/__tests__/route.test.ts +0 -24
- package/src/__tests__/tiff.cache.test.ts +0 -73
- package/src/__tests__/tile.cache.key.test.ts +0 -56
- package/src/__tests__/tile.set.cache.test.ts +0 -80
- package/src/__tests__/tile.set.test.ts +0 -12
- package/src/__tests__/xyz.test.ts +0 -318
- package/src/api.key.ts +0 -23
- package/src/cli/dump.ts +0 -61
- package/src/cli/tile.set.local.ts +0 -51
- package/src/cotar.cache.ts +0 -54
- package/src/router.ts +0 -58
- package/src/routes/api.ts +0 -15
- package/src/routes/esri/rest.ts +0 -90
- package/src/routes/response.ts +0 -4
- package/src/routes/tile.etag.ts +0 -36
- package/src/routes/tile.ts +0 -23
- package/src/tiff.cache.ts +0 -51
- package/src/tile.set.cache.ts +0 -84
- package/src/tile.set.raster.ts +0 -230
- package/src/tile.set.ts +0 -4
- package/src/tile.set.vector.ts +0 -61
- package/src/validate.ts +0 -32
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConfigTileSet, TileSetType } from '@basemaps/config';
|
|
2
2
|
import {
|
|
3
3
|
AttributionCollection,
|
|
4
4
|
AttributionItem,
|
|
@@ -7,32 +7,20 @@ import {
|
|
|
7
7
|
GoogleTms,
|
|
8
8
|
NamedBounds,
|
|
9
9
|
Stac,
|
|
10
|
-
StacCollection,
|
|
11
10
|
StacExtent,
|
|
12
11
|
TileMatrixSet,
|
|
13
12
|
} from '@basemaps/geo';
|
|
14
|
-
import {
|
|
15
|
-
CompositeError,
|
|
16
|
-
Config,
|
|
17
|
-
extractYearRangeFromName,
|
|
18
|
-
fsa,
|
|
19
|
-
Projection,
|
|
20
|
-
setNameAndProjection,
|
|
21
|
-
tileAttributionFromPath,
|
|
22
|
-
titleizeImageryName,
|
|
23
|
-
} from '@basemaps/shared';
|
|
13
|
+
import { Config, extractYearRangeFromName, Projection, titleizeImageryName } from '@basemaps/shared';
|
|
24
14
|
import { BBox, MultiPolygon, multiPolygonToWgs84, Pair, union, Wgs84 } from '@linzjs/geojson';
|
|
25
15
|
import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
|
|
26
|
-
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
16
|
+
|
|
17
|
+
import { Etag } from '../util/etag.js';
|
|
18
|
+
import { NotFound, NotModified } from '../util/response.js';
|
|
19
|
+
import { Validate } from '../util/validate.js';
|
|
30
20
|
|
|
31
21
|
/** Amount to pad imagery bounds to avoid fragmenting polygons */
|
|
32
22
|
const SmoothPadding = 1 + 1e-10; // about 1/100th of a millimeter at equator
|
|
33
23
|
|
|
34
|
-
const NotFound = new LambdaHttpResponse(404, 'Not Found');
|
|
35
|
-
|
|
36
24
|
const Precision = 10 ** 8;
|
|
37
25
|
|
|
38
26
|
/**
|
|
@@ -74,75 +62,30 @@ function createCoordinates(bbox: BBox, files: NamedBounds[], proj: Projection):
|
|
|
74
62
|
return multiPolygonToWgs84(coordinates, roundToWgs84);
|
|
75
63
|
}
|
|
76
64
|
|
|
77
|
-
async function readStac(uri: string): Promise<StacCollection | null> {
|
|
78
|
-
try {
|
|
79
|
-
return await fsa.readJson<StacCollection>(uri);
|
|
80
|
-
} catch (err) {
|
|
81
|
-
if (CompositeError.isCompositeError(err) && err.code < 500) {
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
throw err;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function createAttributionCollection(
|
|
89
|
-
tileSet: TileSetRaster,
|
|
90
|
-
imagery: ConfigImagery,
|
|
91
|
-
layer: ConfigLayer,
|
|
92
|
-
host: ConfigProvider,
|
|
93
|
-
extent: StacExtent,
|
|
94
|
-
): AttributionCollection {
|
|
95
|
-
const tileMatrix = tileSet.tileMatrix;
|
|
96
|
-
return {
|
|
97
|
-
stac_version: Stac.Version,
|
|
98
|
-
license: Stac.License,
|
|
99
|
-
id: imagery.id,
|
|
100
|
-
providers: [{ name: host.serviceProvider.name, url: host.serviceProvider.site, roles: ['host'] }],
|
|
101
|
-
title: imagery.title ?? titleizeImageryName(imagery.name),
|
|
102
|
-
description: 'No description',
|
|
103
|
-
extent,
|
|
104
|
-
links: [],
|
|
105
|
-
summaries: {
|
|
106
|
-
'linz:category': imagery.category,
|
|
107
|
-
'linz:zoom': {
|
|
108
|
-
min: TileMatrixSet.convertZoomLevel(layer.minZoom ? layer.minZoom : 0, GoogleTms, tileMatrix, true),
|
|
109
|
-
max: TileMatrixSet.convertZoomLevel(layer.maxZoom ? layer.maxZoom : 32, GoogleTms, tileMatrix, true),
|
|
110
|
-
},
|
|
111
|
-
'linz:priority': [1000 + tileSet.tileSet.layers.indexOf(layer)],
|
|
112
|
-
},
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
65
|
/**
|
|
117
66
|
* Build a Single File STAC for the given TileSet.
|
|
118
67
|
*
|
|
119
68
|
* For now this is the minimal set required for attribution. This can be embellished later with
|
|
120
69
|
* links and assets for a more comprehensive STAC file.
|
|
121
70
|
*/
|
|
122
|
-
async function tileSetAttribution(
|
|
123
|
-
|
|
124
|
-
|
|
71
|
+
async function tileSetAttribution(
|
|
72
|
+
req: LambdaHttpRequest,
|
|
73
|
+
tileSet: ConfigTileSet,
|
|
74
|
+
tileMatrix: TileMatrixSet,
|
|
75
|
+
): Promise<AttributionStac | null> {
|
|
76
|
+
const proj = Projection.get(tileMatrix);
|
|
125
77
|
const cols: AttributionCollection[] = [];
|
|
126
78
|
const items: AttributionItem[] = [];
|
|
127
79
|
|
|
128
|
-
|
|
129
|
-
for (const layer of tileSet.tileSet.layers) {
|
|
130
|
-
const imgId = layer[proj.epsg.code];
|
|
131
|
-
if (imgId == null) continue;
|
|
132
|
-
const im = tileSet.imagery.get(imgId);
|
|
133
|
-
if (im == null) continue;
|
|
134
|
-
if (stacFiles.get(im.uri) == null) {
|
|
135
|
-
stacFiles.set(im.uri, readStac(fsa.join(im.uri, 'collection.json')));
|
|
136
|
-
}
|
|
137
|
-
}
|
|
80
|
+
const imagery = await Config.getAllImagery(tileSet.layers, [tileMatrix.projection]);
|
|
138
81
|
|
|
139
82
|
const host = await Config.Provider.get(Config.Provider.id('linz'));
|
|
140
83
|
if (host == null) return null;
|
|
141
84
|
|
|
142
|
-
for (const layer of tileSet.
|
|
85
|
+
for (const layer of tileSet.layers) {
|
|
143
86
|
const imgId = layer[proj.epsg.code];
|
|
144
87
|
if (imgId == null) continue;
|
|
145
|
-
const im =
|
|
88
|
+
const im = imagery.get(imgId);
|
|
146
89
|
if (im == null) continue;
|
|
147
90
|
|
|
148
91
|
const bbox = proj.boundsToWgs84BoundingBox(im.bounds).map(roundNumber) as BBox;
|
|
@@ -161,10 +104,7 @@ async function tileSetAttribution(tileSet: TileSetRaster): Promise<AttributionSt
|
|
|
161
104
|
assets: {},
|
|
162
105
|
links: [],
|
|
163
106
|
bbox,
|
|
164
|
-
geometry: {
|
|
165
|
-
type: 'MultiPolygon',
|
|
166
|
-
coordinates: createCoordinates(bbox, im.files, proj),
|
|
167
|
-
},
|
|
107
|
+
geometry: { type: 'MultiPolygon', coordinates: createCoordinates(bbox, im.files, proj) },
|
|
168
108
|
properties: {
|
|
169
109
|
title: im.title ?? titleizeImageryName(im.name),
|
|
170
110
|
category: im.category,
|
|
@@ -174,56 +114,70 @@ async function tileSetAttribution(tileSet: TileSetRaster): Promise<AttributionSt
|
|
|
174
114
|
},
|
|
175
115
|
});
|
|
176
116
|
|
|
177
|
-
|
|
117
|
+
const zoomMin = TileMatrixSet.convertZoomLevel(layer.minZoom ? layer.minZoom : 0, GoogleTms, tileMatrix, true);
|
|
118
|
+
const zoomMax = TileMatrixSet.convertZoomLevel(layer.maxZoom ? layer.maxZoom : 32, GoogleTms, tileMatrix, true);
|
|
119
|
+
cols.push({
|
|
120
|
+
stac_version: Stac.Version,
|
|
121
|
+
license: Stac.License,
|
|
122
|
+
id: im.id,
|
|
123
|
+
providers: [{ name: host.serviceProvider.name, url: host.serviceProvider.site, roles: ['host'] }],
|
|
124
|
+
title: im.title ?? titleizeImageryName(im.name),
|
|
125
|
+
description: 'No description',
|
|
126
|
+
extent,
|
|
127
|
+
links: [],
|
|
128
|
+
summaries: {
|
|
129
|
+
'linz:category': im.category,
|
|
130
|
+
'linz:zoom': { min: zoomMin, max: zoomMax },
|
|
131
|
+
'linz:priority': [1000 + tileSet.layers.indexOf(layer)],
|
|
132
|
+
},
|
|
133
|
+
});
|
|
178
134
|
}
|
|
179
135
|
return {
|
|
180
136
|
id: tileSet.id,
|
|
181
137
|
type: 'FeatureCollection',
|
|
182
138
|
stac_version: Stac.Version,
|
|
183
139
|
stac_extensions: ['single-file-stac'],
|
|
184
|
-
title: tileSet.title,
|
|
185
|
-
description: tileSet.description,
|
|
140
|
+
title: tileSet.title ?? 'No title',
|
|
141
|
+
description: tileSet.description ?? 'No Description',
|
|
186
142
|
features: items,
|
|
187
143
|
collections: cols,
|
|
188
144
|
links: [],
|
|
189
145
|
};
|
|
190
146
|
}
|
|
191
147
|
|
|
148
|
+
export interface TileAttributionGet {
|
|
149
|
+
Params: {
|
|
150
|
+
tileSet: string;
|
|
151
|
+
tileMatrix: string;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
192
155
|
/**
|
|
193
156
|
* Create a LambdaHttpResponse for a attribution request
|
|
194
157
|
*/
|
|
195
|
-
export async function
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
if (data == null) return NotFound;
|
|
199
|
-
setNameAndProjection(req, data);
|
|
158
|
+
export async function tileAttributionGet(req: LambdaHttpRequest<TileAttributionGet>): Promise<LambdaHttpResponse> {
|
|
159
|
+
const tileMatrix = Validate.getTileMatrixSet(req.params.tileMatrix);
|
|
160
|
+
if (tileMatrix == null) throw new LambdaHttpResponse(404, 'Tile Matrix not found');
|
|
200
161
|
|
|
201
162
|
req.timer.start('tileset:load');
|
|
202
|
-
const tileSet = await
|
|
163
|
+
const tileSet = await Config.TileSet.get(Config.TileSet.id(req.params.tileSet));
|
|
203
164
|
req.timer.end('tileset:load');
|
|
204
|
-
if (tileSet == null || tileSet.type === TileSetType.Vector) return NotFound;
|
|
165
|
+
if (tileSet == null || tileSet.type === TileSetType.Vector) return NotFound();
|
|
205
166
|
|
|
206
|
-
const cacheKey =
|
|
207
|
-
|
|
208
|
-
const ifNoneMatch = req.header(HttpHeader.IfNoneMatch);
|
|
209
|
-
if (ifNoneMatch != null && ifNoneMatch.indexOf(cacheKey) > -1) {
|
|
210
|
-
req.set('cache', { key: cacheKey, hit: true, match: ifNoneMatch });
|
|
211
|
-
return new LambdaHttpResponse(304, 'Not modified');
|
|
212
|
-
}
|
|
167
|
+
const cacheKey = Etag.key(tileSet);
|
|
168
|
+
if (Etag.isNotModified(req, cacheKey)) return NotModified();
|
|
213
169
|
|
|
214
170
|
req.timer.start('stac:load');
|
|
215
|
-
const attributions = await tileSetAttribution(tileSet);
|
|
171
|
+
const attributions = await tileSetAttribution(req, tileSet, tileMatrix);
|
|
216
172
|
req.timer.end('stac:load');
|
|
217
173
|
|
|
218
|
-
if (attributions == null) return NotFound;
|
|
174
|
+
if (attributions == null) return NotFound();
|
|
219
175
|
|
|
220
176
|
const response = new LambdaHttpResponse(200, 'ok');
|
|
221
177
|
|
|
222
178
|
response.header(HttpHeader.ETag, cacheKey);
|
|
223
|
-
// Keep fresh for
|
|
224
|
-
response.header(HttpHeader.CacheControl, 'public, max-age=
|
|
225
|
-
|
|
179
|
+
// Keep fresh for 7 days; otherwise use cache but refresh cache for next time
|
|
180
|
+
response.header(HttpHeader.CacheControl, 'public, max-age=604800, stale-while-revalidate=86400');
|
|
226
181
|
response.json(attributions);
|
|
227
|
-
|
|
228
182
|
return response;
|
|
229
183
|
}
|
package/src/routes/fonts.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Env } from '@basemaps/shared';
|
|
2
2
|
import { fsa } from '@chunkd/fs';
|
|
3
|
-
import { LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
|
|
3
|
+
import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
|
|
4
4
|
import path from 'path';
|
|
5
|
-
import { serveFromCotar } from '../cotar.
|
|
6
|
-
import {
|
|
5
|
+
import { isGzip, serveFromCotar } from '../util/cotar.serve.js';
|
|
6
|
+
import { Etag } from '../util/etag.js';
|
|
7
|
+
import { NotFound, NotModified } from '../util/response.js';
|
|
7
8
|
|
|
8
9
|
interface FontGet {
|
|
9
10
|
Params: { fontStack: string; range: string };
|
|
@@ -11,20 +12,27 @@ interface FontGet {
|
|
|
11
12
|
|
|
12
13
|
export async function fontGet(req: LambdaHttpRequest<FontGet>): Promise<LambdaHttpResponse> {
|
|
13
14
|
const assetLocation = Env.get(Env.AssetLocation);
|
|
14
|
-
if (assetLocation == null) return NotFound;
|
|
15
|
+
if (assetLocation == null) return NotFound();
|
|
15
16
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
const targetFile = path.join('fonts', req.params.fontStack, req.params.range) + '.pbf';
|
|
18
|
+
if (assetLocation.endsWith('.tar.co')) {
|
|
19
|
+
return serveFromCotar(req, assetLocation, targetFile, 'application/x-protobuf');
|
|
20
|
+
}
|
|
20
21
|
|
|
21
22
|
try {
|
|
22
23
|
const filePath = fsa.join(assetLocation, targetFile);
|
|
23
24
|
const buf = await fsa.read(filePath);
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
const cacheKey = Etag.key(buf);
|
|
27
|
+
if (Etag.isNotModified(req, cacheKey)) return NotModified();
|
|
28
|
+
|
|
29
|
+
const response = LambdaHttpResponse.ok().buffer(buf, 'application/x-protobuf');
|
|
30
|
+
response.header(HttpHeader.ETag, cacheKey);
|
|
31
|
+
response.header(HttpHeader.CacheControl, 'public, max-age=604800, stale-while-revalidate=86400');
|
|
32
|
+
if (isGzip(buf)) response.header(HttpHeader.ContentEncoding, 'gzip');
|
|
33
|
+
return response;
|
|
26
34
|
} catch (e: any) {
|
|
27
|
-
if (e.code === 404) return NotFound;
|
|
35
|
+
if (e.code === 404) return NotFound();
|
|
28
36
|
throw e;
|
|
29
37
|
}
|
|
30
38
|
}
|
|
@@ -44,19 +52,25 @@ export async function getFonts(fontPath: string): Promise<string[]> {
|
|
|
44
52
|
return [...fonts].sort();
|
|
45
53
|
}
|
|
46
54
|
|
|
47
|
-
export async function fontList(): Promise<LambdaHttpResponse> {
|
|
55
|
+
export async function fontList(req: LambdaHttpRequest): Promise<LambdaHttpResponse> {
|
|
48
56
|
const assetLocation = Env.get(Env.AssetLocation);
|
|
49
|
-
if (assetLocation == null) return NotFound;
|
|
57
|
+
if (assetLocation == null) return NotFound();
|
|
50
58
|
|
|
51
|
-
if (assetLocation.endsWith('.tar.co')) return serveFromCotar(assetLocation, 'fonts.json', 'application/json');
|
|
59
|
+
if (assetLocation.endsWith('.tar.co')) return serveFromCotar(req, assetLocation, 'fonts.json', 'application/json');
|
|
52
60
|
|
|
53
61
|
try {
|
|
54
62
|
const filePath = fsa.join(assetLocation, '/fonts');
|
|
55
63
|
const fonts = await getFonts(filePath);
|
|
56
64
|
|
|
57
|
-
|
|
65
|
+
const cacheKey = Etag.key(fonts);
|
|
66
|
+
if (Etag.isNotModified(req, cacheKey)) return NotModified();
|
|
67
|
+
|
|
68
|
+
const response = LambdaHttpResponse.ok().buffer(JSON.stringify(fonts), 'application/json');
|
|
69
|
+
response.header(HttpHeader.ETag, cacheKey);
|
|
70
|
+
response.header(HttpHeader.CacheControl, 'public, max-age=604800, stale-while-revalidate=86400');
|
|
71
|
+
return response;
|
|
58
72
|
} catch (e: any) {
|
|
59
|
-
if (e.code === 404) return NotFound;
|
|
73
|
+
if (e.code === 404) return NotFound();
|
|
60
74
|
throw e;
|
|
61
75
|
}
|
|
62
76
|
}
|
package/src/routes/health.ts
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { Config, ConfigTileSetRaster } from '@basemaps/config';
|
|
2
|
+
import { GoogleTms, ImageFormat, Nztm2000QuadTms } from '@basemaps/geo';
|
|
3
3
|
import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
|
|
4
4
|
import * as fs from 'fs';
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import PixelMatch from 'pixelmatch';
|
|
7
7
|
import Sharp from 'sharp';
|
|
8
8
|
import url from 'url';
|
|
9
|
-
import {
|
|
9
|
+
import { TileXyz } from '../util/validate.js';
|
|
10
|
+
import { TileXyzRaster } from './tile.xyz.raster.js';
|
|
10
11
|
|
|
11
|
-
interface TestTile extends
|
|
12
|
+
interface TestTile extends TileXyz {
|
|
12
13
|
buf?: Buffer;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export const TestTiles: TestTile[] = [
|
|
16
|
-
{
|
|
17
|
-
{
|
|
17
|
+
{ tileSet: 'health', tileMatrix: GoogleTms, tileType: ImageFormat.Png, tile: { x: 252, y: 156, z: 8 } },
|
|
18
|
+
{ tileSet: 'health', tileMatrix: Nztm2000QuadTms, tileType: ImageFormat.Png, tile: { x: 30, y: 33, z: 6 } },
|
|
18
19
|
];
|
|
19
20
|
const TileSize = 256;
|
|
20
21
|
|
|
21
22
|
export async function getTestBuffer(test: TestTile): Promise<Buffer> {
|
|
22
23
|
if (Buffer.isBuffer(test.buf)) return test.buf;
|
|
24
|
+
const tile = test.tile;
|
|
23
25
|
|
|
24
|
-
const expectedFile = `static/expected_tile_${test.tileMatrix.identifier}_${
|
|
26
|
+
const expectedFile = `static/expected_tile_${test.tileMatrix.identifier}_${tile.x}_${tile.y}_z${tile.z}.${test.tileType}`;
|
|
25
27
|
// Initiate test img buffer if not defined
|
|
26
28
|
try {
|
|
27
29
|
return await fs.promises.readFile(expectedFile);
|
|
@@ -33,7 +35,9 @@ export async function getTestBuffer(test: TestTile): Promise<Buffer> {
|
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
export async function updateExpectedTile(test: TestTile, newTileData: Buffer, difference: Buffer): Promise<void> {
|
|
36
|
-
const
|
|
38
|
+
const tile = test.tile;
|
|
39
|
+
|
|
40
|
+
const expectedFileName = `static/expected_tile_${test.tileMatrix.identifier}_${tile.x}_${tile.y}_z${tile.z}.${test.tileType}`;
|
|
37
41
|
await fs.promises.writeFile(expectedFileName, newTileData);
|
|
38
42
|
const imgPng = await Sharp(difference, { raw: { width: TileSize, height: TileSize, channels: 4 } })
|
|
39
43
|
.png()
|
|
@@ -48,12 +52,12 @@ export async function updateExpectedTile(test: TestTile, newTileData: Buffer, di
|
|
|
48
52
|
*
|
|
49
53
|
* @throws LambdaHttpResponse for failure health test
|
|
50
54
|
*/
|
|
51
|
-
export async function
|
|
55
|
+
export async function healthGet(req: LambdaHttpRequest): Promise<LambdaHttpResponse> {
|
|
56
|
+
const tileSet = await Config.TileSet.get(Config.TileSet.id('health'));
|
|
57
|
+
if (tileSet == null) throw new LambdaHttpResponse(500, 'TileSet: "health" not found');
|
|
52
58
|
for (const test of TestTiles) {
|
|
53
|
-
const tileSet = await TileSets.get('health', test.tileMatrix);
|
|
54
|
-
if (tileSet == null) throw new LambdaHttpResponse(500, 'TileSet: "health" not found');
|
|
55
59
|
// Get the parse response tile to raw buffer
|
|
56
|
-
const response = await
|
|
60
|
+
const response = await TileXyzRaster.tile(req, tileSet as ConfigTileSetRaster, test);
|
|
57
61
|
if (response.status !== 200) return new LambdaHttpResponse(500, response.statusDescription);
|
|
58
62
|
if (!Buffer.isBuffer(response._body)) throw new LambdaHttpResponse(500, 'Not a Buffer response content.');
|
|
59
63
|
const resImgBuffer = await Sharp(response._body).raw().toBuffer();
|
|
@@ -68,10 +72,7 @@ export async function Health(req: LambdaHttpRequest): Promise<LambdaHttpResponse
|
|
|
68
72
|
if (missMatchedPixels) {
|
|
69
73
|
/** Uncomment this to overwite the expected files */
|
|
70
74
|
// await updateExpectedTile(test, response._body as Buffer, outputBuffer);
|
|
71
|
-
req.log.error(
|
|
72
|
-
{ missMatchedPixels, projection: test.tileMatrix.identifier, xyz: { x: test.x, y: test.y, z: test.z } },
|
|
73
|
-
'Health:MissMatch',
|
|
74
|
-
);
|
|
75
|
+
req.log.error({ missMatchedPixels, projection: test.tileMatrix.identifier, xyz: test.tile }, 'Health:MissMatch');
|
|
75
76
|
return new LambdaHttpResponse(500, 'TileSet does not match.');
|
|
76
77
|
}
|
|
77
78
|
}
|
package/src/routes/imagery.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Config } from '@basemaps/config';
|
|
2
2
|
import { fsa } from '@basemaps/shared';
|
|
3
3
|
import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
|
|
4
|
-
import { createHash } from 'crypto';
|
|
5
4
|
import { promisify } from 'util';
|
|
6
5
|
import { gzip } from 'zlib';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { isGzip } from '../util/cotar.serve.js';
|
|
7
|
+
import { Etag } from '../util/etag.js';
|
|
8
|
+
import { NotFound, NotModified } from '../util/response.js';
|
|
9
9
|
|
|
10
10
|
const gzipP = promisify(gzip);
|
|
11
11
|
|
|
@@ -32,27 +32,28 @@ interface ImageryGet {
|
|
|
32
32
|
*/
|
|
33
33
|
export async function imageryGet(req: LambdaHttpRequest<ImageryGet>): Promise<LambdaHttpResponse> {
|
|
34
34
|
const requestedFile = req.params.fileName;
|
|
35
|
-
if (!isAllowedFile(requestedFile)) return
|
|
35
|
+
if (!isAllowedFile(requestedFile)) return NotFound();
|
|
36
36
|
|
|
37
37
|
const imagery = await Config.Imagery.get(Config.Imagery.id(req.params.imageryId));
|
|
38
|
-
if (imagery == null) return
|
|
38
|
+
if (imagery == null) return NotFound();
|
|
39
39
|
|
|
40
40
|
const targetPath = fsa.join(imagery.uri, requestedFile);
|
|
41
41
|
|
|
42
42
|
try {
|
|
43
43
|
const buf = await fsa.read(targetPath);
|
|
44
|
-
const cacheKey = createHash('sha256').update(buf).digest('base64');
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
const cacheKey = Etag.key(buf);
|
|
46
|
+
if (Etag.isNotModified(req, cacheKey)) return NotModified();
|
|
47
47
|
|
|
48
48
|
const response = new LambdaHttpResponse(200, 'ok');
|
|
49
49
|
response.header(HttpHeader.ETag, cacheKey);
|
|
50
50
|
response.header(HttpHeader.ContentEncoding, 'gzip');
|
|
51
|
-
response.
|
|
51
|
+
response.header(HttpHeader.CacheControl, 'public, max-age=604800, stale-while-revalidate=86400');
|
|
52
|
+
response.buffer(isGzip(buf) ? buf : await gzipP(buf), 'application/json');
|
|
52
53
|
req.set('bytes', buf.byteLength);
|
|
53
54
|
return response;
|
|
54
55
|
} catch (e) {
|
|
55
56
|
req.log.warn({ targetPath }, 'ImageryMetadata:Failed');
|
|
56
|
-
return
|
|
57
|
+
return NotFound();
|
|
57
58
|
}
|
|
58
59
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { LambdaHttpResponse, HttpHeader } from '@linzjs/lambda';
|
|
2
|
+
|
|
3
|
+
const OkResponse = new LambdaHttpResponse(200, 'ok');
|
|
4
|
+
OkResponse.header(HttpHeader.CacheControl, 'no-store');
|
|
5
|
+
|
|
6
|
+
export async function pingGet(): Promise<LambdaHttpResponse> {
|
|
7
|
+
return OkResponse;
|
|
8
|
+
}
|
package/src/routes/sprites.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Env } from '@basemaps/shared';
|
|
2
2
|
import { fsa } from '@chunkd/fs';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
import { LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
|
|
5
|
-
import { NotFound } from '
|
|
6
|
-
import { isGzip, serveFromCotar } from '../cotar.
|
|
4
|
+
import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
|
|
5
|
+
import { NotFound, NotModified } from '../util/response.js';
|
|
6
|
+
import { isGzip, serveFromCotar } from '../util/cotar.serve.js';
|
|
7
|
+
import { Etag } from '../util/etag.js';
|
|
7
8
|
|
|
8
9
|
interface SpriteGet {
|
|
9
10
|
Params: {
|
|
@@ -17,25 +18,30 @@ Extensions.set('.json', 'application/json');
|
|
|
17
18
|
|
|
18
19
|
export async function spriteGet(req: LambdaHttpRequest<SpriteGet>): Promise<LambdaHttpResponse> {
|
|
19
20
|
const assetLocation = Env.get(Env.AssetLocation);
|
|
20
|
-
if (assetLocation == null) return NotFound;
|
|
21
|
+
if (assetLocation == null) return NotFound();
|
|
21
22
|
|
|
22
23
|
const extension = path.extname(req.params.spriteName);
|
|
23
24
|
const mimeType = Extensions.get(extension);
|
|
24
|
-
if (mimeType == null) return NotFound;
|
|
25
|
+
if (mimeType == null) return NotFound();
|
|
25
26
|
|
|
26
27
|
const targetFile = fsa.join('sprites', req.params.spriteName);
|
|
27
|
-
if (assetLocation.endsWith('.tar.co')) return serveFromCotar(assetLocation, targetFile, mimeType);
|
|
28
|
+
if (assetLocation.endsWith('.tar.co')) return serveFromCotar(req, assetLocation, targetFile, mimeType);
|
|
28
29
|
|
|
29
30
|
try {
|
|
30
31
|
const filePath = fsa.join(assetLocation, targetFile);
|
|
31
32
|
req.set('target', filePath);
|
|
32
33
|
|
|
33
34
|
const buf = await fsa.read(filePath);
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
36
|
-
|
|
35
|
+
const cacheKey = Etag.key(buf);
|
|
36
|
+
if (Etag.isNotModified(req, cacheKey)) return NotModified();
|
|
37
|
+
|
|
38
|
+
const response = LambdaHttpResponse.ok().buffer(buf, mimeType);
|
|
39
|
+
response.header(HttpHeader.ETag, cacheKey);
|
|
40
|
+
response.header(HttpHeader.CacheControl, 'public, max-age=604800, stale-while-revalidate=86400');
|
|
41
|
+
if (isGzip(buf)) response.header(HttpHeader.ContentEncoding, 'gzip');
|
|
42
|
+
return response;
|
|
37
43
|
} catch (e: any) {
|
|
38
|
-
if (e.code === 404) return NotFound;
|
|
44
|
+
if (e.code === 404) return NotFound();
|
|
39
45
|
throw e;
|
|
40
46
|
}
|
|
41
47
|
}
|
package/src/routes/tile.json.ts
CHANGED
|
@@ -1,35 +1,41 @@
|
|
|
1
1
|
import { GoogleTms, TileJson, TileMatrixSet } from '@basemaps/geo';
|
|
2
|
-
import {
|
|
2
|
+
import { Config, Env } from '@basemaps/shared';
|
|
3
3
|
import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
4
|
+
import { NotFound } from '../util/response.js';
|
|
5
|
+
import { Validate } from '../util/validate.js';
|
|
6
|
+
|
|
7
|
+
export interface TileJsonGet {
|
|
8
|
+
Params: {
|
|
9
|
+
tileSet: string;
|
|
10
|
+
tileMatrix: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
7
13
|
|
|
8
|
-
export async function
|
|
9
|
-
const
|
|
10
|
-
if (
|
|
14
|
+
export async function tileJsonGet(req: LambdaHttpRequest<TileJsonGet>): Promise<LambdaHttpResponse> {
|
|
15
|
+
const tileMatrix = Validate.getTileMatrixSet(req.params.tileMatrix);
|
|
16
|
+
if (tileMatrix == null) return NotFound();
|
|
11
17
|
|
|
12
|
-
const
|
|
13
|
-
if (tileMatrix == null) return NotFound;
|
|
18
|
+
const apiKey = Validate.apiKey(req);
|
|
14
19
|
|
|
15
20
|
req.timer.start('tileset:load');
|
|
16
|
-
const tileSet = await
|
|
21
|
+
const tileSet = await Config.TileSet.get(Config.TileSet.id(req.params.tileSet));
|
|
17
22
|
req.timer.end('tileset:load');
|
|
18
|
-
if (tileSet == null) return NotFound;
|
|
23
|
+
if (tileSet == null) return NotFound();
|
|
24
|
+
|
|
25
|
+
const format = Validate.getRequestedFormats(req) ?? [tileSet.format];
|
|
19
26
|
|
|
20
|
-
const apiKey = Router.apiKey(req);
|
|
21
27
|
const host = Env.get(Env.PublicUrlBase) ?? '';
|
|
22
28
|
|
|
23
29
|
const tileUrl =
|
|
24
|
-
[host,
|
|
25
|
-
`.${
|
|
30
|
+
[host, 'v1', 'tiles', tileSet.name, tileMatrix.identifier, '{z}', '{x}', '{y}'].join('/') +
|
|
31
|
+
`.${format[0]}?api=${apiKey}`;
|
|
26
32
|
|
|
27
33
|
const tileJson: TileJson = { tiles: [tileUrl], tilejson: '3.0.0' };
|
|
28
|
-
const maxZoom = TileMatrixSet.convertZoomLevel(tileSet.
|
|
29
|
-
const minZoom = TileMatrixSet.convertZoomLevel(tileSet.
|
|
34
|
+
const maxZoom = TileMatrixSet.convertZoomLevel(tileSet.maxZoom ?? 30, GoogleTms, tileMatrix, true);
|
|
35
|
+
const minZoom = TileMatrixSet.convertZoomLevel(tileSet.minZoom ?? 0, GoogleTms, tileMatrix, true);
|
|
30
36
|
|
|
31
|
-
if (tileSet.
|
|
32
|
-
if (tileSet.
|
|
37
|
+
if (tileSet.maxZoom) tileJson.maxzoom = maxZoom;
|
|
38
|
+
if (tileSet.minZoom) tileJson.minzoom = minZoom;
|
|
33
39
|
|
|
34
40
|
const json = JSON.stringify(tileJson);
|
|
35
41
|
const data = Buffer.from(json);
|
|
@@ -2,11 +2,10 @@ import { Sources, StyleJson } from '@basemaps/config';
|
|
|
2
2
|
import { Config, Env } from '@basemaps/shared';
|
|
3
3
|
import { fsa } from '@chunkd/fs';
|
|
4
4
|
import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
|
|
5
|
-
import { createHash } from 'crypto';
|
|
6
5
|
import { URL } from 'url';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
6
|
+
import { NotFound, NotModified } from '../util/response.js';
|
|
7
|
+
import { Validate } from '../util/validate.js';
|
|
8
|
+
import { Etag } from '../util/etag.js';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* Convert relative URLS into a full hostname url
|
|
@@ -54,23 +53,27 @@ export function convertStyleJson(style: StyleJson, apiKey: string): StyleJson {
|
|
|
54
53
|
} as StyleJson;
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
export
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
export interface StyleGet {
|
|
57
|
+
Params: {
|
|
58
|
+
styleName: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function styleJsonGet(req: LambdaHttpRequest<StyleGet>): Promise<LambdaHttpResponse> {
|
|
63
|
+
const apiKey = Validate.apiKey(req);
|
|
64
|
+
const styleName = req.params.styleName;
|
|
61
65
|
|
|
62
66
|
// Get style Config from db
|
|
63
67
|
const dbId = Config.Style.id(styleName);
|
|
64
68
|
const styleConfig = await Config.Style.get(dbId);
|
|
65
|
-
if (styleConfig == null) return NotFound;
|
|
69
|
+
if (styleConfig == null) return NotFound();
|
|
66
70
|
|
|
67
71
|
// Prepare sources and add linz source
|
|
68
72
|
const style = convertStyleJson(styleConfig.style, apiKey);
|
|
69
73
|
const data = Buffer.from(JSON.stringify(style));
|
|
70
74
|
|
|
71
|
-
const cacheKey =
|
|
72
|
-
|
|
73
|
-
if (TileEtag.isNotModified(req, cacheKey)) return NotModified;
|
|
75
|
+
const cacheKey = Etag.key(data);
|
|
76
|
+
if (Etag.isNotModified(req, cacheKey)) return NotModified();
|
|
74
77
|
|
|
75
78
|
const response = new LambdaHttpResponse(200, 'ok');
|
|
76
79
|
response.header(HttpHeader.ETag, cacheKey);
|