Atasu Maps

Список изменений

Выпуски SDK и API Atasu Maps.

API

HTTP API — версия v1 (спецификация 1.0.0-draft.1). Методы с пометкой Запланировано в справочнике API описаны, но пока не обслуживаются; они станут доступны без смены версии. Несовместимые изменения выйдут как /v2; новые необязательные поля и новые коды ошибок могут появиться в v1 в любой момент.

Android SDK

В пилоте — внутренняя предварительная версия; первый публичный выпуск — в бета-версии (Maven Central).

Web SDK — @atasu/maps-gl

Записи ниже ведутся на английском (CHANGELOG.md пакета).

All notable changes to the Atasu Maps Web SDK. Versions follow Semantic Versioning; before 1.0.0 a minor version (0.x.0) may contain breaking changes, which are listed under Breaking.

0.2.0 — 2026-10-24

Not published yet (the npm organization does not exist; decision D35).

Breaking

  • MapLibre's attribution control (.maplibregl-ctrl-attrib, bottom-right) is no longer on the map: the SDK draws its own credit, bottom-left (.atasu-attrib, see Changed). CSS or tests aimed at MapLibre's control have to target .atasu-attrib instead.

Changed

  • Reports: a road-event report (reportEvent) still in the outbox after 30 minutes is dropped instead of sent, as in the Android SDK: its body has no observation time, so the server would take it as happening now. flush() reports it as failed with the new AtasuReportStaleError (code: 'stale_on_device'); votes carry observed_at and are never dropped. EVENT_MAX_AGE_MS; ReportsContext.eventMaxAgeMs to change it. (Beta: the spec gains observed_at and the server enforces it.)
  • Attribution (ADR 0010): the SDK's own credit control replaces MapLibre's, bottom-left. It opens expanded and collapses to an ⓘ on ✕, on the first map interaction or after 5 s. ⓘ reopens it. It shows every visible source's declared credit (TomTom only while traffic is drawn) and cannot be hidden. New: map.attribution (credits, expanded, expand(), onChange).
  • LocateControl follows the position (follow-me camera): a press keeps the camera centred on it as it moves; a press while following, a pan by the user or another camera move of the app ends it, zooming does not. New: following, stopFollowing(), options follow (false: the old fly-to-position behaviour) and onFollowChange. The button is pressed (aria-pressed) while following. A passing gap in the fixes (POSITION_UNAVAILABLE, TIMEOUT after a first fix) no longer stops the watch; only a denied permission, or no fix at all, reports an error.
  • Package: the JavaScript in dist ships without comments (the source maps still carry the full sources), and the type-only dist/generated/openapi.js with its source map is gone; its .d.ts stays. Nothing imported it at run time.

Added

  • Map controls for 2GIS-level basics: ZoomControl (zoom + compass), LocateControl (my location; the position stays in the page), RulerControl (distance measuring), ThreeDControl and LayersControl (traffic, road events, community places / entrances, 3D). Titles in kk / ru / en, following map.language.
  • map.buildings: building highlight (highlightAt, highlightWhenRendered, seamless across tiles through feature-state) and 3D buildings (set3D).
  • map.entrances.show(entrances): entrance markers with number and flat range.
  • map.trees: the style's tree canopy (Almaty, Astana; Meta & WRI canopy height, CC BY 4.0) on / off (set, isOn, available, onChange; on by default, extruded with 3D on), and a "Trees" switch in the Layers panel. A hidden canopy drops its credit from the attribution.
  • map.overlays: optional traffic (traffic scope, TomTom attribution while on), road events and community layers (overlay scope); unavailable layers cannot be switched on.
  • map.search.browse(categories) and search(q, { category }): places by category (/v1/geocode/search?category=).
  • map.onLanguageChange(fn); formatDistance, distanceM, lengthM.
  • Traffic freshness (K6): map.overlays.trafficFreshness (off / pending / fresh with fetchedAt / unavailable with the proxy's X-Traffic-Status / no_coverage), reported through map.overlays.onChange. The Layers panel shows "updated N min ago", "traffic temporarily unavailable", "no traffic data for this area" or "zoom in to see traffic" under Traffic, in kk / ru / en. MapLibre does not expose tile headers, so the SDK re-requests the centre tile through its network hook. That is the same URL, so the browser or proxy cache answers it.
  • Traffic refresh, measured on MapLibre GL JS 6.15: an expired tile with a positive max-age is reloaded by MapLibre itself, but a no-store answer (204 unavailable, labelled stale) never is. So while traffic is on, the SDK checks the centre tile every 60 s and refreshes the traffic tiles when that tile was not cacheable or the state changed.
  • AtasuApiError.retryAfterSeconds: the API's Retry-After (seconds or HTTP date) on 429 / 503 answers.
  • Routing handles the new 503 routing_busy (the API's routing capacity is full for a moment). After a routing_busy or routing_unavailable with Retry-After, map.routing.route() throws that error again, without a request, until the time has passed (the API is not hammered by immediate retries).

Fixed

  • Traffic at z15 and above (above the proxy's z14, zoomLevelsToOverscale) kept showing the first data it loaded, even after a reload or an outage: MapLibre 6.15 caches overzoomed slices by tile id and URL. Traffic tile requests now carry a URL fragment that changes with every refresh. Fragments are never sent, so the proxy and the browser cache see the same request.

0.1.0 — 2026-10-22

First public release (pilot). Requires an Atasu Maps web key from https://atasumaps.com/console, restricted to the origins of your pages.

Added

  • AtasuMap.create() — starts a map session, gets a tile token and only then loads the standard style, so no tile is requested without a token; the token is refreshed before it expires, after the tab sleeps and when the browser comes back online. Several maps per page, destroy and re-create are supported.
  • Labels in Kazakh (default), Russian and English, and day / night / auto, switched without reloading the map (setLanguage, setTheme); language, theme, the drawn route and your own sources and layers survive setStyle.
  • Attribution "© OpenStreetMap contributors · Overture Maps Foundation" on every map, expanded; it cannot be turned off (customAttribution adds to it).
  • map.search — autocomplete (keystrokes share one session token, counted once), search (free text or structured: city, street, house, microdistrict), reverse (with the nearest entrance), place.
  • map.routing.route() — driving / walking routes between coordinates, places or entrances; map.routes.draw() / clear() draw it with the style's route layers; decodePolyline().
  • map.reports — place and entrance submissions, road events and votes, each sent exactly once (Idempotency-Key + offline outbox); needs a signed-in user (userToken). createReports() without a map.
  • Errors: AtasuApiError (status, stable code from the RFC 9457 problem body), AtasuNetworkError, AtasuDestroyedError, isNotAvailable().
  • Credentials go only to Atasu hosts: the key (X-Atasu-Key) to api.atasumaps.com, the tile token (?t=) to tiles.atasumaps.com (exact host, https, default port), but not to its public fonts and sprites (/v1/fonts/…, /v1/sprites/…), so those stay cacheable; server keys are refused in the browser.
  • Local development against your own Atasu stack: apiBaseUrl may be a loopback URL (http://localhost:…, 127.0.0.1, [::1]); the tile token then goes only to the loopback tile host that API names in its map session. dev mode (tiles straight from a local Martin, no key) is unchanged.
  • Types for every request and response, generated from the Atasu OpenAPI 3.1 specification.

Package

  • ESM only, TypeScript declarations included, sideEffects limited to the stylesheet (import '@atasu/maps-gl/maplibre-gl.css').
  • Works with bundlers without configuration: the SDK ships MapLibre's worker (dist/maplibre-gl-worker.mjs) and points MapLibre at it with a static new URL(…, import.meta.url), unless the app already called setWorkerUrl(). (MapLibre 6 alone fails in a bundled app with "Worker failed to load".)
  • Built on MapLibre GL JS 6.15.0 (BSD-3-Clause, notice in NOTICE); third-party licenses in THIRD_PARTY_LICENSES.md. Apache-2.0.

Changes since the internal 0.0.1 preview

  • Breaking: sideEffects was false, which let bundlers drop the stylesheet import; it is now ["*.css"].
  • apiBaseUrl accepts a loopback URL (see above); before, only dev.apiBaseUrl could, without map sessions.
  • sdk_version sent with a map session is 0.1.0.
  • Fixed: a route drawn right after create() (while tiles were still loading) was dropped.