@basemaps/lambda-tiler 6.24.2 → 6.25.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 +12 -0
- package/build/__test__/tile.cache.key.test.js +2 -3
- package/build/__test__/tile.import.test.d.ts +2 -0
- package/build/__test__/tile.import.test.d.ts.map +1 -0
- package/build/__test__/tile.import.test.js +115 -0
- package/build/__test__/xyz.test.js +55 -28
- package/build/__test__/xyz.util.d.ts +4 -0
- package/build/__test__/xyz.util.d.ts.map +1 -1
- package/build/__test__/xyz.util.js +8 -1
- package/build/cli/dump.js +2 -3
- package/build/import/imagery.find.d.ts +17 -0
- package/build/import/imagery.find.d.ts.map +1 -0
- package/build/import/imagery.find.js +38 -0
- package/build/import/make.cog.d.ts +5 -0
- package/build/import/make.cog.d.ts.map +1 -0
- package/build/import/make.cog.js +21 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -0
- package/build/routes/__test__/health.test.js +1 -2
- package/build/routes/health.d.ts.map +1 -1
- package/build/routes/health.js +3 -4
- package/build/routes/import.d.ts +9 -0
- package/build/routes/import.d.ts.map +1 -0
- package/build/routes/import.js +61 -0
- package/build/routes/tile.json.d.ts +0 -7
- package/build/routes/tile.json.d.ts.map +1 -1
- package/build/routes/tile.json.js +26 -18
- package/build/tile.set.cache.js +1 -1
- package/build/tile.set.raster.d.ts +3 -1
- package/build/tile.set.raster.d.ts.map +1 -1
- package/build/tile.set.raster.js +7 -2
- package/build/tile.set.vector.d.ts +4 -1
- package/build/tile.set.vector.d.ts.map +1 -1
- package/build/tile.set.vector.js +9 -1
- package/build/wmts.capability.d.ts +4 -0
- package/build/wmts.capability.d.ts.map +1 -1
- package/build/wmts.capability.js +1 -1
- package/package.json +9 -8
- package/src/__test__/tile.cache.key.test.ts +3 -3
- package/src/__test__/tile.import.test.ts +140 -0
- package/src/__test__/xyz.test.ts +59 -28
- package/src/__test__/xyz.util.ts +10 -2
- package/src/cli/dump.ts +2 -3
- package/src/import/imagery.find.ts +60 -0
- package/src/import/make.cog.ts +29 -0
- package/src/index.ts +2 -0
- package/src/routes/__test__/health.test.ts +1 -3
- package/src/routes/health.ts +3 -4
- package/src/routes/import.ts +66 -0
- package/src/routes/tile.json.ts +26 -27
- package/src/tile.set.cache.ts +1 -1
- package/src/tile.set.raster.ts +7 -2
- package/src/tile.set.vector.ts +11 -2
- package/src/wmts.capability.ts +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,30 +1,38 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GoogleTms, TileMatrixSet } from '@basemaps/geo';
|
|
2
|
+
import { Env, extractTileMatrixSet } from '@basemaps/shared';
|
|
2
3
|
import { HttpHeader, LambdaHttpResponse } from '@linzjs/lambda';
|
|
3
|
-
import { createHash } from 'crypto';
|
|
4
4
|
import { Router } from '../router.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { TileSets } from '../tile.set.cache.js';
|
|
6
|
+
import { getTileMatrixId } from '../wmts.capability.js';
|
|
7
|
+
import { NotFound } from './response.js';
|
|
7
8
|
export async function tileJson(req) {
|
|
8
|
-
var _a;
|
|
9
|
+
var _a, _b, _c;
|
|
9
10
|
const { version, rest, name } = Router.action(req);
|
|
11
|
+
if (rest.length !== 3)
|
|
12
|
+
return NotFound;
|
|
13
|
+
const tileMatrix = extractTileMatrixSet(rest[1]);
|
|
14
|
+
if (tileMatrix == null)
|
|
15
|
+
return NotFound;
|
|
16
|
+
req.timer.start('tileset:load');
|
|
17
|
+
const tileSet = await TileSets.get(rest[0], tileMatrix);
|
|
18
|
+
req.timer.end('tileset:load');
|
|
19
|
+
if (tileSet == null)
|
|
20
|
+
return NotFound;
|
|
10
21
|
const apiKey = Router.apiKey(req);
|
|
11
22
|
const host = (_a = Env.get(Env.PublicUrlBase)) !== null && _a !== void 0 ? _a : '';
|
|
12
|
-
const tileUrl =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
const tileUrl = [host, version, name, tileSet.fullName, getTileMatrixId(tileMatrix), '{z}', '{x}', '{y}'].join('/') +
|
|
24
|
+
`.${tileSet.format}?api=${apiKey}`;
|
|
25
|
+
const tileJson = { tiles: [tileUrl], vector_layers: [], tilejson: '3.0.0' };
|
|
26
|
+
const maxZoom = TileMatrixSet.convertZoomLevel((_b = tileSet.tileSet.maxZoom) !== null && _b !== void 0 ? _b : 30, GoogleTms, tileMatrix, true);
|
|
27
|
+
const minZoom = TileMatrixSet.convertZoomLevel((_c = tileSet.tileSet.minZoom) !== null && _c !== void 0 ? _c : 0, GoogleTms, tileMatrix, true);
|
|
28
|
+
if (tileSet.tileSet.maxZoom)
|
|
29
|
+
tileJson.maxzoom = maxZoom;
|
|
30
|
+
if (tileSet.tileSet.minZoom)
|
|
31
|
+
tileJson.minzoom = minZoom;
|
|
20
32
|
const json = JSON.stringify(tileJson);
|
|
21
33
|
const data = Buffer.from(json);
|
|
22
|
-
const cacheKey = createHash('sha256').update(data).digest('base64');
|
|
23
|
-
if (TileEtag.isNotModified(req, cacheKey))
|
|
24
|
-
return NotModified;
|
|
25
34
|
const response = new LambdaHttpResponse(200, 'ok');
|
|
26
|
-
response.header(HttpHeader.
|
|
27
|
-
response.header(HttpHeader.CacheControl, 'max-age=120');
|
|
35
|
+
response.header(HttpHeader.CacheControl, 'no-store');
|
|
28
36
|
response.buffer(data, 'application/json');
|
|
29
37
|
req.set('bytes', data.byteLength);
|
|
30
38
|
return response;
|
package/build/tile.set.cache.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { ConfigImagery, ConfigTileSetRaster, TileSetNameComponents, TileSetType } from '@basemaps/config';
|
|
3
|
-
import { Bounds, Tile, TileMatrixSet } from '@basemaps/geo';
|
|
3
|
+
import { Bounds, ImageFormat, Tile, TileMatrixSet } from '@basemaps/geo';
|
|
4
4
|
import { LogType, TileDataXyz } from '@basemaps/shared';
|
|
5
5
|
import { Tiler } from '@basemaps/tiler';
|
|
6
6
|
import { TileMakerSharp } from '@basemaps/tiler-sharp';
|
|
@@ -35,6 +35,8 @@ export declare class TileSetRaster {
|
|
|
35
35
|
get title(): string;
|
|
36
36
|
get description(): string;
|
|
37
37
|
get extent(): Bounds;
|
|
38
|
+
/** Preferred default imagery format */
|
|
39
|
+
get format(): ImageFormat;
|
|
38
40
|
init(record: ConfigTileSetRaster): Promise<void>;
|
|
39
41
|
initTiffs(tile: Tile, log: LogType): Promise<CogTiff[]>;
|
|
40
42
|
tile(req: LambdaHttpRequest, xyz: TileDataXyz): Promise<LambdaHttpResponse>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tile.set.raster.d.ts","sourceRoot":"","sources":["../src/tile.set.raster.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,aAAa,EAEb,mBAAmB,EACnB,qBAAqB,EAErB,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAQ,IAAI,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"tile.set.raster.d.ts","sourceRoot":"","sources":["../src/tile.set.raster.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,aAAa,EAEb,mBAAmB,EACnB,qBAAqB,EAErB,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAQ,WAAW,EAAE,IAAI,EAAE,aAAa,EAAgC,MAAM,eAAe,CAAC;AAC7G,OAAO,EAAoB,OAAO,EAAE,WAAW,EAAuB,MAAM,kBAAkB,CAAC;AAC/F,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAc,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAU1C,eAAO,MAAM,YAAY,gBAA0B,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAKD,qBAAa,aAAa;IACxB,IAAI,EAAE,WAAW,CAAC,MAAM,CAAsB;IAE9C,UAAU,EAAE,aAAa,CAAC;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACpC,cAAc,EAAE,MAAM,CAAC;IAEvB,UAAU,EAAE,qBAAqB,CAAC;IAClC,OAAO,EAAE,mBAAmB,CAAC;IAE7B;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;gBAMjD,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa;IAMnD,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,uCAAuC;IACvC,IAAI,MAAM,IAAI,WAAW,CAExB;IAEK,IAAI,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAKhD,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAmBhD,IAAI,CAAC,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA8BxF;;;;OAIG;IACI,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,EAAE;IAgC5D,OAAO,CAAC,cAAc;IAwBtB,oDAAoD;IACpD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAShD,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;CAqB3C"}
|
package/build/tile.set.raster.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TileSetNameParser, TileSetType, } from '@basemaps/config';
|
|
2
|
-
import { Bounds, Epsg, TileMatrixSet, TileMatrixSets } from '@basemaps/geo';
|
|
3
|
-
import { Config, Env, fsa, titleizeImageryName
|
|
2
|
+
import { Bounds, Epsg, ImageFormat, TileMatrixSet, TileMatrixSets, VectorFormat } from '@basemaps/geo';
|
|
3
|
+
import { Config, Env, fsa, titleizeImageryName } from '@basemaps/shared';
|
|
4
4
|
import { Tiler } from '@basemaps/tiler';
|
|
5
5
|
import { TileMakerSharp } from '@basemaps/tiler-sharp';
|
|
6
6
|
import { CogTiff } from '@cogeotiff/core';
|
|
@@ -52,6 +52,11 @@ export class TileSetRaster {
|
|
|
52
52
|
var _a;
|
|
53
53
|
return (_a = this.extentOverride) !== null && _a !== void 0 ? _a : this.tileMatrix.extent;
|
|
54
54
|
}
|
|
55
|
+
/** Preferred default imagery format */
|
|
56
|
+
get format() {
|
|
57
|
+
var _a;
|
|
58
|
+
return (_a = this.tileSet.format) !== null && _a !== void 0 ? _a : ImageFormat.Webp;
|
|
59
|
+
}
|
|
55
60
|
async init(record) {
|
|
56
61
|
this.tileSet = record;
|
|
57
62
|
this.imagery = await Config.getAllImagery(this.tileSet.layers, this.tileMatrix.projection);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ConfigTileSetVector, TileSetNameComponents, TileSetType } from '@basemaps/config';
|
|
2
|
-
import { TileMatrixSet } from '@basemaps/geo';
|
|
2
|
+
import { TileMatrixSet, VectorFormat } from '@basemaps/geo';
|
|
3
3
|
import { TileDataXyz } from '@basemaps/shared';
|
|
4
4
|
import { Cotar } from '@cotar/core';
|
|
5
5
|
import { LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
|
|
@@ -14,6 +14,9 @@ export declare class TileSetVector {
|
|
|
14
14
|
tileMatrix: TileMatrixSet;
|
|
15
15
|
tileSet: ConfigTileSetVector;
|
|
16
16
|
constructor(name: string, tileMatrix: TileMatrixSet);
|
|
17
|
+
init(record: ConfigTileSetVector): Promise<void>;
|
|
18
|
+
/** What format does tile set use */
|
|
19
|
+
get format(): VectorFormat;
|
|
17
20
|
get id(): string;
|
|
18
21
|
get fullName(): string;
|
|
19
22
|
tile(req: LambdaHttpRequest, xyz: TileDataXyz): Promise<LambdaHttpResponse>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tile.set.vector.d.ts","sourceRoot":"","sources":["../src/tile.set.vector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAqB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9G,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"tile.set.vector.d.ts","sourceRoot":"","sources":["../src/tile.set.vector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAqB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9G,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAO,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAc,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAKnF,cAAM,UAAU;IACd,KAAK,qCAA4C;IAEjD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;CAUxC;AAED,eAAO,MAAM,MAAM,YAAmB,CAAC;AAEvC,qBAAa,aAAa;IACxB,IAAI,EAAE,WAAW,CAAC,MAAM,CAAsB;IAC9C,UAAU,EAAE,qBAAqB,CAAC;IAClC,UAAU,EAAE,aAAa,CAAC;IAC1B,OAAO,EAAE,mBAAmB,CAAC;gBACjB,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa;IAK7C,IAAI,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,oCAAoC;IACpC,IAAI,MAAM,IAAI,YAAY,CAEzB;IAED,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAEK,IAAI,CAAC,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAwBlF"}
|
package/build/tile.set.vector.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TileSetNameParser, TileSetType } from '@basemaps/config';
|
|
2
|
-
import {
|
|
2
|
+
import { VectorFormat } from '@basemaps/geo';
|
|
3
|
+
import { fsa } from '@basemaps/shared';
|
|
3
4
|
import { Cotar } from '@cotar/core';
|
|
4
5
|
import { HttpHeader, LambdaHttpResponse } from '@linzjs/lambda';
|
|
5
6
|
import { NotFound } from './routes/response.js';
|
|
@@ -27,6 +28,13 @@ export class TileSetVector {
|
|
|
27
28
|
this.components = TileSetNameParser.parse(name);
|
|
28
29
|
this.tileMatrix = tileMatrix;
|
|
29
30
|
}
|
|
31
|
+
async init(record) {
|
|
32
|
+
this.tileSet = record;
|
|
33
|
+
}
|
|
34
|
+
/** What format does tile set use */
|
|
35
|
+
get format() {
|
|
36
|
+
return VectorFormat.MapboxVectorTiles;
|
|
37
|
+
}
|
|
30
38
|
get id() {
|
|
31
39
|
return TileSets.id(this.fullName, this.tileMatrix);
|
|
32
40
|
}
|
|
@@ -2,6 +2,10 @@ import { ConfigProvider } from '@basemaps/config';
|
|
|
2
2
|
import { Bounds, TileMatrixSet, WmtsProvider } from '@basemaps/geo';
|
|
3
3
|
import { VNodeElement } from '@basemaps/shared';
|
|
4
4
|
import { TileSetRaster } from './tile.set.raster.js';
|
|
5
|
+
/**
|
|
6
|
+
* Default the tile matrix id to the projection of the TileMatrixSet
|
|
7
|
+
*/
|
|
8
|
+
export declare function getTileMatrixId(tileMatrix: TileMatrixSet): string;
|
|
5
9
|
export declare class WmtsCapabilities {
|
|
6
10
|
httpBase: string;
|
|
7
11
|
provider: WmtsProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wmts.capability.d.ts","sourceRoot":"","sources":["../src/wmts.capability.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAmB,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAiB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG/D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"wmts.capability.d.ts","sourceRoot":"","sources":["../src/wmts.capability.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAmB,aAAa,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAiB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAG/D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAiBrD;;GAEG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,aAAa,GAAG,MAAM,CAIjE;AAED,qBAAa,gBAAgB;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IAEvB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CAAa;IAEjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,6BAAoC;gBAEtC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM;IAmB9F,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,OAAO,SAAyB,GAAG,YAAY;IAe9F,gBAAgB,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY;IAQlE,aAAa,IAAI,YAAY,EAAE;IAkC/B,YAAY,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAc5D,gBAAgB,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY;IAQtE,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,YAAY;IAuBjD,UAAU,IAAI,YAAY;IAI1B,kBAAkB,CAAC,GAAG,EAAE,aAAa,GAAG,YAAY;IAoBpD,OAAO,IAAI,YAAY;IAUvB,QAAQ,IAAI,MAAM;IAIlB,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM;CAG5G"}
|
package/build/wmts.capability.js
CHANGED
|
@@ -17,7 +17,7 @@ function wgs84Extent(layer) {
|
|
|
17
17
|
/**
|
|
18
18
|
* Default the tile matrix id to the projection of the TileMatrixSet
|
|
19
19
|
*/
|
|
20
|
-
function getTileMatrixId(tileMatrix) {
|
|
20
|
+
export function getTileMatrixId(tileMatrix) {
|
|
21
21
|
// TODO this should really change everything to identifier
|
|
22
22
|
if (tileMatrix.identifier === Nztm2000QuadTms.identifier)
|
|
23
23
|
return Nztm2000QuadTms.identifier;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basemaps/lambda-tiler",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.25.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/linz/basemaps.git",
|
|
@@ -22,12 +22,13 @@
|
|
|
22
22
|
"types": "./build/index.d.ts",
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@basemaps/
|
|
26
|
-
"@basemaps/
|
|
25
|
+
"@basemaps/cli": "^6.25.0",
|
|
26
|
+
"@basemaps/config": "^6.25.0",
|
|
27
|
+
"@basemaps/geo": "^6.25.0",
|
|
27
28
|
"@basemaps/lambda": "^6.7.0",
|
|
28
|
-
"@basemaps/shared": "^6.
|
|
29
|
-
"@basemaps/tiler": "^6.
|
|
30
|
-
"@basemaps/tiler-sharp": "^6.
|
|
29
|
+
"@basemaps/shared": "^6.25.0",
|
|
30
|
+
"@basemaps/tiler": "^6.25.0",
|
|
31
|
+
"@basemaps/tiler-sharp": "^6.25.0",
|
|
31
32
|
"@chunkd/fs": "^8.1.0",
|
|
32
33
|
"@cogeotiff/core": "^7.0.0",
|
|
33
34
|
"@cotar/core": "^5.3.0",
|
|
@@ -52,12 +53,12 @@
|
|
|
52
53
|
"bundle": "./bundle.sh"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
|
-
"@basemaps/attribution": "^6.
|
|
56
|
+
"@basemaps/attribution": "^6.25.0",
|
|
56
57
|
"@types/aws-lambda": "^8.10.75",
|
|
57
58
|
"@types/node": "^14.11.2",
|
|
58
59
|
"@types/pixelmatch": "^5.0.0",
|
|
59
60
|
"@types/sharp": "^0.29.3",
|
|
60
61
|
"pretty-json-log": "^1.0.0"
|
|
61
62
|
},
|
|
62
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "7ef26df6d42b79298035033fb6434d086fa642f8"
|
|
63
64
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { GoogleTms, Nztm2000Tms } from '@basemaps/geo';
|
|
1
|
+
import { GoogleTms, Nztm2000Tms, ImageFormat } from '@basemaps/geo';
|
|
2
2
|
import { TileDataXyz, TileType } from '@basemaps/shared';
|
|
3
3
|
import { TestTiff } from '@basemaps/test';
|
|
4
|
-
import { Composition
|
|
4
|
+
import { Composition } from '@basemaps/tiler';
|
|
5
5
|
import o from 'ospec';
|
|
6
6
|
import { TileEtag } from '../routes/tile.etag.js';
|
|
7
7
|
|
|
@@ -14,7 +14,7 @@ o.spec('TileCacheKey', () => {
|
|
|
14
14
|
z: 0,
|
|
15
15
|
tileMatrix: GoogleTms,
|
|
16
16
|
name: 'foo',
|
|
17
|
-
ext: ImageFormat.
|
|
17
|
+
ext: ImageFormat.Png,
|
|
18
18
|
type: TileType.Tile,
|
|
19
19
|
};
|
|
20
20
|
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { JobCreationContext } from '@basemaps/cli/build/cog/cog.stac.job';
|
|
2
|
+
import { Nztm2000Tms } from '@basemaps/geo';
|
|
3
|
+
import { Config, Env, fsa, LogConfig } from '@basemaps/shared';
|
|
4
|
+
import o from 'ospec';
|
|
5
|
+
import { createHash } from 'crypto';
|
|
6
|
+
import sinon from 'sinon';
|
|
7
|
+
import { LambdaAlbRequest, LambdaHttpRequest } from '@linzjs/lambda';
|
|
8
|
+
import { Context } from 'aws-lambda';
|
|
9
|
+
import { Import } from '../routes/import.js';
|
|
10
|
+
import { RoleConfig } from '../import/imagery.find.js';
|
|
11
|
+
import { CogJobFactory } from '@basemaps/cli';
|
|
12
|
+
import { ConfigProcessingJob } from '@basemaps/config';
|
|
13
|
+
|
|
14
|
+
o.spec('Import', () => {
|
|
15
|
+
const sandbox = sinon.createSandbox();
|
|
16
|
+
const outputBucket = 'testOutputBucket';
|
|
17
|
+
const configBucket = 'testConfigBucket';
|
|
18
|
+
const origConfigBucket = process.env[Env.AwsRoleConfigBucket];
|
|
19
|
+
const origOutputBucket = process.env[Env.ImportImageryBucket];
|
|
20
|
+
o.beforeEach(() => {
|
|
21
|
+
process.env[Env.AwsRoleConfigBucket] = configBucket;
|
|
22
|
+
process.env[Env.ImportImageryBucket] = outputBucket;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
o.afterEach(() => {
|
|
26
|
+
process.env[Env.AwsRoleConfigBucket] = origConfigBucket;
|
|
27
|
+
process.env[Env.ImportImageryBucket] = origOutputBucket;
|
|
28
|
+
sandbox.restore();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const tileMatrix = Nztm2000Tms;
|
|
32
|
+
const bucket = 'testSourceBucket';
|
|
33
|
+
const path = `s3://${bucket}/imagery/`;
|
|
34
|
+
const role: RoleConfig = {
|
|
35
|
+
bucket,
|
|
36
|
+
accountId: '123456',
|
|
37
|
+
roleArn: 'arn:aws:iam::123456:role/read-role',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const files = [`${path}/1.tiff`, `${path}/2.tiff`];
|
|
41
|
+
async function* listFiles(): AsyncGenerator<string, any, unknown> {
|
|
42
|
+
for (const key in files) yield files[key];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const ctx: JobCreationContext = {
|
|
46
|
+
override: {
|
|
47
|
+
projection: tileMatrix.projection,
|
|
48
|
+
resampling: {
|
|
49
|
+
warp: 'bilinear',
|
|
50
|
+
overview: 'lanczos',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
outputLocation: { type: 's3' as const, path: `s3://${outputBucket}` },
|
|
54
|
+
sourceLocation: { type: 's3', path: path, ...role, files: files },
|
|
55
|
+
batch: true,
|
|
56
|
+
tileMatrix,
|
|
57
|
+
oneCogCovering: false,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const id = createHash('sha256').update(JSON.stringify(ctx)).digest('base64');
|
|
61
|
+
const jobId = Config.ProcessingJob.id(id);
|
|
62
|
+
|
|
63
|
+
function getRequest(path: string, projection: string): LambdaHttpRequest {
|
|
64
|
+
return new LambdaAlbRequest(
|
|
65
|
+
{
|
|
66
|
+
requestContext: null as any,
|
|
67
|
+
httpMethod: 'get',
|
|
68
|
+
path: '/v1/tiles/import',
|
|
69
|
+
body: null,
|
|
70
|
+
isBase64Encoded: false,
|
|
71
|
+
queryStringParameters: { path: path, p: projection },
|
|
72
|
+
},
|
|
73
|
+
{} as Context,
|
|
74
|
+
LogConfig.get(),
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
o('should return projection not found', async () => {
|
|
79
|
+
// Given ... wrong projection
|
|
80
|
+
const req = getRequest(path, '0000');
|
|
81
|
+
|
|
82
|
+
// When ... Then ...
|
|
83
|
+
const res = await Import(req);
|
|
84
|
+
o(res.body).equals('{"status":404,"message":"Target projection Not found"}');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
o('should return Invalid s3 location', async () => {
|
|
88
|
+
// Given... wrong s3 path
|
|
89
|
+
const req = getRequest('s3::testbucket/', '2193');
|
|
90
|
+
|
|
91
|
+
// When ...Then ...
|
|
92
|
+
const res = await Import(req);
|
|
93
|
+
o(res.body).equals('{"status":500,"message":"Invalid s3 path"}');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
o('should return Unable to access bucket', async () => {
|
|
97
|
+
// Given... different bucket have no access role
|
|
98
|
+
sandbox.stub(fsa, 'readJson').resolves({ buckets: [role] });
|
|
99
|
+
const req = getRequest(`s3://wrong-bucket/imagery/`, '2193');
|
|
100
|
+
|
|
101
|
+
// When ...Then ...
|
|
102
|
+
const res = await Import(req);
|
|
103
|
+
o(res.body).equals('{"status":500,"message":"Unable to Access the bucket"}');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
o('should return Imagery not found', async () => {
|
|
107
|
+
// Given... none imagery find from bucket
|
|
108
|
+
sandbox.stub(fsa, 'readJson').resolves({ buckets: [role] });
|
|
109
|
+
sandbox.stub(fsa, 'list').callsFake(async function* () {
|
|
110
|
+
yield `${path}1.json`;
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const req = getRequest(path, '2193');
|
|
114
|
+
|
|
115
|
+
// When ...Then ...
|
|
116
|
+
const res = await Import(req);
|
|
117
|
+
o(res.body).equals('{"status":404,"message":"Imagery Not Found"}');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
o('should return 200 with existing import', async () => {
|
|
121
|
+
// Given... different bucket have no access role
|
|
122
|
+
sandbox.stub(fsa, 'readJson').resolves({ buckets: [role] });
|
|
123
|
+
sandbox.stub(fsa, 'list').callsFake(listFiles);
|
|
124
|
+
sandbox.stub(CogJobFactory, 'create').resolves(undefined);
|
|
125
|
+
|
|
126
|
+
const jobConfig = {
|
|
127
|
+
id: jobId,
|
|
128
|
+
name: path,
|
|
129
|
+
status: 'complete',
|
|
130
|
+
} as ConfigProcessingJob;
|
|
131
|
+
sandbox.stub(Config.ProcessingJob, 'get').resolves(jobConfig);
|
|
132
|
+
const req = getRequest(path, '2193');
|
|
133
|
+
|
|
134
|
+
// When ...Then ...
|
|
135
|
+
const res = await Import(req);
|
|
136
|
+
o(res.status).equals(200);
|
|
137
|
+
const body = Buffer.from(res.body ?? '', 'base64').toString();
|
|
138
|
+
o(JSON.parse(body)).deepEquals(jobConfig);
|
|
139
|
+
});
|
|
140
|
+
});
|
package/src/__test__/xyz.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ConfigProvider, StyleJson } from '@basemaps/config';
|
|
2
|
-
import { TileMatrixSets } from '@basemaps/geo';
|
|
2
|
+
import { GoogleTms, Nztm2000QuadTms, TileMatrixSets } from '@basemaps/geo';
|
|
3
3
|
import { Config, Env, LogConfig, VNodeParser } from '@basemaps/shared';
|
|
4
4
|
import { round } from '@basemaps/test/build/rounding.js';
|
|
5
5
|
import o from 'ospec';
|
|
@@ -8,7 +8,7 @@ import { handleRequest } from '../index.js';
|
|
|
8
8
|
import { TileEtag } from '../routes/tile.etag.js';
|
|
9
9
|
import { TileSets } from '../tile.set.cache.js';
|
|
10
10
|
import { TileComposer } from '../tile.set.raster.js';
|
|
11
|
-
import { FakeTileSet, mockRequest, Provider } from './xyz.util.js';
|
|
11
|
+
import { FakeTileSet, FakeTileSetVector, mockRequest, Provider } from './xyz.util.js';
|
|
12
12
|
|
|
13
13
|
const sandbox = sinon.createSandbox();
|
|
14
14
|
|
|
@@ -53,6 +53,8 @@ o.spec('LambdaXyz', () => {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
TileSets.add(new FakeTileSetVector('topographic', GoogleTms));
|
|
57
|
+
|
|
56
58
|
(Config.Provider as any).get = async (): Promise<ConfigProvider> => Provider;
|
|
57
59
|
});
|
|
58
60
|
|
|
@@ -186,51 +188,80 @@ o.spec('LambdaXyz', () => {
|
|
|
186
188
|
});
|
|
187
189
|
|
|
188
190
|
o.spec('tileJson', () => {
|
|
189
|
-
o('should
|
|
190
|
-
|
|
191
|
+
o('should 404 if invalid url is given', async () => {
|
|
192
|
+
const request = mockRequest('/v1/tiles/tile.json', 'get', apiKeyHeader);
|
|
191
193
|
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
+
const res = await handleRequest(request);
|
|
195
|
+
o(res.status).equals(404);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
o('should serve tile json for tile_set', async () => {
|
|
199
|
+
const request = mockRequest('/v1/tiles/aerial/NZTM2000Quad/tile.json', 'get', apiKeyHeader);
|
|
194
200
|
|
|
195
201
|
const res = await handleRequest(request);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
202
|
+
o(res.status).equals(200);
|
|
203
|
+
o(res.header('cache-control')).equals('no-store');
|
|
200
204
|
|
|
201
|
-
|
|
202
|
-
o(
|
|
205
|
+
const body = Buffer.from(res.body ?? '', 'base64').toString();
|
|
206
|
+
o(JSON.parse(body)).deepEquals({
|
|
207
|
+
tiles: [`https://tiles.test/v1/tiles/aerial/NZTM2000Quad/{z}/{x}/{y}.webp?api=${apiKey}`],
|
|
208
|
+
vector_layers: [],
|
|
209
|
+
tilejson: '3.0.0',
|
|
210
|
+
});
|
|
211
|
+
});
|
|
203
212
|
|
|
204
|
-
|
|
213
|
+
o('should serve vector tiles', async () => {
|
|
214
|
+
const request = mockRequest('/v1/tiles/topographic/WebMercatorQuad/tile.json', 'get', apiKeyHeader);
|
|
215
|
+
|
|
216
|
+
const res = await handleRequest(request);
|
|
217
|
+
o(res.status).equals(200);
|
|
218
|
+
|
|
219
|
+
const body = Buffer.from(res.body ?? '', 'base64').toString();
|
|
220
|
+
o(JSON.parse(body)).deepEquals({
|
|
221
|
+
tiles: [`https://tiles.test/v1/tiles/topographic/EPSG:3857/{z}/{x}/{y}.pbf?api=${apiKey}`],
|
|
222
|
+
vector_layers: [],
|
|
223
|
+
tilejson: '3.0.0',
|
|
224
|
+
});
|
|
205
225
|
});
|
|
206
226
|
|
|
207
|
-
o('should
|
|
208
|
-
const
|
|
209
|
-
|
|
227
|
+
o('should serve vector tiles with min/max zoom', async () => {
|
|
228
|
+
const fakeTileSet = new FakeTileSetVector('fake-vector', GoogleTms);
|
|
229
|
+
fakeTileSet.tileSet.maxZoom = 15;
|
|
230
|
+
fakeTileSet.tileSet.minZoom = 3;
|
|
231
|
+
TileSets.add(fakeTileSet);
|
|
232
|
+
const request = mockRequest('/v1/tiles/fake-vector/WebMercatorQuad/tile.json', 'get', apiKeyHeader);
|
|
210
233
|
|
|
211
234
|
const res = await handleRequest(request);
|
|
212
235
|
o(res.status).equals(200);
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
o(
|
|
216
|
-
|
|
236
|
+
|
|
237
|
+
const body = Buffer.from(res.body ?? '', 'base64').toString();
|
|
238
|
+
o(JSON.parse(body)).deepEquals({
|
|
239
|
+
tiles: [`https://tiles.test/v1/tiles/fake-vector/EPSG:3857/{z}/{x}/{y}.pbf?api=${apiKey}`],
|
|
240
|
+
vector_layers: [],
|
|
241
|
+
maxzoom: 15,
|
|
242
|
+
minzoom: 3,
|
|
243
|
+
tilejson: '3.0.0',
|
|
244
|
+
});
|
|
217
245
|
});
|
|
218
246
|
|
|
219
|
-
o('should serve
|
|
220
|
-
const
|
|
247
|
+
o('should serve convert zoom to tile matrix', async () => {
|
|
248
|
+
const fakeTileSet = new FakeTileSetVector('fake-vector', Nztm2000QuadTms);
|
|
249
|
+
fakeTileSet.tileSet.maxZoom = 15;
|
|
250
|
+
fakeTileSet.tileSet.minZoom = 1;
|
|
251
|
+
TileSets.add(fakeTileSet);
|
|
252
|
+
|
|
253
|
+
const request = mockRequest('/v1/tiles/fake-vector/NZTM2000Quad/tile.json', 'get', apiKeyHeader);
|
|
221
254
|
|
|
222
255
|
const res = await handleRequest(request);
|
|
223
256
|
o(res.status).equals(200);
|
|
224
|
-
o(res.header('content-type')).equals('application/json');
|
|
225
|
-
o(res.header('cache-control')).equals('max-age=120');
|
|
226
257
|
|
|
227
258
|
const body = Buffer.from(res.body ?? '', 'base64').toString();
|
|
228
259
|
o(JSON.parse(body)).deepEquals({
|
|
229
|
-
tiles: [`https://tiles.test/v1/tiles/
|
|
260
|
+
tiles: [`https://tiles.test/v1/tiles/fake-vector/NZTM2000Quad/{z}/{x}/{y}.pbf?api=${apiKey}`],
|
|
261
|
+
vector_layers: [],
|
|
262
|
+
maxzoom: 13,
|
|
230
263
|
minzoom: 0,
|
|
231
|
-
|
|
232
|
-
format: 'pbf',
|
|
233
|
-
tilejson: '2.0.0',
|
|
264
|
+
tilejson: '3.0.0',
|
|
234
265
|
});
|
|
235
266
|
});
|
|
236
267
|
});
|
package/src/__test__/xyz.util.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ConfigProvider } from '@basemaps/config';
|
|
2
2
|
import { TileMatrixSet } from '@basemaps/geo';
|
|
3
|
-
import { LambdaHttpRequest, LambdaAlbRequest } from '@linzjs/lambda';
|
|
4
3
|
import { LogConfig } from '@basemaps/shared';
|
|
5
|
-
import {
|
|
4
|
+
import { LambdaAlbRequest, LambdaHttpRequest } from '@linzjs/lambda';
|
|
6
5
|
import { Context } from 'aws-lambda';
|
|
6
|
+
import { TileSetRaster } from '../tile.set.raster.js';
|
|
7
|
+
import { TileSetVector } from '../tile.set.vector.js';
|
|
7
8
|
|
|
8
9
|
export function mockRequest(path: string, method = 'get', headers: Record<string, string> = {}): LambdaHttpRequest {
|
|
9
10
|
return new LambdaAlbRequest(
|
|
@@ -27,6 +28,13 @@ export class FakeTileSet extends TileSetRaster {
|
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
export class FakeTileSetVector extends TileSetVector {
|
|
32
|
+
constructor(name: string, tileMatrix: TileMatrixSet) {
|
|
33
|
+
super(name, tileMatrix);
|
|
34
|
+
this.tileSet = {} as any;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
30
38
|
export const Provider: ConfigProvider = {
|
|
31
39
|
createdAt: Date.now(),
|
|
32
40
|
name: 'main',
|
package/src/cli/dump.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Nztm2000Tms } from '@basemaps/geo';
|
|
1
|
+
import { Nztm2000Tms, ImageFormat } from '@basemaps/geo';
|
|
2
2
|
import { LogConfig } from '@basemaps/shared';
|
|
3
|
-
import { ImageFormat } from '@basemaps/tiler';
|
|
4
3
|
import { LambdaAlbRequest } from '@linzjs/lambda';
|
|
5
4
|
import { Context } from 'aws-lambda';
|
|
6
5
|
import { promises as fs } from 'fs';
|
|
@@ -12,7 +11,7 @@ import { TileSetLocal } from './tile.set.local.js';
|
|
|
12
11
|
const xyz = { x: 0, y: 0, z: 0 };
|
|
13
12
|
const tileMatrix = Nztm2000Tms;
|
|
14
13
|
const tileSetName = 'aerial';
|
|
15
|
-
const ext = ImageFormat.
|
|
14
|
+
const ext = ImageFormat.Png;
|
|
16
15
|
|
|
17
16
|
/** Load a tileset form a file path otherwise default to the hard coded one from AWS */
|
|
18
17
|
async function getTileSet(filePath?: string): Promise<TileSet> {
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AwsCredentials } from '@chunkd/source-aws-v2';
|
|
2
|
+
import { fsa } from '@chunkd/fs';
|
|
3
|
+
import { Env } from '@basemaps/shared';
|
|
4
|
+
|
|
5
|
+
export interface RoleConfig {
|
|
6
|
+
bucket: string;
|
|
7
|
+
accountId: string;
|
|
8
|
+
roleArn: string;
|
|
9
|
+
externalId?: string;
|
|
10
|
+
roleSessionDuration?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface BucketConfig {
|
|
14
|
+
v: number;
|
|
15
|
+
buckets: RoleConfig[];
|
|
16
|
+
version: string;
|
|
17
|
+
package: string;
|
|
18
|
+
hash: string;
|
|
19
|
+
updatedAt: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class RoleRegister {
|
|
23
|
+
/** Get all imagery source aws roles */
|
|
24
|
+
static async _loadRoles(): Promise<RoleConfig[]> {
|
|
25
|
+
const configBucket = Env.get(Env.AwsRoleConfigBucket);
|
|
26
|
+
if (configBucket == null) return [];
|
|
27
|
+
const configPath = `s3://${configBucket}/config.json`;
|
|
28
|
+
const config: BucketConfig = await fsa.readJson(configPath);
|
|
29
|
+
const roles = [];
|
|
30
|
+
for (const role of config.buckets) {
|
|
31
|
+
fsa.register(
|
|
32
|
+
's3://' + role.bucket,
|
|
33
|
+
AwsCredentials.fsFromRole(role.roleArn, role.externalId, role.roleSessionDuration),
|
|
34
|
+
);
|
|
35
|
+
roles.push(role);
|
|
36
|
+
}
|
|
37
|
+
return roles;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static _loadRolesPromise: Promise<RoleConfig[]> | undefined;
|
|
41
|
+
static loadRoles(): Promise<RoleConfig[]> {
|
|
42
|
+
if (RoleRegister._loadRolesPromise == null) RoleRegister._loadRolesPromise = this._loadRoles();
|
|
43
|
+
return RoleRegister._loadRolesPromise;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static async findRole(path: string): Promise<RoleConfig | undefined> {
|
|
47
|
+
const roles = await this.loadRoles();
|
|
48
|
+
return roles.find((f) => path.startsWith(`s3://${f.bucket}`));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Search for the imagery across all of our buckets */
|
|
53
|
+
export async function findImagery(path: string): Promise<string[]> {
|
|
54
|
+
const files: string[] = [];
|
|
55
|
+
for await (const key of fsa.list(path)) {
|
|
56
|
+
const searchKey = key.toLowerCase();
|
|
57
|
+
if (searchKey.endsWith('.tif') || searchKey.endsWith('.tiff')) files.push(key);
|
|
58
|
+
}
|
|
59
|
+
return files;
|
|
60
|
+
}
|