mirror of
https://github.com/BigBodyCobain/Shadowbroker.git
synced 2026-09-17 06:35:29 +02:00
Review follow-up: - Drop the Next.js route. CARTO_API_KEY is now a regular backend registry key (env, .env, or the API Keys panel) served by public GET /api/basemap-config. Every frontend mode already proxies /api/* to the backend (Next.js proxy in web mode, companion server in packaged desktop), so this covers web and desktop with one mechanism and leaves the static export untouched. Also removes the invalid non-handler export from the route module by removing the module. - useBasemapConfig: fail open to the unkeyed style after 3 s, abort the request at 15 s, apply a late key when it arrives, cache successes per page and retry failures on the next mount. - Declare OSM/CARTO attribution on the raster source (same markup as the viewer's existing AttributionControl so MapLibre de-duplicates it). - Tests: backend endpoint (unset / set+trimmed / persisted operator key / registry), hook behaviour (success, non-OK, network error, soft timeout then late key, hard abort, shared request and retry), attribution and gating source checks. - CARTO_API_KEY moves to the backend service in docker-compose.yml; docs updated accordingly. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
57 lines
2.2 KiB
TypeScript
57 lines
2.2 KiB
TypeScript
/**
|
|
* MapLibre basemap styles on CARTO raster tiles. CARTO requires an API key
|
|
* (unkeyed tiles are watermarked); MaplibreViewer passes one from
|
|
* useBasemapConfig() via buildBasemapStyle(). The key is served by the
|
|
* backend at GET /api/basemap-config.
|
|
*/
|
|
|
|
export type BasemapTheme = 'dark' | 'light';
|
|
|
|
const CARTO_SUBDOMAINS = ['a', 'b', 'c', 'd'] as const;
|
|
const CARTO_RASTER_STYLE: Record<BasemapTheme, string> = {
|
|
dark: 'dark_all',
|
|
light: 'light_all',
|
|
};
|
|
const GLYPHS_URL = 'https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf';
|
|
|
|
// Declared on the raster source so MapLibre's AttributionControl shows it
|
|
// even without the custom list in MaplibreViewer. Same markup as that list so
|
|
// the control de-duplicates instead of showing both.
|
|
export const OSM_ATTRIBUTION_HTML =
|
|
'<a href="https://www.openstreetmap.org/copyright" target="_blank" rel="noopener">© OpenStreetMap contributors</a>';
|
|
export const CARTO_ATTRIBUTION_HTML =
|
|
'<a href="https://carto.com/attribution" target="_blank" rel="noopener">CARTO</a>';
|
|
|
|
/** Tile URL templates for a CARTO raster style, keyed when a key is supplied. */
|
|
export function cartoTileUrls(theme: BasemapTheme, cartoApiKey?: string | null): string[] {
|
|
const style = CARTO_RASTER_STYLE[theme];
|
|
const key = (cartoApiKey || '').trim();
|
|
const query = key ? `?key=${encodeURIComponent(key)}` : '';
|
|
return CARTO_SUBDOMAINS.map(
|
|
(s) => `https://${s}.basemaps.cartocdn.com/rastertiles/${style}/{z}/{x}/{y}@2x.png${query}`,
|
|
);
|
|
}
|
|
|
|
export function buildBasemapStyle(theme: BasemapTheme, cartoApiKey?: string | null) {
|
|
const sourceId = `carto-${theme}`;
|
|
return {
|
|
version: 8,
|
|
glyphs: GLYPHS_URL,
|
|
sources: {
|
|
[sourceId]: {
|
|
type: 'raster',
|
|
tiles: cartoTileUrls(theme, cartoApiKey),
|
|
tileSize: 256,
|
|
attribution: `${OSM_ATTRIBUTION_HTML} ${CARTO_ATTRIBUTION_HTML}`,
|
|
},
|
|
},
|
|
layers: [
|
|
{ id: `${sourceId}-layer`, type: 'raster', source: sourceId, minzoom: 0, maxzoom: 22 },
|
|
{ id: 'imagery-ceiling', type: 'background', paint: { 'background-opacity': 0 } },
|
|
],
|
|
};
|
|
}
|
|
|
|
export const darkStyle = buildBasemapStyle('dark');
|
|
export const lightStyle = buildBasemapStyle('light');
|