ems-client
TypeScript client library for the Elastic Maps Service, resolving tile and vector map layer manifests, styles, and localized labels.
Repository Health
Technical Analysis
@elastic/ems-client is the official TypeScript client for the Elastic Maps Service (EMS), the tile and vector-map layer catalog that powers Kibana’s Maps app and other Elastic mapping features. It resolves the EMS manifest hierarchy — main catalog, then TMS (tile map service) and file-layer sub-catalogs — into typed TMSService and FileLayer objects that expose raster tile URLs, inlined vector style sheets, sprite sheets, and GeoJSON/TopoJSON file downloads.
Beyond simple manifest fetching, the library handles the practical wiring a map consumer actually needs: URL templating with app-name/version query parameters, an LRU cache for downloaded GeoJSON, locale-aware label selection across 50+ languages with OpenMapTiles fallback, and color-blending helpers for recoloring vector map styles (dark mode, desaturation, custom tints) directly in MapLibre GL style specs.
What You Get
EMSCliententry point that resolves the EMS manifest hierarchy (main catalog to TMS/file sub-catalogs) from a single tile/file API URL and app versionTMSServiceobjects exposing raster tile URL templates, inlined vector style sheets (with sources, sprites, and glyphs resolved to absolute URLs), and zoom-level metadataFileLayerobjects for downloading GeoJSON/TopoJSON boundary layers with format negotiation and an internal LRU cache- Locale-aware label resolution across 50+ OpenMapTiles-supported languages, with automatic fallback to the default locale
- Vector style color-blending utilities (
transformColorProperties,colorizeColor) for recoloring MapLibre GL paint properties to build dark/light/tinted map variants - Legacy
kbnVersionconfig support alongside the currentappVersion/REST-API manifest scheme for backward compatibility across Kibana versions
Common Use Cases
- Kibana Maps app - Kibana’s own Maps visualization uses this client to list and render EMS basemaps and boundary layers.
- Custom mapping dashboards - Teams building bespoke geospatial dashboards on Elastic Maps Service reuse the same manifest-resolution and styling logic instead of re-implementing it.
- Themed basemaps - Applications that need a dark-mode or brand-tinted basemap use the color-blending helpers to recolor EMS vector styles without hosting their own tile server.
- Localized map labels - Multi-language products use the locale-aware label transform to switch place-name labels between 50+ supported languages at render time.
Under The Hood
Architecture
The library is a thin, three-class facade over the EMS HTTP API: EMSClient (src/ems_client.ts) resolves the top-level catalog and hands off to TMSService (src/tms_service.ts) and FileLayer (src/file_layer.ts), both extending a shared AbstractEmsService (src/ems_service.ts) that stores the proxy path and parent client reference. Manifest-fetching methods are wired up in EMSClient._invalidateSettings() using lodash’s _.once, so each catalog level (main, TMS, file) and each service’s style/sprite sub-manifests are fetched exactly once per client lifetime and re-derived only if addQueryParams() triggers _invalidateSettings() again; this makes the whole client effectively a lazy, memoized dependency graph rather than an eagerly-loaded object. A consumer-supplied fetchFunction (not a hardcoded HTTP client) keeps the library runtime-agnostic between Kibana’s server and browser fetch implementations.
Tech Stack
Written in TypeScript, built with Babel (separate build-web/build-node targets via BABEL_ENV) and typed with tsc --emitDeclarationOnly. Runtime dependencies are narrow and purposeful: lru-cache for the GeoJSON cache, semver for EMS version negotiation, lodash for the _.once/_.merge memoization plumbing, and topojson-client for TopoJSON-to-GeoJSON conversion; maplibre-gl types anchor the vector style-spec shapes. Tests run under Jest with ts-jest, linting is ESLint + Prettier via a prelint/pretest chain, and husky wires a pre-commit hook.
Code Quality
The test suite (test/ems_client.test.ts, ems_client_colour.test.ts, ems_client_lang.test.ts) covers manifest URL construction, tile/vector style resolution, color-blending output, and locale fallback behavior using a shared mock-client helper (ems_client_util.ts) rather than live network calls. Error handling is explicit — getManifest() normalizes thrown values into Error instances and a request-timeout wrapper (_fetchWithTimeout) guards against hung fetches. TypeScript strict typing is used throughout the public API surface (exported FileLayerConfig, TMSServiceConfig, EmsSpriteSheet, etc.), and CI-oriented scripts (prelint, pretest) gate merges on type-checking and lint passing before tests run.
What Makes It Unique
Rather than shipping a generic map-tile SDK, this library is purpose-built around one narrow, well-understood problem: correctly walking the EMS’s own layered manifest scheme (catalog -> tile/file service -> per-locale style/format) and inlining every relative reference (style sources, sprites, glyphs, tile templates) into absolute, query-stamped URLs a map renderer can use directly — including the version-negotiation logic needed to support both the legacy kbnVersion manifest scheme and the newer REST API path. The vector-style color-blending utilities are a distinctive extra: they let a consumer produce dark-mode or brand-tinted variants of EMS’s official vector styles at runtime, without EMS needing to publish and host a separate style per theme.