@ingissa/navcore-core 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,279 +1,136 @@
1
- # @ingissa/navcore-core
2
-
3
- > **The navigation layer you own.** A framework-agnostic, zero-dependency navigation engine that runs everywhere — browsers, React Native, Node.js, and CI/CD.
4
-
5
- [![npm version](https://img.shields.io/npm/v/@ingissa/navcore-core)](https://www.npmjs.com/package/@ingissa/navcore-core)
6
- [![License](https://img.shields.io/badge/license-MIT%20%2F%20Commercial-purple)]()
7
- [![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue)](https://www.typescriptlang.org/)
8
- [![Zero deps](https://img.shields.io/badge/runtime_deps-0-brightgreen)](https://www.npmjs.com/package/@ingissa/navcore-core)
9
-
10
- ---
11
-
12
- ## Why NavCore?
13
-
14
- | Feature | NavCore | Mapbox Nav SDK | Google Maps |
15
- |---|---|---|---|
16
- | **Framework** | Any (pure TS) | React Native only | Platform-locked |
17
- | **Runtime deps** | 0 | 50+ | N/A |
18
- | **Map renderer** | BYO (adapter) | Mapbox GL only | Google Maps only |
19
- | **Directions** | BYO (adapter) | Mapbox API only | Google API only |
20
- | **Off-route detection** | Built-in FSM | Basic | Basic |
21
- | **U-turn protection** | ✅ Bearing penalty | ❌ | ❌ |
22
- | **Parallel road resolver** | ✅ Built-in | ❌ | ❌ |
23
- | **Dead reckoning** | ✅ Built-in | ❌ | ❌ |
24
- | **Geofencing** | ✅ Built-in | ❌ | Paid API |
25
- | **ETA** | ✅ Offline | API only | API only |
26
- | **Voice triggers** | ✅ Built-in | SDK only | ❌ |
27
- | **Headless testing** | ✅ Full pipeline | ❌ | ❌ |
28
- | **Custom routes** | ✅ GPX/GeoJSON/Builder | ❌ | ❌ |
29
- | **License** | Core MIT / Pro commercial | Commercial | Commercial |
30
-
31
- ---
32
-
33
- ## Tier Model
34
-
35
- NavCore uses a two-tier model controlled by a signed license key:
36
-
37
- | Tier | Import | License | Includes |
38
- |---|---|---|---|
39
- | **Core** | `@ingissa/navcore-core/core` | MIT — free forever | Geo utils, Kalman filter, route snapping, directions adapters, route builder |
40
- | **Pro** | `@ingissa/navcore-core/pro` | Commercial key required | Dead reckoning, advanced bearing, deviation detection, FSMs, voice, ETA, geofencing |
41
- | **Engine** | `@ingissa/navcore-core` | Gated internally at runtime | Full `NavCore` orchestrator (license key unlocks Pro features) |
42
-
43
- ---
44
-
45
- ## Installation
46
-
47
- ```bash
48
- npm install @ingissa/navcore-core
49
- ```
50
-
51
- ---
52
-
53
- ## Quick Start
54
-
55
- ### Core tier (no license needed)
56
-
57
- ```typescript
58
- import { NavCore } from '@ingissa/navcore-core';
59
- import { OSRMDirectionsProvider } from '@ingissa/navcore-core/core';
60
-
61
- // 1. Get a route from your self-hosted OSRM (free)
62
- const provider = new OSRMDirectionsProvider({ baseUrl: 'http://router.project-osrm.org' });
63
- const route = await provider.getRoute([[2.3522, 48.8566], [2.3400, 48.8700]]);
64
-
65
- // 2. Create engine (Core features work without a key)
66
- const engine = new NavCore();
67
- engine.setRoute(route.geometry);
68
- engine.startNavigation();
69
-
70
- // 3. Feed GPS updates
71
- engine.on('arrival', () => console.log('Arrived!'));
72
-
73
- navigator.geolocation.watchPosition(({ coords }) => {
74
- const state = engine.update({
75
- coord: [coords.longitude, coords.latitude],
76
- accuracy: coords.accuracy,
77
- bearing: coords.heading,
78
- speed: coords.speed ?? 0,
79
- timestamp: Date.now(),
80
- });
81
-
82
- console.log('Distance remaining:', state.distanceToDestination, 'm');
83
- });
84
- ```
85
-
86
- ### Pro tier (with license key)
87
-
88
- ```typescript
89
- import { NavCore } from '@ingissa/navcore-core';
90
-
91
- // Pro features unlock automatically with a valid key
92
- const engine = new NavCore({ licenseKey: 'your-signed-license-key' });
93
- engine.setRoute(routeCoords, instructions);
94
- engine.startNavigation();
95
-
96
- engine.on('instruction', (instr) => speak(instr.text)); // voice cues (PRO)
97
- engine.on('deviation', ({ anchorIndex }) => recalculate(anchorIndex));
98
- engine.on('arrival', () => console.log('Arrived!'));
99
- ```
100
-
101
- ### Using subpath imports directly
102
-
103
- ```typescript
104
- // Free MIT tier
105
- import { KalmanFilter2D } from '@ingissa/navcore-core/core';
106
- import { OSRMDirectionsProvider } from '@ingissa/navcore-core/core';
107
- import { CustomRouteBuilder } from '@ingissa/navcore-core/core';
108
-
109
- // Commercial Pro tier
110
- import { DeadReckoningEngine } from '@ingissa/navcore-core/pro';
111
- import { VoiceTriggerEngine } from '@ingissa/navcore-core/pro';
112
- import { ETAEngine } from '@ingissa/navcore-core/pro';
113
- import { GeofencingEngine } from '@ingissa/navcore-core/pro';
114
- ```
115
-
116
- ---
117
-
118
- ## Directions Providers (built-in, no extra install)
119
-
120
- ```typescript
121
- import {
122
- OSRMDirectionsProvider, // Self-hosted OSRM (recommended, free)
123
- ValhallaDirectionsProvider, // Self-hosted Valhalla (free)
124
- OpenRouteServiceProvider, // openrouteservice.org (free tier)
125
- } from '@ingissa/navcore-core/core';
126
-
127
- // OSRM
128
- const osrm = new OSRMDirectionsProvider({ baseUrl: 'http://router.project-osrm.org' });
129
- const route = await osrm.getRoute([[lng1, lat1], [lng2, lat2]]);
130
-
131
- // Valhalla
132
- const valhalla = new ValhallaDirectionsProvider({ baseUrl: 'https://valhalla1.openstreetmap.de' });
133
- const route = await valhalla.getRoute([[lng1, lat1], [lng2, lat2]], { costing: 'auto' });
134
- ```
135
-
136
- ---
137
-
138
- ## Renderer Adapters (separate packages)
139
-
140
- ```bash
141
- npm install @ingissa/navcore-maplibre # Web + MapLibre GL
142
- npm install @ingissa/navcore-leaflet # Web + Leaflet.js
143
- npm install @ingissa/navcore-google-maps # Google Maps JS API
144
- npm install @ingissa/navcore-mapbox # React Native + @rnmapbox/maps
145
- npm install @ingissa/navcore-react-native # React Native bindings
146
- npm install @ingissa/navcore-headless # Node.js / CI testing
147
- ```
148
-
149
- > ⚠️ Renderer adapter packages require a commercial license. [Get yours at Not yet available]()
150
-
151
- ---
152
-
153
- ## Feature Reference
154
-
155
- ### CORE — free, MIT
156
-
157
- | Feature | API |
158
- |---|---|
159
- | GPS smoothing | `KalmanFilter2D` |
160
- | Route snapping | `RouteSnapper` |
161
- | Haversine & bearing | `haversineDistance`, `getBearingBetweenPoints` |
162
- | Cumulative distances | `buildForwardCumulativeDistances` |
163
- | Route builder | `CustomRouteBuilder` |
164
- | Directions — OSRM | `OSRMDirectionsProvider` |
165
- | Directions — Valhalla | `ValhallaDirectionsProvider` |
166
- | Directions — ORS | `OpenRouteServiceProvider` |
167
- | Renderer interface | `MapRendererAdapter` |
168
- | License verification | `LicenseManager` |
169
-
170
- ### PRO — commercial license required
171
-
172
- | Feature | API | FEATURES key |
173
- |---|---|---|
174
- | Advanced snapping (bearing + inertia) | `RouteSnapper` options | `ADVANCED_SNAPPING` |
175
- | Parallel road resolver | `ParallelRoadResolver` | `PARALLEL_ROAD_RESOLUTION` |
176
- | Dead reckoning | `DeadReckoningEngine` | `DEAD_RECKONING` |
177
- | Compound deviation detection | `DeviationDetector` | `COMPOUND_DEVIATION` |
178
- | Advanced bearing engine | `BearingEngine` | `ADVANCED_BEARING` |
179
- | Progress anti-regression | `ProgressTracker` | `PROGRESS_TRACKING` |
180
- | Route offset predictor | `RouteOffsetPredictor` | `ROUTE_OFFSET` |
181
- | Navigation lifecycle FSM | `NavigationFSM` | — |
182
- | Off-route FSM | `OffRouteFSM` | — |
183
- | Instruction editor | `InstructionEditor` | — |
184
- | Voice trigger engine | `VoiceTriggerEngine` | `VOICE_TRIGGERS` |
185
- | ETA engine (offline) | `ETAEngine` | `ETA` |
186
- | Geofencing engine | `GeofencingEngine` | `GEOFENCING` |
187
-
188
- ---
189
-
190
- ## License Gate Behaviour
191
-
192
- | Condition | Result |
193
- |---|---|
194
- | No `licenseKey` | Core features work; Pro features blocked with `console.warn` |
195
- | Valid Pro key | All features unlocked; `🔑 [NavCore] License validation complete. Plan: pro` logged |
196
- | `isDev: true` | All features bypassed (development mode) |
197
- | Expired / tampered key | Pro features blocked; status: `EXPIRED` / `INVALID` |
198
-
199
- License keys are verified **offline** using ECDSA P-256 — no network calls, no tracking.
200
-
201
- ---
202
-
203
- ## NavCore Engine API
204
-
205
- ```typescript
206
- const engine = new NavCore(options?: NavCoreOptions);
207
-
208
- // Setup
209
- engine.setRoute(coords: Coordinate[], instructions?: NavInstruction[]);
210
- engine.startNavigation();
211
-
212
- // GPS update (returns state snapshot)
213
- const state: NavCoreState = engine.update(gpsUpdate: NavGpsUpdate);
214
-
215
- // Render tick (call at ~60fps between GPS updates)
216
- engine.tick(nowMs: number);
217
-
218
- // Events
219
- engine.on('instruction', (instr: NavInstruction) => void);
220
- engine.on('deviation', ({ anchorIndex, ghostCoord }) => void);
221
- engine.on('arrival', () => void);
222
- engine.on('routeLoaded', ({ routeLength }) => void);
223
- engine.off(event, handler);
224
-
225
- // State & introspection
226
- engine.getState(): NavCoreState;
227
- engine.getLicenseManager(): LicenseManager;
228
- engine.getRoute(): ReadonlyArray<Coordinate>;
229
- engine.destroy();
230
- ```
231
-
232
- ### NavCoreState
233
-
234
- ```typescript
235
- interface NavCoreState {
236
- snappedCoord: Coordinate | null; // GPS-snapped position on route
237
- rawGpsCoord: Coordinate | null; // Raw GPS position
238
- bearing: number; // Smoothed heading (degrees)
239
- routeIndex: number; // Current segment index
240
- distanceToRoute: number; // Distance from route (metres)
241
- corridor: number; // Dynamic off-route threshold (metres)
242
- isOffRoute: boolean; // True when deviation confirmed
243
- hasArrived: boolean;
244
- distanceToDestination: number | null; // Remaining distance (metres)
245
- distanceToNextInstruction: number | null; // Distance to next turn
246
- nextInstructionIndex: number | null;
247
- currentSpeed: number; // m/s
248
- isGpsStale: boolean;
249
- gpsAgeMs: number;
250
- licenseStatus: string; // 'VALID' | 'INVALID' | 'EXPIRED' | 'MISSING'
251
- }
252
- ```
253
-
254
- ---
255
-
256
- ## Documentation
257
-
258
- | Guide | Link |
259
- |---|---|
260
- | Architecture | [docs/architecture.md](./docs/architecture.md) |
261
- | Getting Started | [docs/getting-started.md](./docs/getting-started.md) |
262
- | Directions Providers | [docs/directions-providers.md](./docs/directions-providers.md) |
263
- | Renderer Adapters | [docs/renderer-adapters.md](./docs/renderer-adapters.md) |
264
- | API Reference | [docs/api-reference.md](./docs/api-reference.md) |
265
- | Custom Routes | [docs/custom-routes.md](./docs/custom-routes.md) |
266
- | Instructions & Voice | [docs/instructions.md](./docs/instructions.md) |
267
- | Pro Features | [docs/p3-features.md](./docs/p3-features.md) |
268
- | Testing Guide | [docs/testing.md](./docs/testing.md) |
269
-
270
- ---
271
-
272
- ## License
273
-
274
- - **Core engine** (`@ingissa/navcore-core`): [MIT](./LICENSE) for open-source projects
275
- - **Pro features & adapters**: Commercial license required — [Not yet available]()
276
-
277
- ---
278
-
279
- © Ingissa · [8abnav@gmail.com](mailto:8abnav@gmail.com)
1
+ # @ingissa/navcore-core
2
+
3
+ Framework-agnostic TypeScript navigation engine for browser, React Native,
4
+ Node.js, and CI environments.
5
+
6
+ [![npm version](https://img.shields.io/npm/v/@ingissa/navcore-core)](https://www.npmjs.com/package/@ingissa/navcore-core)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue)](https://www.typescriptlang.org/)
8
+ [![Pricing](https://img.shields.io/badge/licence_key-pricing-green)](https://navcore-web.vercel.app/pricing)
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install @ingissa/navcore-core
14
+ ```
15
+
16
+ ## Quick Start
17
+
18
+ ```typescript
19
+ import { NavCore, OSRMDirectionsProvider } from '@ingissa/navcore-core';
20
+
21
+ const provider = new OSRMDirectionsProvider({
22
+ baseUrl: 'http://router.project-osrm.org',
23
+ });
24
+
25
+ const route = await provider.getRoute([
26
+ [2.3522, 48.8566],
27
+ [2.3400, 48.8700],
28
+ ]);
29
+
30
+ const engine = new NavCore({
31
+ licenseKey: process.env.NAVCORE_LICENSE_KEY,
32
+ });
33
+
34
+ engine.setRoute(route.geometry);
35
+ engine.startNavigation();
36
+
37
+ const state = engine.update({
38
+ coord: [2.3522, 48.8566],
39
+ accuracy: 8,
40
+ bearing: 90,
41
+ speed: 9,
42
+ timestamp: Date.now(),
43
+ });
44
+
45
+ console.log(state.snappedCoord, state.distanceToDestination);
46
+ ```
47
+
48
+ ## What Is Included
49
+
50
+ Core runtime behavior works without a licence key:
51
+
52
+ | Area | APIs |
53
+ |---|---|
54
+ | Geo utilities | `haversineDistance`, `getBearingBetweenPoints`, cumulative distance helpers |
55
+ | GPS smoothing | `KalmanFilter2D` |
56
+ | Route snapping | `RouteSnapper` |
57
+ | Route building | `CustomRouteBuilder` |
58
+ | Directions | `OSRMDirectionsProvider`, `ValhallaDirectionsProvider`, `OpenRouteServiceProvider` |
59
+ | Renderer contract | `MapRendererAdapter` types |
60
+ | Licence status | `LicenseManager` |
61
+
62
+ Pro behavior unlocks with a signed licence key:
63
+
64
+ | Area | APIs |
65
+ |---|---|
66
+ | Advanced route matching | `ParallelRoadResolver`, bearing and inertia scoring |
67
+ | Deviation handling | `DeviationDetector`, `OffRouteFSM`, `NavigationFSM` |
68
+ | Dead reckoning | `DeadReckoningEngine` |
69
+ | Turn guidance | `InstructionEditor`, voice trigger helpers |
70
+ | Driver UX | `ETAEngine`, `GeofencingEngine` |
71
+
72
+ Get a licence key:
73
+
74
+ https://navcore-web.vercel.app/pricing
75
+
76
+ ## Direction Providers
77
+
78
+ ```typescript
79
+ import {
80
+ OSRMDirectionsProvider,
81
+ ValhallaDirectionsProvider,
82
+ OpenRouteServiceProvider,
83
+ } from '@ingissa/navcore-core';
84
+ ```
85
+
86
+ All providers implement:
87
+
88
+ ```typescript
89
+ interface DirectionsProvider {
90
+ getRoute(
91
+ waypoints: Coordinate[],
92
+ options?: DirectionsOptions
93
+ ): Promise<DirectionsResult>;
94
+ }
95
+ ```
96
+
97
+ Provider options include:
98
+
99
+ | Option | Purpose |
100
+ |---|---|
101
+ | `profile` | Driving, cycling, or walking route mode |
102
+ | `steps` | Include maneuver data |
103
+ | `language` | Instruction language when supported |
104
+ | `fetchFn` | Custom fetch implementation for tests or runtimes |
105
+ | `timeoutMs` | Abort slow requests |
106
+
107
+ ## Public Subpaths
108
+
109
+ ```typescript
110
+ // Full engine and all public APIs
111
+ import { NavCore } from '@ingissa/navcore-core';
112
+
113
+ // Core-oriented subpath
114
+ import { RouteSnapper } from '@ingissa/navcore-core/core';
115
+
116
+ // Pro-oriented subpath
117
+ import { DeadReckoningEngine } from '@ingissa/navcore-core/pro';
118
+ ```
119
+
120
+ ## Licence Model
121
+
122
+ `@ingissa/navcore-core` is published publicly on npm and uses a commercial
123
+ licence model.
124
+
125
+ | Condition | Result |
126
+ |---|---|
127
+ | No licence key | Core behavior works with Core fallbacks. |
128
+ | Valid licence key | Pro features unlock according to the signed key. |
129
+ | Expired or invalid key | Pro features are blocked and status is reported. |
130
+ | Development key | Accepted only in local development/test environments. |
131
+
132
+ Pricing and licence keys:
133
+
134
+ https://navcore-web.vercel.app/pricing
135
+
136
+ Copyright Ingissa. All rights reserved.
@@ -151,8 +151,12 @@ declare class OffRouteFSM {
151
151
  /**
152
152
  * Feature flag constants for SDK consumers.
153
153
  *
154
- * CORE features: available to all users (MIT license).
155
- * PRO features: require a valid commercial license key.
154
+ * CORE features: available to all users without a license key.
155
+ * - GPS smoothing, basic snapping, route building, directions providers,
156
+ * progress tracking, and route offset prediction are all free.
157
+ *
158
+ * PRO features: require a valid commercial license key.
159
+ * Each PRO engine checks the license at runtime and gracefully degrades.
156
160
  */
157
161
  declare const FEATURES: {
158
162
  /**
@@ -161,43 +165,45 @@ declare const FEATURES: {
161
165
  */
162
166
  readonly GPS_SMOOTHING: "gps_smoothing";
163
167
  /**
164
- * Basic route snapping (nearest-point projection).
165
- * Snaps GPS position to the closest route segment.
168
+ * Basic route snapping (nearest-point projection) with bearing and inertia
169
+ * penalties to prevent U-turn snaps and oscillation.
170
+ * Both basic and advanced snapping quality are available in the free tier.
166
171
  */
167
172
  readonly BASIC_SNAPPING: "basic_snapping";
168
173
  /**
169
- * Advanced route snapping with bearing penalty + inertia.
170
- * Prevents incorrect snaps on parallel roads and U-turns.
171
- */
172
- readonly ADVANCED_SNAPPING: "advanced_snapping";
173
- /**
174
- * Dead reckoning: continues navigation during GPS signal loss.
175
- * Predicts position based on last known speed and bearing.
174
+ * Progress anti-regression: prevents route index from jumping backward.
175
+ * Essential for circuit routes and motorway slip roads.
176
+ * Used unconditionally inside NavCore — available in the free tier.
176
177
  */
177
- readonly DEAD_RECKONING: "dead_reckoning";
178
+ readonly PROGRESS_TRACKING: "progress_tracking";
178
179
  /**
179
180
  * Smooth route offset predictor for jitter-free map rendering.
180
181
  * Advances render position at frame rate between GPS fixes.
182
+ * Used unconditionally inside NavCore — available in the free tier.
181
183
  */
182
184
  readonly ROUTE_OFFSET: "route_offset";
183
185
  /**
184
- * Progress anti-regression: prevents route index from jumping backward.
185
- * Essential for circuit routes and motorway slip roads.
186
+ * Dead reckoning: continues navigation during GPS signal loss.
187
+ * Predicts position based on last known speed and bearing.
188
+ * DeadReckoningEngine.predict() is a no-op without a Pro license.
186
189
  */
187
- readonly PROGRESS_TRACKING: "progress_tracking";
190
+ readonly DEAD_RECKONING: "dead_reckoning";
188
191
  /**
189
192
  * Advanced bearing engine with look-ahead and speed-adaptive alpha.
190
193
  * Produces stable heading for smooth map camera rotation.
194
+ * Gated inside NavCore.update() via this.has(FEATURES.ADVANCED_BEARING).
191
195
  */
192
196
  readonly ADVANCED_BEARING: "advanced_bearing";
193
197
  /**
194
198
  * Compound deviation detection: combines distance, bearing, and speed signals.
195
199
  * Eliminates false off-route triggers in tunnels and urban canyons.
200
+ * DeviationDetector.evaluate() returns a neutral signal without a Pro license.
196
201
  */
197
202
  readonly COMPOUND_DEVIATION: "compound_deviation";
198
203
  /**
199
204
  * Parallel road disambiguation + U-turn snap protection.
200
205
  * Prevents snapping to the wrong carriageway when bearing mismatches route direction.
206
+ * ParallelRoadResolver falls back to pure distance sorting without a Pro license.
201
207
  */
202
208
  readonly PARALLEL_ROAD_RESOLUTION: "parallel_road_resolution";
203
209
  /**
@@ -207,14 +213,17 @@ declare const FEATURES: {
207
213
  readonly U_TURN_PROTECTION: "u_turn_protection";
208
214
  /**
209
215
  * Timed voice instruction cues with deduplication and priority levels.
216
+ * VoiceTriggerEngine.update() returns null without a Pro license.
210
217
  */
211
218
  readonly VOICE_TRIGGERS: "voice_triggers";
212
219
  /**
213
220
  * Local ETA computation using rolling speed average — zero API calls.
221
+ * ETAEngine.update() returns isReliable=false without a Pro license.
214
222
  */
215
223
  readonly ETA: "eta";
216
224
  /**
217
225
  * Circular and polygon geofencing with enter/exit/dwell events.
226
+ * GeofencingEngine.update() returns [] without a Pro license.
218
227
  */
219
228
  readonly GEOFENCING: "geofencing";
220
229
  /**
@@ -247,9 +256,25 @@ declare class LicenseManager {
247
256
  private payload;
248
257
  private enabledFeatures;
249
258
  private warnedFeatures;
250
- private isDev;
259
+ private static activeManager;
260
+ static getActive(): LicenseManager | null;
261
+ /**
262
+ * Clear the active manager reference.
263
+ * Intended for test teardown only — not for production use.
264
+ */
265
+ static clearActive(): void;
266
+ /**
267
+ * Promote this instance to the global active manager.
268
+ *
269
+ * Security rule: A VALID license context cannot be overwritten by an
270
+ * INVALID / MISSING / EXPIRED one. Once a valid license is registered,
271
+ * it holds the slot until explicitly cleared or replaced by another
272
+ * valid license.
273
+ */
274
+ private promoteToActive;
251
275
  private static PUBLIC_KEY_SPKI;
252
- constructor(licenseKey?: string, isDev?: boolean);
276
+ constructor(licenseKey?: string);
277
+ private tryValidateSync;
253
278
  validate(key: string): Promise<LicenseStatus>;
254
279
  private extractFeatures;
255
280
  hasFeature(feature: FeatureKey): boolean;
@@ -286,7 +311,6 @@ interface NavGpsUpdate {
286
311
  }
287
312
  interface NavCoreOptions {
288
313
  licenseKey?: string;
289
- isDev?: boolean;
290
314
  isCircuit?: boolean;
291
315
  kalmanQ?: number;
292
316
  kalmanRBase?: number;
@@ -347,11 +371,8 @@ declare class NavCore {
347
371
  private readonly options;
348
372
  private listeners;
349
373
  constructor(options?: NavCoreOptions);
350
- /**
351
- * Returns true if the feature is unlocked (dev mode OR valid license).
352
- * Emits a one-time console warning when a Pro feature is blocked.
353
- */
354
- private has;
374
+ /** Internal license check for automatic fallbacks that should not warn Core users every tick. */
375
+ private canUse;
355
376
  /** Load route geometry and instructions */
356
377
  setRoute(route: Coordinate[], instructions?: NavInstruction[]): void;
357
378
  /** Start navigation */