diff --git a/packages/server/src/route.link.ts b/packages/server/src/route.link.ts new file mode 100644 index 000000000..652711970 --- /dev/null +++ b/packages/server/src/route.link.ts @@ -0,0 +1,27 @@ +import { BasemapsConfigProvider, getAllImagery, } from '@basemaps/config'; +import { Epsg } from '@basemaps/geo'; +import { getPreviewUrl } from '@basemaps/shared'; + +/** + * If a tileset layer of the given id and projection exists, this function returns a Basemaps URL + * path that is already zoomed to the extent of the tileset. Otherwise, this function returns null. + * + * @param id - The id of the tileset. + * @example "ashburton-2023-0.1m" + * + * @param projection - The projection from the tileset's layers to consider. + * @example Epsg.Google = 3857 + */ +export async function getTileSetPath(cfg: BasemapsConfigProvider, id: string, projection: Epsg): Promise { + const tileSet = await cfg.TileSet.get(id) + if (!tileSet) return null + + const imageryMap = await getAllImagery(cfg, tileSet.layers, [projection]); + + const [_, imagery] = Array.from(imageryMap)[0] + if (!imagery) return null + + const url = getPreviewUrl({ imagery }) + + return (`${url.slug}?i=${url.name}`) +} diff --git a/packages/server/src/server.ts b/packages/server/src/server.ts index d27c2c723..29a032da9 100644 --- a/packages/server/src/server.ts +++ b/packages/server/src/server.ts @@ -1,5 +1,6 @@ // Fastfiy uses a lot of floating promises /* eslint-disable @typescript-eslint/no-floating-promises */ +import { Epsg } from '@basemaps/geo'; import { handler } from '@basemaps/lambda-tiler'; import { Env, fsa, getDefaultConfig, LogType, setDefaultConfig } from '@basemaps/shared'; import formBodyPlugin from '@fastify/formbody'; @@ -14,6 +15,7 @@ import { URL } from 'url'; import { loadConfig, ServerOptions } from './config.js'; import { createLayersHtml } from './route.layers.js'; +import { getTileSetPath } from './route.link.js'; const instanceId = ulid.ulid(); @@ -95,5 +97,26 @@ export async function createServer(opts: ServerOptions, logger: LogType): Promis res.send(doc); }); + /** + * @route GET /link/:tileSetId + * + * @example /link/ashburton-2023-0.1m + * + * @description If a tileset layer of the given id and 3857 projection exists, the server redirects the client to a Basemaps + * URL that is already zoomed to the extent of the layer. Otherwise, the server returns an 'HTTP 404 Not found' status code. + * + */ + BasemapsServer.get('/link/:tileSetId', async (req: FastifyRequest<{ Params: { tileSetId: string } }>, res: FastifyReply) => { + const { tileSetId } = req.params + + const path = await getTileSetPath(cfg, tileSetId, Epsg.Google); + + if (path) { + res.redirect(`/${path}`) + } else { + res.status(404) + } + }); + return BasemapsServer; }