OptionalDEBUGGeoLeaf.DEBUG — debug mode, set by the INTEGRATOR, never by the library.
getDebugMode() reads it at call time, precisely so that setting
window.GeoLeaf.DEBUG = true after boot takes effect without a reload.
⚠️ It was missing from this contract until 19/08/2026, and the gap was invisible from
the inside: nothing here writes it, so no gate that watches what the library MOUNTS
could see it. An integrator following the accessor's own instruction got
TS2339: Property 'DEBUG' does not exist on type 'GeoLeafGlobal' — the top-level
index signature that used to absorb it is gone, deliberately, so a member only
reachable through it became unreachable. A read-only member of the public surface is
declared here or it does not exist for the consumer.
OptionalUIGeoLeaf.UI — the kernel UI facade.
⚠️ Long declared Record<string, unknown>, it was counted among the "typed"
members while verifying nothing: that type accepts any object and yields
unknown on every access, exactly like the tail it was supposed to replace.
HOST-06 (check-namespace-typing-coverage.cjs) found it, by refusing to count
an empty declaration as typing.
⚠️ globals.ui.ts sets _gl.UI = {} when absent: every member of
GeoLeafUIFacade is therefore optional. And its typing canNOT go through
typeof import(...) — the facade is self-mounted, the detail sits on the
interface.
Optional_Optional_Optional_OptionalFilterPublic GeoLeaf.Filter facade — generic attribute filter capability (S5/S13).
Whether the capability is active — mirrors the modules.filter.enabled gate.
The resolved filter configuration for the active profile.
The panel's current selection, as a serialisable { fields } state. A
taxonomy field lists its checked categories and sub-categories in values,
and names each checked sub-category's category in subValues.
Writes a state back onto the panel's controls and applies it to the map, synchronously.
Re-reads the panel and applies it to the map now, without waiting for the auto-apply delay.
Clears every active filter and restores the unfiltered view.
Whether at least one filter is currently narrowing the view.
Proximity (radius-around-a-point) sub-filter.
Sets the proximity radius, in kilometres.
Toggles proximity mode. Returns the resulting state: true once the map is
waiting for the user to place the centre point, false when switched off.
OptionalradiusKm: numberOptionaloptions: { onPointPlaced?: () => void }OptionalConfigOptionaldef: unknownEnriched active profile. Its layers array carries the complete layer
configurations — unlike getAllLayerConfigs(), which is a whitelist
projection and carries neither offline, nor data, nor write.
⚠️ Config.Profile is NOT mounted here, although the Config module
carries it: measured in a browser. Go through getActiveProfile().
Drops the cached themes.json of a profile, so the next theme read goes back
to its source.
Clears one profile when profileId is given, all of them otherwise —
and in both cases the in-flight loading promises too, so a reload started
before the call cannot repopulate the cache behind it.
⚠️ This is the cache of the theme configuration, not the IndexedDB cache of
layer data — that one is GeoLeaf.ThemeCache, a trap homonym.
OptionalprofileId: string
Profile to clear. Omit to clear every profile.
OptionalUtilsOptionalcreateElement?: (Optionalevents?: GeoLeafUtilsEventsOptionalapplyCssText?: (el: HTMLElement, css: string) => voidApplies a CSS declaration string property by property, through the CSSOM.
OptionalvalidateUrl?: (url: string | null | undefined, allowedProtocols?: string[]) => string | nullA URL resolved against the allowed protocols, or null when its protocol is refused.
OptionalgetDistance?: (lat1: number, lng1: number, lat2: number, lng2: number) => numberThe distance between two points, in kilometres.
OptionalFormatters?: {Date and size formatters.
OptionalDOMSecurity?: {The DOM sanitisation helpers — the same object as GeoLeaf.DOMSecurity.
OptionalDOMOptionalSecurityOptionalLegendLegend facade (GeoLeaf.Legend).
⚠️ The 8 members below were implemented and documented in
capabilities/legend/legend.ts — @example included — but not declared
here, hence absent from the GeoLeafGlobal page TypeDoc renders and an
integrator reads, until 11/08/2026. The [key: string]: unknown tail remains —
it only ever shrinks.
Mounts the legend on a map. Returns false when mounting fails.
Optionaloptions: Record<string, unknown>Loads and renders a layer's legend entry, for a given style.
Shows or hides a layer from the legend.
Every layer the legend knows, indexed by identifier.
Hides the panel without unmounting it — layer state is preserved.
Unmounts the panel and releases its listeners.
Whether the panel is currently visible.
Collapses or expands a layer's section.
OptionalTaxonomyTaxonomy capability facade (in-core, gated by modules.taxonomy).
The value → symbol table of a given layer (empty when the layer declares
no taxonomy). Implemented and documented in
capabilities/taxonomy/public-api.ts, but not declared here until
11/08/2026.
Resolves a point's sprite icon, accounting for its category and tint.
Every (icon × tint) pair the config references, so the MapLibre adapter can rasterise and register them. Empty when nothing is tinted.
MapLibre paint of a marker layer, or null when taxonomy does not apply.
The symbolId of the icon to show next to a feature's TITLE on a
feature-info surface, honouring the per-surface render flags
(priority: subcategory → category → default).
A field's badge style, or null when none applies.
Guarantees the active profile's SVG sprite (its <symbol> elements) is in
the DOM, so a <use href="#…"> can reference it. Non-blocking and
idempotent — the loader deduplicates.
Optional_Optional_Optional_GeoLeaf._LayerVisibilityManager — internal, and no longer the only route
to the visibility state.
🔻 The refusal written here on 2026-08 is OVERTURNED on 2026-09-04, and one of its two reasons is why the replacement has the shape it has. It read:
"It would have removed no key" — the core re-reads this manager through
the global at 5 sites, so promoting it could not retire the key. Still
true, and it never was the question. It answers "can we DELETE this?";
what was asked is "does a consumer have a SUPPORTED route?". A published
plugin of this repo — plugin-table — had none, and reached into an
underscore key of the core to get one. The key stays; the reach is gone.
"The shape is a trap, and publishing would engrave it" — getVisibilityState()
returns 6 fields, among them current (PHYSICAL visibility, which zoom
forces to false) and logicalState (the user's intent); reading current
to drive a toggle is a defect that was ALREADY committed once. This one
holds entirely, and it is the reason nothing of this shape was published.
It condemns the FORM, not the need. What went public instead is two NAMED
booleans — Layers.isVisible() for the physical state, Layers.isEnabled()
for the intent — which make the confusion unstateable at the call site
rather than merely warned against. The 6-field object is still not public,
and the irreversibility rule (subpaths are added, never removed) is what
made publishing two accessors rather than one object the only safe move.
De-facto readers outside the core: none. plugin-table moved to
GeoLeaf.Layers.isVisible() on 2026-09-04 (panel.ts, table-layer.ts).
OptionalSyncGeoLeaf.Sync — the offline sync-handler registry seam (S14 Phase B).
A public API of fact (B.25): it is how a data plugin pushes its offline
sync handler into the core (@geoleaf-plugins/editor does
GeoLeaf.Sync.registerHandler("poi", EditorSyncHandler) at its own entry.ts),
and the offline engine reads them back at replay time. It was reachable and
documented but typed NOWHERE — a third-party plugin integrated against
unknown. Mounted twice on purpose: geoleaf.sync.ts self-mounts at import
so a plugin can register before boot completes, and offline/install.ts
re-assigns the same singleton (Layer B).
Register (or replace) a handler under a stable id (e.g. "poi").
The handler registered under id, or undefined.
Registers a step to run BEFORE each outbox drain; null removes it.
A DIFFERENT registry from registerHandler: a handler DRIVES a replay,
a step must FINISH before one. See kernel/shared/drain-hooks-seam.ts.
Registers the reader of the write session, which Storage.preflight() reports;
null removes it. One slot, the last registration wins. The reader tells the
session without renewing it; one that throws, or does not answer within two
seconds, leaves session at null. See kernel/shared/session-reader-seam.ts.
OptionalThemeTheme switch bar — in-core theme-selector capability (see above).
Optional_GeoLeaf._VectorTiles — the MVT policy seam published by the vector-tiles
installer. Internal (underscore), but read through the global by two kernel
modules that each wrote their own narrow VectorTilesLike — and the two were
DISJOINT (loader-types.ts declares shouldUseVectorTiles /
loadVectorTileLayer, layer-manager/style.ts declares updateLayerStyle),
so neither described the seam. Typed here as the capability's own export, the
only shape that covers both (B.25).
Determines if a layer definition should use vector tiles. Returns true only when the VT config provides an absolute tile URL. Relative paths (auto-generated from profile structure) are not used because PBF files may not exist — the layer falls back to GeoJSON.
Extracts the vectorTiles config block from a layer definition.
Supports both def.vectorTiles and def.data.vectorTiles.
Resolves the full tile URL template from the layer definition.
⚠️ The tilesDirectory fallback below is UNREACHABLE from the production flow,
and deliberately so. _createVectorTileLayer only calls this after
shouldUseVectorTiles() has returned true, and that guard requires an ABSOLUTE
tilesUrl — so by the time we get here, the first branch always wins. The
derived …/{z}/{x}/{y}.pbf path is therefore dead code in practice.
It is kept, not purged. Two reasons: it is covered by
13 assertions across __tests__/geojson/vector-tiles.test.js and
__tests__/config/s13-layer-data.test.js, several of them asserting the derived
path specifically; and it becomes live again the moment the absolute-URL guard is
relaxed, which is what "arming" a profile's vector tiles would mean. Removing it
would delete tested behaviour to fix a promise that was really a data problem —
the six tourism layers that declared enabled:true without a tilesUrl have
been disarmed in the profiles instead.
Creates a vector tile layer by delegating to the adapter, then binds
interactions, records shared state and arms the labels the layer declares.
The adapter builds one vector source and up to 3 render layers
(fill/line/circle) from the resolved spec.
Unique layer ID.
Display label.
Normalised layer definition (must include vectorTiles block).
Base options (unused in MapLibre mode).
Layer metadata.
Updates the style of an existing VT layer via the adapter.
Optional_GeoLeaf._Cluster — the bag of PURE resolvers the cluster installer
publishes for the GeoJSON loader. Same mechanism as _VectorTiles just above,
and the same motive: a build that leaves the capability out has no writer,
the loader falls back to { shouldCluster: false }, and the core imports
nothing statically.
⚠️ This is NOT the whole module: the installer writes only two members
(install.ts). Typing them via typeof import(...) keeps them tied to the
SOURCE — a signature hand-copied here would drift with nothing saying so, which
is exactly the defect _VectorTiles documents for its two disjoint local
views.
📌 The reader's local view, ClusterResolversLike (loader/loader-types.ts),
widens def/geojsonData to unknown and COPIES the return shape. It agrees
with the source as of 20/10/2026 — ClusterStrategyResult is indeed
{ shouldCluster } — but nothing holds it there: the
local-views guard compares NAMES, not SHAPES, and says so.
OptionalIntrospectionOptionalCapabilitiesCapability-unavailable bus — declareUnavailable / onUnavailable.
OptionalLayersOptionalGeolocationIn-core geolocation capability seam (GPS state + config helpers).
OptionalBrandingBranding overlay (logo, attribution) — GeoLeaf.Branding.
OptionalClusterPOI clustering controls — GeoLeaf.Cluster.
OptionalCoordinatesCoordinate readout control — GeoLeaf.Coordinates.
OptionalFeatureFeature detail panel — GeoLeaf.FeatureInfo. Type declared in types.ts.
OptionalLabelsMap labels toggle + renderer — GeoLeaf.Labels.
OptionalNotificationToast/notification CLASS mounted by the toast-renderer installer.
OptionalPWAPWA install/update manager — GeoLeaf.PWA. No named public type, see above.
Initializes the PWA install prompt for the current platform.
config.installPrompt.enabled === true.beforeinstallprompt and shows a custom banner.Call this method after the GeoLeaf config has been loaded (i.e. from app/boot.ts).
PWA section from the loaded geoleaf.config.json.
true when the app can still be installed on this device — for integrators who
want to render their own install button instead of (or alongside) the built-in
banner.
Mirrors the platform split of PWAManager.init:
beforeinstallprompt; answers from the UA +
navigator.standalone check (installable = iOS and not already installed).true once the browser has handed us a
deferred beforeinstallprompt event.⚠️ On Android this reports "a prompt is available", not "the browser could
install this app": the deferred event is only captured if PWAManager.init
has run, which is gated on modules.pwa.installPrompt.enabled === true. With the
prompt disabled, it answers false even on an installable Chrome. iOS is
unaffected — its check needs no listener.
true if an install path is available right now.
true when a newer version of the application is installed and this page has not
been reloaded onto it.
A new service worker no longer takes a page that is in use: it waits, and
geoleaf:sw:update-waiting says so. This reads the same fact at any time — a
listener set after the boot may have missed the event. It also answers true when
the update was applied from another tab: the worker changed under this page, which
still runs the previous version's code.
Always false at a first install, when modules.pwa.enabled is not true, and
before the service worker has been registered (it is registered at idle, up to three
seconds after the boot).
true if PWAManager.applyUpdate has something to apply.
Applies the waiting update: the new service worker takes over, and the page reloads once it does.
Call it from a user gesture — unsaved input in the page is lost with the reload. Captures already queued by the offline write cycle are not: they live in IndexedDB. The reload is not instantaneous: the browser lets the new worker take over once the previous one has finished the requests it is serving, and the page reloads then — once.
⚠️ Without this call the new version stays installed and unused until every tab of the application is closed. The offline plugin calls it from its « Reload » banner; an application that does not embed that plugin has to offer the gesture itself.
true when an update is being applied — the page will reload; false
when nothing was waiting, and nothing happens.
Registry destroy / test seam: tears down both install sub-flows (the Android install-prompt global listeners and the iOS banner timer/banner) so a re-init starts clean (no listener / timer leak).
OptionalPermalinkURL state serialisation — GeoLeaf.Permalink. No named public type.
Initialise the Permalink module with the config extracted from the active profile.
Must be called before readAndStore().
The profile's modules.permalink block, or an empty object.
Read the current URL and cache the parsed state.
Call this before map creation so the stored state is available for applyStoredState.
Apply the stored state (from readAndStore) to the given map instance.
Must be called after the map and all modules are initialised.
MapLibre map adapter instance.
Begin continuous URL synchronisation on map move/zoom events.
Call this after applyStoredState to avoid overwriting the restored state.
MapLibre map adapter instance.
Stop URL synchronisation started by Permalink.startSync, removing every
listener it attached (map moveend + the three document listeners). Safe to call
when no sync is active.
Return the currently cached permalink state (read-only).
Returns null if readAndStore was not called or found no permalink in the URL.
⚠️ A null therefore means two different things — the page was not opened through a
permalink, or Permalink.readAndStore has not run yet. Only the boot order tells
them apart.
Serialise state (or the cached stored state) to a URL fragment / query string.
Optionalstate: PermalinkState | null
Optional explicit state. Falls back to _storedState.
URL string starting with # or ?, or empty string if no state.
Returns true when permalink is enabled (modules.permalink.enabled !== false).
Returns the resolved modules.permalink config (merged over the built-in defaults).
OptionalScaleScale bar control — GeoLeaf.Scale.
OptionalProfileData-profile selector — GeoLeaf.ProfileSwitcher.
OptionalLanguageUI language selector — GeoLeaf.LanguageSwitcher.
OptionalThemeAccent-colour palette — GeoLeaf.ThemePalette.
OptionalShareShare sheet — GeoLeaf.Share, subdirectory of the permalink capability.
OptionalThemeLight/dark toggle — GeoLeaf.ThemeToggle.
OptionalBaselayersBase layer catalogue façade.
OptionalBaseHistorical alias of GeoLeafGlobal.Baselayers — same reference, same type.
OptionalEventsTyped event bus façade (on/off/once/dispatch).
Registers a listener for a GeoLeaf event.
The listener is called every time the event fires until it is removed — by the
function this call returns, or by off() with the same handler.
Event name (see module docs for full reference).
Callback receiving the CustomEvent with typed detail.
A function that removes this listener. It is off(event, handler) bound to
this subscription: calling it twice is harmless, and since the DOM registers one
listener per handler reference, it also removes an identical earlier on(). Without a
document (SSR), nothing is registered and the function does nothing.
Removes a previously registered listener.
The exact same handler reference must be passed.
Event name.
The handler reference originally passed to on().
// With off(), the handler must be NAMED — an anonymous one is removed through the
// function on() returns.
const handlePoiPanel = (e) => {
console.log(e.detail.poiId);
};
GeoLeaf.Events.on("geoleaf:poi:panel:open", handlePoiPanel);
// Plus tard :
GeoLeaf.Events.off("geoleaf:poi:panel:open", handlePoiPanel);
Registers a listener that fires once then automatically removes itself.
Uses the native {once: true} option — no wrapper function needed.
Event name.
Callback called at most once.
A function that cancels the listener if it has not fired yet — the teardown of
a component unmounted before the event arrives. Calling it after the listener fired is
harmless. Without a document (SSR), the function does nothing.
OptionaleventsLowercase alias of GeoLeafGlobal.Events — same reference, same type.
Registers a listener for a GeoLeaf event.
The listener is called every time the event fires until it is removed — by the
function this call returns, or by off() with the same handler.
Event name (see module docs for full reference).
Callback receiving the CustomEvent with typed detail.
A function that removes this listener. It is off(event, handler) bound to
this subscription: calling it twice is harmless, and since the DOM registers one
listener per handler reference, it also removes an identical earlier on(). Without a
document (SSR), nothing is registered and the function does nothing.
Removes a previously registered listener.
The exact same handler reference must be passed.
Event name.
The handler reference originally passed to on().
// With off(), the handler must be NAMED — an anonymous one is removed through the
// function on() returns.
const handlePoiPanel = (e) => {
console.log(e.detail.poiId);
};
GeoLeaf.Events.on("geoleaf:poi:panel:open", handlePoiPanel);
// Plus tard :
GeoLeaf.Events.off("geoleaf:poi:panel:open", handlePoiPanel);
Registers a listener that fires once then automatically removes itself.
Uses the native {once: true} option — no wrapper function needed.
Event name.
Callback called at most once.
A function that cancels the listener if it has not fired yet — the teardown of
a component unmounted before the event arrives. Calling it after the listener fired is
harmless. Without a document (SSR), the function does nothing.
OptionalCONSTANTSFrozen runtime constants — set by globals.core.ts.
OptionalErrorsError helpers — set by globals.core.ts.
The machine-readable code carried by each error subclass, frozen.
Keys are the short family names; values are the strings that land on error.code. Compare
against these rather than against literals, so a rename stays a compile-time concern.
GeoLeaf.Errors.ErrorCodes.VALIDATION; // 'VALIDATION_ERROR'
GeoLeaf.Errors.ErrorCodes.SECURITY; // 'SECURITY_ERROR'
GeoLeaf.Errors.ErrorCodes.CONFIG; // 'CONFIG_ERROR'
GeoLeaf.Errors.ErrorCodes.NETWORK; // 'NETWORK_ERROR'
GeoLeaf.Errors.ErrorCodes.INITIALIZATION; // 'INITIALIZATION_ERROR'
GeoLeaf.Errors.ErrorCodes.MAP; // 'MAP_ERROR'
GeoLeaf.Errors.ErrorCodes.DATA; // 'DATA_ERROR'
GeoLeaf.Errors.ErrorCodes.POI; // 'POI_ERROR'
GeoLeaf.Errors.ErrorCodes.ROUTE; // 'ROUTE_ERROR'
GeoLeaf.Errors.ErrorCodes.UI; // 'UI_ERROR'
OptionalHelpersGeneral-purpose helpers façade.
OptionalLayerLayer manager façade (visibility, ordering, legend wiring).
Mounts the layer-manager panel.
Called without arguments, everything comes from the profile configuration — the recommended path. Anything passed here overrides that, field by field.
Position, title, and collapsible/collapsed state.
Registers a GeoJSON layer into its LayerManager section.
Not the legend capability: this fills the COUCHES panel (.gl-layer-manager),
not .gl-map-legend. The section named by layerManagerId is created on the fly
when unknown, with a generic label and no accordion flag — those placeholder
values are meant to be overwritten by _applyLayerManagerConfig, which
runs later (at init()), since registration happens first.
The layer id
Layer options
Redraws the panel to match the current layer state.
Debounced by default, so a burst of layer changes costs one redraw. Passing immediate
cancels any pending debounce and redraws synchronously — needed when the caller is
about to read the rendered DOM.
A no-op, logged at debug, when the control is not yet mounted (early boot).
Skip the debounce and redraw now. Defaults to false.
Resets the module back to its post-import state.
Run on map teardown so the control, the map handle and the accumulated sections do not survive a destroy → recreate cycle. A pending debounced refresh is cancelled too: its callback closes over the old control and would fire against a detached DOM node.
Idempotent — safe to call more than once.
OptionalThemeTheme cache — set by globals.ui.ts, outside the facade chain.
Retrieves a layer from the cache si elle est encore valide.
OptionalprofileId: string | nullStocke a layer in the cache.
OptionalprofileId: string | nullOptionalmetadata: Record<string, unknown> = {}Invalid a layer en cache.
OptionalValidatorsStyle/config validators façade.
OptionalversionPackage version string.
✅ A single writer: globals/globals.api.ts, under an if (!_gl.version)
guard — which makes setupAPIKernel() re-callable without overwriting an
already-set version.
⚠️ This note used to say "Written in TWO places: globals.api.ts […] and
kernel/api/geoleaf-api.ts unguarded. Last writer wins" — that was true,
and both line numbers had drifted (208 and 164 by the time of removal). A
line citation in a comment ages silently; this one now points only at the
file.
OptionalAPIGeoLeaf.API — the API constructors, assembled as a literal by
globals.api.ts.
⚠️ Hand-written, and that is measured: contracts/api.contract.ts does
declare IGeoLeafAPIConstructors, but it covers only the 3 aliases, not
the 7 keys actually set. Referencing it would have typed under half the object
while looking like it typed it — the defect HOST-06 hunts, one level up.
Optionalinit{@inheritDoc GeoLeafTopLevelApi.init}
Optionalset{@inheritDoc GeoLeafTopLevelApi.setTheme}
Optionalload{@inheritDoc GeoLeafTopLevelApi.loadConfig}
Optionalcreate{@inheritDoc GeoLeafTopLevelApi.createMap}
Optionalget{@inheritDoc GeoLeafTopLevelApi.getMap}
Optionalget{@inheritDoc GeoLeafTopLevelApi.getAllMaps}
Optionalget{@inheritDoc GeoLeafTopLevelApi.getModule}
Optionalhas{@inheritDoc GeoLeafTopLevelApi.hasModule}
Optionalget{@inheritDoc GeoLeafTopLevelApi.getNamespace}
Optionalget{@inheritDoc GeoLeafTopLevelApi.getHealth}
Optionalget{@inheritDoc GeoLeafTopLevelApi.getMetrics}
OptionalfetchFetchHelper.fetch, bound — instrumented HTTP request.
OptionalgetFetchHelper.get, bound.
OptionalpostFetchHelper.post, bound.
OptionalbootBoot report (⚠️ lowercase on the namespace side, BootInfo on the module side).
OptionalbootStarts the GeoLeaf application: loads the profile, creates the map, initialises
the modules. This is the application entry — apps/geoleaf-app/init.js calls
it, and the load order of every plugin refers to it.
⚠️ Not to be confused with GeoLeafGlobal.init, the manual wrapper
around Core.init(). The boot path goes through registry.init() — the
ModuleRegistry's — and never calls GeoLeaf.init.
The two options are the only channel through which a host sets an auth gate
(SSO) or retrieves the startup metrics; they are re-read from
_beforeBootCallback and _perfCallback. Those two stay out of this contract:
they are service-locator keys, _-prefixed because they are internal to the
core and no integrator has to write them — they are the channel, not the
rendezvous.
OptionalmountMounts the application in a map container and returns the handle that unmounts it —
the lifecycle a host that mounts and unmounts views can run again. Boots as
GeoLeafGlobal.boot does, with the same options; unmount() takes the whole
application down, and the next mount() gives it back whole. One application per
page: a mount() while one is alive unmounts it first.
OptionalmarkSets a named performance mark.
OptionalmeasureMeasures between two marks; returns the duration in milliseconds.
OptionalgetAggregated performance report from the profiler.
OptionalestablishFreezes the current measurement as the comparison reference.
OptionalnotifyUser notification — primitive, renderer-independent.
Emits a user-facing notification.
Text to display.
Optionallevel: NotifyLevel
Severity level (default: "info").
OptionalCoreCore map façade (GeoLeaf.Core) — low-level map lifecycle.
Since v3.0.0, Core holds an indexed registry of adapters
(Map<mapId, IMapAdapter>): N maps coexist on one page, each with its own
lifecycle. The module singleton of versions ≤ 2.1.x no longer exists.
⚠️ The [key: string]: unknown tail remains: the 8 members below are now
declared and documented, the rest of the namespace is not yet. Never widen it
back to any.
Initialises a map. Requires options.mapId — without it, returns
null and logs. Re-initialising an existing mapId returns the instance
already in place rather than creating a second one.
Optionaloptions: Record<string, unknown>The instance targeted by mapId; with no argument, the first active
instance — the backward-compatible form for single-map applications.
OptionalmapId: stringDestroys the instance (map.remove() then frees the registry slot).
Returns true when it existed. Call it at unmount on the consumer side.
Whether an instance is registered under this mapId.
The identifiers of every active instance.
Whether an instance is registered and its container is still in the
document. Stronger than hasMap, which only answers for the
registration: a host that removes the subtree without calling destroy()
leaves a registered map that renders nowhere. Returns false after
destroy().
Moves a live map into another parent, without destroying or rebuilding it.
The ENTIRE container is re-parented — MapLibre remembers its construction
element, so moving its children would leave getContainer() pointing at
the old node.
⚠️ The shell does not follow: the side panel and the mobile pill live
in glMain, not in the map container. Remounting them is the host's job,
and it is two recipes — UI.destroyDesktopPanel() → initDesktopPanel() →
activateDesktopPanel() for the panel, UI.destroyMobileToolbar() →
initMobileToolbar() for the pill. 🛑 Run either destroy BEFORE dropping
the old shell: both give back nodes they had moved, and only to a parent
that still exists.
Applies a theme to the map container.
⚠️ The theme stays global in v3.0.0 and applies to the first instance: per-map isolation is out of this version's scope.
The current theme's name.
OptionalpluginsPlugin registry / lifecycle façade (GeoLeaf.plugins).
⚠️ getLoadedPlugins, canActivate and registerLazy were added on
31/07/2026, and not for typing comfort. All three have long been taught by
docs/API_REFERENCE.md ("Plugins" section), exist in
kernel/api/plugin-registry.ts and ship in the delivered bundle — but were
declared nowhere here, so they fell into the [key: string]: unknown tail.
What that cost, measured: showBootInfo(GeoLeaf) — the call its own doc shows
— did not compile. BootInfoNamespace requires
plugins?.getLoadedPlugins?: () => string[]; resolved through the tail the
member was unknown, and unknown is not assignable to
(() => string[]) | undefined. The defect was visible to no gate as long as
the showBootInfo example was written showBootInfo() — that is, as long as
it was wrong in ANOTHER way, frozen in the typecheck baseline. A frozen
diagnostic masks what lives under it.
Shrinking the tail is the only allowed direction: never widen back to any.
Optionalmeta: Record<string, unknown>OptionalregisterLazyForAction?: (action: string, pluginName: string, ui?: PluginLazyUI) => voidDeclares the toolbar slot of a plugin loaded on demand — its button exists before its bundle does, and the first press loads the plugin. Call it before the boot.
OptionalregistryModule registry (GeoLeaf.registry) — lifecycle modules AND UI-only slots.
Typed as the contract itself rather than as a structural { register?; [key]: unknown }:
ModuleRegistry is a CLASS, and TypeScript does not give classes an implicit index
signature, so the loose shape rejected the very object boot-install.ts assigns.
OptionalI18nInternationalization façade (GeoLeaf.I18n).
OptionalStorageOffline storage façade (GeoLeaf.Storage), mounted in-core by kernel/storage/facade.ts.
⚠️ The [key: string]: unknown tail makes any member not named here unknown
— hence not callable — and no gate flags it: HOST-06 only rejects a fully
empty declaration. A member that is a public API gets named.
OptionalDB?: GeoLeafStorageDBThe IndexedDB engine. Its relays are named by GeoLeafStorageDB; what is not
named there stays in ITS OWN tail — the namespace's tail is gone, this one is not.
Optionaldb?: GeoLeafStorageDBLower-case alias of DB — the same engine.
OptionalwhenReady?: () => Promise<void>Resolves when the offline engine is ready; never while modules.offline is off.
OptionalmayEdit?: (layerId: string, kind: "delete" | "create" | "update") => booleanDoes the layer grant this operation? Synchronous, read from the active profile;
an unknown layer yields false.
OptionalcanQueueWrites?: (layerId: string) => booleanWill a write to this layer be held on the device? false without the engine.
OptionalapplyEdit?: (Records a capture on the device and queues it for the server — possibly merged
into, or cancelling, an entry already owed for that entity. Never throws:
refused carries the motive.
OptionalpushOutbox?: () => Promise<StoragePushReport>Runs a drain pass — or joins the one in progress — and returns its tally. Never throws.
OptionalrequeueQuarantined?: (id: string) => Promise<StorageQuarantineOutcome>Puts one set-aside entry back in the queue, if its motive is requeueable and, where that is checkable, its cause is observed as lifted.
OptionalrequeueAll?: (reason?: string) => Promise<StorageBatchRequeueOutcome>Same rule, for every set-aside entry — or for those of one motive only.
OptionaldiscardQuarantined?: (id: string, confirmedLocalId: string) => Promise<StorageQuarantineOutcome>Destroys one set-aside entry, confirmed by the localId the caller listed.
OptionalrequeueableReasons?: () => readonly string[]The set-aside motives a requeue can lift.
OptionallistConflicts?: (The server versions a lastWriteWins conflict overwrote, one per entity.
OptionalclearConflicts?: (layerId?: string, scope?: { allProfiles?: boolean }) => Promise<boolean>Drops the archived conflicts of one layer, or of all.
Bounded pull of a declared layer into the features store.
Never confers editability (a standing invariant). Does not throw:
refused carries the motive when nothing was written.
Optionaloptions: { bbox?: [number, number, number, number]; signal?: AbortSignal }Per-layer synchronisation report.
Makes declaredNeverPulled observable: a layer declaring a pull source
(offline.source) but never pulled is otherwise indistinguishable from a pulled
one, until the instant the network drops. Does not throw — with no engine wired,
returns [].
The write queue as a whole — network, entries owed, entries set aside, and the last accepted push.
Distinct from getSyncReport above, which answers per layer. This one
answers the question a field user asks before closing the application, and
that question has no layer in it. Does not throw — with no engine wired, it
answers zeros, which is what "there is no queue here" looks like.
The choices of a dropdown declared by URL — held on the device first, fetched
and kept otherwise. null when nothing can answer: the caller fetches itself.
"Can I leave?" — persistence regime, quota, per-layer report, queue and last
preparation in one read, with a verdict. null when the engine is not wired.
OptionalprefetchVerdict?: (url: string) => StoragePrefetchVerdictWill the offline preparation download this URL, and if not, why — the origin rule
of modules.offline.dataOrigins, asked before the download.
OptionalwireModules?: (Injects the offline engine's modules — called by the engine itself when it loads.
Optionalinit?: (options?: StorageInitOptions) => Promise<boolean>Initialises the wired sub-modules; resolves false when nothing is wired.
OptionalisAvailable?: () => booleanWhether the offline engine is wired and its database usable.
OptionalisPluginLoaded?: () => booleanWhether the offline engine's modules have been injected.
OptionalisOffline?: () => booleanWhether the network detector currently says offline.
OptionalgetStats?: () => Promise<Quota, usage and the tallies of the data-bearing stores.
OptionalgetOfflineProfiles?: () => Promise<string[]>The profiles prepared for offline use on this device.
OptionalisProfileAvailableOffline?: (profileId: string) => Promise<boolean>Whether one profile was prepared for offline use.
OptionalclearAll?: () => Promise<void>Erases every prepared profile, the cached tiles and the engine's own stores.
Optionalclose?: () => voidCloses the database handle.
OptionalCacheManager?: CacheManagerLikeThe cache manager, when the engine is wired — the façade's narrow view of it.
OptionalcacheManager?: CacheManagerLikeLower-case alias of CacheManager.
OptionalOfflineDetector?: OfflineDetectorLikeThe network detector, when the engine is wired — the façade's narrow view of it.
OptionalCache?: unknownThe cache namespace of the engine. Untyped: the façade hands it over as unknown.
Optionalcache?: unknownLower-case alias of Cache.
OptionalGeoGeoJSON subsystem façade (GeoLeaf.GeoJSON) — 87 call sites across the plugins,
the single most-used member of the host, and typed nowhere before S3.
⚠️ Distinct from Layers above: Layers is the per-layer data seam.
Sets the URL of the GeoJSON Web Worker script — null restores the default. For a
bundle run as a module, that is geojson-worker.js in the directory of the last
<script src> of the page naming a geoleaf…js file (a plugin's included), or
resolved against the page when none does (a bundle imported from an inline module
script, with no plugin loaded by <script src>). Applies to the
next worker built; call it before GeoLeaf.boot() to cover the first one. Throws a
TypeError on any value other than a non-blank string or null.
OptionalLogLogger façade (GeoLeaf.Log).
Same reason as registry above — LogImplInterface is an interface, so it carries
no implicit index signature and a loose { error?; …; [key]: unknown } shape would
reject what globals.core.ts actually mounts.
OptionalNotificationsToast façade (GeoLeaf.Notifications), mounted by the toast-renderer capability.
OptionalTable@geoleaf-plugins/table — tabular panel.
OptionalGeocoding@geoleaf-plugins/geocoding — address search.
OptionalRealtime@geoleaf-plugins/realtime-layer — realtime feeds (GTFS-RT…).
OptionalPosition@geoleaf-plugins/position-share — user position broadcasting.
OptionalRouting@geoleaf-plugins/routing — multi-stop route computation.
OptionalNavigation@geoleaf-plugins/navigation — realtime guidance.
⚠️ Two packages and not one: computation has value alone, guidance has none
without it. The dependency is asymmetric, so the boundary sits there — and
navigation imports only TYPES from routing.
OptionalIsochrone@geoleaf-plugins/isochrone — zones reachable from a point, asked of a routing engine.
OptionalFlat@geoleaf-plugins/flatgeobuf — FlatGeobuf reads by bbox.
OptionalConnector@geoleaf-plugins/connector — bridge to the Connector backend.
OptionalCOG@geoleaf-plugins/cog — Cloud Optimized GeoTIFF.
OptionalFile@geoleaf-plugins/file-import — GPX/KML/KMZ/CSV/TSV/TopoJSON conversion.
OptionalMeasure@geoleaf-plugins/measure — measuring tools.
⚠️ Not to be confused with lowercase measure, higher in this same
interface: that one is the performance-measuring helper between two marks. The
two differ only by case. The compiler is in fact what flagged it — the
declaration probe yielded TS2551 "Did you mean 'measure'?" on this name.
OptionalPrint@geoleaf-plugins/print — printable map export.
OptionalEditor@geoleaf-plugins/editor — feature editing.
OptionalWs@geoleaf-plugins/websocket — WebSocket feeds (mounted as Ws, not Websocket).
OptionalgetRuntime metrics (historical alias of getRuntimeMetrics).
OptionalgetRuntime metrics — init time, memory, rendering.
OptionalresetResets the metric counters to zero.
Canonical shape of the global
GeoLeafnamespace. All members are optional (assembled at boot) and tolerate extra keys.