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
10 stars
Elastic License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
65 /100 Good
Development Activity 96
Maintenance 72
Community 20
Maturity 60
Momentum 12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
68 /100 Good
Architecture 76
Code Quality 78
Innovation 62
Learning Curve 55

@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