@basemaps/lambda-tiler 7.14.0 → 7.16.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.
@@ -27,20 +27,13 @@ const diff = (version1, version2) => {
27
27
  return 'major'
28
28
  }
29
29
 
30
- // Otherwise it can be determined by checking the high version
31
-
32
- if (highVersion.patch) {
33
- // anything higher than a patch bump would result in the wrong version
30
+ // If the main part has no difference
31
+ if (lowVersion.compareMain(highVersion) === 0) {
32
+ if (lowVersion.minor && !lowVersion.patch) {
33
+ return 'minor'
34
+ }
34
35
  return 'patch'
35
36
  }
36
-
37
- if (highVersion.minor) {
38
- // anything higher than a minor bump would result in the wrong version
39
- return 'minor'
40
- }
41
-
42
- // bumping major/minor/patch all have same result
43
- return 'major'
44
37
  }
45
38
 
46
39
  // add the `pre` prefix if we are going to a prerelease version
@@ -10,6 +10,7 @@ exports = module.exports = {}
10
10
  const re = exports.re = []
11
11
  const safeRe = exports.safeRe = []
12
12
  const src = exports.src = []
13
+ const safeSrc = exports.safeSrc = []
13
14
  const t = exports.t = {}
14
15
  let R = 0
15
16
 
@@ -42,6 +43,7 @@ const createToken = (name, value, isGlobal) => {
42
43
  debug(name, index, value)
43
44
  t[name] = index
44
45
  src[index] = value
46
+ safeSrc[index] = safe
45
47
  re[index] = new RegExp(value, isGlobal ? 'g' : undefined)
46
48
  safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined)
47
49
  }
@@ -1,20 +1,21 @@
1
1
  {
2
2
  "name": "semver",
3
- "version": "7.6.3",
3
+ "version": "7.7.1",
4
4
  "description": "The semantic version parser used by npm.",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "tap",
8
8
  "snap": "tap",
9
- "lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
9
+ "lint": "npm run eslint",
10
10
  "postlint": "template-oss-check",
11
- "lintfix": "npm run lint -- --fix",
11
+ "lintfix": "npm run eslint -- --fix",
12
12
  "posttest": "npm run lint",
13
- "template-oss-apply": "template-oss-apply --force"
13
+ "template-oss-apply": "template-oss-apply --force",
14
+ "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\""
14
15
  },
15
16
  "devDependencies": {
16
- "@npmcli/eslint-config": "^4.0.0",
17
- "@npmcli/template-oss": "4.22.0",
17
+ "@npmcli/eslint-config": "^5.0.0",
18
+ "@npmcli/template-oss": "4.23.4",
18
19
  "benchmark": "^2.1.4",
19
20
  "tap": "^16.0.0"
20
21
  },
@@ -51,7 +52,7 @@
51
52
  "author": "GitHub Inc.",
52
53
  "templateOSS": {
53
54
  "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
54
- "version": "4.22.0",
55
+ "version": "4.23.4",
55
56
  "engines": ">=10",
56
57
  "distPaths": [
57
58
  "classes/",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@basemaps/lambda-tiler",
3
- "version": "7.14.0",
3
+ "version": "7.16.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@basemaps/lambda-tiler",
9
- "version": "7.14.0",
9
+ "version": "7.16.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "lerc": "4.0.4",
@@ -539,9 +539,9 @@
539
539
  "license": "Apache-2.0"
540
540
  },
541
541
  "node_modules/semver": {
542
- "version": "7.6.3",
543
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
544
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
542
+ "version": "7.7.1",
543
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
544
+ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
545
545
  "license": "ISC",
546
546
  "bin": {
547
547
  "semver": "bin/semver.js"
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basemaps/lambda-tiler",
3
- "version": "7.14.0",
3
+ "version": "7.16.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": "7.14.0",
3
+ "version": "7.16.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/linz/basemaps.git",
@@ -22,12 +22,12 @@
22
22
  "types": "./build/index.d.ts",
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "@basemaps/config": "^7.14.0",
26
- "@basemaps/config-loader": "^7.14.0",
27
- "@basemaps/geo": "^7.12.0",
28
- "@basemaps/shared": "^7.14.0",
29
- "@basemaps/tiler": "^7.12.0",
30
- "@basemaps/tiler-sharp": "^7.14.0",
25
+ "@basemaps/config": "^7.16.0",
26
+ "@basemaps/config-loader": "^7.16.0",
27
+ "@basemaps/geo": "^7.16.0",
28
+ "@basemaps/shared": "^7.16.0",
29
+ "@basemaps/tiler": "^7.16.0",
30
+ "@basemaps/tiler-sharp": "^7.16.0",
31
31
  "@linzjs/geojson": "^7.10.0",
32
32
  "@linzjs/lambda": "^4.0.0",
33
33
  "@mapbox/vector-tile": "^2.0.3",
@@ -50,11 +50,11 @@
50
50
  "bundle": "./bundle.sh"
51
51
  },
52
52
  "devDependencies": {
53
- "@basemaps/attribution": "^7.12.0",
53
+ "@basemaps/attribution": "^7.16.0",
54
54
  "@chunkd/fs": "^11.2.0",
55
55
  "@types/aws-lambda": "^8.10.75",
56
56
  "@types/pixelmatch": "^5.0.0",
57
57
  "pretty-json-log": "^1.0.0"
58
58
  },
59
- "gitHead": "72f2a811d4851c6f50758617c9e65179d2b27bc8"
59
+ "gitHead": "25fa7659b84a40205ceacda8b2ca5f48e1dc6f7b"
60
60
  }
@@ -63,6 +63,24 @@ export const TileSetElevation: ConfigTileSetRaster = {
63
63
  ],
64
64
  outputs: [DefaultTerrainRgbOutput, DefaultColorRampOutput],
65
65
  };
66
+ export const TileSetHillshadeElevation: ConfigTileSetRaster = {
67
+ id: 'ts_hillshade',
68
+ name: 'hillshade',
69
+ type: TileSetType.Raster,
70
+ description: 'hillshade__description',
71
+ title: 'hillshade Imagery',
72
+ category: 'hillshade',
73
+ layers: [
74
+ {
75
+ // TODO: create one band imagery to reference
76
+ 2193: 'im_01FYWKAJ86W9P7RWM1VB62KD0H',
77
+ 3857: 'im_01FYWKATAEK2ZTJQ2PX44Y0XNT',
78
+ title: 'New Zealand 8m Hillshade DEM (2012)',
79
+ name: 'new-zealand_hillshade_2012_dem_8m',
80
+ },
81
+ ],
82
+ outputs: [DefaultColorRampOutput],
83
+ };
66
84
 
67
85
  export const Imagery2193: ConfigImagery = {
68
86
  id: 'im_01FYWKAJ86W9P7RWM1VB62KD0H',
@@ -8,6 +8,7 @@ import { fsa, FsMemory } from '@chunkd/fs';
8
8
  import { Api, mockRequest, mockUrlRequest } from '../../__tests__/xyz.util.js';
9
9
  import { handler } from '../../index.js';
10
10
  import { CachedConfig } from '../../util/config.cache.js';
11
+ import { ConfigLoader } from '../../util/config.loader.js';
11
12
  import { CoSources } from '../../util/source.cache.js';
12
13
  import { fontList } from '../fonts.js';
13
14
 
@@ -28,12 +29,15 @@ describe('/v1/fonts', () => {
28
29
  memory.files.clear();
29
30
  });
30
31
 
31
- it('should return 404 if no font found', async () => {
32
+ it('should return 404 if no font found', async (t) => {
33
+ t.mock.method(ConfigLoader, 'getDefaultConfig', () => config);
32
34
  const res = await fontList(mockRequest('/v1/fonts.json'));
33
35
  assert.equal(res.status, 404);
34
36
  });
35
37
 
36
- it('should return a list of fonts found', async () => {
38
+ it('should return a list of fonts found', async (t) => {
39
+ t.mock.method(ConfigLoader, 'getDefaultConfig', () => config);
40
+
37
41
  await fsa.write(
38
42
  new URL('memory://assets/fonts/fonts.json'),
39
43
  Buffer.from(JSON.stringify(['Roboto Black', 'Roboto Thin'])),
@@ -45,7 +49,9 @@ describe('/v1/fonts', () => {
45
49
  assert.equal(res._body?.toString(), JSON.stringify(['Roboto Black', 'Roboto Thin']));
46
50
  });
47
51
 
48
- it('should get the correct font', async () => {
52
+ it('should get the correct font', async (t) => {
53
+ t.mock.method(ConfigLoader, 'getDefaultConfig', () => config);
54
+
49
55
  await fsa.write(new URL('memory://assets/fonts/Roboto Thin/0-255.pbf'), Buffer.from(''));
50
56
  const res255 = await handler.router.handle(mockRequest('/v1/fonts/Roboto Thin/0-255.pbf'));
51
57
  assert.equal(res255.status, 200);
@@ -58,7 +64,9 @@ describe('/v1/fonts', () => {
58
64
  assert.equal(res404.status, 404);
59
65
  });
60
66
 
61
- it('should get the correct utf8 font', async () => {
67
+ it('should get the correct utf8 font', async (t) => {
68
+ t.mock.method(ConfigLoader, 'getDefaultConfig', () => config);
69
+
62
70
  await fsa.write(new URL('memory://assets/fonts/🦄 🌈/0-255.pbf'), Buffer.from(''));
63
71
  const res255 = await handler.router.handle(mockRequest('/v1/fonts/🦄 🌈/0-255.pbf'));
64
72
  assert.equal(res255.status, 200);
@@ -68,7 +76,9 @@ describe('/v1/fonts', () => {
68
76
  assert.equal(res255.header('cache-control'), 'public, max-age=604800, stale-while-revalidate=86400');
69
77
  });
70
78
 
71
- it('should return 404 if no asset location set', async () => {
79
+ it('should return 404 if no asset location set', async (t) => {
80
+ t.mock.method(ConfigLoader, 'getDefaultConfig', () => config);
81
+
72
82
  config.assets = undefined;
73
83
  const res = await fontList(mockRequest('/v1/fonts.json'));
74
84
  assert.equal(res.status, 404);
@@ -76,11 +86,14 @@ describe('/v1/fonts', () => {
76
86
 
77
87
  it('should get the correct utf8 font with default assets', async () => {
78
88
  config.assets = undefined;
89
+ const configJson = config.toJson();
90
+ await fsa.write(new URL(`memory://config-${configJson.hash}.json`), JSON.stringify(configJson));
91
+
79
92
  config.objects.set('cb_latest', {
80
93
  id: 'cb_latest',
81
94
  name: 'latest',
82
- path: 'latest',
83
- hash: 'hash',
95
+ path: `memory://config-${configJson.hash}.json`,
96
+ hash: configJson.hash,
84
97
  assets: 'memory://new-location/',
85
98
  } as BaseConfig);
86
99
 
@@ -93,7 +106,9 @@ describe('/v1/fonts', () => {
93
106
  assert.equal(res255.header('cache-control'), 'public, max-age=604800, stale-while-revalidate=86400');
94
107
  });
95
108
 
96
- it('should get the correct utf8 font with config assets', async () => {
109
+ it('should get the correct utf8 font with config assets', async (t) => {
110
+ t.mock.method(ConfigLoader, 'getDefaultConfig', () => config);
111
+
97
112
  const cfgBundle = new ConfigProviderMemory();
98
113
  cfgBundle.assets = 'memory://config/assets/';
99
114
  await fsa.write(new URL('memory://linz-basemaps/bar.json'), JSON.stringify(cfgBundle.toJson()));
@@ -135,7 +135,10 @@ describe('/v1/tiles', () => {
135
135
 
136
136
  const elevation = FakeData.tileSetRaster('elevation');
137
137
 
138
- elevation.outputs = [{ title: 'Terrain RGB', name: 'terrain-rgb' }];
138
+ elevation.outputs = [
139
+ { title: 'Terrain RGB', name: 'terrain-rgb' },
140
+ { title: 'Color Ramp', name: 'color-ramp' },
141
+ ];
139
142
  config.put(elevation);
140
143
 
141
144
  const request = mockRequest('/v1/tiles/elevation/3857/11/2022/1283.webp', 'get', Api.header);
@@ -145,6 +148,21 @@ describe('/v1/tiles', () => {
145
148
  assert.equal(res.status, 404, res.statusDescription);
146
149
  });
147
150
 
151
+ it('should default to the pipeline if only one pipeline is defined', async (t) => {
152
+ t.mock.method(ConfigLoader, 'getDefaultConfig', () => Promise.resolve(config));
153
+
154
+ const elevation = FakeData.tileSetRaster('elevation');
155
+
156
+ elevation.outputs = [{ title: 'Terrain RGB', name: 'terrain-rgb' }];
157
+ config.put(elevation);
158
+
159
+ const request = mockRequest('/v1/tiles/elevation/3857/11/2022/1283.webp', 'get', Api.header);
160
+
161
+ const res = await handler.router.handle(request);
162
+
163
+ assert.equal(res.status, 200, res.statusDescription);
164
+ });
165
+
148
166
  it('should generate a terrain-rgb 11/2022/1283 in webp', async (t) => {
149
167
  t.mock.method(ConfigLoader, 'getDefaultConfig', () => Promise.resolve(config));
150
168
 
@@ -18,13 +18,21 @@ const SafeProtocols = new Set([new URL('s3://foo').protocol, new URL('memory://f
18
18
 
19
19
  export class ConfigLoader {
20
20
  /** Exposed for testing */
21
- static async getDefaultConfig(): Promise<BasemapsConfigProvider> {
21
+ static async getDefaultConfig(req?: LambdaHttpRequest): Promise<BasemapsConfigProvider> {
22
22
  const config = getDefaultConfig();
23
- if (config.assets == null) {
24
- const cb = await config.ConfigBundle.get(config.ConfigBundle.id('latest'));
25
- if (cb) config.assets = cb.assets;
26
- }
27
- return config;
23
+
24
+ // Look up the latest config bundle out of dynamodb, then load the config from the provided path
25
+ const cb = await config.ConfigBundle.get('cb_latest');
26
+ if (cb == null) return config;
27
+
28
+ req?.timer.start('config:load');
29
+
30
+ return CachedConfig.get(fsa.toUrl(cb.path)).then((cfg) => {
31
+ req?.timer.end('config:load');
32
+ if (cfg == null) throw new LambdaHttpResponse(500, 'Unable to find latest configuration');
33
+ if (cfg.assets == null) cfg.assets = cb.assets;
34
+ return cfg;
35
+ });
28
36
  }
29
37
 
30
38
  /** Lookup the config path from a request and return a standardized location */
@@ -125,6 +125,9 @@ export const Validate = {
125
125
  * Defaults to standard image format output if no outputs are defined on the tileset
126
126
  */
127
127
  pipeline(tileSet: ConfigTileSetRaster, tileType: string, pipeline?: string | null): ConfigTileSetRasterOutput | null {
128
+ // If there is only one pipeline force the use of it
129
+ if (tileSet.outputs?.length === 1 && pipeline == null) pipeline = tileSet.outputs[0].name;
130
+
128
131
  if (pipeline != null && pipeline !== 'rgba') {
129
132
  if (tileSet.outputs == null) throw new LambdaHttpResponse(404, 'TileSet has no pipelines');
130
133
  const output = tileSet.outputs.find((f) => f.name === pipeline);
@@ -136,7 +139,8 @@ export const Validate = {
136
139
  }
137
140
  return output;
138
141
  }
139
- // If the tileset has pipelines defined the user MUST specify which one
142
+
143
+ // If the tileset has multiple pipelines defined the user MUST specify which one
140
144
  if (tileSet.outputs) {
141
145
  throw new LambdaHttpResponse(404, 'TileSet needs pipeline: ' + tileSet.outputs.map((f) => f.name).join(', '));
142
146
  }