@basemaps/lambda-tiler 6.34.0 → 6.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/build/__tests__/config.data.d.ts +2 -1
  3. package/build/__tests__/config.data.d.ts.map +1 -1
  4. package/build/__tests__/config.data.js +14 -1
  5. package/build/__tests__/config.data.js.map +1 -1
  6. package/build/__tests__/tile.style.json.test.js +17 -3
  7. package/build/__tests__/tile.style.json.test.js.map +1 -1
  8. package/build/__tests__/wmts.capability.test.js +17 -0
  9. package/build/__tests__/wmts.capability.test.js.map +1 -1
  10. package/build/arcgis/__tests__/arcgis.style.json.test.js +18 -15
  11. package/build/arcgis/__tests__/arcgis.style.json.test.js.map +1 -1
  12. package/build/arcgis/__tests__/vector.tiler.server.test.js +14 -7
  13. package/build/arcgis/__tests__/vector.tiler.server.test.js.map +1 -1
  14. package/build/arcgis/arcgis.style.json.d.ts.map +1 -1
  15. package/build/arcgis/arcgis.style.json.js +6 -4
  16. package/build/arcgis/arcgis.style.json.js.map +1 -1
  17. package/build/arcgis/vector.tile.server.d.ts.map +1 -1
  18. package/build/arcgis/vector.tile.server.js +4 -2
  19. package/build/arcgis/vector.tile.server.js.map +1 -1
  20. package/build/index.d.ts +1 -3
  21. package/build/index.d.ts.map +1 -1
  22. package/build/index.js +7 -8
  23. package/build/index.js.map +1 -1
  24. package/build/routes/__tests__/attribution.test.js +3 -2
  25. package/build/routes/__tests__/attribution.test.js.map +1 -1
  26. package/build/routes/__tests__/fonts.test.js +36 -7
  27. package/build/routes/__tests__/fonts.test.js.map +1 -1
  28. package/build/routes/__tests__/health.test.js +4 -2
  29. package/build/routes/__tests__/health.test.js.map +1 -1
  30. package/build/routes/__tests__/sprites.test.js +3 -4
  31. package/build/routes/__tests__/sprites.test.js.map +1 -1
  32. package/build/routes/__tests__/tile.json.test.js +24 -2
  33. package/build/routes/__tests__/tile.json.test.js.map +1 -1
  34. package/build/routes/__tests__/tile.style.json.test.js +58 -7
  35. package/build/routes/__tests__/tile.style.json.test.js.map +1 -1
  36. package/build/routes/__tests__/wmts.test.js +17 -14
  37. package/build/routes/__tests__/wmts.test.js.map +1 -1
  38. package/build/routes/__tests__/xyz.test.js +4 -2
  39. package/build/routes/__tests__/xyz.test.js.map +1 -1
  40. package/build/routes/attribution.d.ts.map +1 -1
  41. package/build/routes/attribution.js +20 -10
  42. package/build/routes/attribution.js.map +1 -1
  43. package/build/routes/config.d.ts +22 -0
  44. package/build/routes/config.d.ts.map +1 -0
  45. package/build/routes/config.js +63 -0
  46. package/build/routes/config.js.map +1 -0
  47. package/build/routes/health.d.ts.map +1 -1
  48. package/build/routes/health.js +3 -2
  49. package/build/routes/health.js.map +1 -1
  50. package/build/routes/imagery.d.ts.map +1 -1
  51. package/build/routes/imagery.js +3 -2
  52. package/build/routes/imagery.js.map +1 -1
  53. package/build/routes/tile.json.d.ts.map +1 -1
  54. package/build/routes/tile.json.js +7 -4
  55. package/build/routes/tile.json.js.map +1 -1
  56. package/build/routes/tile.style.json.d.ts +4 -3
  57. package/build/routes/tile.style.json.d.ts.map +1 -1
  58. package/build/routes/tile.style.json.js +53 -12
  59. package/build/routes/tile.style.json.js.map +1 -1
  60. package/build/routes/tile.wmts.d.ts.map +1 -1
  61. package/build/routes/tile.wmts.js +7 -4
  62. package/build/routes/tile.wmts.js.map +1 -1
  63. package/build/routes/tile.xyz.d.ts.map +1 -1
  64. package/build/routes/tile.xyz.js +4 -2
  65. package/build/routes/tile.xyz.js.map +1 -1
  66. package/build/routes/tile.xyz.raster.d.ts.map +1 -1
  67. package/build/routes/tile.xyz.raster.js +4 -2
  68. package/build/routes/tile.xyz.raster.js.map +1 -1
  69. package/build/util/__test__/config.loader.test.d.ts +2 -0
  70. package/build/util/__test__/config.loader.test.d.ts.map +1 -0
  71. package/build/util/__test__/config.loader.test.js +79 -0
  72. package/build/util/__test__/config.loader.test.js.map +1 -0
  73. package/build/util/assets.provider.d.ts +1 -4
  74. package/build/util/assets.provider.d.ts.map +1 -1
  75. package/build/util/assets.provider.js +23 -10
  76. package/build/util/assets.provider.js.map +1 -1
  77. package/build/util/config.cache.d.ts +3 -3
  78. package/build/util/config.cache.d.ts.map +1 -1
  79. package/build/util/config.cache.js +14 -15
  80. package/build/util/config.cache.js.map +1 -1
  81. package/build/util/config.loader.d.ts +10 -0
  82. package/build/util/config.loader.d.ts.map +1 -0
  83. package/build/util/config.loader.js +47 -0
  84. package/build/util/config.loader.js.map +1 -0
  85. package/build/wmts.capability.d.ts +3 -1
  86. package/build/wmts.capability.d.ts.map +1 -1
  87. package/build/wmts.capability.js +5 -15
  88. package/build/wmts.capability.js.map +1 -1
  89. package/dist/index.js +66 -66
  90. package/dist/node_modules/.package-lock.json +1 -1
  91. package/dist/package-lock.json +2 -2
  92. package/dist/package.json +1 -1
  93. package/package.json +8 -9
  94. package/src/__tests__/config.data.ts +25 -1
  95. package/src/__tests__/tile.style.json.test.ts +19 -3
  96. package/src/__tests__/wmts.capability.test.ts +21 -0
  97. package/src/arcgis/__tests__/arcgis.style.json.test.ts +21 -17
  98. package/src/arcgis/__tests__/vector.tiler.server.test.ts +17 -8
  99. package/src/arcgis/arcgis.style.json.ts +6 -4
  100. package/src/arcgis/vector.tile.server.ts +5 -2
  101. package/src/index.ts +9 -10
  102. package/src/routes/__tests__/attribution.test.ts +4 -2
  103. package/src/routes/__tests__/fonts.test.ts +44 -7
  104. package/src/routes/__tests__/health.test.ts +4 -2
  105. package/src/routes/__tests__/sprites.test.ts +3 -4
  106. package/src/routes/__tests__/tile.json.test.ts +30 -2
  107. package/src/routes/__tests__/tile.style.json.test.ts +68 -9
  108. package/src/routes/__tests__/wmts.test.ts +23 -17
  109. package/src/routes/__tests__/xyz.test.ts +4 -2
  110. package/src/routes/attribution.ts +23 -8
  111. package/src/routes/config.ts +83 -0
  112. package/src/routes/health.ts +4 -2
  113. package/src/routes/imagery.ts +3 -2
  114. package/src/routes/tile.json.ts +10 -4
  115. package/src/routes/tile.style.json.ts +58 -12
  116. package/src/routes/tile.wmts.ts +9 -4
  117. package/src/routes/tile.xyz.raster.ts +4 -2
  118. package/src/routes/tile.xyz.ts +5 -2
  119. package/src/util/__test__/config.loader.test.ts +116 -0
  120. package/src/util/assets.provider.ts +11 -12
  121. package/src/util/config.cache.ts +18 -18
  122. package/src/util/config.loader.ts +50 -0
  123. package/src/wmts.capability.ts +9 -15
  124. package/tsconfig.tsbuildinfo +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basemaps/lambda-tiler",
3
- "version": "6.34.0",
3
+ "version": "6.35.0",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@basemaps/lambda-tiler",
3
- "version": "6.34.0",
3
+ "version": "6.35.0",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@basemaps/lambda-tiler",
9
- "version": "6.34.0",
9
+ "version": "6.35.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "sharp": "0.30.7"
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basemaps/lambda-tiler",
3
- "version": "6.34.0",
3
+ "version": "6.35.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/linz/basemaps.git",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basemaps/lambda-tiler",
3
- "version": "6.34.0",
3
+ "version": "6.35.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/linz/basemaps.git",
@@ -22,17 +22,16 @@
22
22
  "types": "./build/index.d.ts",
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@basemaps/config": "^6.34.0",
25
+ "@basemaps/config": "^6.35.0",
26
26
  "@basemaps/geo": "^6.32.1",
27
- "@basemaps/lambda": "^6.7.0",
28
- "@basemaps/shared": "^6.34.0",
29
- "@basemaps/tiler": "^6.32.1",
30
- "@basemaps/tiler-sharp": "^6.32.1",
31
- "@chunkd/fs": "^8.4.0",
27
+ "@basemaps/shared": "^6.35.0",
28
+ "@basemaps/tiler": "^6.35.0",
29
+ "@basemaps/tiler-sharp": "^6.35.0",
30
+ "@chunkd/fs": "^8.5.1",
32
31
  "@cogeotiff/core": "^7.0.0",
33
32
  "@cotar/core": "^5.4.0",
34
33
  "@linzjs/geojson": "^6.32.1",
35
- "@linzjs/lambda": "^3.2.1",
34
+ "@linzjs/lambda": "^4.0.0",
36
35
  "p-limit": "^4.0.0",
37
36
  "path-to-regexp": "^6.1.0",
38
37
  "pixelmatch": "^5.1.0",
@@ -59,5 +58,5 @@
59
58
  "@types/sharp": "^0.30.3",
60
59
  "pretty-json-log": "^1.0.0"
61
60
  },
62
- "gitHead": "1685fa12be66df74bc64d7f76b7355390980a43f"
61
+ "gitHead": "dcebd7149ab318ea979b5d1ba34a9f82fc41b935"
63
62
  }
@@ -1,5 +1,16 @@
1
- import { ConfigImagery, ConfigProvider, ConfigTileSetRaster, ConfigTileSetVector, TileSetType } from '@basemaps/config';
1
+ import {
2
+ base58,
3
+ BaseConfig,
4
+ ConfigImagery,
5
+ ConfigProvider,
6
+ ConfigProviderMemory,
7
+ ConfigTileSetRaster,
8
+ ConfigTileSetVector,
9
+ TileSetType,
10
+ } from '@basemaps/config';
2
11
  import { ImageFormat, VectorFormat } from '@basemaps/geo';
12
+ import { fsa } from '@basemaps/shared';
13
+ import { FsMemory } from '../routes/__tests__/memory.fs.js';
3
14
 
4
15
  export const TileSetAerial: ConfigTileSetRaster = {
5
16
  id: 'ts_aerial',
@@ -117,4 +128,17 @@ export class FakeData {
117
128
 
118
129
  return tileSet;
119
130
  }
131
+
132
+ static bundle(configs: BaseConfig[]): string {
133
+ const cfg = new ConfigProviderMemory();
134
+ for (const rec of configs) cfg.put(rec);
135
+ const output = cfg.toJson();
136
+ const fsMemory = new FsMemory();
137
+
138
+ const configPath = `memory://linz-basemaps/${output.hash}.json`;
139
+ fsMemory.files.set(configPath, Buffer.from(JSON.stringify(output)));
140
+ fsa.register(configPath, fsMemory);
141
+
142
+ return base58.encode(Buffer.from(configPath));
143
+ }
120
144
  }
@@ -55,7 +55,7 @@ o.spec('TileStyleJson', () => {
55
55
 
56
56
  o('should not destroy the original configuration', () => {
57
57
  const apiKey = 'abc123';
58
- const converted = convertStyleJson(baseStyleJson, apiKey);
58
+ const converted = convertStyleJson(baseStyleJson, apiKey, null);
59
59
 
60
60
  o(converted.sources.vector).deepEquals({
61
61
  type: 'vector',
@@ -68,7 +68,7 @@ o.spec('TileStyleJson', () => {
68
68
 
69
69
  o(JSON.stringify(baseStyleJson).includes(apiKey)).equals(false);
70
70
 
71
- const convertedB = convertStyleJson(baseStyleJson, '0x1234');
71
+ const convertedB = convertStyleJson(baseStyleJson, '0x1234', null);
72
72
  o(convertedB.sources.vector).deepEquals({
73
73
  type: 'vector',
74
74
  url: 'https://tiles.test/v1/tiles/topographic/EPSG:3857/tile.json?api=0x1234',
@@ -85,11 +85,27 @@ o.spec('TileStyleJson', () => {
85
85
 
86
86
  o('should convert relative glyphs and sprites', () => {
87
87
  const apiKey = '0x9f9f';
88
- const converted = convertStyleJson(baseStyleJson, apiKey);
88
+ const converted = convertStyleJson(baseStyleJson, apiKey, null);
89
89
  o(converted.sprite).equals('https://tiles.test/v1/sprites');
90
90
  o(converted.glyphs).equals('https://tiles.test/v1/glyphs');
91
91
 
92
92
  o(JSON.stringify(baseStyleJson).includes(apiKey)).equals(false);
93
93
  o(JSON.stringify(baseStyleJson).includes('?api=')).equals(false);
94
94
  });
95
+
96
+ o('should convert with config', () => {
97
+ const apiKey = '0x9f9f';
98
+ const converted = convertStyleJson(baseStyleJson, apiKey, 'config.json');
99
+ o(converted.sprite).equals('https://tiles.test/v1/sprites?config=config.json');
100
+ o(converted.glyphs).equals('https://tiles.test/v1/glyphs?config=config.json');
101
+
102
+ o(converted.sources.vector).deepEquals({
103
+ type: 'vector',
104
+ url: 'https://tiles.test/v1/tiles/topographic/EPSG:3857/tile.json?api=0x9f9f&config=config.json',
105
+ });
106
+ o(converted.sources.raster).deepEquals({
107
+ type: 'raster',
108
+ tiles: ['https://tiles.test/v1/tiles/aerial/EPSG:3857/{z}/{x}/{y}.webp?api=0x9f9f&config=config.json'],
109
+ });
110
+ });
95
111
  });
@@ -41,6 +41,27 @@ o.spec('WmtsCapabilities', () => {
41
41
  );
42
42
  });
43
43
 
44
+ o('should include config location', () => {
45
+ const wmts = new WmtsCapabilities({
46
+ httpBase: 'https://basemaps.test',
47
+ provider: Provider,
48
+ tileMatrix: [GoogleTms],
49
+ tileSet: TileSetAerial,
50
+ imagery: allImagery,
51
+ apiKey,
52
+ config: 's3://linz-basemaps/config.json',
53
+ formats: [ImageFormat.Avif],
54
+ isIndividualLayers: false,
55
+ }).toVNode();
56
+
57
+ const urls = tags(wmts, 'ResourceURL');
58
+ o(urls.length).equals(1);
59
+ o(urls[0].attrs.format).equals('image/avif');
60
+ o(urls[0].attrs.template).equals(
61
+ 'https://basemaps.test/v1/tiles/aerial/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}.avif?api=secret1234&config=s3%3A%2F%2Flinz-basemaps%2Fconfig.json',
62
+ );
63
+ });
64
+
44
65
  o('should be seting encoding to utf-8', () => {
45
66
  const xml = new WmtsCapabilities({
46
67
  httpBase: 'https://basemaps.test',
@@ -1,33 +1,40 @@
1
- import { Config, StyleJson } from '@basemaps/config';
1
+ import { BaseConfig, ConfigProviderMemory, StyleJson } from '@basemaps/config';
2
2
  import { Env } from '@basemaps/shared';
3
3
  import o from 'ospec';
4
4
  import { createSandbox } from 'sinon';
5
5
  import { handler } from '../../index.js';
6
+ import { ConfigLoader } from '../../util/config.loader.js';
6
7
  import { FakeData } from '../../__tests__/config.data.js';
7
8
  import { Api, mockRequest, mockUrlRequest } from '../../__tests__/xyz.util.js';
8
9
 
9
- o.spec('v1/arcgis/rest/services/', () => {
10
+ o.spec('arcgis/stylejson', () => {
10
11
  const host = 'https://tiles.test';
11
12
  const sandbox = createSandbox();
13
+ const config = new ConfigProviderMemory();
12
14
 
13
15
  o.before(() => {
14
16
  process.env[Env.PublicUrlBase] = host;
15
17
  });
16
- o.afterEach(() => sandbox.restore());
18
+
19
+ o.beforeEach(() => {
20
+ sandbox.stub(ConfigLoader, 'getDefaultConfig').resolves(config);
21
+ config.objects.clear();
22
+ });
23
+
24
+ o.afterEach(() => {
25
+ sandbox.restore();
26
+ });
27
+
17
28
  o('should not found tile set', async () => {
18
29
  const request = mockRequest('/v1/arcgis/rest/services/topographic/VectorTileServer/root.json', 'get', Api.header);
19
30
 
20
- sandbox.stub(Config.TileSet, 'get').resolves(null);
21
-
22
31
  const res = await handler.router.handle(request);
23
32
  o(res.status).equals(404);
24
33
  });
25
34
 
26
35
  o('should not found style', async () => {
27
36
  const request = mockRequest('/v1/arcgis/rest/services/topographic/VectorTileServer/root.json', 'get', Api.header);
28
-
29
- sandbox.stub(Config.TileSet, 'get').resolves(FakeData.tileSetVector('topographic'));
30
- sandbox.stub(Config.Style, 'get').resolves(null);
37
+ config.put(FakeData.tileSetVector('topographic'));
31
38
 
32
39
  const res = await handler.router.handle(request);
33
40
  o(res.status).equals(404);
@@ -87,8 +94,8 @@ o.spec('v1/arcgis/rest/services/', () => {
87
94
  o('should serve style json and remove the raster source and layers, then replace the vector url', async () => {
88
95
  const request = mockRequest('/v1/arcgis/rest/services/topographic/VectorTileServer/root.json', 'get', Api.header);
89
96
 
90
- sandbox.stub(Config.TileSet, 'get').resolves(FakeData.tileSetVector('topographic'));
91
- sandbox.stub(Config.Style, 'get').resolves(fakeRecord as any);
97
+ config.put(FakeData.tileSetVector('topographic'));
98
+ config.put(fakeRecord);
92
99
 
93
100
  const res = await handler.router.handle(request);
94
101
  o(res.status).equals(200);
@@ -112,8 +119,8 @@ o.spec('v1/arcgis/rest/services/', () => {
112
119
  o('should not found for raster tileset', async () => {
113
120
  const request = mockRequest('/v1/arcgis/rest/services/raster/VectorTileServer/root.json', 'get', Api.header);
114
121
 
115
- sandbox.stub(Config.TileSet, 'get').resolves(FakeData.tileSetRaster('raster'));
116
- sandbox.stub(Config.Style, 'get').resolves(fakeRecord as any);
122
+ config.put(FakeData.tileSetRaster('raster'));
123
+ config.put(fakeRecord);
117
124
 
118
125
  const res = await handler.router.handle(request);
119
126
  o(res.status).equals(404);
@@ -126,11 +133,8 @@ o.spec('v1/arcgis/rest/services/', () => {
126
133
  Api.header,
127
134
  );
128
135
 
129
- sandbox.stub(Config.TileSet, 'get').resolves(FakeData.tileSetVector('topographic'));
130
- sandbox
131
- .stub(Config.Style, 'get')
132
- .withArgs('st_topolite')
133
- .resolves(fakeRecord as any);
136
+ config.put({ id: 'st_topolite', name: 'topographic', style: fakeStyle } as BaseConfig);
137
+ config.put(FakeData.tileSetVector('topographic'));
134
138
 
135
139
  const res = await handler.router.handle(request);
136
140
  o(res.status).equals(200);
@@ -1,31 +1,40 @@
1
- import { Config } from '@basemaps/config';
1
+ import { ConfigProviderMemory } from '@basemaps/config';
2
2
  import { Env } from '@basemaps/shared';
3
3
  import o from 'ospec';
4
4
  import { createSandbox } from 'sinon';
5
5
  import { handler } from '../../index.js';
6
+ import { ConfigLoader } from '../../util/config.loader.js';
6
7
  import { FakeData } from '../../__tests__/config.data.js';
7
8
  import { Api, mockRequest, mockUrlRequest } from '../../__tests__/xyz.util.js';
8
9
 
9
- o.spec('v1/arcgis/rest/services/', () => {
10
+ o.spec('arcgis/VectorTileServer', () => {
10
11
  const host = 'https://tiles.test';
11
12
  const sandbox = createSandbox();
13
+ const config = new ConfigProviderMemory();
12
14
 
13
15
  o.before(() => {
14
16
  process.env[Env.PublicUrlBase] = host;
15
17
  });
16
- o.afterEach(() => sandbox.restore());
18
+
19
+ o.beforeEach(() => {
20
+ sandbox.stub(ConfigLoader, 'getDefaultConfig').resolves(config);
21
+ config.objects.clear();
22
+ });
23
+
24
+ o.afterEach(() => {
25
+ sandbox.restore();
26
+ });
27
+
17
28
  o('should not found tile set', async () => {
18
29
  const request = mockUrlRequest('/v1/arcgis/rest/services/topographic/VectorTileServer', 'f=json', Api.header);
19
30
 
20
- sandbox.stub(Config.TileSet, 'get').resolves(null);
21
-
22
31
  const res = await handler.router.handle(request);
23
32
  o(res.status).equals(404);
24
33
  });
25
34
  o('should return the vector tile server', async () => {
26
35
  const request = mockUrlRequest('/v1/arcgis/rest/services/topographic/VectorTileServer', 'f=json', Api.header);
27
36
 
28
- sandbox.stub(Config.TileSet, 'get').resolves(FakeData.tileSetVector('topographic'));
37
+ config.put(FakeData.tileSetVector('topographic'));
29
38
 
30
39
  const res = await handler.router.handle(request);
31
40
  o(res.status).equals(200);
@@ -39,7 +48,7 @@ o.spec('v1/arcgis/rest/services/', () => {
39
48
  o('should not return with no f=json query', async () => {
40
49
  const request = mockRequest('/v1/arcgis/rest/services/topographic/VectorTileServer', 'get', Api.header);
41
50
 
42
- sandbox.stub(Config.TileSet, 'get').resolves(FakeData.tileSetVector('topographic'));
51
+ config.put(FakeData.tileSetVector('topographic'));
43
52
 
44
53
  const res = await handler.router.handle(request);
45
54
  o(res.status).equals(404);
@@ -52,7 +61,7 @@ o.spec('v1/arcgis/rest/services/', () => {
52
61
  'POST',
53
62
  );
54
63
 
55
- sandbox.stub(Config.TileSet, 'get').resolves(FakeData.tileSetVector('topographic'));
64
+ config.put(FakeData.tileSetVector('topographic'));
56
65
 
57
66
  const res = await handler.router.handle(request);
58
67
  o(res.status).equals(200);
@@ -1,7 +1,8 @@
1
- import { Config, Sources, StyleJson, TileSetType } from '@basemaps/config';
1
+ import { Sources, StyleJson, TileSetType } from '@basemaps/config';
2
2
  import { Env, fsa } from '@basemaps/shared';
3
3
  import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
4
4
  import { convertRelativeUrl } from '../routes/tile.style.json.js';
5
+ import { ConfigLoader } from '../util/config.loader.js';
5
6
  import { Etag } from '../util/etag.js';
6
7
  import { NotFound, NotModified } from '../util/response.js';
7
8
  import { Validate } from '../util/validate.js';
@@ -54,15 +55,16 @@ function convertStyleJson(tileSet: string, style: StyleJson, apiKey: string): St
54
55
 
55
56
  export async function arcgisStyleJsonGet(req: LambdaHttpRequest<StyleGet>): Promise<LambdaHttpResponse> {
56
57
  const apiKey = Validate.apiKey(req);
57
- const tileSet = await Config.TileSet.get(Config.TileSet.id(req.params.tileSet));
58
+ const config = await ConfigLoader.load(req);
59
+ const tileSet = await config.TileSet.get(config.TileSet.id(req.params.tileSet));
58
60
  if (tileSet?.type !== TileSetType.Vector) return NotFound();
59
61
 
60
62
  const style = req.query.get('style');
61
63
  const styleName = style ? style : 'topographic'; // Defalut to topographic style
62
64
 
63
65
  // Get style Config from db
64
- const dbId = Config.Style.id(styleName);
65
- const styleConfig = await Config.Style.get(dbId);
66
+ const dbId = config.Style.id(styleName);
67
+ const styleConfig = await config.Style.get(dbId);
66
68
  if (styleConfig == null) return NotFound();
67
69
 
68
70
  // Prepare sources and add linz source
@@ -1,7 +1,8 @@
1
- import { Config, TileSetType } from '@basemaps/config';
1
+ import { TileSetType } from '@basemaps/config';
2
2
  import { GoogleTms } from '@basemaps/geo';
3
3
  import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
4
4
  import { convertRelativeUrl } from '../routes/tile.style.json.js';
5
+ import { ConfigLoader } from '../util/config.loader.js';
5
6
  import { NotFound } from '../util/response.js';
6
7
  import { Validate } from '../util/validate.js';
7
8
 
@@ -16,7 +17,9 @@ export interface VectorTileServer {
16
17
  }
17
18
 
18
19
  export async function arcgisTileServerGet(req: LambdaHttpRequest<VectorTileServer>): Promise<LambdaHttpResponse> {
19
- const tileSet = await Config.TileSet.get(Config.TileSet.id(req.params.tileSet));
20
+ const config = await ConfigLoader.load(req);
21
+
22
+ const tileSet = await config.TileSet.get(config.TileSet.id(req.params.tileSet));
20
23
  if (tileSet?.type !== TileSetType.Vector) return NotFound();
21
24
  const apiKey = Validate.apiKey(req);
22
25
  const f = req.query.get('f');
package/src/index.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { Env, LogConfig } from '@basemaps/shared';
1
+ import { LogConfig } from '@basemaps/shared';
2
2
  import { LambdaHttpResponse, lf } from '@linzjs/lambda';
3
3
  import { arcgisInfoGet } from './arcgis/arcgis.info.js';
4
4
  import { arcgisStyleJsonGet } from './arcgis/arcgis.style.json.js';
5
5
  import { arcgisTileServerGet } from './arcgis/vector.tile.server.js';
6
6
  import { tileAttributionGet } from './routes/attribution.js';
7
+ import { configImageryGet, configTileSetGet } from './routes/config.js';
7
8
  import { fontGet, fontList } from './routes/fonts.js';
8
9
  import { healthGet } from './routes/health.js';
9
10
  import { imageryGet } from './routes/imagery.js';
@@ -14,29 +15,23 @@ import { styleJsonGet } from './routes/tile.style.json.js';
14
15
  import { wmtsCapabilitiesGet } from './routes/tile.wmts.js';
15
16
  import { tileXyzGet } from './routes/tile.xyz.js';
16
17
  import { versionGet } from './routes/version.js';
17
- import { assetProvider } from './util/assets.provider.js';
18
18
  import { NotFound, OkResponse } from './util/response.js';
19
19
  import { CoSources } from './util/source.cache.js';
20
20
  import { St } from './util/source.tracer.js';
21
21
 
22
22
  export const handler = lf.http(LogConfig.get());
23
23
 
24
+ /** If the request takes too long, respond with a 408 timeout when there is approx 1 second remaining */
25
+ handler.router.timeoutEarlyMs = 1_000;
26
+
24
27
  handler.router.hook('request', (req) => {
25
28
  req.set('name', 'LambdaTiler');
26
29
 
27
- // Set the asset location for asset provider
28
- const assetLocation = Env.get(Env.AssetLocation);
29
- assetProvider.set(assetLocation);
30
-
31
30
  // Reset the request tracing before every request
32
31
  St.reset();
33
32
  });
34
33
 
35
- let totalRequests = 0;
36
34
  handler.router.hook('response', (req, res) => {
37
- totalRequests++;
38
- req.set('requestsTotal', totalRequests); // Number of requests served by this lambda
39
-
40
35
  if (St.requests.length > 0) {
41
36
  // TODO this could be relaxed to every say 5% of requests if logging gets too verbose.
42
37
  req.set('requests', St.requests.slice(0, 100)); // limit to 100 requests (some tiles need 100s of requests)
@@ -76,6 +71,10 @@ handler.router.get('/v1/version', versionGet);
76
71
  // Image Metadata
77
72
  handler.router.get('/v1/imagery/:imageryId/:fileName', imageryGet);
78
73
 
74
+ // Config
75
+ handler.router.get('/v1/config/:tileSet.json', configTileSetGet);
76
+ handler.router.get('/v1/config/:tileSet/:imageryId.json', configImageryGet);
77
+
79
78
  // Sprites
80
79
  handler.router.get('/v1/sprites/:spriteName', spriteGet);
81
80
 
@@ -1,11 +1,12 @@
1
1
  import { Attribution } from '@basemaps/attribution';
2
- import { Config, ConfigProviderMemory } from '@basemaps/config';
2
+ import { ConfigProviderMemory } from '@basemaps/config';
3
3
  import { Nztm2000QuadTms } from '@basemaps/geo';
4
4
  import { LogConfig } from '@basemaps/shared';
5
5
  import { HttpHeader } from '@linzjs/lambda';
6
6
  import o from 'ospec';
7
7
  import sinon from 'sinon';
8
8
  import { handler } from '../../index.js';
9
+ import { ConfigLoader } from '../../util/config.loader.js';
9
10
  import { FakeData, Imagery2193, Imagery3857, Provider, TileSetAerial } from '../../__tests__/config.data.js';
10
11
  import { mockUrlRequest } from '../../__tests__/xyz.util.js';
11
12
 
@@ -283,7 +284,8 @@ o.spec('/v1/attribution', () => {
283
284
 
284
285
  o.beforeEach(() => {
285
286
  LogConfig.get().level = 'silent';
286
- Config.setConfigProvider(config);
287
+ sandbox.stub(ConfigLoader, 'getDefaultConfig').resolves(config);
288
+
287
289
  config.objects.clear();
288
290
 
289
291
  config.put(TileSetAerial);
@@ -1,9 +1,11 @@
1
- import { Env } from '@basemaps/shared';
1
+ import { base58, ConfigProviderMemory } from '@basemaps/config';
2
+ import { Env, getDefaultConfig } from '@basemaps/shared';
2
3
  import { fsa } from '@chunkd/fs';
3
4
  import o from 'ospec';
4
5
  import { handler } from '../../index.js';
5
- import { assetProvider } from '../../util/assets.provider.js';
6
- import { mockRequest } from '../../__tests__/xyz.util.js';
6
+ import { CachedConfig } from '../../util/config.cache.js';
7
+ import { CoSources } from '../../util/source.cache.js';
8
+ import { Api, mockRequest, mockUrlRequest } from '../../__tests__/xyz.util.js';
7
9
  import { fontList } from '../fonts.js';
8
10
  import { FsMemory } from './memory.fs.js';
9
11
 
@@ -15,12 +17,14 @@ o.spec('/v1/fonts', () => {
15
17
  const assetLocation = process.env[Env.AssetLocation];
16
18
 
17
19
  o.beforeEach(() => {
18
- process.env[Env.AssetLocation] = 'memory://';
19
- assetProvider.set('memory://');
20
+ process.env[Env.AssetLocation] = 'memory://config';
21
+ getDefaultConfig().assets = 'memory://';
20
22
  });
21
23
 
22
24
  o.afterEach(() => {
23
- assetProvider.set(assetLocation);
25
+ getDefaultConfig().assets = assetLocation;
26
+ CachedConfig.cache.clear();
27
+ CoSources.cache.clear();
24
28
  memory.files.clear();
25
29
  });
26
30
 
@@ -64,8 +68,41 @@ o.spec('/v1/fonts', () => {
64
68
  });
65
69
 
66
70
  o('should return 404 if no asset location set', async () => {
67
- assetProvider.set(undefined);
71
+ getDefaultConfig().assets = undefined;
68
72
  const res = await fontList(mockRequest('/v1/fonts.json'));
69
73
  o(res.status).equals(404);
70
74
  });
75
+
76
+ o('should get the correct utf8 font with default assets', async () => {
77
+ const cfgBundle = new ConfigProviderMemory();
78
+ await fsa.write('memory://linz-basemaps/bar.json', JSON.stringify(cfgBundle.toJson()));
79
+ await fsa.write('memory://config/fonts/🦄 🌈/0-255.pbf', Buffer.from(''));
80
+
81
+ const configLocation = base58.encode(Buffer.from('memory://linz-basemaps/bar.json'));
82
+ const res255 = await handler.router.handle(
83
+ mockUrlRequest('/v1/fonts/🦄 🌈/0-255.pbf', `?config=${configLocation}`, Api.header),
84
+ );
85
+ o(res255.status).equals(200);
86
+ o(res255.header('content-type')).equals('application/x-protobuf');
87
+ o(res255.header('content-encoding')).equals(undefined);
88
+ o(res255.header('etag')).notEquals(undefined);
89
+ o(res255.header('cache-control')).equals('public, max-age=604800, stale-while-revalidate=86400');
90
+ });
91
+
92
+ o('should get the correct utf8 font with config assets', async () => {
93
+ const cfgBundle = new ConfigProviderMemory();
94
+ cfgBundle.assets = 'memory://config/assets';
95
+ await fsa.write('memory://linz-basemaps/bar.json', JSON.stringify(cfgBundle.toJson()));
96
+ await fsa.write('memory://config/assets/fonts/🦄 🌈/0-255.pbf', Buffer.from(''));
97
+
98
+ const configLocation = base58.encode(Buffer.from('memory://linz-basemaps/bar.json'));
99
+ const res255 = await handler.router.handle(
100
+ mockUrlRequest('/v1/fonts/🦄 🌈/0-255.pbf', `?config=${configLocation}`, Api.header),
101
+ );
102
+ o(res255.status).equals(200);
103
+ o(res255.header('content-type')).equals('application/x-protobuf');
104
+ o(res255.header('content-encoding')).equals(undefined);
105
+ o(res255.header('etag')).notEquals(undefined);
106
+ o(res255.header('cache-control')).equals('public, max-age=604800, stale-while-revalidate=86400');
107
+ });
71
108
  });
@@ -1,9 +1,10 @@
1
- import { Config, ConfigProviderMemory } from '@basemaps/config';
1
+ import { ConfigProviderMemory } from '@basemaps/config';
2
2
  import { LogConfig } from '@basemaps/shared';
3
3
  import { LambdaAlbRequest, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
4
4
  import { Context } from 'aws-lambda';
5
5
  import o from 'ospec';
6
6
  import sinon from 'sinon';
7
+ import { ConfigLoader } from '../../util/config.loader.js';
7
8
  import { FakeData } from '../../__tests__/config.data.js';
8
9
 
9
10
  import { getTestBuffer, healthGet, TestTiles } from '../health.js';
@@ -29,11 +30,12 @@ o.spec('/v1/health', async () => {
29
30
  const fakeTileSet = FakeData.tileSetRaster('health');
30
31
  o.beforeEach(() => {
31
32
  config.objects.clear();
32
- Config.setConfigProvider(config);
33
+ sandbox.stub(ConfigLoader, 'getDefaultConfig').resolves(config);
33
34
  config.put(fakeTileSet);
34
35
  });
35
36
 
36
37
  o.afterEach(() => {
38
+ config.objects.clear();
37
39
  sandbox.restore();
38
40
  });
39
41
 
@@ -1,10 +1,9 @@
1
- import { Env } from '@basemaps/shared';
1
+ import { Env, getDefaultConfig } from '@basemaps/shared';
2
2
  import { fsa } from '@chunkd/fs';
3
3
  import o from 'ospec';
4
4
  import { createSandbox } from 'sinon';
5
5
  import { gunzipSync, gzipSync } from 'zlib';
6
6
  import { handler } from '../../index.js';
7
- import { assetProvider } from '../../util/assets.provider.js';
8
7
  import { mockRequest } from '../../__tests__/xyz.util.js';
9
8
  import { FsMemory } from './memory.fs.js';
10
9
 
@@ -18,11 +17,11 @@ o.spec('/v1/sprites', () => {
18
17
 
19
18
  o.beforeEach(() => {
20
19
  process.env[Env.AssetLocation] = 'memory://';
21
- assetProvider.set('memory://');
20
+ getDefaultConfig().assets = 'memory://';
22
21
  });
23
22
 
24
23
  o.afterEach(() => {
25
- assetProvider.set(assetLocation);
24
+ getDefaultConfig().assets = assetLocation;
26
25
  memory.files.clear();
27
26
  sandbox.restore();
28
27
  });
@@ -1,23 +1,33 @@
1
- import { Config, ConfigProviderMemory } from '@basemaps/config';
1
+ import { base58, ConfigProviderMemory } from '@basemaps/config';
2
2
  import { Env } from '@basemaps/shared';
3
+ import { fsa } from '@chunkd/fs';
3
4
  import o from 'ospec';
5
+ import sinon from 'sinon';
4
6
  import { handler } from '../../index.js';
7
+ import { ConfigLoader } from '../../util/config.loader.js';
5
8
  import { CoSources } from '../../util/source.cache.js';
6
9
  import { FakeData } from '../../__tests__/config.data.js';
7
10
  import { Api, mockRequest, mockUrlRequest } from '../../__tests__/xyz.util.js';
11
+ import { FsMemory } from './memory.fs.js';
8
12
 
9
13
  o.spec('/v1/tiles/:tileSet/:tileMatrix/tile.json', () => {
10
14
  const config = new ConfigProviderMemory();
15
+ const sandbox = sinon.createSandbox();
16
+
11
17
  o.before(() => {
12
18
  process.env[Env.PublicUrlBase] = 'https://tiles.test';
13
- Config.setConfigProvider(config);
14
19
  });
15
20
 
16
21
  o.beforeEach(() => {
22
+ sandbox.stub(ConfigLoader, 'getDefaultConfig').resolves(config);
17
23
  config.objects.clear();
18
24
  CoSources.cache.clear();
19
25
  });
20
26
 
27
+ o.afterEach(() => {
28
+ sandbox.restore();
29
+ });
30
+
21
31
  o('should 404 if invalid url is given', async () => {
22
32
  const request = mockRequest('/v1/tiles/tile.json', 'get', Api.header);
23
33
 
@@ -123,6 +133,24 @@ o.spec('/v1/tiles/:tileSet/:tileMatrix/tile.json', () => {
123
133
  });
124
134
  });
125
135
 
136
+ o('should load from config bundle', async () => {
137
+ const memoryFs = new FsMemory();
138
+ fsa.register('memory://', memoryFs);
139
+ const fakeTileSet = FakeData.tileSetRaster('🦄 🌈');
140
+
141
+ const cfgBundle = new ConfigProviderMemory();
142
+ cfgBundle.put(fakeTileSet);
143
+ memoryFs.write('memory://linz-basemaps/bar.json', JSON.stringify(cfgBundle.toJson()));
144
+
145
+ const configLocation = base58.encode(Buffer.from('memory://linz-basemaps/bar.json'));
146
+ const request = mockUrlRequest('/v1/tiles/🦄 🌈/NZTM2000Quad/tile.json', `?config=${configLocation}`, Api.header);
147
+ const res = await handler.router.handle(request);
148
+ o(res.status).equals(200);
149
+
150
+ const body = JSON.parse(Buffer.from(res.body, 'base64').toString());
151
+ o(body.tiles[0].includes(`config=${configLocation}`)).equals(true);
152
+ });
153
+
126
154
  o('should serve convert zoom to tile matrix', async () => {
127
155
  const fakeTileSet = FakeData.tileSetVector('fake-vector');
128
156
  fakeTileSet.maxZoom = 15;