From 9fa3681acc2ce25037c5d6e0326255aad9815b7d Mon Sep 17 00:00:00 2001 From: Blayne Chard Date: Fri, 18 Oct 2024 11:43:32 +1300 Subject: [PATCH 01/12] fix(lambda-tiler): correctly log fetch requests (#3359) ### Motivation Requests tracing has been broken for a while (not entire sure when it broke) It is very very helpful to have statistics on the number of s3 requests required to make a tile ### Modifications - `requestCount` is reserved for the number of lambda invocations so move to `fetchCount` for number of fetches - include the fetchIds to trace hot fetches - increase the percent of requests with tracing enabled - Use async local storage to gain access to the logger for the request that triggers the log message, this fixes a bug where the request may be in `trace` but the fetch is using the base logger which is set to `info` so no logs are generated. ### Verification Ran locally and verified logs are now appearing. --------- Co-authored-by: Wentao Kuang --- packages/lambda-tiler/src/index.ts | 10 ++++++---- packages/shared/src/file.system.ts | 5 +++-- packages/shared/src/index.ts | 2 +- packages/shared/src/log.ts | 9 +++++++++ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/lambda-tiler/src/index.ts b/packages/lambda-tiler/src/index.ts index f14ffbd38..050a21dec 100644 --- a/packages/lambda-tiler/src/index.ts +++ b/packages/lambda-tiler/src/index.ts @@ -1,4 +1,4 @@ -import { FsaCache, FsaLog, LogConfig } from '@basemaps/shared'; +import { FsaCache, FsaLog, LogConfig, LogStorage } from '@basemaps/shared'; import { LambdaHttpRequest, LambdaHttpResponse, lf } from '@linzjs/lambda'; import { tileAttributionGet } from './routes/attribution.js'; @@ -34,13 +34,14 @@ function randomTrace(req: LambdaHttpRequest): void { const rand = Math.random(); // 1% trace if (rand < 0.01) req.log.level = 'trace'; - // 5% debug - else if (rand < 0.04) req.log.level = 'debug'; + // 25% debug + else if (rand < 0.25) req.log.level = 'debug'; // everything else info else req.log.level = 'info'; } handler.router.hook('request', (req) => { + LogStorage.enterWith({ log: req.log }); FsaLog.reset(); randomTrace(req); @@ -49,7 +50,8 @@ handler.router.hook('request', (req) => { }); handler.router.hook('response', (req, res) => { - req.set('requestCount', FsaLog.requests.length); + req.set('fetchCount', FsaLog.count); + req.set('fetches', FsaLog.requests); req.set('cacheSize', FsaCache.size); // Force access-control-allow-origin to everything res.header('access-control-allow-origin', '*'); diff --git a/packages/shared/src/file.system.ts b/packages/shared/src/file.system.ts index 63d49fdc8..c48b9a38c 100644 --- a/packages/shared/src/file.system.ts +++ b/packages/shared/src/file.system.ts @@ -45,7 +45,7 @@ applyS3MiddleWare(s3Fs); const credentials = new AwsS3CredentialProvider(); credentials.onFileSystemCreated = (acc: AwsCredentialConfig, fs: FileSystem): void => { - LogConfig.get().debug({ prefix: acc.prefix, roleArn: acc.roleArn }, 'FileSystem:Register'); + LogConfig.get().info({ prefix: acc.prefix, roleArn: acc.roleArn }, 'FileSystem:Register'); applyS3MiddleWare(fs as FsAwsS3); fsa.register(acc.prefix, fs); }; @@ -81,9 +81,10 @@ export const FsaLog = { this.requests.push(requestId); const startTime = performance.now(); const res = await next(req); - LogConfig.get().trace( + LogConfig.get().debug( { source: req.source.url.href, + sourceHost: req.source.url.hostname, offset: req.offset, length: req.length, requestId, diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 68b3c0ce4..8f7bf6eef 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -8,7 +8,7 @@ export { ConfigProviderDynamo } from './dynamo/dynamo.config.js'; export { Fsa as fsa, FsaCache, FsaChunk, FsaLog, stringToUrlFolder, urlToString } from './file.system.js'; export { Fqdn } from './file.system.middleware.js'; export { getImageryCenterZoom, getPreviewQuery, getPreviewUrl, PreviewSize } from './imagery.url.js'; -export { LogConfig, LogType } from './log.js'; +export { LogConfig, LogStorage, LogType } from './log.js'; export { LoggerFatalError } from './logger.fatal.error.js'; export { toQueryString } from './url.js'; export * from './util.js'; diff --git a/packages/shared/src/log.ts b/packages/shared/src/log.ts index 15b70476f..fecdcaae2 100644 --- a/packages/shared/src/log.ts +++ b/packages/shared/src/log.ts @@ -1,3 +1,5 @@ +import { AsyncLocalStorage } from 'node:async_hooks'; + import pino from 'pino'; import { PrettyTransform } from 'pretty-json-log'; @@ -29,6 +31,11 @@ const defaultOpts = { level: 'debug' }; export const LogConfig = { /** Get the currently configured logger */ get(): LogType { + // If this .get() is called inside a async function eg a HTTP request + // use the logger from the async context if it has one + const localStorage = LogStorage.getStore()?.log; + if (localStorage) return localStorage; + if (currentLog == null) { currentLog = process.stdout.isTTY ? pino.default(defaultOpts, PrettyTransform.stream()) @@ -46,3 +53,5 @@ export const LogConfig = { LogConfig.get().level = 'silent'; }, }; + +export const LogStorage = new AsyncLocalStorage<{ log: LogType }>(); From 6655441e48fd226f81daeb98987a95dd649128a7 Mon Sep 17 00:00:00 2001 From: Wentao Kuang Date: Fri, 18 Oct 2024 14:54:17 +1300 Subject: [PATCH 02/12] fix(landing): Fix debug hillshade infinite loading. BM-1110 (#3360) ### Motivation Debug.hillshade keep loading network because the skip check with un-prefix hillshade sourceId and get the hillshade layer been removed and added for every rendering. ### Modifications Correct the check sourceId with prefixed one. ### Verification Tested with locally build, was infinite loading before fix, and only load once after fix. --- packages/landing/src/components/debug.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/landing/src/components/debug.tsx b/packages/landing/src/components/debug.tsx index d96414c92..ccf12784b 100644 --- a/packages/landing/src/components/debug.tsx +++ b/packages/landing/src/components/debug.tsx @@ -335,11 +335,12 @@ export class Debug extends Component<{ map: maplibregl.Map }, DebugState> { if (currentLayer) map.removeLayer(HillShadeLayerId); return; } - if (currentLayer?.source === sourceId) return; + + const hillShadeSourceId = `${HillShadePrefix}${sourceId}`; + if (currentLayer?.source === hillShadeSourceId) return; // Hillshading from an existing raster-dem source gives very mixed results and looks very blury // so add a new source layer to generate from - const hillShadeSourceId = `${HillShadePrefix}${sourceId}`; const existingSource = map.getSource(hillShadeSourceId); if (existingSource == null) { const source = map.getSource(sourceId); From 4a684f271c518f7d01edbb21673701c5e3133732 Mon Sep 17 00:00:00 2001 From: Blayne Chard Date: Tue, 22 Oct 2024 11:47:22 +1300 Subject: [PATCH 03/12] build: set lambda to log as JSON (#3362) ### Motivation since the end of 2023, lambda functions can now output JSON as their logging format, since all of our other logs are structured move to JSON logs for everything ### Modifications Convert lambda functions to log as JSON ### Verification Need to verify everything is working correctly after deploy, eg alerts/log shipping --- package-lock.json | 152 +++++++++++------- packages/_infra/package.json | 6 +- .../_infra/src/analytics/edge.analytics.ts | 11 +- packages/_infra/src/serve/lambda.tiler.ts | 1 + 4 files changed, 102 insertions(+), 68 deletions(-) diff --git a/package-lock.json b/package-lock.json index a52acd3ae..1a87b76f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,9 +35,9 @@ } }, "node_modules/@aws-cdk/asset-awscli-v1": { - "version": "2.2.201", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.201.tgz", - "integrity": "sha512-INZqcwDinNaIdb5CtW3ez5s943nX5stGBQS6VOP2JDlOFP81hM3fds/9NDknipqfUkZM43dx+HgVvkXYXXARCQ==", + "version": "2.2.208", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.208.tgz", + "integrity": "sha512-r4CuHZaiBioU6waWhCNdEL4MO1+rfbcYVS/Ndz1XNGB5cxIRZwAS0Si6qD2D6nsgpPojiruFl67T1t5M9Va8kQ==", "dev": true }, "node_modules/@aws-cdk/asset-kubectl-v20": { @@ -47,11 +47,46 @@ "dev": true }, "node_modules/@aws-cdk/asset-node-proxy-agent-v6": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.1.tgz", - "integrity": "sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.1.0.tgz", + "integrity": "sha512-7bY3J8GCVxLupn/kNmpPc5VJz8grx+4RKfnnJiO1LG+uxkZfANZG3RMHhE+qQxxwkyQ9/MfPtTpf748UhR425A==", "dev": true }, + "node_modules/@aws-cdk/cloud-assembly-schema": { + "version": "38.0.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-38.0.1.tgz", + "integrity": "sha512-KvPe+NMWAulfNVwY7jenFhzhuLhLqJ/OPy5jx7wUstbjnYnjRVLpUHPU3yCjXFE0J8cuJVdx95BJ4rOs66Pi9w==", + "bundleDependencies": [ + "jsonschema", + "semver" + ], + "dev": true, + "dependencies": { + "jsonschema": "^1.4.1", + "semver": "^7.6.3" + } + }, + "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/jsonschema": { + "version": "1.4.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/semver": { + "version": "7.6.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@aws-crypto/crc32": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", @@ -6147,9 +6182,9 @@ } }, "node_modules/aws-cdk": { - "version": "2.114.1", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.114.1.tgz", - "integrity": "sha512-iLOCPb3WAJOgVYQ4GvAnrjtScJfPwcczlB4995h3nUYQdHbus0jNffFv13zBShdWct3cuX+bqLuZ4JyEmJ9+rg==", + "version": "2.162.1", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.162.1.tgz", + "integrity": "sha512-p9WeiJ7wfiWj0Bpr1HhNdWENf0TxSZN73JtNqvqyaK6SptiLJc+R+ELo0hF3qKT99NWHTCbwWA/JH3BvEXbFxA==", "dev": true, "bin": { "cdk": "bin/cdk" @@ -6162,9 +6197,9 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.114.1", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.114.1.tgz", - "integrity": "sha512-pJy+Sa3+s6K9I0CXYGU8J5jumw9uQEbl8zPK8EMA+A6hP9qb1JN+a8ohyw6a1O1cb4D5S6gwH+hE7Fq7hGPY3A==", + "version": "2.162.1", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.162.1.tgz", + "integrity": "sha512-XiZLVE5ISNajNNmLye8l5w4EGqm6/d8C8shw63QwxaRVYdHl5e+EAaUEmZJpWc4sYtY/sS+GHOfhoKFLjha2rg==", "bundleDependencies": [ "@balena/dockerignore", "case", @@ -6175,22 +6210,25 @@ "punycode", "semver", "table", - "yaml" + "yaml", + "mime-types" ], "dev": true, "dependencies": { - "@aws-cdk/asset-awscli-v1": "^2.2.201", + "@aws-cdk/asset-awscli-v1": "^2.2.202", "@aws-cdk/asset-kubectl-v20": "^2.1.2", - "@aws-cdk/asset-node-proxy-agent-v6": "^2.0.1", + "@aws-cdk/asset-node-proxy-agent-v6": "^2.1.0", + "@aws-cdk/cloud-assembly-schema": "^38.0.0", "@balena/dockerignore": "^1.0.2", "case": "1.6.3", - "fs-extra": "^11.1.1", - "ignore": "^5.3.0", + "fs-extra": "^11.2.0", + "ignore": "^5.3.2", "jsonschema": "^1.4.1", + "mime-types": "^2.1.35", "minimatch": "^3.1.2", "punycode": "^2.3.1", - "semver": "^7.5.4", - "table": "^6.8.1", + "semver": "^7.6.3", + "table": "^6.8.2", "yaml": "1.10.2" }, "engines": { @@ -6207,15 +6245,15 @@ "license": "Apache-2.0" }, "node_modules/aws-cdk-lib/node_modules/ajv": { - "version": "8.12.0", + "version": "8.17.1", "dev": true, "inBundle": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -6316,8 +6354,14 @@ "inBundle": true, "license": "MIT" }, + "node_modules/aws-cdk-lib/node_modules/fast-uri": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT" + }, "node_modules/aws-cdk-lib/node_modules/fs-extra": { - "version": "11.1.1", + "version": "11.2.0", "dev": true, "inBundle": true, "license": "MIT", @@ -6337,7 +6381,7 @@ "license": "ISC" }, "node_modules/aws-cdk-lib/node_modules/ignore": { - "version": "5.3.0", + "version": "5.3.2", "dev": true, "inBundle": true, "license": "MIT", @@ -6387,16 +6431,25 @@ "inBundle": true, "license": "MIT" }, - "node_modules/aws-cdk-lib/node_modules/lru-cache": { - "version": "6.0.0", + "node_modules/aws-cdk-lib/node_modules/mime-db": { + "version": "1.52.0", "dev": true, "inBundle": true, - "license": "ISC", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/mime-types": { + "version": "2.1.35", + "dev": true, + "inBundle": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "mime-db": "1.52.0" }, "engines": { - "node": ">=10" + "node": ">= 0.6" } }, "node_modules/aws-cdk-lib/node_modules/minimatch": { @@ -6430,13 +6483,10 @@ } }, "node_modules/aws-cdk-lib/node_modules/semver": { - "version": "7.5.4", + "version": "7.6.3", "dev": true, "inBundle": true, "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -6488,7 +6538,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/table": { - "version": "6.8.1", + "version": "6.8.2", "dev": true, "inBundle": true, "license": "BSD-3-Clause", @@ -6512,21 +6562,6 @@ "node": ">= 10.0.0" } }, - "node_modules/aws-cdk-lib/node_modules/uri-js": { - "version": "4.4.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/aws-cdk-lib/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, "node_modules/aws-cdk-lib/node_modules/yaml": { "version": "1.10.2", "dev": true, @@ -7333,13 +7368,10 @@ "dev": true }, "node_modules/constructs": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.3.0.tgz", - "integrity": "sha512-vbK8i3rIb/xwZxSpTjz3SagHn1qq9BChLEfy5Hf6fB3/2eFbrwt2n9kHwQcS0CPTRBesreeAcsJfMq2229FnbQ==", - "dev": true, - "engines": { - "node": ">= 16.14.0" - } + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.4.2.tgz", + "integrity": "sha512-wsNxBlAott2qg8Zv87q3eYZYgheb9lchtBfjHzzLHtXbttwSrHPs1NNQbBrmbb1YZvYg2+Vh0Dor76w4mFxJkA==", + "dev": true }, "node_modules/content-disposition": { "version": "0.5.4", @@ -19306,9 +19338,9 @@ "@basemaps/lambda-tiler": "^7.11.0", "@basemaps/shared": "^7.11.0", "@linzjs/cdk-tags": "^1.7.0", - "aws-cdk": "2.114.x", - "aws-cdk-lib": "2.114.x", - "constructs": "^10.3.0" + "aws-cdk": "2.162.x", + "aws-cdk-lib": "2.162.x", + "constructs": "^10.4.2" }, "engines": { "node": ">=16.0.0" diff --git a/packages/_infra/package.json b/packages/_infra/package.json index d860b92f4..66829642e 100644 --- a/packages/_infra/package.json +++ b/packages/_infra/package.json @@ -29,8 +29,8 @@ "@basemaps/lambda-tiler": "^7.11.0", "@basemaps/shared": "^7.11.0", "@linzjs/cdk-tags": "^1.7.0", - "aws-cdk": "2.114.x", - "aws-cdk-lib": "2.114.x", - "constructs": "^10.3.0" + "aws-cdk": "2.162.x", + "aws-cdk-lib": "2.162.x", + "constructs": "^10.4.2" } } diff --git a/packages/_infra/src/analytics/edge.analytics.ts b/packages/_infra/src/analytics/edge.analytics.ts index 193d2df1c..61558f54c 100644 --- a/packages/_infra/src/analytics/edge.analytics.ts +++ b/packages/_infra/src/analytics/edge.analytics.ts @@ -2,7 +2,7 @@ import { Env } from '@basemaps/shared'; import { Duration, Stack, StackProps } from 'aws-cdk-lib'; import { Rule, Schedule } from 'aws-cdk-lib/aws-events'; import { LambdaFunction } from 'aws-cdk-lib/aws-events-targets'; -import lf from 'aws-cdk-lib/aws-lambda'; +import lambda from 'aws-cdk-lib/aws-lambda'; import { RetentionDays } from 'aws-cdk-lib/aws-logs'; import { BlockPublicAccess, Bucket } from 'aws-cdk-lib/aws-s3'; import { Construct } from 'constructs'; @@ -18,7 +18,7 @@ export interface EdgeAnalyticsProps extends StackProps { * Every hour create analytics based off the logs given to us from cloudwatch */ export class EdgeAnalytics extends Stack { - public lambda: lf.Function; + public lambda: lambda.Function; public constructor(scope: Construct, id: string, props: EdgeAnalyticsProps) { super(scope, id, props); @@ -31,12 +31,12 @@ export class EdgeAnalytics extends Stack { blockPublicAccess: BlockPublicAccess.BLOCK_ALL, }); - this.lambda = new lf.Function(this, 'AnalyticLambda', { - runtime: lf.Runtime.NODEJS_18_X, + this.lambda = new lambda.Function(this, 'AnalyticLambda', { + runtime: lambda.Runtime.NODEJS_18_X, memorySize: 2048, timeout: Duration.minutes(10), handler: 'index.handler', - code: lf.Code.fromAsset(CODE_PATH), + code: lambda.Code.fromAsset(CODE_PATH), environment: { [Env.Analytics.CloudFrontId]: distributionId, [Env.Analytics.CacheBucket]: `s3://${cacheBucket.bucketName}`, @@ -44,6 +44,7 @@ export class EdgeAnalytics extends Stack { AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1', }, logRetention: RetentionDays.ONE_MONTH, + loggingFormat: lambda.LoggingFormat.JSON, }); cacheBucket.grantReadWrite(this.lambda); diff --git a/packages/_infra/src/serve/lambda.tiler.ts b/packages/_infra/src/serve/lambda.tiler.ts index 3d9382fdb..3007b12fb 100644 --- a/packages/_infra/src/serve/lambda.tiler.ts +++ b/packages/_infra/src/serve/lambda.tiler.ts @@ -54,6 +54,7 @@ export class LambdaTiler extends Construct { architecture: lambda.Architecture.ARM_64, environment, logRetention: RetentionDays.ONE_MONTH, + loggingFormat: lambda.LoggingFormat.JSON, }); this.functionUrl = new lambda.FunctionUrl(this, 'LambdaCogUrl', { From e702c7e53d28aaa8db9d624acab048f8ec3a2309 Mon Sep 17 00:00:00 2001 From: Tawera Manaena Date: Fri, 25 Oct 2024 09:49:55 +1300 Subject: [PATCH 04/12] feat(lambda-tiler): update imagery layer attributions to show licensor details BM-897 (#3357) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Motivation As an Imagery Data Maintainer, I want to ensure that imagery is attributed to the correct licensor(s) for all published surveys so that councils and government departments receive appropriate recognition. --- ### Attribution Types || Compact | Extended | | - | - | - | | Template | © `stac_license` `licensor_names` | © `stac_license` `licensor_names` - `tileset_info` | | Example | © CC BY 4.0 Otago Regional Council | © CC BY 4.0 Otago Regional Council - Otago 0.3 Rural Aerial Photos (2017-2019) | --- ### Modifications #### packages/config-loader - Updated the package so that it copies through `providers` metadata when generating config files. #### packages/lambda-tiler - Updated the attribution endpoint to include `providers` metadata as part of collections when returning `AttributionStac` responses. - Updated the style endpoint to include a _compact attribution_ on sources when returning `StyleJson` responses. #### packages/attribution - Updated the attribution class to return an _extended attribution_ for the bottom-right of the landing page. ### Verification #### packages/lambda-tiler 1. Implemented a test suite for the style endpoint to ensure it generates the correct _compact attribution_ for a given tileset. #### packages/attribution 5. Implemented a test suite to verify that the new utility function `createLicensorAttribution()` generates the correct _compact attribution_ for a given list of providers. --- ### Example Layer: Top of the South 0.15m Flood Aerial Photos (2022) > To recreate this example, you will need to locally download the `collection.json` file and at least one of the .TIFF files. You will then need to run them through the `cogify` process and serve them using the `server` package. #### Landing Page Screenshot showing the _extended attribution_ for the bottom-right of the landing page. ![top-of-the-south-flood-2022-0 15m](https://github.com/user-attachments/assets/d90bb27c-0b66-41c1-91b8-402a5e10e2bc) #### Styles Endpoint `/v1/styles/:styleName.json` Excerpt from the JSON response showing the provider metadata: ```json { ... "collections": [ { ... "providers": [ { "name": "Nelson City Council", "roles": [ "licensor" ] }, { "name": "Tasman District Council", "roles": [ "licensor" ] }, { "name": "Waka Kotahi", "roles": [ "licensor" ] }, ... ], ... } ], ... } ``` #### Attribution Endpoint `/v1/tiles/:tileSet/:tileMatrix/attribution.json` Excerpt from the JSON response showing the _compact attribution_ for the layer source: ```json { ... "sources": { "basemaps-top-of-the-south-flood-2022-0.15m": { ... "attribution": "© CC BY 4.0 Nelson City Council, Tasman District Council, Waka Kotahi", ... } }, ... } ``` --- .../attribution/src/__tests__/utils.test.ts | 65 +++++ packages/attribution/src/attribution.ts | 70 +++++- packages/attribution/src/utils.ts | 25 ++ .../config-loader/src/json/tiff.config.ts | 1 + packages/config/src/config/imagery.ts | 33 +++ packages/geo/src/stac/index.ts | 24 +- .../tile.style.json.attribution.test.ts | 224 ++++++++++++++++++ .../lambda-tiler/src/routes/attribution.ts | 55 ++++- .../src/routes/tile.style.json.ts | 19 +- packages/landing/src/attribution.ts | 12 +- 10 files changed, 497 insertions(+), 31 deletions(-) create mode 100644 packages/attribution/src/__tests__/utils.test.ts create mode 100644 packages/attribution/src/utils.ts create mode 100644 packages/lambda-tiler/src/routes/__tests__/tile.style.json.attribution.test.ts diff --git a/packages/attribution/src/__tests__/utils.test.ts b/packages/attribution/src/__tests__/utils.test.ts new file mode 100644 index 000000000..533a42ce6 --- /dev/null +++ b/packages/attribution/src/__tests__/utils.test.ts @@ -0,0 +1,65 @@ +import { strictEqual } from 'node:assert'; +import { describe, it } from 'node:test'; + +import { StacProvider } from '@basemaps/geo'; + +import { copyright, createLicensorAttribution } from '../utils.js'; + +const defaultAttribution = `${copyright} LINZ`; + +describe('utils', () => { + const FakeHost: StacProvider = { + name: 'FakeHost', + roles: ['host'], + }; + const FakeLicensor1: StacProvider = { + name: 'FakeLicensor1', + roles: ['licensor'], + }; + const FakeLicensor2: StacProvider = { + name: 'FakeLicensor2', + roles: ['licensor'], + }; + + it('default attribution: no providers', () => { + const providers = undefined; + const attribution = createLicensorAttribution(providers); + + strictEqual(attribution, defaultAttribution); + }); + + it('default attribution: empty providers', () => { + const providers: StacProvider[] = []; + const attribution = createLicensorAttribution(providers); + + strictEqual(attribution, defaultAttribution); + }); + + it('default attribution: one provider, no licensors', () => { + const providers = [FakeHost]; + + const attribution = createLicensorAttribution(providers); + strictEqual(attribution, defaultAttribution); + }); + + it('custom attribution: one provider, one licensor', () => { + const providers = [FakeLicensor1]; + + const attribution = createLicensorAttribution(providers); + strictEqual(attribution, `${copyright} ${FakeLicensor1.name}`); + }); + + it('custom attribution: two providers, one licensor', () => { + const providers = [FakeHost, FakeLicensor1]; + + const attribution = createLicensorAttribution(providers); + strictEqual(attribution, `${copyright} ${FakeLicensor1.name}`); + }); + + it('custom attribution: two providers, two licensors', () => { + const providers = [FakeLicensor1, FakeLicensor2]; + + const attribution = createLicensorAttribution(providers); + strictEqual(attribution, `${copyright} ${FakeLicensor1.name}, ${FakeLicensor2.name}`); + }); +}); diff --git a/packages/attribution/src/attribution.ts b/packages/attribution/src/attribution.ts index 2b51119d9..9d5a5b52c 100644 --- a/packages/attribution/src/attribution.ts +++ b/packages/attribution/src/attribution.ts @@ -1,6 +1,8 @@ import { AttributionCollection, AttributionStac } from '@basemaps/geo'; import { BBox, intersection, MultiPolygon, Ring, Wgs84 } from '@linzjs/geojson'; +import { createLicensorAttribution } from './utils.js'; + export interface AttributionFilter { extent: BBox; zoom: number; @@ -181,20 +183,66 @@ export class Attribution { isIgnored?: (attr: AttributionBounds) => boolean; /** - * Render the filtered attributions as a simple string suitable to display as attribution + * Parse the filtered list of attributions into a formatted string comprising license information. + * + * @param filtered The filtered list of attributions. + * + * @returns A formatted license string. + * + * @example + * if (filtered[0] contains no providers or licensors): + * return "CC BY 4.0 LINZ - Otago 0.3 Rural Aerial Photos (2017-2019)" + * + * @example + * if (filtered[0] contains licensors): + * return "CC BY 4.0 Otago Regional Council - Otago 0.3 Rural Aerial Photos (2017-2019)" + */ + renderLicense(filtered: AttributionBounds[]): string { + const providers = filtered[0]?.collection.providers; + const attribution = createLicensorAttribution(providers); + const list = this.renderList(filtered); + + if (list.length > 0) { + return `${attribution} - ${list}`; + } else { + return attribution; + } + } + + /** + * Render the filtered attributions as a simple string suitable to display as attribution. + * + * @param filtered The filtered list of attributions. + * + * @returns {string} An empty string, if the filtered list is empty. + * Otherwise, a formatted string comprising attribution details. + * + * @example + * if (filtered.length === 0): + * return "" + * + * @example + * if (filtered.length === 1): + * return "Ashburton 0.1m Urban Aerial Photos (2023)" + * + * @example + * if (filtered.length === 2): + * return "Wellington 0.3m Rural Aerial Photos (2021) & New Zealand 10m Satellite Imagery (2023-2024)" * - * @param list the filtered list of attributions + * @example + * if (filtered.length > 2): + * return "Canterbury 0.2 Rural Aerial Photos (2020-2021) & others 2012-2024" */ - renderList(list: AttributionBounds[]): string { - if (list.length === 0) return ''; - let result = escapeHtml(list[0].collection.title); - if (list.length > 1) { - if (list.length === 2) { - result += ` & ${escapeHtml(list[1].collection.title)}`; + renderList(filtered: AttributionBounds[]): string { + if (filtered.length === 0) return ''; + let result = escapeHtml(filtered[0].collection.title); + if (filtered.length > 1) { + if (filtered.length === 2) { + result += ` & ${escapeHtml(filtered[1].collection.title)}`; } else { - let [minYear, maxYear] = getYears(list[1].collection); - for (let i = 1; i < list.length; ++i) { - const [a, b] = getYears(list[i].collection); + let [minYear, maxYear] = getYears(filtered[1].collection); + for (let i = 1; i < filtered.length; ++i) { + const [a, b] = getYears(filtered[i].collection); if (a !== -1 && (minYear === -1 || a < minYear)) minYear = a; if (b !== -1 && (maxYear === -1 || b > maxYear)) maxYear = b; } diff --git a/packages/attribution/src/utils.ts b/packages/attribution/src/utils.ts new file mode 100644 index 000000000..b719e9964 --- /dev/null +++ b/packages/attribution/src/utils.ts @@ -0,0 +1,25 @@ +import { Stac, StacProvider } from '@basemaps/geo'; + +export const copyright = `© ${Stac.License}`; + +/** + * Create a licensor attribution string. + * + * @param providers The optional list of providers. + * + * @returns A copyright string comprising the names of licensor providers. + * + * @example + * "CC BY 4.0 LINZ" + * + * @example + * "CC BY 4.0 Nelson City Council, Tasman District Council, Waka Kotahi" + */ +export function createLicensorAttribution(providers?: StacProvider[]): string { + if (providers == null) return `${copyright} LINZ`; + + const licensors = providers.filter((p) => p.roles?.includes('licensor')); + if (licensors.length === 0) return `${copyright} LINZ`; + + return `${copyright} ${licensors.map((l) => l.name).join(', ')}`; +} diff --git a/packages/config-loader/src/json/tiff.config.ts b/packages/config-loader/src/json/tiff.config.ts index e92898642..9f3686375 100644 --- a/packages/config-loader/src/json/tiff.config.ts +++ b/packages/config-loader/src/json/tiff.config.ts @@ -384,6 +384,7 @@ export async function initImageryFromTiffUrl( noData: params.noData, files: params.files, collection: stac ?? undefined, + providers: stac?.providers, }; imagery.overviews = await ConfigJson.findImageryOverviews(imagery); log?.info({ title, imageryName, files: imagery.files.length }, 'Tiff:Loaded'); diff --git a/packages/config/src/config/imagery.ts b/packages/config/src/config/imagery.ts index d8d9458ae..93cbbc088 100644 --- a/packages/config/src/config/imagery.ts +++ b/packages/config/src/config/imagery.ts @@ -46,6 +46,34 @@ export const ConfigImageryOverviewParser = z }) .refine((obj) => obj.minZoom < obj.maxZoom); +/** + * Provides information about a provider. + * + * @link https://github.com/radiantearth/stac-spec/blob/master/commons/common-metadata.md#provider + */ +export const ProvidersParser = z.object({ + /** + * The name of the organization or the individual. + */ + name: z.string(), + + /** + * Multi-line description to add further provider information such as processing details + * for processors and producers, hosting details for hosts or basic contact information. + */ + description: z.string().optional(), + + /** + * Roles of the provider. Any of `licensor`, `producer`, `processor` or `host`. + */ + roles: z.array(z.string()).optional(), + + /** + * Homepage on which the provider describes the dataset and publishes contact information. + */ + url: z.string().optional(), +}); + export const BoundingBoxParser = z.object({ x: z.number(), y: z.number(), width: z.number(), height: z.number() }); export const NamedBoundsParser = z.object({ /** @@ -140,6 +168,11 @@ export const ConfigImageryParser = ConfigBase.extend({ * Separate overview cache */ overviews: ConfigImageryOverviewParser.optional(), + + /** + * list of providers and their metadata + */ + providers: z.array(ProvidersParser).optional(), }); export type ConfigImagery = z.infer; diff --git a/packages/geo/src/stac/index.ts b/packages/geo/src/stac/index.ts index 542128c55..3f73dac8a 100644 --- a/packages/geo/src/stac/index.ts +++ b/packages/geo/src/stac/index.ts @@ -21,9 +21,31 @@ export interface StacAsset { description?: string; } +/** + * Provides information about a provider. + * + * @link https://github.com/radiantearth/stac-spec/blob/master/commons/common-metadata.md#provider + */ export interface StacProvider { + /** + * The name of the organization or the individual. + */ name: string; - roles: string[]; + + /** + * Multi-line description to add further provider information such as processing details + * for processors and producers, hosting details for hosts or basic contact information. + */ + description?: string; + + /** + * Roles of the provider. Any of `licensor`, `producer`, `processor` or `host`. + */ + roles?: string[]; + + /** + * Homepage on which the provider describes the dataset and publishes contact information. + */ url?: string; } diff --git a/packages/lambda-tiler/src/routes/__tests__/tile.style.json.attribution.test.ts b/packages/lambda-tiler/src/routes/__tests__/tile.style.json.attribution.test.ts new file mode 100644 index 000000000..d67420fea --- /dev/null +++ b/packages/lambda-tiler/src/routes/__tests__/tile.style.json.attribution.test.ts @@ -0,0 +1,224 @@ +import assert, { strictEqual } from 'node:assert'; +import { afterEach, before, describe, it } from 'node:test'; + +import { copyright, createLicensorAttribution } from '@basemaps/attribution/build/utils.js'; +import { ConfigProviderMemory, StyleJson } from '@basemaps/config'; +import { StacProvider } from '@basemaps/geo'; +import { Env } from '@basemaps/shared'; + +import { FakeData, Imagery3857 } from '../../__tests__/config.data.js'; +import { Api, mockRequest } from '../../__tests__/xyz.util.js'; +import { handler } from '../../index.js'; +import { ConfigLoader } from '../../util/config.loader.js'; + +const defaultAttribution = `${copyright} LINZ`; + +describe('/v1/styles', () => { + const host = 'https://tiles.test'; + const config = new ConfigProviderMemory(); + + const FakeTileSetName = 'tileset'; + const FakeLicensor1: StacProvider = { + name: 'L1', + roles: ['licensor'], + }; + const FakeLicensor2: StacProvider = { + name: 'L2', + roles: ['licensor'], + }; + + before(() => { + process.env[Env.PublicUrlBase] = host; + }); + afterEach(() => { + config.objects.clear(); + }); + + // tileset exists, imagery not found + it('default: imagery not found', async (t) => { + t.mock.method(ConfigLoader, 'getDefaultConfig', () => Promise.resolve(config)); + + // insert + config.put(FakeData.tileSetRaster(FakeTileSetName)); + + // request + const req = mockRequest(`/v1/styles/${FakeTileSetName}.json`, 'get', Api.header); + const res = await handler.router.handle(req); + strictEqual(res.status, 200); + + // extract + const body = Buffer.from(res.body, 'base64').toString(); + const json = JSON.parse(body) as StyleJson; + + const source = Object.values(json.sources)[0]; + assert(source != null); + assert(source.attribution != null); + + // verify + strictEqual(source.attribution, defaultAttribution); + }); + + // tileset exists, imagery found, more than one layer + it('default: too many layers', async (t) => { + t.mock.method(ConfigLoader, 'getDefaultConfig', () => Promise.resolve(config)); + + // insert + const tileset = FakeData.tileSetRaster(FakeTileSetName); + assert(tileset.layers[0] != null); + + tileset.layers.push(tileset.layers[0]); + assert(tileset.layers.length > 1); + + config.put(tileset); + config.put(Imagery3857); + + // request + const req = mockRequest(`/v1/styles/${FakeTileSetName}.json`, 'get', Api.header); + const res = await handler.router.handle(req); + strictEqual(res.status, 200); + + // extract + const body = Buffer.from(res.body, 'base64').toString(); + const json = JSON.parse(body) as StyleJson; + + const source = Object.values(json.sources)[0]; + assert(source != null); + assert(source.attribution != null); + + // verify + strictEqual(source.attribution, defaultAttribution); + }); + + // tileset exists, imagery found, one layer, no providers + it('default: no providers', async (t) => { + t.mock.method(ConfigLoader, 'getDefaultConfig', () => Promise.resolve(config)); + + // insert + const tileset = FakeData.tileSetRaster(FakeTileSetName); + assert(tileset.layers[0] != null); + assert(tileset.layers.length === 1); + + const imagery = Imagery3857; + assert(imagery.providers == null); + + config.put(tileset); + config.put(imagery); + + // request + const req = mockRequest(`/v1/styles/${FakeTileSetName}.json`, 'get', Api.header); + const res = await handler.router.handle(req); + strictEqual(res.status, 200); + + // extract + const body = Buffer.from(res.body, 'base64').toString(); + const json = JSON.parse(body) as StyleJson; + + const source = Object.values(json.sources)[0]; + assert(source != null); + assert(source.attribution != null); + + // verify + strictEqual(source.attribution, defaultAttribution); + }); + + // tileset exists, imagery found, one layer, has providers, no licensors + it('default: no licensors', async (t) => { + t.mock.method(ConfigLoader, 'getDefaultConfig', () => Promise.resolve(config)); + + // insert + const tileset = FakeData.tileSetRaster(FakeTileSetName); + assert(tileset.layers[0] != null); + assert(tileset.layers.length === 1); + + const imagery = Imagery3857; + imagery.providers = []; + assert(imagery.providers != null); + + config.put(tileset); + config.put(imagery); + + // request + const req = mockRequest(`/v1/styles/${FakeTileSetName}.json`, 'get', Api.header); + const res = await handler.router.handle(req); + strictEqual(res.status, 200); + + // extract + const body = Buffer.from(res.body, 'base64').toString(); + const json = JSON.parse(body) as StyleJson; + + const source = Object.values(json.sources)[0]; + assert(source != null); + assert(source.attribution != null); + + // verify + strictEqual(source.attribution, defaultAttribution); + }); + + // tileset exists, imagery found, one layer, has providers, one licensor + it('custom: one licensor', async (t) => { + t.mock.method(ConfigLoader, 'getDefaultConfig', () => Promise.resolve(config)); + + // insert + const tileset = FakeData.tileSetRaster(FakeTileSetName); + assert(tileset.layers[0] != null); + assert(tileset.layers.length === 1); + + const imagery = Imagery3857; + imagery.providers = [FakeLicensor1]; + assert(imagery.providers != null); + + config.put(tileset); + config.put(imagery); + + // request + const req = mockRequest(`/v1/styles/${FakeTileSetName}.json`, 'get', Api.header); + const res = await handler.router.handle(req); + strictEqual(res.status, 200); + + // extract + const body = Buffer.from(res.body, 'base64').toString(); + const json = JSON.parse(body) as StyleJson; + + const source = Object.values(json.sources)[0]; + assert(source != null); + assert(source.attribution != null); + + // verify + strictEqual(source.attribution, `${copyright} ${FakeLicensor1.name}`); + strictEqual(source.attribution, createLicensorAttribution([FakeLicensor1])); + }); + + // tileset exists, imagery found, one layer, has providers, two licensors + it('custom: two licensors', async (t) => { + t.mock.method(ConfigLoader, 'getDefaultConfig', () => Promise.resolve(config)); + + // insert + const tileset = FakeData.tileSetRaster(FakeTileSetName); + assert(tileset.layers[0] != null); + assert(tileset.layers.length === 1); + + const imagery = Imagery3857; + imagery.providers = [FakeLicensor1, FakeLicensor2]; + assert(imagery.providers != null); + + config.put(tileset); + config.put(imagery); + + // request + const req = mockRequest(`/v1/styles/${FakeTileSetName}.json`, 'get', Api.header); + const res = await handler.router.handle(req); + strictEqual(res.status, 200); + + // extract + const body = Buffer.from(res.body, 'base64').toString(); + const json = JSON.parse(body) as StyleJson; + + const source = Object.values(json.sources)[0]; + assert(source != null); + assert(source.attribution != null); + + // verify + strictEqual(source.attribution, `${copyright} ${FakeLicensor1.name}, ${FakeLicensor2.name}`); + strictEqual(source.attribution, createLicensorAttribution([FakeLicensor1, FakeLicensor2])); + }); +}); diff --git a/packages/lambda-tiler/src/routes/attribution.ts b/packages/lambda-tiler/src/routes/attribution.ts index cd866bcd9..83c565eb0 100644 --- a/packages/lambda-tiler/src/routes/attribution.ts +++ b/packages/lambda-tiler/src/routes/attribution.ts @@ -1,9 +1,11 @@ -import { ConfigProvider, ConfigTileSet, getAllImagery, TileSetType } from '@basemaps/config'; +import { createLicensorAttribution } from '@basemaps/attribution/build/utils.js'; +import { BasemapsConfigProvider, ConfigProvider, ConfigTileSet, getAllImagery, TileSetType } from '@basemaps/config'; import { AttributionCollection, AttributionItem, AttributionStac, Bounds, + Epsg, GoogleTms, NamedBounds, Projection, @@ -93,10 +95,11 @@ async function tileSetAttribution( const config = await ConfigLoader.load(req); const imagery = await getAllImagery(config, tileSet.layers, [tileMatrix.projection]); - const host = await config.Provider.get(config.Provider.id('linz')); - for (const layer of tileSet.layers) { + for (let i = 0; i < tileSet.layers.length; i++) { + const layer = tileSet.layers[i]; + const imgId = layer[proj.epsg.code]; if (imgId == null) continue; @@ -138,11 +141,12 @@ async function tileSetAttribution( const zoomMin = TileMatrixSet.convertZoomLevel(layer.minZoom ? layer.minZoom : 0, GoogleTms, tileMatrix, true); const zoomMax = TileMatrixSet.convertZoomLevel(layer.maxZoom ? layer.maxZoom : 32, GoogleTms, tileMatrix, true); + cols.push({ stac_version: Stac.Version, license: Stac.License, id: im.id, - providers: getHost(host), + providers: im.providers ?? getHost(host), title, description: 'No description', extent, @@ -150,10 +154,11 @@ async function tileSetAttribution( summaries: { 'linz:category': im.category, 'linz:zoom': { min: zoomMin, max: zoomMax }, - 'linz:priority': [1000 + tileSet.layers.indexOf(layer)], + 'linz:priority': [1000 + i], }, }); } + return { id: tileSet.id, type: 'FeatureCollection', @@ -205,3 +210,43 @@ export async function tileAttributionGet(req: LambdaHttpRequest { + // ensure the tileset has exactly one layer + if (tileSet.layers.length > 1 || tileSet.layers[0] == null) { + return createLicensorAttribution(); + } + + // ensure imagery exist for the given projection + const imgId = tileSet.layers[0][projection.code]; + if (imgId == null) return ''; + + // attempt to load the imagery + const imagery = await provider.Imagery.get(imgId); + if (imagery?.providers == null) { + return createLicensorAttribution(); + } + + // return a licensor attribution string + return createLicensorAttribution(imagery.providers); +} diff --git a/packages/lambda-tiler/src/routes/tile.style.json.ts b/packages/lambda-tiler/src/routes/tile.style.json.ts index f7b302eef..efa7c7044 100644 --- a/packages/lambda-tiler/src/routes/tile.style.json.ts +++ b/packages/lambda-tiler/src/routes/tile.style.json.ts @@ -19,6 +19,7 @@ import { Etag } from '../util/etag.js'; import { convertStyleToNztmStyle } from '../util/nztm.style.js'; import { NotFound, NotModified } from '../util/response.js'; import { Validate } from '../util/validate.js'; +import { createTileSetAttribution } from './attribution.js'; /** * Convert relative URL into a full hostname URL, converting {tileMatrix} into the provided tileMatrix @@ -153,12 +154,13 @@ async function ensureTerrain( * Generate a StyleJSON from a tileset * @returns */ -export function tileSetToStyle( +export async function tileSetToStyle( req: LambdaHttpRequest, + config: BasemapsConfigProvider, tileSet: ConfigTileSetRaster, tileMatrix: TileMatrixSet, apiKey: string, -): StyleJson { +): Promise { // If the style has outputs defined it has a different process for generating the stylejson if (tileSet.outputs) return tileSetOutputToStyle(req, tileSet, tileMatrix, apiKey); @@ -175,12 +177,21 @@ export function tileSetToStyle( (Env.get(Env.PublicUrlBase) ?? '') + `/v1/tiles/${tileSet.name}/${tileMatrix.identifier}/{z}/{x}/{y}.${tileFormat}${query}`; + const attribution = await createTileSetAttribution(config, tileSet, tileMatrix.projection); + const styleId = `basemaps-${tileSet.name}`; return { id: ConfigId.prefix(ConfigPrefix.Style, tileSet.name), name: tileSet.name, version: 8, - sources: { [styleId]: { type: 'raster', tiles: [tileUrl], tileSize: 256 } }, + sources: { + [styleId]: { + type: 'raster', + tiles: [tileUrl], + tileSize: 256, + attribution, + }, + }, layers: [{ id: styleId, type: 'raster', source: styleId }], }; } @@ -248,7 +259,7 @@ async function generateStyleFromTileSet( throw new LambdaHttpResponse(400, 'Only raster tile sets can generate style JSON'); } if (tileSet.outputs) return tileSetOutputToStyle(req, tileSet, tileMatrix, apiKey); - else return tileSetToStyle(req, tileSet, tileMatrix, apiKey); + return tileSetToStyle(req, config, tileSet, tileMatrix, apiKey); } export interface StyleGet { diff --git a/packages/landing/src/attribution.ts b/packages/landing/src/attribution.ts index 2f56eb5e2..2c132f4df 100644 --- a/packages/landing/src/attribution.ts +++ b/packages/landing/src/attribution.ts @@ -1,6 +1,6 @@ import { Attribution } from '@basemaps/attribution'; import { AttributionBounds } from '@basemaps/attribution/build/attribution.js'; -import { GoogleTms, Stac } from '@basemaps/geo'; +import { GoogleTms } from '@basemaps/geo'; import * as maplibre from 'maplibre-gl'; import { onMapLoaded } from './components/map.js'; @@ -8,8 +8,6 @@ import { Config } from './config.js'; import { mapToBoundingBox } from './tile.matrix.js'; import { MapOptionType } from './url.js'; -const Copyright = `© ${Stac.License} LINZ`; - export class MapAttributionState { /** Cache the loading of attribution */ attrs: Map> = new Map(); @@ -168,13 +166,7 @@ export class MapAttribution implements maplibre.IControl { const filteredLayerIds = filtered.map((x) => x.collection.id).join('_'); Config.map.emit('visibleLayers', filteredLayerIds); - let attributionHTML = attr.renderList(filtered); - if (attributionHTML === '') { - attributionHTML = Copyright; - } else { - attributionHTML = Copyright + ' - ' + attributionHTML; - } - + const attributionHTML = attr.renderLicense(filtered); this.setAttribution(attributionHTML); }; From dcc8a9b8af50e7ab3e5fc53e081ed7954b3b26ea Mon Sep 17 00:00:00 2001 From: Wentao Kuang Date: Thu, 31 Oct 2024 11:41:54 +1300 Subject: [PATCH 05/12] feat(landing): Update new feature pop ups to include google analytics. BM-1113 (#3363) ### Motivation We want to capture the event of pop screenshot in google analyst, also try to enable the 3d map pop up for 3 months and see how it goes. ### Modifications - Add gEvent for both open and close of 3d map pop up - Set the end date to 31th Jan 2025 ### Verification --- packages/landing/src/components/feature.updates.tsx | 4 +++- packages/landing/src/components/new-features/3d.map.tsx | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/landing/src/components/feature.updates.tsx b/packages/landing/src/components/feature.updates.tsx index a6c61e807..0db121756 100644 --- a/packages/landing/src/components/feature.updates.tsx +++ b/packages/landing/src/components/feature.updates.tsx @@ -2,7 +2,7 @@ import { clsx } from 'clsx'; import { Component, ReactNode } from 'react'; import ReactModal from 'react-modal'; -import { Config } from '../config.js'; +import { Config, GaEvent, gaEvent } from '../config.js'; type FeatureUpdatesProps = { header: string; @@ -37,6 +37,7 @@ export class FeatureUpdates extends Component { this.setState({ showModal: false }); window.localStorage.setItem(this.props.id, this.props.dismissedKey); + gaEvent(GaEvent.Ui, `news:${this.props.id.toLowerCase()}:close`); }; override render(): ReactNode { @@ -46,6 +47,7 @@ export class FeatureUpdates extends Component Date: Mon, 4 Nov 2024 09:43:27 +1300 Subject: [PATCH 06/12] feat(landing): enable labels upon first visit BM-1101 (#3364) ### Motivation As a Basemaps user, I would like to see labels when I arrive at the site so I can see the context of the imagery displayed to me. ### Modifications - Updated the **landing** package so that labels are enabled upon first visit to the site via the default Basemaps URL (https://basemaps.linz.govt.nz). Situations where labels are **not enabled** upon first visit: - The `labels` URL query string is `false`, e.g. https://basemaps.linz.govt.nz/?labels=false - The `debug` URL query string is present, e.g. https://basemaps.linz.govt.nz/?debug ### Verification - Added additional tests to the **landing** package's `map.config.test` test suite. #### Labels should be enabled | https://basemaps.linz.govt.nz | | - | | ![][default] | | Viewing the **aerial** layer and not in debug mode. Enable labels upon first visit. | #### Labels should be disabled | https://basemaps.linz.govt.nz/?labels=false | | - | | ![][labels=false] | | The `labels` query string is present and equals `false`. Don't enable labels upon first visit. | | https://basemaps.linz.govt.nz/?debug | | - | | ![][debug] | | In debug mode. Don't enable labels upon first visit. | | https://basemaps.linz.govt.nz/?i=ashburton-2023-0.1m | | - | | ![][individual_layer] | | _Adjusted viewport to show imagery_ | | Not viewing the `aerial` layer. Don't enable labels upon first visit. | --- Resolves bug: [BM-1114](https://toitutewhenua.atlassian.net/browse/BM-1114) [default]: https://github.com/user-attachments/assets/1b450c01-3409-400e-b794-6eccc6582021 [labels=false]: https://github.com/user-attachments/assets/2ca74653-d868-4420-8fd4-4e22273efa7d [debug]: https://github.com/user-attachments/assets/462ac80d-a603-47a7-9b9b-683b59988521 [individual_layer]: https://github.com/user-attachments/assets/bac0f8a7-9a67-4683-880b-5a5fe484ae8b [BM-1114]: https://toitutewhenua.atlassian.net/browse/BM-1114?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --- .../landing/src/__tests__/map.config.test.ts | 46 +++++++++++++++++++ packages/landing/src/config.map.ts | 10 ++-- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/packages/landing/src/__tests__/map.config.test.ts b/packages/landing/src/__tests__/map.config.test.ts index a4de5f406..cf91ec0d7 100644 --- a/packages/landing/src/__tests__/map.config.test.ts +++ b/packages/landing/src/__tests__/map.config.test.ts @@ -174,4 +174,50 @@ describe('WindowUrl', () => { mc.updateFromUrl('i=01EDA2YFXH2JN264VG1HKBT625'); assert.equal(mc.layerId, '01EDA2YFXH2JN264VG1HKBT625'); }); + + it('should enable labels by default', () => { + // aerial layer & debug disabled + mc.updateFromUrl(''); + assert.equal(mc.layerId, 'aerial'); + assert.equal(mc.isDebug, false); + assert.equal(mc.labels, true); + + // aerial layer, labels enabled & debug disabled + mc.updateFromUrl('?labels=true'); + assert.equal(mc.layerId, 'aerial'); + assert.equal(mc.isDebug, false); + assert.equal(mc.labels, true); + }); + + it('should not enable labels by default', () => { + // aerial layer, but labels disabled + mc.updateFromUrl('?labels=false'); + assert.equal(mc.layerId, 'aerial'); + assert.equal(mc.isDebug, false); + assert.equal(mc.labels, false); + + // aerial layer, but debug enabled + mc.updateFromUrl('?debug'); + assert.equal(mc.layerId, 'aerial'); + assert.equal(mc.isDebug, true); + assert.equal(mc.labels, false); + + // aerial layer, labels disabled & debug enabled + mc.updateFromUrl('?labels=false&debug'); + assert.equal(mc.layerId, 'aerial'); + assert.equal(mc.isDebug, true); + assert.equal(mc.labels, false); + + // debug disabled, but individual layer + mc.updateFromUrl('i=abc123'); + assert.equal(mc.layerId, 'abc123'); + assert.equal(mc.isDebug, false); + assert.equal(mc.labels, false); + + // individual layer & debug enabled + mc.updateFromUrl('i=abc123&debug'); + assert.equal(mc.layerId, 'abc123'); + assert.equal(mc.isDebug, true); + assert.equal(mc.labels, false); + }); }); diff --git a/packages/landing/src/config.map.ts b/packages/landing/src/config.map.ts index 09c528a85..2d0a899fe 100644 --- a/packages/landing/src/config.map.ts +++ b/packages/landing/src/config.map.ts @@ -69,7 +69,7 @@ export class MapConfig extends Emitter { } get isDebug(): boolean { - return this.debug.debug; + return this.debug.debug === true; } /** Map location in WGS84 */ @@ -128,7 +128,7 @@ export class MapConfig extends Emitter { const config = urlParams.get('c') ?? urlParams.get('config'); const layerId = urlParams.get('i') ?? style ?? 'aerial'; const terrain = urlParams.get('t') ?? urlParams.get('terrain'); - const labels = Boolean(urlParams.get('labels')); + const labels = urlParams.get('labels'); const projectionParam = (urlParams.get('p') ?? urlParams.get('tileMatrix') ?? GoogleTms.identifier).toLowerCase(); let tileMatrix = TileMatrixSets.All.find((f) => f.identifier.toLowerCase() === projectionParam); @@ -145,7 +145,11 @@ export class MapConfig extends Emitter { this.style = style ?? null; this.layerId = layerId.startsWith('im_') ? layerId.slice(3) : layerId; this.tileMatrix = tileMatrix; - this.labels = labels; + if (labels == null) { + this.labels = layerId === 'aerial' && this.isDebug === false; + } else { + this.labels = labels !== 'false'; + } if (this.layerId === 'topographic' && this.style == null) this.style = 'topographic'; this.emit('tileMatrix', this.tileMatrix); From 385971dc23c0b1cd9c354c5028d47d01ab5ae584 Mon Sep 17 00:00:00 2001 From: Blayne Chard Date: Mon, 4 Nov 2024 15:05:19 +1300 Subject: [PATCH 07/12] fix: register file systems correctly when using duplicate roleArns BM-1055 (#3367) ### Motivation We have been seeing some tiff files intermitently fail to load when loading across AWS accounts, this was tracked down a failure to register a AWS roleArn against the target bucket when the roleArn was used in multiple different buckets ### Modifications Use the more general "onFileSystemFound" as "onFileSystemCreated" only happens once per roleArn. ### Verification Tested locally --- package-lock.json | 16 ++++++++-------- packages/shared/package.json | 2 +- packages/shared/src/file.system.ts | 14 +++++++++----- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a87b76f5..71892f5ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1482,15 +1482,15 @@ } }, "node_modules/@chunkd/fs-aws": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/@chunkd/fs-aws/-/fs-aws-11.2.2.tgz", - "integrity": "sha512-zTF0sVXHkzHIOZWwav4Qe1AcdTCCHgY5fyd9IWd7XjZtOjgYwlakwKV6GnkRkhD5QqAjTW/SVJRLca8Z7T1snw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@chunkd/fs-aws/-/fs-aws-11.3.0.tgz", + "integrity": "sha512-Oq3knOYibBvBTGpjNrfol0x9w/H0Gyf0WbasX5NL6q8fJBrynR1vbBUnlT7s/DfSgu9AZLuMcD1dQa7t2ouNlA==", "dependencies": { "@aws-sdk/client-s3": "*", "@aws-sdk/credential-providers": "*", "@aws-sdk/lib-storage": "*", "@chunkd/fs": "11.2.0", - "@chunkd/source-aws": "11.0.3" + "@chunkd/source-aws": "11.0.4" }, "engines": { "node": ">=16.0.0" @@ -1516,9 +1516,9 @@ } }, "node_modules/@chunkd/source-aws": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chunkd/source-aws/-/source-aws-11.0.3.tgz", - "integrity": "sha512-zWWV39cOKdTmgiSW1PiNJLRM9PoxpaBkMD/z2Wn+8c8JnLt4NNILsdne0qrl722xc4vcFar0xXFdAxy9Stlolg==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@chunkd/source-aws/-/source-aws-11.0.4.tgz", + "integrity": "sha512-HvQ44z6Zz0f/tRFMyvfF4sQDCNXlorp5d6skei1mC0vZyMTn8BJfMkZKgvpDDUpyt5lGCxFREd3/LI140E0rZg==", "dependencies": { "@aws-sdk/client-s3": "*", "@chunkd/source": "^11.1.0" @@ -19726,7 +19726,7 @@ "@basemaps/config": "^7.11.0", "@basemaps/geo": "^7.11.0", "@chunkd/fs": "^11.2.0", - "@chunkd/fs-aws": "^11.2.2", + "@chunkd/fs-aws": "^11.3.0", "@chunkd/middleware": "^11.1.0", "@cogeotiff/core": "^9.0.3", "@cotar/core": "^6.0.1", diff --git a/packages/shared/package.json b/packages/shared/package.json index 9de1322e3..67a34e764 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -29,7 +29,7 @@ "@basemaps/config": "^7.11.0", "@basemaps/geo": "^7.11.0", "@chunkd/fs": "^11.2.0", - "@chunkd/fs-aws": "^11.2.2", + "@chunkd/fs-aws": "^11.3.0", "@chunkd/middleware": "^11.1.0", "@cogeotiff/core": "^9.0.3", "@cotar/core": "^6.0.1", diff --git a/packages/shared/src/file.system.ts b/packages/shared/src/file.system.ts index c48b9a38c..9ce91628c 100644 --- a/packages/shared/src/file.system.ts +++ b/packages/shared/src/file.system.ts @@ -2,7 +2,7 @@ import { fileURLToPath } from 'node:url'; import { S3Client } from '@aws-sdk/client-s3'; import { sha256base58 } from '@basemaps/config'; -import { FileSystem, fsa, FsHttp } from '@chunkd/fs'; +import { fsa, FsHttp } from '@chunkd/fs'; import { AwsCredentialConfig, AwsS3CredentialProvider, FsAwsS3 } from '@chunkd/fs-aws'; import { SourceCache, SourceChunk } from '@chunkd/middleware'; import type { SourceCallback, SourceRequest } from '@chunkd/source'; @@ -36,7 +36,10 @@ export const s3FsPublic = new FsAwsS3( /** Ensure middleware are added to all s3 clients that are created */ function applyS3MiddleWare(fs: FsAwsS3): void { if (fs.s3 == null) return; - fs.s3.middlewareStack.add(Fqdn.middleware, { name: 'FQDN', step: 'finalizeRequest' }); + const stacks = fs.s3.middlewareStack.identify(); + if (stacks.find((f) => f.startsWith('FQDN - ')) == null) { + fs.s3.middlewareStack.add(Fqdn.middleware, { name: 'FQDN', step: 'finalizeRequest' }); + } } applyS3MiddleWare(s3FsPublic); @@ -44,9 +47,10 @@ applyS3MiddleWare(s3Fs); const credentials = new AwsS3CredentialProvider(); -credentials.onFileSystemCreated = (acc: AwsCredentialConfig, fs: FileSystem): void => { - LogConfig.get().info({ prefix: acc.prefix, roleArn: acc.roleArn }, 'FileSystem:Register'); - applyS3MiddleWare(fs as FsAwsS3); +credentials.onFileSystemFound = (acc: AwsCredentialConfig, fs?: FsAwsS3, path?: URL): void => { + if (fs == null) return; + LogConfig.get().info({ prefix: acc.prefix, roleArn: acc.roleArn, path: path?.href }, 'FileSystem:Register'); + applyS3MiddleWare(fs); fsa.register(acc.prefix, fs); }; From ae07a9588aa620801b6d1578c4e32f884882b53a Mon Sep 17 00:00:00 2001 From: Wentao Kuang Date: Thu, 14 Nov 2024 14:37:10 +1300 Subject: [PATCH 08/12] release: v7.12.0 (#3372) ### Motivation ### Modifications ### Verification --- CHANGELOG.md | 22 +++++ lerna.json | 2 +- package-lock.json | 126 ++++++++++++------------- packages/_infra/CHANGELOG.md | 8 ++ packages/_infra/package.json | 6 +- packages/attribution/CHANGELOG.md | 11 +++ packages/attribution/package.json | 4 +- packages/bathymetry/CHANGELOG.md | 8 ++ packages/bathymetry/package.json | 8 +- packages/cli/CHANGELOG.md | 8 ++ packages/cli/package.json | 16 ++-- packages/cogify/CHANGELOG.md | 8 ++ packages/cogify/package.json | 12 +-- packages/config-loader/CHANGELOG.md | 11 +++ packages/config-loader/package.json | 8 +- packages/config/CHANGELOG.md | 11 +++ packages/config/package.json | 4 +- packages/geo/CHANGELOG.md | 11 +++ packages/geo/package.json | 2 +- packages/lambda-analytics/CHANGELOG.md | 8 ++ packages/lambda-analytics/package.json | 8 +- packages/lambda-tiler/CHANGELOG.md | 17 ++++ packages/lambda-tiler/package.json | 16 ++-- packages/landing/CHANGELOG.md | 19 ++++ packages/landing/package.json | 12 +-- packages/server/CHANGELOG.md | 8 ++ packages/server/package.json | 12 +-- packages/shared/CHANGELOG.md | 12 +++ packages/shared/package.json | 6 +- packages/tiler-sharp/CHANGELOG.md | 8 ++ packages/tiler-sharp/package.json | 8 +- packages/tiler/CHANGELOG.md | 8 ++ packages/tiler/package.json | 4 +- 33 files changed, 305 insertions(+), 127 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5415bddaa..d2a9c4179 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,28 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + + +### Bug Fixes + +* **lambda-tiler:** correctly log fetch requests ([#3359](https://github.com/linz/basemaps/issues/3359)) ([9fa3681](https://github.com/linz/basemaps/commit/9fa3681acc2ce25037c5d6e0326255aad9815b7d)) +* **landing:** Fix debug hillshade infinite loading. BM-1110 ([#3360](https://github.com/linz/basemaps/issues/3360)) ([6655441](https://github.com/linz/basemaps/commit/6655441e48fd226f81daeb98987a95dd649128a7)) +* register file systems correctly when using duplicate roleArns BM-1055 ([#3367](https://github.com/linz/basemaps/issues/3367)) ([385971d](https://github.com/linz/basemaps/commit/385971dc23c0b1cd9c354c5028d47d01ab5ae584)) + + +### Features + +* **lambda-tiler:** update imagery layer attributions to show licensor details BM-897 ([#3357](https://github.com/linz/basemaps/issues/3357)) ([e702c7e](https://github.com/linz/basemaps/commit/e702c7e53d28aaa8db9d624acab048f8ec3a2309)) +* **landing:** Add new features pop up to alert users for recent releases. BM-1064 ([#3356](https://github.com/linz/basemaps/issues/3356)) ([a61b652](https://github.com/linz/basemaps/commit/a61b652d80efd29acc198cc52456b5a28a65d09c)) +* **landing:** enable labels upon first visit BM-1101 ([#3364](https://github.com/linz/basemaps/issues/3364)) ([af656bf](https://github.com/linz/basemaps/commit/af656bfe72e8afb3b072cf18d2dbbb538709127c)) +* **landing:** Update new feature pop ups to include google analytics. BM-1113 ([#3363](https://github.com/linz/basemaps/issues/3363)) ([dcc8a9b](https://github.com/linz/basemaps/commit/dcc8a9b8af50e7ab3e5fc53e081ed7954b3b26ea)) +* **server:** add redirect route to pre-zoomed tileset BM-1076 ([#3354](https://github.com/linz/basemaps/issues/3354)) ([5b207de](https://github.com/linz/basemaps/commit/5b207de92b76e0d445a41ef8e1e9b9b91e5363c6)) + + + + + ## [7.11.1](https://github.com/linz/basemaps/compare/v7.11.0...v7.11.1) (2024-10-01) diff --git a/lerna.json b/lerna.json index d190accd5..6e1c795c5 100644 --- a/lerna.json +++ b/lerna.json @@ -7,5 +7,5 @@ "conventionalCommits": true } }, - "version": "7.11.1" + "version": "7.12.0" } diff --git a/package-lock.json b/package-lock.json index 71892f5ae..22393446c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19330,13 +19330,13 @@ }, "packages/_infra": { "name": "@basemaps/infra", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "devDependencies": { "@aws-sdk/client-acm": "^3.470.0", "@aws-sdk/client-cloudformation": "^3.470.0", - "@basemaps/lambda-tiler": "^7.11.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/lambda-tiler": "^7.12.0", + "@basemaps/shared": "^7.12.0", "@linzjs/cdk-tags": "^1.7.0", "aws-cdk": "2.162.x", "aws-cdk-lib": "2.162.x", @@ -19348,10 +19348,10 @@ }, "packages/attribution": { "name": "@basemaps/attribution", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "dependencies": { - "@basemaps/geo": "^7.11.0", + "@basemaps/geo": "^7.12.0", "@linzjs/geojson": "^7.10.0" }, "engines": { @@ -19360,12 +19360,12 @@ }, "packages/bathymetry": { "name": "@basemaps/bathymetry", - "version": "7.11.1", + "version": "7.12.0", "license": "MIT", "dependencies": { - "@basemaps/cli": "^7.11.1", - "@basemaps/geo": "^7.11.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/cli": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/shared": "^7.12.0", "@rushstack/ts-command-line": "^4.3.13", "ulid": "^2.3.0" }, @@ -19388,16 +19388,16 @@ }, "packages/cli": { "name": "@basemaps/cli", - "version": "7.11.1", + "version": "7.12.0", "license": "MIT", "dependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/config-loader": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/server": "^7.11.0", - "@basemaps/shared": "^7.11.0", - "@basemaps/tiler": "^7.11.0", - "@basemaps/tiler-sharp": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/config-loader": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/server": "^7.12.0", + "@basemaps/shared": "^7.12.0", + "@basemaps/tiler": "^7.12.0", + "@basemaps/tiler-sharp": "^7.12.0", "@chunkd/source-memory": "^11.0.2", "@cotar/builder": "^6.0.1", "@cotar/tar": "^6.0.1", @@ -19451,17 +19451,17 @@ }, "packages/cogify": { "name": "@basemaps/cogify", - "version": "7.11.1", + "version": "7.12.0", "license": "MIT", "bin": { "cogify": "build/bin.js" }, "devDependencies": { - "@basemaps/cli": "^7.11.1", - "@basemaps/config": "^7.11.0", - "@basemaps/config-loader": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/cli": "^7.12.0", + "@basemaps/config": "^7.12.0", + "@basemaps/config-loader": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/shared": "^7.12.0", "cmd-ts": "^0.12.1", "p-limit": "^4.0.0", "stac-ts": "^1.0.0" @@ -19472,10 +19472,10 @@ }, "packages/config": { "name": "@basemaps/config", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "dependencies": { - "@basemaps/geo": "^7.11.0", + "@basemaps/geo": "^7.12.0", "base-x": "^4.0.0", "zod": "^3.17.3" }, @@ -19485,12 +19485,12 @@ }, "packages/config-loader": { "name": "@basemaps/config-loader", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "dependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/shared": "^7.11.0" + "@basemaps/config": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/shared": "^7.12.0" }, "engines": { "node": ">=16.0.0" @@ -19498,7 +19498,7 @@ }, "packages/geo": { "name": "@basemaps/geo", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "dependencies": { "@linzjs/tile-matrix-set": "^0.0.1", @@ -19521,12 +19521,12 @@ }, "packages/lambda-analytics": { "name": "@basemaps/lambda-analytics", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "dependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/shared": "^7.12.0", "ua-parser-js": "^1.0.2" }, "devDependencies": { @@ -19538,15 +19538,15 @@ }, "packages/lambda-tiler": { "name": "@basemaps/lambda-tiler", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "dependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/config-loader": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/shared": "^7.11.0", - "@basemaps/tiler": "^7.11.0", - "@basemaps/tiler-sharp": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/config-loader": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/shared": "^7.12.0", + "@basemaps/tiler": "^7.12.0", + "@basemaps/tiler-sharp": "^7.12.0", "@linzjs/geojson": "^7.10.0", "@linzjs/lambda": "^4.0.0", "@mapbox/vector-tile": "^2.0.3", @@ -19556,7 +19556,7 @@ "sharp": "^0.33.0" }, "devDependencies": { - "@basemaps/attribution": "^7.11.0", + "@basemaps/attribution": "^7.12.0", "@chunkd/fs": "^11.2.0", "@types/aws-lambda": "^8.10.75", "@types/pixelmatch": "^5.0.0", @@ -19604,14 +19604,14 @@ }, "packages/landing": { "name": "@basemaps/landing", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "devDependencies": { - "@basemaps/attribution": "^7.11.0", - "@basemaps/config": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/infra": "^7.11.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/attribution": "^7.12.0", + "@basemaps/config": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/infra": "^7.12.0", + "@basemaps/shared": "^7.12.0", "@linzjs/lui": "^21.46.0", "@servie/events": "^3.0.0", "@types/proj4": "^2.5.2", @@ -19677,7 +19677,7 @@ }, "packages/server": { "name": "@basemaps/server", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "dependencies": { "lerc": "^4.0.4", @@ -19687,12 +19687,12 @@ "basemaps-server": "bin/basemaps-server.cjs" }, "devDependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/config-loader": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/lambda-tiler": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/config-loader": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/lambda-tiler": "^7.12.0", "@basemaps/landing": "^6.39.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/shared": "^7.12.0", "@fastify/formbody": "^7.0.1", "@fastify/static": "^6.5.0", "cmd-ts": "^0.12.1", @@ -19717,14 +19717,14 @@ }, "packages/shared": { "name": "@basemaps/shared", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "dependencies": { "@aws-sdk/client-dynamodb": "^3.470.0", "@aws-sdk/client-s3": "^3.472.0", "@aws-sdk/util-dynamodb": "^3.470.0", - "@basemaps/config": "^7.11.0", - "@basemaps/geo": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/geo": "^7.12.0", "@chunkd/fs": "^11.2.0", "@chunkd/fs-aws": "^11.3.0", "@chunkd/middleware": "^11.1.0", @@ -19782,10 +19782,10 @@ }, "packages/tiler": { "name": "@basemaps/tiler", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "dependencies": { - "@basemaps/geo": "^7.11.0", + "@basemaps/geo": "^7.12.0", "@cogeotiff/core": "^9.0.3", "@linzjs/metrics": "^7.5.0" }, @@ -19801,12 +19801,12 @@ }, "packages/tiler-sharp": { "name": "@basemaps/tiler-sharp", - "version": "7.11.0", + "version": "7.12.0", "license": "MIT", "dependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/tiler": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/tiler": "^7.12.0", "@linzjs/metrics": "^7.5.0", "lerc": "^4.0.4" }, diff --git a/packages/_infra/CHANGELOG.md b/packages/_infra/CHANGELOG.md index a90b5ccc2..c6ba21967 100644 --- a/packages/_infra/CHANGELOG.md +++ b/packages/_infra/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + +**Note:** Version bump only for package @basemaps/infra + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) **Note:** Version bump only for package @basemaps/infra diff --git a/packages/_infra/package.json b/packages/_infra/package.json index 66829642e..d6bdb32ef 100644 --- a/packages/_infra/package.json +++ b/packages/_infra/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/infra", - "version": "7.11.0", + "version": "7.12.0", "private": true, "repository": { "type": "git", @@ -26,8 +26,8 @@ "devDependencies": { "@aws-sdk/client-acm": "^3.470.0", "@aws-sdk/client-cloudformation": "^3.470.0", - "@basemaps/lambda-tiler": "^7.11.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/lambda-tiler": "^7.12.0", + "@basemaps/shared": "^7.12.0", "@linzjs/cdk-tags": "^1.7.0", "aws-cdk": "2.162.x", "aws-cdk-lib": "2.162.x", diff --git a/packages/attribution/CHANGELOG.md b/packages/attribution/CHANGELOG.md index 1b5ed23fd..2b09bb316 100644 --- a/packages/attribution/CHANGELOG.md +++ b/packages/attribution/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + + +### Features + +* **lambda-tiler:** update imagery layer attributions to show licensor details BM-897 ([#3357](https://github.com/linz/basemaps/issues/3357)) ([e702c7e](https://github.com/linz/basemaps/commit/e702c7e53d28aaa8db9d624acab048f8ec3a2309)) + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) **Note:** Version bump only for package @basemaps/attribution diff --git a/packages/attribution/package.json b/packages/attribution/package.json index eb65536e9..f28bd3296 100644 --- a/packages/attribution/package.json +++ b/packages/attribution/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/attribution", - "version": "7.11.0", + "version": "7.12.0", "repository": { "type": "git", "url": "https://github.com/linz/basemaps.git", @@ -30,7 +30,7 @@ "build/" ], "dependencies": { - "@basemaps/geo": "^7.11.0", + "@basemaps/geo": "^7.12.0", "@linzjs/geojson": "^7.10.0" }, "bundle": { diff --git a/packages/bathymetry/CHANGELOG.md b/packages/bathymetry/CHANGELOG.md index 6fc9894ea..7ea33d77a 100644 --- a/packages/bathymetry/CHANGELOG.md +++ b/packages/bathymetry/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + +**Note:** Version bump only for package @basemaps/bathymetry + + + + + ## [7.11.1](https://github.com/linz/basemaps/compare/v7.11.0...v7.11.1) (2024-10-01) **Note:** Version bump only for package @basemaps/bathymetry diff --git a/packages/bathymetry/package.json b/packages/bathymetry/package.json index 2bbb3a39e..7ba67f22d 100644 --- a/packages/bathymetry/package.json +++ b/packages/bathymetry/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/bathymetry", - "version": "7.11.1", + "version": "7.12.0", "repository": { "type": "git", "url": "https://github.com/linz/basemaps.git", @@ -28,9 +28,9 @@ "build/" ], "dependencies": { - "@basemaps/cli": "^7.11.1", - "@basemaps/geo": "^7.11.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/cli": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/shared": "^7.12.0", "@rushstack/ts-command-line": "^4.3.13", "ulid": "^2.3.0" }, diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 83fe1f92a..e886fcf12 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + +**Note:** Version bump only for package @basemaps/cli + + + + + ## [7.11.1](https://github.com/linz/basemaps/compare/v7.11.0...v7.11.1) (2024-10-01) diff --git a/packages/cli/package.json b/packages/cli/package.json index 3e8715fc7..cfccda2fc 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/cli", - "version": "7.11.1", + "version": "7.12.0", "private": false, "repository": { "type": "git", @@ -40,13 +40,13 @@ "node": ">=16.0.0" }, "dependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/config-loader": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/server": "^7.11.0", - "@basemaps/shared": "^7.11.0", - "@basemaps/tiler": "^7.11.0", - "@basemaps/tiler-sharp": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/config-loader": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/server": "^7.12.0", + "@basemaps/shared": "^7.12.0", + "@basemaps/tiler": "^7.12.0", + "@basemaps/tiler-sharp": "^7.12.0", "@chunkd/source-memory": "^11.0.2", "@cotar/builder": "^6.0.1", "@cotar/tar": "^6.0.1", diff --git a/packages/cogify/CHANGELOG.md b/packages/cogify/CHANGELOG.md index 892033caa..9118a5a71 100644 --- a/packages/cogify/CHANGELOG.md +++ b/packages/cogify/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + +**Note:** Version bump only for package @basemaps/cogify + + + + + ## [7.11.1](https://github.com/linz/basemaps/compare/v7.11.0...v7.11.1) (2024-10-01) **Note:** Version bump only for package @basemaps/cogify diff --git a/packages/cogify/package.json b/packages/cogify/package.json index 723d790dd..0659133fc 100644 --- a/packages/cogify/package.json +++ b/packages/cogify/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/cogify", - "version": "7.11.1", + "version": "7.12.0", "private": false, "repository": { "type": "git", @@ -40,11 +40,11 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "devDependencies": { - "@basemaps/cli": "^7.11.1", - "@basemaps/config": "^7.11.0", - "@basemaps/config-loader": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/cli": "^7.12.0", + "@basemaps/config": "^7.12.0", + "@basemaps/config-loader": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/shared": "^7.12.0", "cmd-ts": "^0.12.1", "p-limit": "^4.0.0", "stac-ts": "^1.0.0" diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 044012d43..69333e7eb 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + + +### Features + +* **lambda-tiler:** update imagery layer attributions to show licensor details BM-897 ([#3357](https://github.com/linz/basemaps/issues/3357)) ([e702c7e](https://github.com/linz/basemaps/commit/e702c7e53d28aaa8db9d624acab048f8ec3a2309)) + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) **Note:** Version bump only for package @basemaps/config-loader diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index e07faf2f9..67a9a98e9 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/config-loader", - "version": "7.11.0", + "version": "7.12.0", "repository": { "type": "git", "url": "https://github.com/linz/basemaps.git", @@ -28,8 +28,8 @@ "build/" ], "dependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/shared": "^7.11.0" + "@basemaps/config": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/shared": "^7.12.0" } } diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index 82b24f88c..d5711ad37 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + + +### Features + +* **lambda-tiler:** update imagery layer attributions to show licensor details BM-897 ([#3357](https://github.com/linz/basemaps/issues/3357)) ([e702c7e](https://github.com/linz/basemaps/commit/e702c7e53d28aaa8db9d624acab048f8ec3a2309)) + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) **Note:** Version bump only for package @basemaps/config diff --git a/packages/config/package.json b/packages/config/package.json index 1103ffd6c..5b6c3c2a9 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/config", - "version": "7.11.0", + "version": "7.12.0", "repository": { "type": "git", "url": "https://github.com/linz/basemaps.git", @@ -28,7 +28,7 @@ "build/" ], "dependencies": { - "@basemaps/geo": "^7.11.0", + "@basemaps/geo": "^7.12.0", "base-x": "^4.0.0", "zod": "^3.17.3" } diff --git a/packages/geo/CHANGELOG.md b/packages/geo/CHANGELOG.md index 6e285fa1d..82a016c34 100644 --- a/packages/geo/CHANGELOG.md +++ b/packages/geo/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + + +### Features + +* **lambda-tiler:** update imagery layer attributions to show licensor details BM-897 ([#3357](https://github.com/linz/basemaps/issues/3357)) ([e702c7e](https://github.com/linz/basemaps/commit/e702c7e53d28aaa8db9d624acab048f8ec3a2309)) + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) diff --git a/packages/geo/package.json b/packages/geo/package.json index 5ca04437c..abe6c000e 100644 --- a/packages/geo/package.json +++ b/packages/geo/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/geo", - "version": "7.11.0", + "version": "7.12.0", "repository": { "type": "git", "url": "https://github.com/linz/basemaps.git", diff --git a/packages/lambda-analytics/CHANGELOG.md b/packages/lambda-analytics/CHANGELOG.md index b3fe2e1de..859d200f5 100644 --- a/packages/lambda-analytics/CHANGELOG.md +++ b/packages/lambda-analytics/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + +**Note:** Version bump only for package @basemaps/lambda-analytics + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) **Note:** Version bump only for package @basemaps/lambda-analytics diff --git a/packages/lambda-analytics/package.json b/packages/lambda-analytics/package.json index 26f964604..37d44c07d 100644 --- a/packages/lambda-analytics/package.json +++ b/packages/lambda-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/lambda-analytics", - "version": "7.11.0", + "version": "7.12.0", "private": true, "repository": { "type": "git", @@ -18,9 +18,9 @@ }, "license": "MIT", "dependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/shared": "^7.12.0", "ua-parser-js": "^1.0.2" }, "scripts": { diff --git a/packages/lambda-tiler/CHANGELOG.md b/packages/lambda-tiler/CHANGELOG.md index a668c36e7..6053db5da 100644 --- a/packages/lambda-tiler/CHANGELOG.md +++ b/packages/lambda-tiler/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + + +### Bug Fixes + +* **lambda-tiler:** correctly log fetch requests ([#3359](https://github.com/linz/basemaps/issues/3359)) ([9fa3681](https://github.com/linz/basemaps/commit/9fa3681acc2ce25037c5d6e0326255aad9815b7d)) + + +### Features + +* **lambda-tiler:** update imagery layer attributions to show licensor details BM-897 ([#3357](https://github.com/linz/basemaps/issues/3357)) ([e702c7e](https://github.com/linz/basemaps/commit/e702c7e53d28aaa8db9d624acab048f8ec3a2309)) +* **server:** add redirect route to pre-zoomed tileset BM-1076 ([#3354](https://github.com/linz/basemaps/issues/3354)) ([5b207de](https://github.com/linz/basemaps/commit/5b207de92b76e0d445a41ef8e1e9b9b91e5363c6)) + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) diff --git a/packages/lambda-tiler/package.json b/packages/lambda-tiler/package.json index 711890cfd..e51bda749 100644 --- a/packages/lambda-tiler/package.json +++ b/packages/lambda-tiler/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/lambda-tiler", - "version": "7.11.0", + "version": "7.12.0", "repository": { "type": "git", "url": "https://github.com/linz/basemaps.git", @@ -22,12 +22,12 @@ "types": "./build/index.d.ts", "license": "MIT", "dependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/config-loader": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/shared": "^7.11.0", - "@basemaps/tiler": "^7.11.0", - "@basemaps/tiler-sharp": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/config-loader": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/shared": "^7.12.0", + "@basemaps/tiler": "^7.12.0", + "@basemaps/tiler-sharp": "^7.12.0", "@linzjs/geojson": "^7.10.0", "@linzjs/lambda": "^4.0.0", "@mapbox/vector-tile": "^2.0.3", @@ -50,7 +50,7 @@ "bundle": "./bundle.sh" }, "devDependencies": { - "@basemaps/attribution": "^7.11.0", + "@basemaps/attribution": "^7.12.0", "@chunkd/fs": "^11.2.0", "@types/aws-lambda": "^8.10.75", "@types/pixelmatch": "^5.0.0", diff --git a/packages/landing/CHANGELOG.md b/packages/landing/CHANGELOG.md index 956eb9a42..01b002bd9 100644 --- a/packages/landing/CHANGELOG.md +++ b/packages/landing/CHANGELOG.md @@ -3,6 +3,25 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + + +### Bug Fixes + +* **landing:** Fix debug hillshade infinite loading. BM-1110 ([#3360](https://github.com/linz/basemaps/issues/3360)) ([6655441](https://github.com/linz/basemaps/commit/6655441e48fd226f81daeb98987a95dd649128a7)) + + +### Features + +* **lambda-tiler:** update imagery layer attributions to show licensor details BM-897 ([#3357](https://github.com/linz/basemaps/issues/3357)) ([e702c7e](https://github.com/linz/basemaps/commit/e702c7e53d28aaa8db9d624acab048f8ec3a2309)) +* **landing:** Add new features pop up to alert users for recent releases. BM-1064 ([#3356](https://github.com/linz/basemaps/issues/3356)) ([a61b652](https://github.com/linz/basemaps/commit/a61b652d80efd29acc198cc52456b5a28a65d09c)) +* **landing:** enable labels upon first visit BM-1101 ([#3364](https://github.com/linz/basemaps/issues/3364)) ([af656bf](https://github.com/linz/basemaps/commit/af656bfe72e8afb3b072cf18d2dbbb538709127c)) +* **landing:** Update new feature pop ups to include google analytics. BM-1113 ([#3363](https://github.com/linz/basemaps/issues/3363)) ([dcc8a9b](https://github.com/linz/basemaps/commit/dcc8a9b8af50e7ab3e5fc53e081ed7954b3b26ea)) + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) diff --git a/packages/landing/package.json b/packages/landing/package.json index 96933684e..5d3bedbc8 100644 --- a/packages/landing/package.json +++ b/packages/landing/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/landing", - "version": "7.11.0", + "version": "7.12.0", "repository": { "type": "git", "url": "https://github.com/linz/basemaps.git", @@ -28,11 +28,11 @@ "last 2 Chrome versions" ], "devDependencies": { - "@basemaps/attribution": "^7.11.0", - "@basemaps/config": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/infra": "^7.11.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/attribution": "^7.12.0", + "@basemaps/config": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/infra": "^7.12.0", + "@basemaps/shared": "^7.12.0", "@linzjs/lui": "^21.46.0", "@servie/events": "^3.0.0", "@types/proj4": "^2.5.2", diff --git a/packages/server/CHANGELOG.md b/packages/server/CHANGELOG.md index 60da9760e..d6a443c56 100644 --- a/packages/server/CHANGELOG.md +++ b/packages/server/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + +**Note:** Version bump only for package @basemaps/server + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) diff --git a/packages/server/package.json b/packages/server/package.json index bc2e81c9b..75c9a80f7 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/server", - "version": "7.11.0", + "version": "7.12.0", "repository": { "type": "git", "url": "https://github.com/linz/basemaps.git", @@ -52,12 +52,12 @@ "sharp": "^0.33.0" }, "devDependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/config-loader": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/lambda-tiler": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/config-loader": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/lambda-tiler": "^7.12.0", "@basemaps/landing": "^6.39.0", - "@basemaps/shared": "^7.11.0", + "@basemaps/shared": "^7.12.0", "@fastify/formbody": "^7.0.1", "@fastify/static": "^6.5.0", "cmd-ts": "^0.12.1", diff --git a/packages/shared/CHANGELOG.md b/packages/shared/CHANGELOG.md index d82ac929f..c0d1bdc84 100644 --- a/packages/shared/CHANGELOG.md +++ b/packages/shared/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + + +### Bug Fixes + +* **lambda-tiler:** correctly log fetch requests ([#3359](https://github.com/linz/basemaps/issues/3359)) ([9fa3681](https://github.com/linz/basemaps/commit/9fa3681acc2ce25037c5d6e0326255aad9815b7d)) +* register file systems correctly when using duplicate roleArns BM-1055 ([#3367](https://github.com/linz/basemaps/issues/3367)) ([385971d](https://github.com/linz/basemaps/commit/385971dc23c0b1cd9c354c5028d47d01ab5ae584)) + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) **Note:** Version bump only for package @basemaps/shared diff --git a/packages/shared/package.json b/packages/shared/package.json index 67a34e764..516555f25 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/shared", - "version": "7.11.0", + "version": "7.12.0", "private": false, "repository": { "type": "git", @@ -26,8 +26,8 @@ "@aws-sdk/client-dynamodb": "^3.470.0", "@aws-sdk/client-s3": "^3.472.0", "@aws-sdk/util-dynamodb": "^3.470.0", - "@basemaps/config": "^7.11.0", - "@basemaps/geo": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/geo": "^7.12.0", "@chunkd/fs": "^11.2.0", "@chunkd/fs-aws": "^11.3.0", "@chunkd/middleware": "^11.1.0", diff --git a/packages/tiler-sharp/CHANGELOG.md b/packages/tiler-sharp/CHANGELOG.md index c002589ab..e6f3712c9 100644 --- a/packages/tiler-sharp/CHANGELOG.md +++ b/packages/tiler-sharp/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + +**Note:** Version bump only for package @basemaps/tiler-sharp + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) **Note:** Version bump only for package @basemaps/tiler-sharp diff --git a/packages/tiler-sharp/package.json b/packages/tiler-sharp/package.json index b3bac6e5f..c36d5c926 100644 --- a/packages/tiler-sharp/package.json +++ b/packages/tiler-sharp/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/tiler-sharp", - "version": "7.11.0", + "version": "7.12.0", "repository": { "type": "git", "url": "https://github.com/linz/basemaps.git", @@ -22,9 +22,9 @@ "test": "node --test" }, "dependencies": { - "@basemaps/config": "^7.11.0", - "@basemaps/geo": "^7.11.0", - "@basemaps/tiler": "^7.11.0", + "@basemaps/config": "^7.12.0", + "@basemaps/geo": "^7.12.0", + "@basemaps/tiler": "^7.12.0", "@linzjs/metrics": "^7.5.0", "lerc": "^4.0.4" }, diff --git a/packages/tiler/CHANGELOG.md b/packages/tiler/CHANGELOG.md index ac474bea0..025f51087 100644 --- a/packages/tiler/CHANGELOG.md +++ b/packages/tiler/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.12.0](https://github.com/linz/basemaps/compare/v7.11.1...v7.12.0) (2024-11-14) + +**Note:** Version bump only for package @basemaps/tiler + + + + + # [7.11.0](https://github.com/linz/basemaps/compare/v7.10.0...v7.11.0) (2024-09-29) **Note:** Version bump only for package @basemaps/tiler diff --git a/packages/tiler/package.json b/packages/tiler/package.json index 2bca1fa1d..be9c64f09 100644 --- a/packages/tiler/package.json +++ b/packages/tiler/package.json @@ -1,6 +1,6 @@ { "name": "@basemaps/tiler", - "version": "7.11.0", + "version": "7.12.0", "repository": { "type": "git", "url": "https://github.com/linz/basemaps.git", @@ -22,7 +22,7 @@ "test": "node --test" }, "dependencies": { - "@basemaps/geo": "^7.11.0", + "@basemaps/geo": "^7.12.0", "@cogeotiff/core": "^9.0.3", "@linzjs/metrics": "^7.5.0" }, From bc334d4f0c36425c3f9d3bd33b1cd338f26c0690 Mon Sep 17 00:00:00 2001 From: Tawera Manaena Date: Fri, 15 Nov 2024 09:28:04 +1300 Subject: [PATCH 09/12] feat: support custom indent sublists BM-1120 (#3371) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR is a sibling of [this PR][pr] in the **basemaps-mkdocs** repository. [pr]: https://github.com/linz/basemaps-mkdocs/pull/8 --- ### Problem When formatting markdown (`.md`) files in Visual Studio Code, sublists are lost due to LINZ's formatting rules around how many spaces prescribe a _tab_. - Currently, MkDocs requires sublist items to be indented 4 spaces relative to the parent. Like so: ```md - Parent - Child ``` - However, LINZ's Prettier formatting rules ([.prettierrc.cjs][prettier]) trims such occurrences down to 2 spaces: ```md - Parent - Child ``` After the formatting, MkDocs interprets the `Child` sublist item as a member of the parent list. Effectively, the sublist is lost. ### Solution I have identified a markdown extension called [mdx_truly_sane_lists][mdx], which can solve the problem. The extension allows us to override the number of spaces required for MkDocs to preserve a sublist item from 4 spaces to 2 spaces, inline with LINZ's Prettier formatting rules. ### Modifications - #### [Sibling pull request][pr] - #### Dockerfile - Added an install command for the `mdx_truly_sane_lists` markdown extension. - Updated the MkDocs base image to the latest version ([9.5.44](mkdocs)). > Not required for the extension to work, just a convenient time to update the image. - #### This pull request - #### MkDocs configuration ([mkdocs.yml][yml]) - Updated the [mkdocs.yml][yml] file of the [linz/basemaps][basemaps] repo so that MkDocs uses the extension. ### Verification - #### Building the Docker image I used the following command to build a Docker image with which I could test my modifications: ```bash # from the root of the `basemaps-mkdocs` repo docker build --tag basemaps-mkdocs-test . ``` - #### Serving MkDocs locally I then used the following command to serve MkDocs locally using the Docker image: ```bash # from the root of the `basemaps` repo docker run --rm -v $PWD:/docs -p 8000:8000 basemaps-mkdocs-test serve -a 0.0.0.0:8000 ``` - #### Testing sublist indent For the given markdown [snippet][snippet]: ```md - build the **basemaps** packages - configure and run the **basemaps/server** package: - using LINZ's imagery - using your own imagery ``` MkDocs correctly preserves the sublist items! 🎉 | Before | After | | - | - | | ![][before] | ![][after] | [jira]: https://toitutewhenua.atlassian.net/browse/BM-1120 [prettier]: https://github.com/linz/style-js/blob/437f754e17eca905a880606219c832e8fc9d5f9c/.prettierrc.cjs [mdx]: https://github.com/radude/mdx_truly_sane_lists [mkdocs]: https://github.com/squidfunk/mkdocs-material/pkgs/container/mkdocs-material/300822759?tag=9.5.44 [yml]: https://github.com/linz/basemaps/blob/385971dc23c0b1cd9c354c5028d47d01ab5ae584/mkdocs.yml [basemaps]: https://github.com/linz/basemaps [snippet]: https://github.com/linz/basemaps/blob/385971dc23c0b1cd9c354c5028d47d01ab5ae584/docs/developer-guide/run-basemaps-locally.md [before]: https://github.com/user-attachments/assets/0ddbbbaa-9b1a-49df-bf54-74c2d7357d0d [after]: https://github.com/user-attachments/assets/301f7ca5-80e5-4bf9-97c2-4841a0bec68b --- docs/developer-guide/run-basemaps-locally.md | 8 ++++---- mkdocs.yml | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/developer-guide/run-basemaps-locally.md b/docs/developer-guide/run-basemaps-locally.md index 3d3a3cbea..42bacfc9d 100644 --- a/docs/developer-guide/run-basemaps-locally.md +++ b/docs/developer-guide/run-basemaps-locally.md @@ -4,8 +4,8 @@ This guide shows you how to set up and run a local instance of the **basemaps** - build the **basemaps** packages - configure and run the **basemaps/server** package: - - using LINZ's imagery - - using your own imagery + - using LINZ's imagery + - using your own imagery !!! note @@ -56,7 +56,7 @@ Clone the [**linz/basemaps**][bm_repo] repository to your machine. !!! abstract "Path" This guide uses variables as shorthand to reference key directories and files. On your machine, consider the following path: - + === "`BM_REPO`" The path to the **basemaps** repository folder on your machine. @@ -102,4 +102,4 @@ There are two main ways you can configure and run the **basemaps/server** packag [bm_repo]: https://github.com/linz/basemaps [configuration]: https://github.com/linz/basemaps/blob/master/docs/configuration.md [contributing]: https://github.com/linz/basemaps/blob/master/CONTRIBUTING.md -[stac]: https://github.com/radiantearth/stac-spec/blob/master/overview.md \ No newline at end of file +[stac]: https://github.com/radiantearth/stac-spec/blob/master/overview.md diff --git a/mkdocs.yml b/mkdocs.yml index ee31016c9..c345947a6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -74,6 +74,12 @@ markdown_extensions: - pymdownx.tabbed: alternate_style: true + # Overrides indent required for sublist items + # + # https://github.com/radude/mdx_truly_sane_lists + - mdx_truly_sane_lists: + nested_indent: 2 + # Load google analytics from the $GOOGLE_ANALYTICS environment var extra: analytics: From 5ce567f5e8cc281fc8cd691d00e8b17a687ee514 Mon Sep 17 00:00:00 2001 From: Wentao Kuang Date: Thu, 21 Nov 2024 13:18:55 +1300 Subject: [PATCH 10/12] fix(server): Bundle the the bin file before publish NPM. BM-1083 (#3375) ### Motivation The [@basemaps/server](https://www.npmjs.com/package/@basemaps/server?activeTab=code) npm package is missing the bin file for excusing the command. We need to bundle it first before publish the package. ### Modifications Add a bundle command before NPM publish ### Verification Locally tested. - delete the `server/bin/basemaps-server.cjs` - run `npx lerna run bundle --stream` -> Got a new `server/bin/basemaps-server.cjs` generated. - run `npm pack --dry-run` -> Got bin file included. ![image](https://github.com/user-attachments/assets/812f27cc-0f0c-47d3-b2fb-c37066f569ea) --------- Co-authored-by: Tawera Manaena --- .github/workflows/push.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 134f45a6e..ae9228ff3 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -23,6 +23,10 @@ jobs: steps: - uses: linz/action-typescript@v3 + - name: Bundle + run: | + npx lerna run bundle --stream + # TODO: running a giant copy command to import CSS and SVG files into the docs file in not super ideal - name: Build docs run: | From 5d2d9c6069ce31bd22539fa41e9b41cc2aa53947 Mon Sep 17 00:00:00 2001 From: Wentao Kuang Date: Thu, 21 Nov 2024 13:32:12 +1300 Subject: [PATCH 11/12] fix(lambda-tiler): NZTM terrain been multiplied twice. BM-1122 (#3373) ### Motivation Basemap terrain exaggeration for NZTM been multiplied twice. ![image](https://github.com/user-attachments/assets/4e7b4a77-431c-4f0e-be5d-206787ae2452) ![image](https://github.com/user-attachments/assets/e8a64789-7e70-4bb9-97f8-c8cac4e06e36) ### Modifications We have manually multiplied the NZTM terrain exaggeration when converting the style json earlier, however, we got default setting to fix them as 4.4 in `DefaultExaggeration`, so we don't need to covert the exaggeration twice to make it too large. ### Verification Local test and unit test. ![image](https://github.com/user-attachments/assets/42f35f6f-6410-4ccd-87f6-c007f9faae7f) --- .../routes/__tests__/tile.style.json.test.ts | 5 ++-- .../src/routes/tile.style.json.ts | 2 +- .../src/util/__test__/nztm.style.test.ts | 26 +++++++++++++------ packages/lambda-tiler/src/util/nztm.style.ts | 3 --- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/lambda-tiler/src/routes/__tests__/tile.style.json.test.ts b/packages/lambda-tiler/src/routes/__tests__/tile.style.json.test.ts index d15ec5f91..edec5c4fa 100644 --- a/packages/lambda-tiler/src/routes/__tests__/tile.style.json.test.ts +++ b/packages/lambda-tiler/src/routes/__tests__/tile.style.json.test.ts @@ -2,7 +2,8 @@ import assert from 'node:assert'; import { afterEach, before, beforeEach, describe, it } from 'node:test'; import { ConfigProviderMemory, SourceRaster, StyleJson } from '@basemaps/config'; -import { Terrain } from '@basemaps/config/src/config/vector.style.js'; +import { DefaultExaggeration, Terrain } from '@basemaps/config/build/config/vector.style.js'; +import { Nztm2000QuadTms } from '@basemaps/geo'; import { Env } from '@basemaps/shared'; import { createSandbox } from 'sinon'; @@ -441,7 +442,7 @@ describe('/v1/styles', () => { }, ], terrain: { - exaggeration: 1.1, + exaggeration: DefaultExaggeration[Nztm2000QuadTms.identifier], }, }, }; diff --git a/packages/lambda-tiler/src/routes/tile.style.json.ts b/packages/lambda-tiler/src/routes/tile.style.json.ts index efa7c7044..327a8ef3e 100644 --- a/packages/lambda-tiler/src/routes/tile.style.json.ts +++ b/packages/lambda-tiler/src/routes/tile.style.json.ts @@ -90,7 +90,7 @@ export interface StyleConfig { /** * Turn on the terrain setting in the style json */ -function setStyleTerrain(style: StyleJson, terrain: string, tileMatrix: TileMatrixSet): void { +export function setStyleTerrain(style: StyleJson, terrain: string, tileMatrix: TileMatrixSet): void { const source = Object.keys(style.sources).find((s) => s === terrain); if (source == null) throw new LambdaHttpResponse(400, `Terrain: ${terrain} does not exists in the style source.`); style.terrain = { diff --git a/packages/lambda-tiler/src/util/__test__/nztm.style.test.ts b/packages/lambda-tiler/src/util/__test__/nztm.style.test.ts index ba907ee14..622d42bc7 100644 --- a/packages/lambda-tiler/src/util/__test__/nztm.style.test.ts +++ b/packages/lambda-tiler/src/util/__test__/nztm.style.test.ts @@ -2,7 +2,9 @@ import assert from 'node:assert'; import { describe, it } from 'node:test'; import { StyleJson } from '@basemaps/config'; +import { GoogleTms, Nztm2000QuadTms } from '@basemaps/geo'; +import { setStyleTerrain } from '../../routes/tile.style.json.js'; import { convertStyleToNztmStyle } from '../nztm.style.js'; describe('NZTM2000QuadStyle', () => { @@ -25,9 +27,6 @@ describe('NZTM2000QuadStyle', () => { convertStyleToNztmStyle(baseStyle); assert.equal(baseStyle.terrain?.exaggeration, 1.1); - - convertStyleToNztmStyle(baseStyle, false); - assert.equal(baseStyle.terrain?.exaggeration, 4.4); }); it('should convert min/maxzooms', () => { @@ -39,13 +38,24 @@ describe('NZTM2000QuadStyle', () => { assert.deepEqual(newStyle.layers[0], { minzoom: 3, maxzoom: 8, id: 'something', type: '' }); }); - it('should offset terrain', () => { - const newStyle = convertStyleToNztmStyle({ + it('should not offset terrain for WebMecator', () => { + const testStyle: StyleJson = { ...fakeStyle, - terrain: { exaggeration: 1.1, source: 'abc' }, - }); + sources: { 'LINZ-Terrain': { type: 'raster-dem', tiles: ['https://example.com/{z}/{x}/{y}.png'] } }, + }; + setStyleTerrain(testStyle, 'LINZ-Terrain', GoogleTms); + + assert.deepEqual(testStyle.terrain, { exaggeration: 1.2, source: 'LINZ-Terrain' }); + }); + + it('should offset terrain for NZTM', () => { + const testStyle: StyleJson = { + ...fakeStyle, + sources: { 'LINZ-Terrain': { type: 'raster-dem', tiles: ['https://example.com/{z}/{x}/{y}.png'] } }, + }; + setStyleTerrain(testStyle, 'LINZ-Terrain', Nztm2000QuadTms); - assert.deepEqual(newStyle.terrain, { exaggeration: 4.4, source: 'abc' }); + assert.deepEqual(testStyle.terrain, { exaggeration: 4.4, source: 'LINZ-Terrain' }); }); it('should convert stops inside of paint and layout', () => { diff --git a/packages/lambda-tiler/src/util/nztm.style.ts b/packages/lambda-tiler/src/util/nztm.style.ts index d297617f1..b3ca78cff 100644 --- a/packages/lambda-tiler/src/util/nztm.style.ts +++ b/packages/lambda-tiler/src/util/nztm.style.ts @@ -37,8 +37,5 @@ export function convertStyleToNztmStyle(inputStyle: StyleJson, clone: boolean = } } - /** Based on {@link DefaultExaggeration} offsetting by 2 two levels changes the exaggeration needed by approx 4x */ - if (style.terrain) style.terrain.exaggeration = style.terrain.exaggeration * 4; - return style; } From 3b1a6faa4452d61e71cfa169ff5603ac28ed1108 Mon Sep 17 00:00:00 2001 From: Blayne Chard Date: Fri, 22 Nov 2024 10:29:18 +1300 Subject: [PATCH 12/12] build: maplibre v4.7.1 (#3366) ### Motivation Fixes a few 3d terrain bugs. ### Modifications Upgraded maplibre to latest ### Verification More exploration once deployed in dev. --- package-lock.json | 317 ++++++++++------------------------------------ 1 file changed, 64 insertions(+), 253 deletions(-) diff --git a/package-lock.json b/package-lock.json index 22393446c..3818e9e7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3327,9 +3327,9 @@ } }, "node_modules/@maplibre/maplibre-gl-style-spec": { - "version": "20.3.0", - "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-20.3.0.tgz", - "integrity": "sha512-eSiQ3E5LUSxAOY9ABXGyfNhout2iEa6mUxKeaQ9nJ8NL1NuaQYU7zKqzx/LEYcXe1neT4uYAgM1wYZj3fTSXtA==", + "version": "20.4.0", + "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-20.4.0.tgz", + "integrity": "sha512-AzBy3095fTFPjDjmWpR2w6HVRAZJ6hQZUCwk5Plz6EyfnfuQW1odeW5i2Ai47Y6TBA2hQnC+azscjBSALpaWgw==", "dev": true, "dependencies": { "@mapbox/jsonlint-lines-primitives": "~2.0.2", @@ -3338,8 +3338,7 @@ "minimist": "^1.2.8", "quickselect": "^2.0.0", "rw": "^1.3.3", - "sort-object": "^3.0.3", - "tinyqueue": "^2.0.3" + "tinyqueue": "^3.0.0" }, "bin": { "gl-style-format": "dist/gl-style-format.mjs", @@ -3347,6 +3346,12 @@ "gl-style-validate": "dist/gl-style-validate.mjs" } }, + "node_modules/@maplibre/maplibre-gl-style-spec/node_modules/quickselect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==", + "dev": true + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -5290,12 +5295,6 @@ "@types/geojson": "*" } }, - "node_modules/@types/junit-report-builder": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/junit-report-builder/-/junit-report-builder-3.0.2.tgz", - "integrity": "sha512-R5M+SYhMbwBeQcNXYWNCZkl09vkVfAtcPIaCGdzIkkbeaTrVbGQ7HVgi4s+EmM/M1K4ZuWQH0jGcvMvNePfxYA==", - "dev": true - }, "node_modules/@types/mapbox__point-geometry": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz", @@ -5928,15 +5927,6 @@ "sprintf-js": "~1.0.2" } }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", @@ -6125,15 +6115,6 @@ "node": ">=0.10.0" } }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/async": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", @@ -6744,25 +6725,6 @@ "node": ">=12.17" } }, - "node_modules/bytewise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz", - "integrity": "sha512-rHuuseJ9iQ0na6UDhnrRVDh8YnWVlU6xM3VH6q/+yHDeUH2zIhUzP+2/h3LIrhLDBtTqzWpE3p3tP/boefskKQ==", - "dev": true, - "dependencies": { - "bytewise-core": "^1.2.2", - "typewise": "^1.0.3" - } - }, - "node_modules/bytewise-core": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bytewise-core/-/bytewise-core-1.2.3.tgz", - "integrity": "sha512-nZD//kc78OOxeYtRlVk8/zXqTB4gf/nlguL1ggWA8FuchMyOxcyHR4QPQZMUmA7czC+YnaBrPUCubqAWe50DaA==", - "dev": true, - "dependencies": { - "typewise-core": "^1.2" - } - }, "node_modules/cacache": { "version": "16.1.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", @@ -8635,9 +8597,9 @@ "license": "BSD-3-Clause" }, "node_modules/earcut": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", - "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.0.tgz", + "integrity": "sha512-41Fs7Q/PLq1SDbqjsgcY7GA42T0jvaCNGXgGtsNdvg+Yv8eIu06bxv4/PoREkZ9nMDNwnUSG9OFB9+yv8eKhDg==", "dev": true }, "node_modules/eastasianwidth": { @@ -9463,18 +9425,6 @@ "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", "dev": true }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -10498,15 +10448,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/gh-got": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-7.1.0.tgz", @@ -10781,29 +10722,50 @@ } }, "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-4.0.0.tgz", + "integrity": "sha512-w0Uf9Y9/nyHinEk5vMJKRie+wa4kR5hmDbEhGGds/kG1PwGLLHKRoNMeJOyCQjjBkANlnScqgzcFwGHgmgLkVA==", "dev": true, "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" + "ini": "^4.1.3", + "kind-of": "^6.0.3", + "which": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=16" + } + }, + "node_modules/global-prefix/node_modules/ini": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/global-prefix/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" } }, "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dev": true, "dependencies": { - "isexe": "^2.0.0" + "isexe": "^3.1.1" }, "bin": { - "which": "bin/which" + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" } }, "node_modules/globals": { @@ -11657,15 +11619,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -13217,9 +13170,9 @@ } }, "node_modules/maplibre-gl": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-4.5.0.tgz", - "integrity": "sha512-qOS1hn4d/pn2i0uva4S5Oz+fACzTkgBKq+NpwT/Tqzi4MSyzcWNtDELzLUSgWqHfNIkGCl5CZ/w7dtis+t4RCw==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-4.7.1.tgz", + "integrity": "sha512-lgL7XpIwsgICiL82ITplfS7IGwrB1OJIw/pCvprDp2dhmSSEBgmPzYRvwYYYvJGJD7fxUv1Tvpih4nZ6VrLuaA==", "dev": true, "dependencies": { "@mapbox/geojson-rewind": "^0.5.2", @@ -13229,25 +13182,24 @@ "@mapbox/unitbezier": "^0.0.1", "@mapbox/vector-tile": "^1.3.1", "@mapbox/whoots-js": "^3.1.0", - "@maplibre/maplibre-gl-style-spec": "^20.3.0", + "@maplibre/maplibre-gl-style-spec": "^20.3.1", "@types/geojson": "^7946.0.14", "@types/geojson-vt": "3.2.5", - "@types/junit-report-builder": "^3.0.2", "@types/mapbox__point-geometry": "^0.1.4", "@types/mapbox__vector-tile": "^1.3.4", "@types/pbf": "^3.0.5", "@types/supercluster": "^7.1.3", - "earcut": "^2.2.4", + "earcut": "^3.0.0", "geojson-vt": "^4.0.2", "gl-matrix": "^3.4.3", - "global-prefix": "^3.0.0", + "global-prefix": "^4.0.0", "kdbush": "^4.0.2", "murmurhash-js": "^1.0.0", - "pbf": "^3.2.1", + "pbf": "^3.3.0", "potpack": "^2.0.0", - "quickselect": "^2.0.0", + "quickselect": "^3.0.0", "supercluster": "^8.0.1", - "tinyqueue": "^2.0.3", + "tinyqueue": "^3.0.0", "vt-pbf": "^3.1.3" }, "engines": { @@ -15403,9 +15355,9 @@ } }, "node_modules/pbf": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz", - "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.3.0.tgz", + "integrity": "sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==", "dev": true, "dependencies": { "ieee754": "^1.1.12", @@ -15921,9 +15873,9 @@ } }, "node_modules/quickselect": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", - "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", "dev": true }, "node_modules/range-parser": { @@ -17002,33 +16954,6 @@ "node": ">= 0.4" } }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -17492,24 +17417,6 @@ "atomic-sleep": "^1.0.0" } }, - "node_modules/sort-asc": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/sort-asc/-/sort-asc-0.2.0.tgz", - "integrity": "sha512-umMGhjPeHAI6YjABoSTrFp2zaBtXBej1a0yKkuMUyjjqu6FJsTF+JYwCswWDg+zJfk/5npWUUbd33HH/WLzpaA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sort-desc": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/sort-desc/-/sort-desc-0.2.0.tgz", - "integrity": "sha512-NqZqyvL4VPW+RAxxXnB8gvE1kyikh8+pR+T+CXLksVRN9eiQqkQlPwqWYU0mF9Jm7UnctShlxLyAt1CaBOTL1w==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/sort-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", @@ -17523,23 +17430,6 @@ "node": ">=4" } }, - "node_modules/sort-object": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sort-object/-/sort-object-3.0.3.tgz", - "integrity": "sha512-nK7WOY8jik6zaG9CRwZTaD5O7ETWDLZYMM12pqY8htll+7dYeqGfEUPcUBHOpSJg2vJOrvFIY2Dl5cX2ih1hAQ==", - "dev": true, - "dependencies": { - "bytewise": "^1.1.0", - "get-value": "^2.0.2", - "is-extendable": "^0.1.1", - "sort-asc": "^0.2.0", - "sort-desc": "^0.2.0", - "union-value": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -17621,55 +17511,6 @@ "integrity": "sha512-ELtFtxc3r5we5GZfe6Fi0BFFxIi2M6BY1YEntBscKRDD3zx4JVHqx2VnTRSQu1BixCYSTH3MTjKd4esI2R7EgQ==", "dev": true }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/split2": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", @@ -18150,9 +17991,9 @@ } }, "node_modules/tinyqueue": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz", - "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz", + "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==", "dev": true }, "node_modules/tippy.js": { @@ -18663,21 +18504,6 @@ "node": ">=14.17" } }, - "node_modules/typewise": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typewise/-/typewise-1.0.3.tgz", - "integrity": "sha512-aXofE06xGhaQSPzt8hlTY+/YWQhm9P0jYUp1f2XtmW/3Bk0qzXcyFWAtPoo2uTGQj1ZwbDuSyuxicq+aDo8lCQ==", - "dev": true, - "dependencies": { - "typewise-core": "^1.2.0" - } - }, - "node_modules/typewise-core": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/typewise-core/-/typewise-core-1.2.0.tgz", - "integrity": "sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg==", - "dev": true - }, "node_modules/ua-parser-js": { "version": "1.0.37", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", @@ -18747,21 +18573,6 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/unique-filename": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz",