@basemaps/lambda-tiler 6.33.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 (156) hide show
  1. package/CHANGELOG.md +47 -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/__tests__/xyz.util.d.ts +1 -1
  11. package/build/__tests__/xyz.util.d.ts.map +1 -1
  12. package/build/__tests__/xyz.util.js +2 -2
  13. package/build/__tests__/xyz.util.js.map +1 -1
  14. package/build/arcgis/__tests__/arcgis.style.json.test.d.ts +2 -0
  15. package/build/arcgis/__tests__/arcgis.style.json.test.d.ts.map +1 -0
  16. package/build/arcgis/__tests__/arcgis.style.json.test.js +131 -0
  17. package/build/arcgis/__tests__/arcgis.style.json.test.js.map +1 -0
  18. package/build/arcgis/__tests__/vector.tiler.server.test.d.ts +2 -0
  19. package/build/arcgis/__tests__/vector.tiler.server.test.d.ts.map +1 -0
  20. package/build/arcgis/__tests__/vector.tiler.server.test.js +54 -0
  21. package/build/arcgis/__tests__/vector.tiler.server.test.js.map +1 -0
  22. package/build/arcgis/arcgis.info.d.ts +3 -0
  23. package/build/arcgis/arcgis.info.d.ts.map +1 -0
  24. package/build/arcgis/arcgis.info.js +25 -0
  25. package/build/arcgis/arcgis.info.js.map +1 -0
  26. package/build/arcgis/arcgis.style.json.d.ts +9 -0
  27. package/build/arcgis/arcgis.style.json.d.ts.map +1 -0
  28. package/build/arcgis/arcgis.style.json.js +75 -0
  29. package/build/arcgis/arcgis.style.json.js.map +1 -0
  30. package/build/arcgis/vector.tile.server.d.ts +8 -0
  31. package/build/arcgis/vector.tile.server.d.ts.map +1 -0
  32. package/build/arcgis/vector.tile.server.js +73 -0
  33. package/build/arcgis/vector.tile.server.js.map +1 -0
  34. package/build/index.d.ts +1 -3
  35. package/build/index.d.ts.map +1 -1
  36. package/build/index.js +15 -4
  37. package/build/index.js.map +1 -1
  38. package/build/routes/__tests__/attribution.test.js +3 -2
  39. package/build/routes/__tests__/attribution.test.js.map +1 -1
  40. package/build/routes/__tests__/fonts.test.js +46 -29
  41. package/build/routes/__tests__/fonts.test.js.map +1 -1
  42. package/build/routes/__tests__/health.test.js +4 -2
  43. package/build/routes/__tests__/health.test.js.map +1 -1
  44. package/build/routes/__tests__/sprites.test.js +7 -2
  45. package/build/routes/__tests__/sprites.test.js.map +1 -1
  46. package/build/routes/__tests__/tile.json.test.js +24 -2
  47. package/build/routes/__tests__/tile.json.test.js.map +1 -1
  48. package/build/routes/__tests__/tile.style.json.test.js +58 -7
  49. package/build/routes/__tests__/tile.style.json.test.js.map +1 -1
  50. package/build/routes/__tests__/wmts.test.js +17 -14
  51. package/build/routes/__tests__/wmts.test.js.map +1 -1
  52. package/build/routes/__tests__/xyz.test.js +4 -2
  53. package/build/routes/__tests__/xyz.test.js.map +1 -1
  54. package/build/routes/attribution.d.ts.map +1 -1
  55. package/build/routes/attribution.js +20 -10
  56. package/build/routes/attribution.js.map +1 -1
  57. package/build/routes/config.d.ts +22 -0
  58. package/build/routes/config.d.ts.map +1 -0
  59. package/build/routes/config.js +63 -0
  60. package/build/routes/config.js.map +1 -0
  61. package/build/routes/fonts.d.ts +0 -2
  62. package/build/routes/fonts.d.ts.map +1 -1
  63. package/build/routes/fonts.js +3 -66
  64. package/build/routes/fonts.js.map +1 -1
  65. package/build/routes/health.d.ts.map +1 -1
  66. package/build/routes/health.js +3 -2
  67. package/build/routes/health.js.map +1 -1
  68. package/build/routes/imagery.d.ts.map +1 -1
  69. package/build/routes/imagery.js +3 -2
  70. package/build/routes/imagery.js.map +1 -1
  71. package/build/routes/sprites.d.ts.map +1 -1
  72. package/build/routes/sprites.js +3 -29
  73. package/build/routes/sprites.js.map +1 -1
  74. package/build/routes/tile.json.d.ts.map +1 -1
  75. package/build/routes/tile.json.js +7 -4
  76. package/build/routes/tile.json.js.map +1 -1
  77. package/build/routes/tile.style.json.d.ts +4 -3
  78. package/build/routes/tile.style.json.d.ts.map +1 -1
  79. package/build/routes/tile.style.json.js +53 -12
  80. package/build/routes/tile.style.json.js.map +1 -1
  81. package/build/routes/tile.wmts.d.ts.map +1 -1
  82. package/build/routes/tile.wmts.js +7 -4
  83. package/build/routes/tile.wmts.js.map +1 -1
  84. package/build/routes/tile.xyz.d.ts.map +1 -1
  85. package/build/routes/tile.xyz.js +4 -2
  86. package/build/routes/tile.xyz.js.map +1 -1
  87. package/build/routes/tile.xyz.raster.d.ts.map +1 -1
  88. package/build/routes/tile.xyz.raster.js +4 -2
  89. package/build/routes/tile.xyz.raster.js.map +1 -1
  90. package/build/util/__test__/config.loader.test.d.ts +2 -0
  91. package/build/util/__test__/config.loader.test.d.ts.map +1 -0
  92. package/build/util/__test__/config.loader.test.js +79 -0
  93. package/build/util/__test__/config.loader.test.js.map +1 -0
  94. package/build/util/assets.provider.d.ts +24 -0
  95. package/build/util/assets.provider.d.ts.map +1 -0
  96. package/build/util/assets.provider.js +69 -0
  97. package/build/util/assets.provider.js.map +1 -0
  98. package/build/util/config.cache.d.ts +16 -0
  99. package/build/util/config.cache.d.ts.map +1 -0
  100. package/build/util/config.cache.js +40 -0
  101. package/build/util/config.cache.js.map +1 -0
  102. package/build/util/config.loader.d.ts +10 -0
  103. package/build/util/config.loader.d.ts.map +1 -0
  104. package/build/util/config.loader.js +47 -0
  105. package/build/util/config.loader.js.map +1 -0
  106. package/build/util/response.d.ts +2 -1
  107. package/build/util/response.d.ts.map +1 -1
  108. package/build/util/response.js +1 -0
  109. package/build/util/response.js.map +1 -1
  110. package/build/wmts.capability.d.ts +3 -1
  111. package/build/wmts.capability.d.ts.map +1 -1
  112. package/build/wmts.capability.js +5 -15
  113. package/build/wmts.capability.js.map +1 -1
  114. package/dist/index.js +68 -68
  115. package/dist/node_modules/.package-lock.json +4 -4
  116. package/dist/node_modules/node-abi/abi_registry.json +8 -1
  117. package/dist/node_modules/node-abi/package.json +1 -1
  118. package/dist/package-lock.json +8 -8
  119. package/dist/package.json +1 -1
  120. package/package.json +8 -9
  121. package/src/__tests__/config.data.ts +25 -1
  122. package/src/__tests__/tile.style.json.test.ts +19 -3
  123. package/src/__tests__/wmts.capability.test.ts +21 -0
  124. package/src/__tests__/xyz.util.ts +7 -2
  125. package/src/arcgis/__tests__/arcgis.style.json.test.ts +157 -0
  126. package/src/arcgis/__tests__/vector.tiler.server.test.ts +70 -0
  127. package/src/arcgis/arcgis.info.ts +26 -0
  128. package/src/arcgis/arcgis.style.json.ts +83 -0
  129. package/src/arcgis/vector.tile.server.ts +81 -0
  130. package/src/index.ts +18 -5
  131. package/src/routes/__tests__/attribution.test.ts +4 -2
  132. package/src/routes/__tests__/fonts.test.ts +54 -32
  133. package/src/routes/__tests__/health.test.ts +4 -2
  134. package/src/routes/__tests__/sprites.test.ts +7 -3
  135. package/src/routes/__tests__/tile.json.test.ts +30 -2
  136. package/src/routes/__tests__/tile.style.json.test.ts +68 -9
  137. package/src/routes/__tests__/wmts.test.ts +23 -17
  138. package/src/routes/__tests__/xyz.test.ts +4 -2
  139. package/src/routes/attribution.ts +23 -8
  140. package/src/routes/config.ts +83 -0
  141. package/src/routes/fonts.ts +4 -64
  142. package/src/routes/health.ts +4 -2
  143. package/src/routes/imagery.ts +3 -2
  144. package/src/routes/sprites.ts +4 -27
  145. package/src/routes/tile.json.ts +10 -4
  146. package/src/routes/tile.style.json.ts +58 -12
  147. package/src/routes/tile.wmts.ts +9 -4
  148. package/src/routes/tile.xyz.raster.ts +4 -2
  149. package/src/routes/tile.xyz.ts +5 -2
  150. package/src/util/__test__/config.loader.test.ts +116 -0
  151. package/src/util/assets.provider.ts +66 -0
  152. package/src/util/config.cache.ts +44 -0
  153. package/src/util/config.loader.ts +50 -0
  154. package/src/util/response.ts +3 -1
  155. package/src/wmts.capability.ts +9 -15
  156. package/tsconfig.tsbuildinfo +1 -1
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basemaps/lambda-tiler",
3
- "version": "6.33.0",
3
+ "version": "6.35.0",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
@@ -226,9 +226,9 @@
226
226
  "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
227
227
  },
228
228
  "node_modules/node-abi": {
229
- "version": "3.22.0",
230
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz",
231
- "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==",
229
+ "version": "3.24.0",
230
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.24.0.tgz",
231
+ "integrity": "sha512-YPG3Co0luSu6GwOBsmIdGW6Wx0NyNDLg/hriIyDllVsNwnI6UeqaWShxC3lbH4LtEQUgoLP3XR1ndXiDAWvmRw==",
232
232
  "dependencies": {
233
233
  "semver": "^7.3.5"
234
234
  },
@@ -202,9 +202,16 @@
202
202
  },
203
203
  {
204
204
  "abi": "107",
205
- "future": true,
205
+ "future": false,
206
206
  "lts": false,
207
207
  "runtime": "electron",
208
208
  "target": "20.0.0-alpha.1"
209
+ },
210
+ {
211
+ "abi": "109",
212
+ "future": true,
213
+ "lts": false,
214
+ "runtime": "electron",
215
+ "target": "21.0.0-alpha.1"
209
216
  }
210
217
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-abi",
3
- "version": "3.22.0",
3
+ "version": "3.24.0",
4
4
  "description": "Get the Node ABI for a given target and runtime, and vice versa.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@basemaps/lambda-tiler",
3
- "version": "6.33.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.33.0",
9
+ "version": "6.35.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "sharp": "0.30.7"
@@ -237,9 +237,9 @@
237
237
  "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
238
238
  },
239
239
  "node_modules/node-abi": {
240
- "version": "3.22.0",
241
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz",
242
- "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==",
240
+ "version": "3.24.0",
241
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.24.0.tgz",
242
+ "integrity": "sha512-YPG3Co0luSu6GwOBsmIdGW6Wx0NyNDLg/hriIyDllVsNwnI6UeqaWShxC3lbH4LtEQUgoLP3XR1ndXiDAWvmRw==",
243
243
  "dependencies": {
244
244
  "semver": "^7.3.5"
245
245
  },
@@ -647,9 +647,9 @@
647
647
  "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
648
648
  },
649
649
  "node-abi": {
650
- "version": "3.22.0",
651
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz",
652
- "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==",
650
+ "version": "3.24.0",
651
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.24.0.tgz",
652
+ "integrity": "sha512-YPG3Co0luSu6GwOBsmIdGW6Wx0NyNDLg/hriIyDllVsNwnI6UeqaWShxC3lbH4LtEQUgoLP3XR1ndXiDAWvmRw==",
653
653
  "requires": {
654
654
  "semver": "^7.3.5"
655
655
  }
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basemaps/lambda-tiler",
3
- "version": "6.33.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.33.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.32.1",
25
+ "@basemaps/config": "^6.35.0",
26
26
  "@basemaps/geo": "^6.32.1",
27
- "@basemaps/lambda": "^6.7.0",
28
- "@basemaps/shared": "^6.33.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": "a53973b7ac19250dea69402478d4843aa91c4907"
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',
@@ -17,10 +17,15 @@ export function mockRequest(path: string, method = 'get', headers: Record<string
17
17
  );
18
18
  }
19
19
 
20
- export function mockUrlRequest(path: string, query = '', headers: Record<string, unknown> = {}): LambdaHttpRequest {
20
+ export function mockUrlRequest(
21
+ path: string,
22
+ query = '',
23
+ headers: Record<string, unknown> = {},
24
+ method?: string,
25
+ ): LambdaHttpRequest {
21
26
  return new LambdaUrlRequest(
22
27
  {
23
- requestContext: { http: { method: 'GET' } },
28
+ requestContext: { http: { method: method ? method.toUpperCase() : 'GET' } },
24
29
  headers,
25
30
  rawPath: encodeURI(path),
26
31
  rawQueryString: query,
@@ -0,0 +1,157 @@
1
+ import { BaseConfig, ConfigProviderMemory, StyleJson } from '@basemaps/config';
2
+ import { Env } from '@basemaps/shared';
3
+ import o from 'ospec';
4
+ import { createSandbox } from 'sinon';
5
+ import { handler } from '../../index.js';
6
+ import { ConfigLoader } from '../../util/config.loader.js';
7
+ import { FakeData } from '../../__tests__/config.data.js';
8
+ import { Api, mockRequest, mockUrlRequest } from '../../__tests__/xyz.util.js';
9
+
10
+ o.spec('arcgis/stylejson', () => {
11
+ const host = 'https://tiles.test';
12
+ const sandbox = createSandbox();
13
+ const config = new ConfigProviderMemory();
14
+
15
+ o.before(() => {
16
+ process.env[Env.PublicUrlBase] = host;
17
+ });
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
+
28
+ o('should not found tile set', async () => {
29
+ const request = mockRequest('/v1/arcgis/rest/services/topographic/VectorTileServer/root.json', 'get', Api.header);
30
+
31
+ const res = await handler.router.handle(request);
32
+ o(res.status).equals(404);
33
+ });
34
+
35
+ o('should not found style', async () => {
36
+ const request = mockRequest('/v1/arcgis/rest/services/topographic/VectorTileServer/root.json', 'get', Api.header);
37
+ config.put(FakeData.tileSetVector('topographic'));
38
+
39
+ const res = await handler.router.handle(request);
40
+ o(res.status).equals(404);
41
+ });
42
+
43
+ const fakeStyle: StyleJson = {
44
+ version: 8,
45
+ id: 'test',
46
+ name: 'topographic',
47
+ sources: {
48
+ basemaps_vector: {
49
+ type: 'vector',
50
+ url: `/vector`,
51
+ },
52
+ basemaps_raster: {
53
+ type: 'raster',
54
+ tiles: [`/raster`],
55
+ },
56
+ },
57
+ layers: [
58
+ {
59
+ source: 'basemaps_vector',
60
+ layout: {
61
+ visibility: 'visible',
62
+ },
63
+ paint: {
64
+ 'background-color': 'rgba(206, 229, 242, 1)',
65
+ },
66
+ id: 'Background-vector',
67
+ type: 'background',
68
+ minzoom: 0,
69
+ },
70
+ {
71
+ source: 'basemaps_raster',
72
+ layout: {
73
+ visibility: 'visible',
74
+ },
75
+ paint: {
76
+ 'background-color': 'rgba(222, 229, 132, 1)',
77
+ },
78
+ id: 'Background-raster',
79
+ type: 'background',
80
+ minzoom: 0,
81
+ },
82
+ ],
83
+ glyphs: '/glyphs',
84
+ sprite: '/sprite',
85
+ metadata: { id: 'test' },
86
+ };
87
+
88
+ const fakeRecord = {
89
+ id: 'st_topographic',
90
+ name: 'topographic',
91
+ style: fakeStyle,
92
+ };
93
+
94
+ o('should serve style json and remove the raster source and layers, then replace the vector url', async () => {
95
+ const request = mockRequest('/v1/arcgis/rest/services/topographic/VectorTileServer/root.json', 'get', Api.header);
96
+
97
+ config.put(FakeData.tileSetVector('topographic'));
98
+ config.put(fakeRecord);
99
+
100
+ const res = await handler.router.handle(request);
101
+ o(res.status).equals(200);
102
+ o(res.header('content-type')).equals('application/json');
103
+ o(res.header('cache-control')).equals('no-store');
104
+
105
+ const body = Buffer.from(res.body ?? '', 'base64').toString();
106
+ fakeStyle.sources.basemaps_vector = {
107
+ type: 'vector',
108
+ url: `${host}/v1/arcgis/rest/services/topographic/VectorTileServer?api=${Api.key}&f=json`,
109
+ };
110
+ delete fakeStyle.sources.basemaps_raster;
111
+ fakeStyle.layers = [fakeStyle.layers[0]];
112
+
113
+ fakeStyle.sprite = `${host}/sprite`;
114
+ fakeStyle.glyphs = `${host}/glyphs`;
115
+
116
+ o(JSON.parse(body)).deepEquals(fakeStyle);
117
+ });
118
+
119
+ o('should not found for raster tileset', async () => {
120
+ const request = mockRequest('/v1/arcgis/rest/services/raster/VectorTileServer/root.json', 'get', Api.header);
121
+
122
+ config.put(FakeData.tileSetRaster('raster'));
123
+ config.put(fakeRecord);
124
+
125
+ const res = await handler.router.handle(request);
126
+ o(res.status).equals(404);
127
+ });
128
+
129
+ o('should fine the new style with url query', async () => {
130
+ const request = mockUrlRequest(
131
+ '/v1/arcgis/rest/services/topographic/VectorTileServer/root.json',
132
+ 'style=topolite',
133
+ Api.header,
134
+ );
135
+
136
+ config.put({ id: 'st_topolite', name: 'topographic', style: fakeStyle } as BaseConfig);
137
+ config.put(FakeData.tileSetVector('topographic'));
138
+
139
+ const res = await handler.router.handle(request);
140
+ o(res.status).equals(200);
141
+ o(res.header('content-type')).equals('application/json');
142
+ o(res.header('cache-control')).equals('no-store');
143
+
144
+ const body = Buffer.from(res.body ?? '', 'base64').toString();
145
+ fakeStyle.sources.basemaps_vector = {
146
+ type: 'vector',
147
+ url: `${host}/v1/arcgis/rest/services/topographic/VectorTileServer?api=${Api.key}&f=json`,
148
+ };
149
+ delete fakeStyle.sources.basemaps_raster;
150
+ fakeStyle.layers = [fakeStyle.layers[0]];
151
+
152
+ fakeStyle.sprite = `${host}/sprite`;
153
+ fakeStyle.glyphs = `${host}/glyphs`;
154
+
155
+ o(JSON.parse(body)).deepEquals(fakeStyle);
156
+ });
157
+ });
@@ -0,0 +1,70 @@
1
+ import { ConfigProviderMemory } from '@basemaps/config';
2
+ import { Env } from '@basemaps/shared';
3
+ import o from 'ospec';
4
+ import { createSandbox } from 'sinon';
5
+ import { handler } from '../../index.js';
6
+ import { ConfigLoader } from '../../util/config.loader.js';
7
+ import { FakeData } from '../../__tests__/config.data.js';
8
+ import { Api, mockRequest, mockUrlRequest } from '../../__tests__/xyz.util.js';
9
+
10
+ o.spec('arcgis/VectorTileServer', () => {
11
+ const host = 'https://tiles.test';
12
+ const sandbox = createSandbox();
13
+ const config = new ConfigProviderMemory();
14
+
15
+ o.before(() => {
16
+ process.env[Env.PublicUrlBase] = host;
17
+ });
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
+
28
+ o('should not found tile set', async () => {
29
+ const request = mockUrlRequest('/v1/arcgis/rest/services/topographic/VectorTileServer', 'f=json', Api.header);
30
+
31
+ const res = await handler.router.handle(request);
32
+ o(res.status).equals(404);
33
+ });
34
+ o('should return the vector tile server', async () => {
35
+ const request = mockUrlRequest('/v1/arcgis/rest/services/topographic/VectorTileServer', 'f=json', Api.header);
36
+
37
+ config.put(FakeData.tileSetVector('topographic'));
38
+
39
+ const res = await handler.router.handle(request);
40
+ o(res.status).equals(200);
41
+ o(res.header('content-type')).equals('application/json');
42
+ o(res.header('cache-control')).equals('no-store');
43
+
44
+ const body = JSON.parse(Buffer.from(res.body ?? '', 'base64').toString());
45
+ o(body.tiles[0]).equals(`${host}/v1/tiles/topographic/WebMercatorQuad/{z}/{x}/{y}.pbf?api=${Api.key}`);
46
+ o(body.tileInfo.lods.length).equals(17);
47
+ });
48
+ o('should not return with no f=json query', async () => {
49
+ const request = mockRequest('/v1/arcgis/rest/services/topographic/VectorTileServer', 'get', Api.header);
50
+
51
+ config.put(FakeData.tileSetVector('topographic'));
52
+
53
+ const res = await handler.router.handle(request);
54
+ o(res.status).equals(404);
55
+ });
56
+ o('should return ok for post request', async () => {
57
+ const request = mockUrlRequest(
58
+ '/v1/arcgis/rest/services/topographic/VectorTileServer',
59
+ 'f=json',
60
+ Api.header,
61
+ 'POST',
62
+ );
63
+
64
+ config.put(FakeData.tileSetVector('topographic'));
65
+
66
+ const res = await handler.router.handle(request);
67
+ o(res.status).equals(200);
68
+ o(res.body).deepEquals(`{"id":"${request.id}","correlationId":"${request.correlationId}","message":"ok"}`);
69
+ });
70
+ });
@@ -0,0 +1,26 @@
1
+ import { Env } from '@basemaps/shared';
2
+ import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
3
+ import { Etag } from '../util/etag.js';
4
+ import { NotFound, NotModified } from '../util/response.js';
5
+
6
+ export async function arcgisInfoGet(req: LambdaHttpRequest): Promise<LambdaHttpResponse> {
7
+ const host = Env.get(Env.PublicUrlBase);
8
+ if (host == null) return NotFound();
9
+ const info = {
10
+ currentVersion: 10.1,
11
+ fullVersion: '10.1',
12
+ owningSystemUrl: host,
13
+ };
14
+
15
+ const json = JSON.stringify(info);
16
+ const data = Buffer.from(json);
17
+
18
+ const cacheKey = Etag.key(data);
19
+ if (Etag.isNotModified(req, cacheKey)) return NotModified();
20
+
21
+ const response = new LambdaHttpResponse(200, 'ok');
22
+ response.header(HttpHeader.CacheControl, 'public, max-age=604800, stale-while-revalidate=86400');
23
+ response.buffer(data, 'application/json');
24
+ req.set('bytes', data.byteLength);
25
+ return response;
26
+ }
@@ -0,0 +1,83 @@
1
+ import { Sources, StyleJson, TileSetType } from '@basemaps/config';
2
+ import { Env, fsa } from '@basemaps/shared';
3
+ import { HttpHeader, LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
4
+ import { convertRelativeUrl } from '../routes/tile.style.json.js';
5
+ import { ConfigLoader } from '../util/config.loader.js';
6
+ import { Etag } from '../util/etag.js';
7
+ import { NotFound, NotModified } from '../util/response.js';
8
+ import { Validate } from '../util/validate.js';
9
+
10
+ interface StyleGet {
11
+ Params: {
12
+ tileSet: string;
13
+ };
14
+ }
15
+
16
+ function tileserverUrl(tileSet: string, apiKey: string): string {
17
+ const host = Env.get(Env.PublicUrlBase) ?? '';
18
+ const url = `/v1/arcgis/rest/services/${tileSet}/VectorTileServer`;
19
+ const fullUrl = new URL(fsa.join(host, url));
20
+ fullUrl.searchParams.set('api', apiKey);
21
+ fullUrl.searchParams.set('f', 'json');
22
+ return fullUrl.toString().replace(/%7B/g, '{').replace(/%7D/g, '}');
23
+ }
24
+
25
+ function convertStyleJson(tileSet: string, style: StyleJson, apiKey: string): StyleJson {
26
+ const sources: Sources = JSON.parse(JSON.stringify(style.sources));
27
+ // Only keep the vector layer and update the source url
28
+ for (const [key, value] of Object.entries(sources)) {
29
+ if (value.type === 'vector') {
30
+ value.url = tileserverUrl(tileSet, apiKey);
31
+ sources[key] = value;
32
+ } else {
33
+ delete sources[key];
34
+ }
35
+ }
36
+
37
+ // Remove all the not vector layers.
38
+ const layers = [];
39
+ for (const layer of style.layers) {
40
+ if (layer.source != null && !sources.hasOwnProperty(layer.source)) continue;
41
+ layers.push(layer);
42
+ }
43
+
44
+ return {
45
+ version: 8,
46
+ id: style.id,
47
+ name: style.name,
48
+ sources,
49
+ layers,
50
+ metadata: style.metadata ?? {},
51
+ glyphs: convertRelativeUrl(style.glyphs),
52
+ sprite: convertRelativeUrl(style.sprite),
53
+ } as StyleJson;
54
+ }
55
+
56
+ export async function arcgisStyleJsonGet(req: LambdaHttpRequest<StyleGet>): Promise<LambdaHttpResponse> {
57
+ const apiKey = Validate.apiKey(req);
58
+ const config = await ConfigLoader.load(req);
59
+ const tileSet = await config.TileSet.get(config.TileSet.id(req.params.tileSet));
60
+ if (tileSet?.type !== TileSetType.Vector) return NotFound();
61
+
62
+ const style = req.query.get('style');
63
+ const styleName = style ? style : 'topographic'; // Defalut to topographic style
64
+
65
+ // Get style Config from db
66
+ const dbId = config.Style.id(styleName);
67
+ const styleConfig = await config.Style.get(dbId);
68
+ if (styleConfig == null) return NotFound();
69
+
70
+ // Prepare sources and add linz source
71
+ const styleJson = convertStyleJson(tileSet.name, styleConfig.style, apiKey);
72
+ const data = Buffer.from(JSON.stringify(styleJson));
73
+
74
+ const cacheKey = Etag.key(data);
75
+ if (Etag.isNotModified(req, cacheKey)) return NotModified();
76
+
77
+ const response = new LambdaHttpResponse(200, 'ok');
78
+ response.header(HttpHeader.ETag, cacheKey);
79
+ response.header(HttpHeader.CacheControl, 'no-store');
80
+ response.buffer(data, 'application/json');
81
+ req.set('bytes', data.byteLength);
82
+ return response;
83
+ }