ems-client

TypeScript client library for the Elastic Maps Service, resolving tile and vector map layer manifests, styles, and localized labels.

SDK
npm
v8.7.0
10stars
Elastic License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
65/100Good
Development Activity96
Maintenance72
Community20
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
68/100Good
Architecture76
Code Quality78
Innovation62
Learning Curve55

@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

  • EMSClient entry point that resolves the EMS manifest hierarchy (main catalog to TMS/file sub-catalogs) from a single tile/file API URL and app version
  • TMSService objects exposing raster tile URL templates, inlined vector style sheets (with sources, sprites, and glyphs resolved to absolute URLs), and zoom-level metadata
  • FileLayer objects 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 kbnVersion config support alongside the current appVersion/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.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search