API reference

The complete public surface of @kinesisjs/core: the Tracker class, its options, the data types it consumes and emits, the adapter contract, events, telemetry and errors.

Tracker

The orchestrator. Construct one with an adapter, feed it positions, and start the loop.

class Tracker { constructor(options: TrackerOptions); ingest(positions: Position[]): void; // feed new positions (validated + throttled) start(): void; // start the tick loop; idempotent stop(): void; // pause without teardown destroy(): void; // full teardown + adapter.destroy() on<K extends keyof TrackerEventMap>( event: K, handler: (payload: TrackerEventMap[K]) => void, ): () => void; // returns an unsubscribe fn markCompleted(vehicleId: string): boolean; // end-of-shift; emits 'vehiclecompleted' removeVehicle(vehicleId: string): boolean; // immediate removal getStats(): Readonly<TrackerStats>; // telemetry snapshot }
Worker mode

Construct with worker: true and you transparently get a WorkerTracker with the same surface — the real tracker runs in a Web Worker while the adapter stays on the main thread.

TrackerOptions

adapter is the only required field. Everything else has a production default.

OptionTypeDefaultNotes
adapterTrackAdapterRequired. Your map binding.
interpolationInterpolationMode | 'adaptive' | CustomInterpolator'linear'Curve or strategy.
renderLagMsnumber1000Interpolation buffer; 0 disables (snap).
adaptiveAdaptiveOptionsZone thresholds for adaptive mode.
playoutPlayoutOptions | 'auto'Jitter-absorbing playout buffer.
maxInterpolationGapnumber30000Above this gap, snap instead of interpolate.
warningThresholdnumber60000Idle → warning.
staleThresholdnumber600000Idle → removal.
staleCheckIntervalnumber60000Sweeper cadence.
ingestThrottlenumber100Minimum ms between ingests per vehicle.
initialPositionBehavior'show-immediately' | 'wait-for-second' | 'fade-in''show-immediately'First-point handling.
shortestArcHeadingbooleantrueInterpolate heading the short way around.
fadeAnimationFadeAnimationOptionsFade duration / easing.
workerboolean | { url: string | URL }Run the tick loop off-thread.

Position & TrailPoint

Position is what you send to ingest(). TrailPoint is the internal representation handed to your adapter.

interface Position { id: string; // stable vehicle id lng: number; // WGS84 longitude lat: number; // WGS84 latitude timestamp?: number; // server time (epoch ms); auto-filled if absent speed?: number; // km/h heading?: number; // degrees 0-360 meta?: Record<string, unknown>; // your own metadata (e.g. colour) } interface TrailPoint { lng: number; lat: number; ts: number; // data timestamp receivedAt: number; // when the client received it speed?: number; heading?: number; meta?: Record<string, unknown>; }

TrackAdapter

A map binding is six methods (three optional). Implement it once per map library.

interface TrackAdapter { addVehicle(id: string, initialPoint: TrailPoint): void; updatePosition(id: string, point: TrailPoint): void; removeVehicle(id: string): void; destroy(): void; updateOpacity?(id: string, opacity: number): void; // for fade setVehicleState?(id: string, state: VehicleState): void; // for gap visualisation getMemoryEstimate?(): number; // for getStats() }

Events

Subscribe with tracker.on(name, handler); it returns an unsubscribe function.

EventPayload
tick{ time: number; activeCount: number }
vehicleadded{ vehicleId: string }
vehiclewarning{ vehicleId: string; lastSeen: number }
vehiclestale{ vehicleId: string }
vehiclecompleted{ vehicleId: string }
vehicleremoved{ vehicleId: string }
ingest{ count: number; throttled: number; latency: number }
errorTrackerError
start · stop · destroyvoid
events.tsts
const off = tracker.on('vehiclewarning', ({ vehicleId, lastSeen }) => {
console.warn(vehicleId, 'silent since', new Date(lastSeen));
});

tracker.on('error', (e) => console.warn('[' + e.code + ']', e.message));

// later
off(); // unsubscribe

getStats()

A frozen snapshot of live telemetry — wire it to a dashboard.

interface TrackerStats { vehicleCount: number; totalBufferedPoints: number; fps: number; lastTickDurationMs: number; lastIngestLatencyMs: number; memoryEstimateBytes: number; staleRemovedTotal: number; uptime: number; memoryBreakdown: { slotsBytes: number; eventListenersBytes: number; adapterEstimateBytes: number }; performanceMetrics: { tickHistoryP50: number; tickHistoryP95: number; tickHistoryP99: number; ingestRate: number; droppedTicks: number; droppedTicksLast60s: number; }; }

Errors

Errors never throw out of the tick loop — they surface as error events.

CodeRaised when
INVALID_POSITIONA position fails validation.
ADAPTER_ERRORAn adapter method throws.
INTERPOLATION_ERRORA (custom) interpolator throws.
WORKER_ERRORThe worker channel fails.
INTERNAL_ERRORAnything else; the loop keeps running.

Math utilities

The core also exports a few allocation-light helpers, used by route-aware and custom interpolators.

function haversineDistance(a, b): number; // metres function shortestArcDiff(a: number, b: number): number; // -180..+180 function linearLerp(from, to, ratio, shortestArcHeading?): TrailPoint; function catmullRomLerp(p0, p1, p2, p3, ratio, shortestArcHeading?): TrailPoint; const VERSION: string; // package version