@faclon-labs/app-sdk 0.1.0 → 0.3.0
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 +39 -1
- package/dist/IOSenseApp.js +26 -6
- package/dist/SignIn.js +2 -2
- package/dist/auth.d.ts +7 -0
- package/dist/auth.js +35 -1
- package/dist/config.d.ts +5 -0
- package/dist/config.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/map/globe.d.ts +5 -0
- package/dist/map/globe.js +5 -0
- package/dist/map/index.d.ts +21 -0
- package/dist/map/index.js +21 -0
- package/dist/map/source.d.ts +48 -0
- package/dist/map/source.js +73 -0
- package/dist/map/testing.d.ts +5 -0
- package/dist/map/testing.js +5 -0
- package/dist/session.d.ts +1 -1
- package/dist/session.js +1 -1
- package/package.json +55 -5
- package/vendor/SOURCE.txt +1 -0
- package/vendor/map-engine/cesium/camera.d.ts +10 -0
- package/vendor/map-engine/cesium/camera.js +25 -0
- package/vendor/map-engine/cesium/index.d.ts +2 -0
- package/vendor/map-engine/cesium/index.js +2 -0
- package/vendor/map-engine/cesium/renderer.d.ts +149 -0
- package/vendor/map-engine/cesium/renderer.js +837 -0
- package/vendor/map-engine/commands/index.d.ts +2 -0
- package/vendor/map-engine/commands/index.js +2 -0
- package/vendor/map-engine/commands/post-message.d.ts +32 -0
- package/vendor/map-engine/commands/post-message.js +77 -0
- package/vendor/map-engine/commands/webmcp.d.ts +17 -0
- package/vendor/map-engine/commands/webmcp.js +59 -0
- package/vendor/map-engine/core/commands.d.ts +82 -0
- package/vendor/map-engine/core/commands.js +46 -0
- package/vendor/map-engine/core/emitter.d.ts +9 -0
- package/vendor/map-engine/core/emitter.js +38 -0
- package/vendor/map-engine/core/equal.d.ts +2 -0
- package/vendor/map-engine/core/equal.js +28 -0
- package/vendor/map-engine/core/errors.d.ts +20 -0
- package/vendor/map-engine/core/errors.js +34 -0
- package/vendor/map-engine/core/geometry-family.d.ts +3 -0
- package/vendor/map-engine/core/geometry-family.js +13 -0
- package/vendor/map-engine/core/index.d.ts +4 -0
- package/vendor/map-engine/core/index.js +3 -0
- package/vendor/map-engine/core/types.d.ts +709 -0
- package/vendor/map-engine/core/types.js +7 -0
- package/vendor/map-engine/data/annotations.d.ts +3 -0
- package/vendor/map-engine/data/annotations.js +63 -0
- package/vendor/map-engine/data/contracts.d.ts +172 -0
- package/vendor/map-engine/data/contracts.js +12 -0
- package/vendor/map-engine/data/index.d.ts +4 -0
- package/vendor/map-engine/data/index.js +3 -0
- package/vendor/map-engine/data/schema.d.ts +7 -0
- package/vendor/map-engine/data/schema.js +40 -0
- package/vendor/map-engine/geofence/evaluator.d.ts +35 -0
- package/vendor/map-engine/geofence/evaluator.js +172 -0
- package/vendor/map-engine/geofence/history.d.ts +9 -0
- package/vendor/map-engine/geofence/history.js +19 -0
- package/vendor/map-engine/geofence/index.d.ts +2 -0
- package/vendor/map-engine/geofence/index.js +2 -0
- package/vendor/map-engine/index.d.ts +27 -0
- package/vendor/map-engine/index.js +14 -0
- package/vendor/map-engine/layers/index.d.ts +1 -0
- package/vendor/map-engine/layers/index.js +1 -0
- package/vendor/map-engine/layers/layers.d.ts +49 -0
- package/vendor/map-engine/layers/layers.js +316 -0
- package/vendor/map-engine/maplibre/deck-host.d.ts +105 -0
- package/vendor/map-engine/maplibre/deck-host.js +401 -0
- package/vendor/map-engine/maplibre/icons.d.ts +17 -0
- package/vendor/map-engine/maplibre/icons.js +65 -0
- package/vendor/map-engine/maplibre/index.d.ts +3 -0
- package/vendor/map-engine/maplibre/index.js +2 -0
- package/vendor/map-engine/maplibre/map-like.d.ts +56 -0
- package/vendor/map-engine/maplibre/map-like.js +1 -0
- package/vendor/map-engine/maplibre/renderer.d.ts +173 -0
- package/vendor/map-engine/maplibre/renderer.js +889 -0
- package/vendor/map-engine/maplibre/style.d.ts +84 -0
- package/vendor/map-engine/maplibre/style.js +493 -0
- package/vendor/map-engine/present/decorations.d.ts +25 -0
- package/vendor/map-engine/present/decorations.js +115 -0
- package/vendor/map-engine/present/index.d.ts +2 -0
- package/vendor/map-engine/present/index.js +2 -0
- package/vendor/map-engine/present/present.d.ts +47 -0
- package/vendor/map-engine/present/present.js +149 -0
- package/vendor/map-engine/query/index.d.ts +1 -0
- package/vendor/map-engine/query/index.js +1 -0
- package/vendor/map-engine/query/planner.d.ts +26 -0
- package/vendor/map-engine/query/planner.js +47 -0
- package/vendor/map-engine/react/MapView.d.ts +87 -0
- package/vendor/map-engine/react/MapView.js +270 -0
- package/vendor/map-engine/react/context.d.ts +39 -0
- package/vendor/map-engine/react/context.js +94 -0
- package/vendor/map-engine/react/index.d.ts +2 -0
- package/vendor/map-engine/react/index.js +2 -0
- package/vendor/map-engine/react/store.d.ts +19 -0
- package/vendor/map-engine/react/store.js +18 -0
- package/vendor/map-engine/realtime/apply.d.ts +74 -0
- package/vendor/map-engine/realtime/apply.js +155 -0
- package/vendor/map-engine/realtime/index.d.ts +1 -0
- package/vendor/map-engine/realtime/index.js +1 -0
- package/vendor/map-engine/render/index.d.ts +1 -0
- package/vendor/map-engine/render/index.js +1 -0
- package/vendor/map-engine/render/offline.d.ts +8 -0
- package/vendor/map-engine/render/offline.js +47 -0
- package/vendor/map-engine/render/renderer.d.ts +74 -0
- package/vendor/map-engine/render/renderer.js +1 -0
- package/vendor/map-engine/render/terrarium.d.ts +48 -0
- package/vendor/map-engine/render/terrarium.js +110 -0
- package/vendor/map-engine/runtime/drawing.d.ts +28 -0
- package/vendor/map-engine/runtime/drawing.js +58 -0
- package/vendor/map-engine/runtime/index.d.ts +5 -0
- package/vendor/map-engine/runtime/index.js +2 -0
- package/vendor/map-engine/runtime/offline.d.ts +24 -0
- package/vendor/map-engine/runtime/offline.js +37 -0
- package/vendor/map-engine/runtime/overlays.d.ts +25 -0
- package/vendor/map-engine/runtime/overlays.js +65 -0
- package/vendor/map-engine/runtime/runtime.d.ts +4 -0
- package/vendor/map-engine/runtime/runtime.js +2105 -0
- package/vendor/map-engine/runtime/types.d.ts +407 -0
- package/vendor/map-engine/runtime/types.js +1 -0
- package/vendor/map-engine/scene/index.d.ts +1 -0
- package/vendor/map-engine/scene/index.js +1 -0
- package/vendor/map-engine/scene/scene.d.ts +31 -0
- package/vendor/map-engine/scene/scene.js +216 -0
- package/vendor/map-engine/selection/index.d.ts +1 -0
- package/vendor/map-engine/selection/index.js +1 -0
- package/vendor/map-engine/selection/selection.d.ts +12 -0
- package/vendor/map-engine/selection/selection.js +28 -0
- package/vendor/map-engine/spatial/geojson.d.ts +15 -0
- package/vendor/map-engine/spatial/geojson.js +83 -0
- package/vendor/map-engine/spatial/geometry.d.ts +13 -0
- package/vendor/map-engine/spatial/geometry.js +206 -0
- package/vendor/map-engine/spatial/import.d.ts +27 -0
- package/vendor/map-engine/spatial/import.js +96 -0
- package/vendor/map-engine/spatial/index.d.ts +38 -0
- package/vendor/map-engine/spatial/index.js +37 -0
- package/vendor/map-engine/spatial/line-of-sight.d.ts +35 -0
- package/vendor/map-engine/spatial/line-of-sight.js +43 -0
- package/vendor/map-engine/spatial/measure.d.ts +28 -0
- package/vendor/map-engine/spatial/measure.js +90 -0
- package/vendor/map-engine/spatial/operations.d.ts +21 -0
- package/vendor/map-engine/spatial/operations.js +171 -0
- package/vendor/map-engine/spatial/query.d.ts +17 -0
- package/vendor/map-engine/spatial/query.js +88 -0
- package/vendor/map-engine/spatial/spatial-index.d.ts +24 -0
- package/vendor/map-engine/spatial/spatial-index.js +36 -0
- package/vendor/map-engine/spatial/volume-mesh.d.ts +19 -0
- package/vendor/map-engine/spatial/volume-mesh.js +56 -0
- package/vendor/map-engine/temporal/index.d.ts +3 -0
- package/vendor/map-engine/temporal/index.js +3 -0
- package/vendor/map-engine/temporal/journal.d.ts +20 -0
- package/vendor/map-engine/temporal/journal.js +34 -0
- package/vendor/map-engine/temporal/playback.d.ts +41 -0
- package/vendor/map-engine/temporal/playback.js +80 -0
- package/vendor/map-engine/temporal/tracks.d.ts +33 -0
- package/vendor/map-engine/temporal/tracks.js +119 -0
- package/vendor/map-engine/testing/annotation-store.d.ts +24 -0
- package/vendor/map-engine/testing/annotation-store.js +43 -0
- package/vendor/map-engine/testing/contracts.d.ts +41 -0
- package/vendor/map-engine/testing/contracts.js +328 -0
- package/vendor/map-engine/testing/fixtures-monitoring.d.ts +22 -0
- package/vendor/map-engine/testing/fixtures-monitoring.js +103 -0
- package/vendor/map-engine/testing/fixtures.d.ts +18 -0
- package/vendor/map-engine/testing/fixtures.js +28 -0
- package/vendor/map-engine/testing/index.d.ts +7 -0
- package/vendor/map-engine/testing/index.js +7 -0
- package/vendor/map-engine/testing/mock-ontology.d.ts +13 -0
- package/vendor/map-engine/testing/mock-ontology.js +24 -0
- package/vendor/map-engine/testing/mock-provider.d.ts +97 -0
- package/vendor/map-engine/testing/mock-provider.js +369 -0
- package/vendor/map-engine/testing/test-renderer.d.ts +72 -0
- package/vendor/map-engine/testing/test-renderer.js +153 -0
- package/vendor/map-engine/viewport/index.d.ts +1 -0
- package/vendor/map-engine/viewport/index.js +1 -0
- package/vendor/map-engine/viewport/viewport.d.ts +19 -0
- package/vendor/map-engine/viewport/viewport.js +102 -0
- package/vendor/map-provider-uns/client.d.ts +75 -0
- package/vendor/map-provider-uns/client.js +111 -0
- package/vendor/map-provider-uns/index.d.ts +2 -0
- package/vendor/map-provider-uns/index.js +2 -0
- package/vendor/map-provider-uns/provider.d.ts +131 -0
- package/vendor/map-provider-uns/provider.js +561 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { AnnotationProvider, RealtimeProvider, WritableSpatialProvider } from './contracts.js';
|
|
2
|
+
/** An AnnotationProvider over a writable provider: each annotation is an object of `ontologyType`. */
|
|
3
|
+
export declare function annotationsOnProvider(provider: WritableSpatialProvider & Partial<RealtimeProvider>, ontologyType: string): AnnotationProvider;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const KINDS = ['point', 'line', 'polygon', 'rectangle', 'circle', 'measurement', 'label', 'note'];
|
|
2
|
+
const str = (v) => (typeof v === 'string' ? v : undefined);
|
|
3
|
+
const json = (v) => {
|
|
4
|
+
if (typeof v !== 'string' || !v)
|
|
5
|
+
return undefined;
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(v);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
/** An AnnotationProvider over a writable provider: each annotation is an object of `ontologyType`. */
|
|
14
|
+
export function annotationsOnProvider(provider, ontologyType) {
|
|
15
|
+
const toAnnotation = (o) => {
|
|
16
|
+
const p = o.properties ?? {};
|
|
17
|
+
const kind = KINDS.includes(p.kind) ? p.kind : 'note';
|
|
18
|
+
const style = json(p.style);
|
|
19
|
+
const metadata = json(p.metadata);
|
|
20
|
+
return {
|
|
21
|
+
id: o.objectId,
|
|
22
|
+
kind,
|
|
23
|
+
geometry: o.geometry,
|
|
24
|
+
...(str(p.label) ? { label: str(p.label) } : {}),
|
|
25
|
+
...(str(p.note) ? { note: str(p.note) } : {}),
|
|
26
|
+
...(str(p.author) ? { author: str(p.author) } : {}),
|
|
27
|
+
...(str(p.createdAt) ? { createdAt: str(p.createdAt) } : {}),
|
|
28
|
+
...(str(p.updatedAt) ? { updatedAt: str(p.updatedAt) } : {}),
|
|
29
|
+
...(style ? { style } : {}),
|
|
30
|
+
...(metadata ? { metadata } : {}),
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
const store = {
|
|
34
|
+
async list(signal) {
|
|
35
|
+
return (await provider.query({ ontologyType }, signal)).map(toAnnotation);
|
|
36
|
+
},
|
|
37
|
+
async save(a) {
|
|
38
|
+
await provider.upsert({
|
|
39
|
+
objectId: a.id,
|
|
40
|
+
geometry: a.geometry,
|
|
41
|
+
properties: {
|
|
42
|
+
kind: a.kind,
|
|
43
|
+
label: a.label ?? '',
|
|
44
|
+
note: a.note ?? '',
|
|
45
|
+
...(a.author ? { author: a.author } : {}),
|
|
46
|
+
...(a.createdAt ? { createdAt: a.createdAt } : {}),
|
|
47
|
+
...(a.updatedAt ? { updatedAt: a.updatedAt } : {}),
|
|
48
|
+
// Nested values travel as JSON text: providers keep flat properties.
|
|
49
|
+
...(a.style ? { style: JSON.stringify(a.style) } : {}),
|
|
50
|
+
...(a.metadata ? { metadata: JSON.stringify(a.metadata) } : {}),
|
|
51
|
+
},
|
|
52
|
+
...(a.updatedAt || a.createdAt ? { observedAt: a.updatedAt ?? a.createdAt } : {}),
|
|
53
|
+
}, { ontologyType });
|
|
54
|
+
},
|
|
55
|
+
async remove(id) {
|
|
56
|
+
await provider.remove(id);
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
if (typeof provider.subscribe === 'function') {
|
|
60
|
+
store.subscribe = (onChange) => provider.subscribe({ ontologyType }, (patch) => onChange({ ...(patch.upserted ? { upserted: patch.upserted.map(toAnnotation) } : {}), ...(patch.removed ? { removed: patch.removed } : {}) }));
|
|
61
|
+
}
|
|
62
|
+
return store;
|
|
63
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data contracts (ADR-005, ADR-018). The engine asks for capabilities, never for a database.
|
|
3
|
+
*
|
|
4
|
+
* Security (Decision 8): providers return data that is ALREADY authorized for the current user.
|
|
5
|
+
* The browser engine is not a security boundary; anything it filters is visibility, not access control.
|
|
6
|
+
*/
|
|
7
|
+
import type { AltitudeReference, Annotation, BoundingBox, Geometry, GeometryFamily, Position, SpatialObject, SpatialQuery, TimeRange, Track, Unsubscribe } from '../core/types.js';
|
|
8
|
+
export interface DataCapabilities {
|
|
9
|
+
supportsSpatialQuery: boolean;
|
|
10
|
+
supportsHistoricalQuery: boolean;
|
|
11
|
+
supportsRealtime: boolean;
|
|
12
|
+
supportsWrite: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface SpatialDataProvider {
|
|
15
|
+
readonly capabilities: DataCapabilities;
|
|
16
|
+
/** Objects matching every field of the query. Must honour `signal` (reject with an AbortError). */
|
|
17
|
+
query(query: SpatialQuery, signal?: AbortSignal): Promise<SpatialObject[]>;
|
|
18
|
+
getCurrentState(objectIds: string[], signal?: AbortSignal): Promise<SpatialObject[]>;
|
|
19
|
+
}
|
|
20
|
+
/** A provider that also accepts writes (used by io-maps authoring and by mocks). Read-only providers stay read-only. */
|
|
21
|
+
export interface WritableSpatialProvider extends SpatialDataProvider {
|
|
22
|
+
upsert(object: SpatialObject, meta?: {
|
|
23
|
+
ontologyType?: string;
|
|
24
|
+
}): Promise<void>;
|
|
25
|
+
remove(objectId: string): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export declare function isWritableProvider(p: SpatialDataProvider): p is WritableSpatialProvider;
|
|
28
|
+
/** Incremental change from a realtime source. */
|
|
29
|
+
export interface SpatialPatch {
|
|
30
|
+
upserted?: SpatialObject[];
|
|
31
|
+
removed?: string[];
|
|
32
|
+
}
|
|
33
|
+
/** Snapshot + stream (ADR-015): callers take a snapshot with `query`, then apply these patches. No RxJS (Decision 12). */
|
|
34
|
+
export interface RealtimeProvider {
|
|
35
|
+
subscribe(query: SpatialQuery, onPatch: (patch: SpatialPatch) => void, onError?: (error: Error) => void): Unsubscribe;
|
|
36
|
+
}
|
|
37
|
+
/** How an Ontology type projects into space. Resolved by the Ontology side; the engine only consumes it. */
|
|
38
|
+
export interface SpatialBinding {
|
|
39
|
+
ontologyType: string;
|
|
40
|
+
geometryProperty: string;
|
|
41
|
+
geometryType: Geometry['type'];
|
|
42
|
+
capabilities: DataCapabilities;
|
|
43
|
+
}
|
|
44
|
+
export interface MissingCapability {
|
|
45
|
+
ontologyType: string;
|
|
46
|
+
missing: 'spatial';
|
|
47
|
+
reason: string;
|
|
48
|
+
}
|
|
49
|
+
export interface OntologySpatialResolver {
|
|
50
|
+
resolve(ontologyType: string, signal?: AbortSignal): Promise<SpatialBinding | MissingCapability>;
|
|
51
|
+
}
|
|
52
|
+
export declare function isMissingCapability(v: SpatialBinding | MissingCapability): v is MissingCapability;
|
|
53
|
+
/**
|
|
54
|
+
* Historical positions (doc 07, doc 11 TrackProvider). Returns tracks of objects matching the query whose
|
|
55
|
+
* positions fall inside `query.bounds` during `range` — including objects no longer present now.
|
|
56
|
+
*/
|
|
57
|
+
export interface TrackProvider {
|
|
58
|
+
getTracks(query: SpatialQuery, range: TimeRange, signal?: AbortSignal): Promise<Track[]>;
|
|
59
|
+
}
|
|
60
|
+
/** What a property holds across a dataset, so an application can build pickers and rules without hard-coding names. */
|
|
61
|
+
export interface PropertySchema {
|
|
62
|
+
name: string;
|
|
63
|
+
type: 'number' | 'string' | 'boolean' | 'mixed';
|
|
64
|
+
/** Objects that have a non-null value. */
|
|
65
|
+
count: number;
|
|
66
|
+
/** Distinct values (all types). */
|
|
67
|
+
distinct: number;
|
|
68
|
+
min?: number;
|
|
69
|
+
max?: number;
|
|
70
|
+
/** Up to a handful of distinct values, most common first (strings and booleans; small numeric sets too). */
|
|
71
|
+
values?: Array<string | number | boolean>;
|
|
72
|
+
}
|
|
73
|
+
/** One kind of spatial object a provider can serve: its type, geometry and property schema. */
|
|
74
|
+
export interface DatasetInfo {
|
|
75
|
+
ontologyType: string;
|
|
76
|
+
label?: string;
|
|
77
|
+
/** Where it comes from, for display ("Plant telemetry", "Imported file"). */
|
|
78
|
+
source?: string;
|
|
79
|
+
/** The single geometry type, or 'Mixed' when objects differ (e.g. Polygon and MultiPolygon). */
|
|
80
|
+
geometryType: Geometry['type'] | 'Mixed';
|
|
81
|
+
/** Point, line or area — what kind of layer can draw it. 'mixed' only when the families differ. */
|
|
82
|
+
geometryFamily: GeometryFamily | 'mixed';
|
|
83
|
+
count: number;
|
|
84
|
+
properties: PropertySchema[];
|
|
85
|
+
bounds?: BoundingBox;
|
|
86
|
+
/** Position history is available (replay, trails). */
|
|
87
|
+
hasHistory: boolean;
|
|
88
|
+
/** Changes stream live. */
|
|
89
|
+
live: boolean;
|
|
90
|
+
/** Units of properties that have one (e.g. { speed: 'm/s' }), for display. */
|
|
91
|
+
units?: Record<string, string>;
|
|
92
|
+
/** When the source last had data for this dataset (epoch ms) — lets an app tell stale data from live data. */
|
|
93
|
+
lastDataAt?: number;
|
|
94
|
+
/** Positions carry `altitude`, measured from this reference — so an app can draw them at height correctly. */
|
|
95
|
+
altitude?: {
|
|
96
|
+
reference: AltitudeReference;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Ground heights (doc 3D plan, ADR-028): metres above mean sea level under each position, null where unknown.
|
|
101
|
+
* A terrain service, or the renderer's own terrain when it has one.
|
|
102
|
+
*/
|
|
103
|
+
export interface ElevationProvider {
|
|
104
|
+
sample(positions: Position[], signal?: AbortSignal): Promise<Array<number | null>>;
|
|
105
|
+
}
|
|
106
|
+
/** Optional: providers that can describe what they hold. Applications use it to discover data instead of hard-coding it. */
|
|
107
|
+
export interface DatasetCatalog {
|
|
108
|
+
listDatasets(signal?: AbortSignal): Promise<DatasetInfo[]>;
|
|
109
|
+
}
|
|
110
|
+
export declare function hasCatalog(p: object): p is DatasetCatalog;
|
|
111
|
+
/** A relation between two objects (UNS neighbours, lineage…). The engine draws it; it never infers one. */
|
|
112
|
+
export interface Link {
|
|
113
|
+
id: string;
|
|
114
|
+
fromId: string;
|
|
115
|
+
toId: string;
|
|
116
|
+
type?: string;
|
|
117
|
+
properties?: Record<string, unknown>;
|
|
118
|
+
}
|
|
119
|
+
/** Links touching any of `objectIds`, of the given types (all when omitted). Authorized data only. */
|
|
120
|
+
export interface LinkProvider {
|
|
121
|
+
getLinks(objectIds: string[], types: string[] | undefined, signal?: AbortSignal): Promise<Link[]>;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* One entry of the event journal (doc 29 §7): what an object was from `at` on. `object` is its full state then
|
|
125
|
+
* (or, for `removed`, absent). Sources may add their own `kind`s; the engine only needs created/updated/removed/
|
|
126
|
+
* snapshot to rebuild the map at a time.
|
|
127
|
+
*/
|
|
128
|
+
export interface JournalEntry {
|
|
129
|
+
/** ISO 8601. */
|
|
130
|
+
at: string;
|
|
131
|
+
objectId: string;
|
|
132
|
+
kind: 'snapshot' | 'created' | 'updated' | 'removed' | (string & {});
|
|
133
|
+
object?: SpatialObject;
|
|
134
|
+
/** What changed, for display (e.g. { status: ['ok', 'alarm'] }). */
|
|
135
|
+
changes?: Record<string, [unknown, unknown]>;
|
|
136
|
+
source?: string;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* The event journal behind replay of whole objects (doc 29 §7–8, doc 28 G5). For a query and a range it returns,
|
|
140
|
+
* per object, its state as of `range.start` (kind `snapshot`) followed by every change inside the range, oldest
|
|
141
|
+
* first. The engine rebuilds the map at any time in the range from that; it never stores history itself.
|
|
142
|
+
*/
|
|
143
|
+
export interface JournalProvider {
|
|
144
|
+
getJournal(query: SpatialQuery, range: TimeRange, signal?: AbortSignal): Promise<JournalEntry[]>;
|
|
145
|
+
}
|
|
146
|
+
/** Where annotations live (doc 28 G10): shared with others when the provider stores them, e.g. as UNS nodes. */
|
|
147
|
+
export interface AnnotationProvider {
|
|
148
|
+
list(signal?: AbortSignal): Promise<Annotation[]>;
|
|
149
|
+
save(annotation: Annotation): Promise<void>;
|
|
150
|
+
remove(id: string): Promise<void>;
|
|
151
|
+
/** Changes made elsewhere (other users), if the store can stream them. */
|
|
152
|
+
subscribe?(onChange: (change: {
|
|
153
|
+
upserted?: Annotation[];
|
|
154
|
+
removed?: string[];
|
|
155
|
+
}) => void): Unsubscribe;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Who is looking (doc 28 G13). The engine never decides access; it hands this to every provider that accepts it
|
|
159
|
+
* (`setAuth`), reloads, and shows what comes back: missing objects are absent, removed properties are listed in
|
|
160
|
+
* `object.redacted`, and a refused layer (an ACCESS_DENIED error) gets the status 'denied'.
|
|
161
|
+
*/
|
|
162
|
+
export interface AuthContext {
|
|
163
|
+
userId?: string;
|
|
164
|
+
/** Opaque to the engine; providers send it to their server. */
|
|
165
|
+
token?: string;
|
|
166
|
+
roles?: string[];
|
|
167
|
+
attributes?: Record<string, unknown>;
|
|
168
|
+
}
|
|
169
|
+
export interface AuthAware {
|
|
170
|
+
setAuth(auth: AuthContext | null): void;
|
|
171
|
+
}
|
|
172
|
+
export declare function isAuthAware(p: unknown): p is AuthAware;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function isWritableProvider(p) {
|
|
2
|
+
return p.capabilities.supportsWrite && typeof p.upsert === 'function';
|
|
3
|
+
}
|
|
4
|
+
export function isMissingCapability(v) {
|
|
5
|
+
return v.missing !== undefined;
|
|
6
|
+
}
|
|
7
|
+
export function hasCatalog(p) {
|
|
8
|
+
return typeof p.listDatasets === 'function';
|
|
9
|
+
}
|
|
10
|
+
export function isAuthAware(p) {
|
|
11
|
+
return typeof p === 'object' && p !== null && typeof p.setAuth === 'function';
|
|
12
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { hasCatalog, isAuthAware, isMissingCapability, isWritableProvider } from './contracts.js';
|
|
2
|
+
export { annotationsOnProvider } from './annotations.js';
|
|
3
|
+
export { describeProperties } from './schema.js';
|
|
4
|
+
export type { AnnotationProvider, AuthAware, AuthContext, JournalEntry, JournalProvider, Link, LinkProvider, DataCapabilities, DatasetCatalog, DatasetInfo, ElevationProvider, MissingCapability, OntologySpatialResolver, PropertySchema, RealtimeProvider, SpatialBinding, SpatialDataProvider, SpatialPatch, TrackProvider, WritableSpatialProvider, } from './contracts.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Property schema inference: what each property holds across a set of objects. Pure; used by providers that
|
|
3
|
+
* describe their datasets and by applications for imported data.
|
|
4
|
+
*/
|
|
5
|
+
import type { SpatialObject } from '../core/types.js';
|
|
6
|
+
import type { PropertySchema } from './contracts.js';
|
|
7
|
+
export declare function describeProperties(objects: SpatialObject[], maxValues?: number): PropertySchema[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export function describeProperties(objects, maxValues = 12) {
|
|
2
|
+
const stats = new Map();
|
|
3
|
+
for (const o of objects) {
|
|
4
|
+
for (const [name, v] of Object.entries(o.properties ?? {})) {
|
|
5
|
+
if (v === null || v === undefined || v === '')
|
|
6
|
+
continue;
|
|
7
|
+
let s = stats.get(name);
|
|
8
|
+
if (!s)
|
|
9
|
+
stats.set(name, (s = { types: new Set(), counts: new Map(), count: 0, min: Infinity, max: -Infinity }));
|
|
10
|
+
s.count++;
|
|
11
|
+
const t = typeof v;
|
|
12
|
+
if (t === 'number' && Number.isFinite(v)) {
|
|
13
|
+
s.types.add('number');
|
|
14
|
+
s.min = Math.min(s.min, v);
|
|
15
|
+
s.max = Math.max(s.max, v);
|
|
16
|
+
}
|
|
17
|
+
else if (t === 'string' || t === 'boolean')
|
|
18
|
+
s.types.add(t);
|
|
19
|
+
else {
|
|
20
|
+
s.types.add('mixed');
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
s.counts.set(v, (s.counts.get(v) ?? 0) + 1);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return [...stats.entries()]
|
|
27
|
+
.map(([name, s]) => {
|
|
28
|
+
const type = (s.types.size === 1 ? [...s.types][0] : 'mixed');
|
|
29
|
+
const out = { name, type, count: s.count, distinct: s.counts.size };
|
|
30
|
+
if (type === 'number') {
|
|
31
|
+
out.min = s.min;
|
|
32
|
+
out.max = s.max;
|
|
33
|
+
}
|
|
34
|
+
if (type !== 'number' || s.counts.size <= maxValues) {
|
|
35
|
+
out.values = [...s.counts.entries()].sort((a, b) => b[1] - a[1] || String(a[0]).localeCompare(String(b[0]))).slice(0, maxValues).map(([v]) => v);
|
|
36
|
+
}
|
|
37
|
+
return out;
|
|
38
|
+
})
|
|
39
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
40
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Geofence evaluation (doc 15): geometry + rule + object + state transition → generic spatial events.
|
|
3
|
+
* Pure and stateful per evaluator; no data access, no rendering, no domain events.
|
|
4
|
+
*/
|
|
5
|
+
import type { Geofence, GeofenceEvent, Position, SpatialObject, ValidationResult } from '../core/types.js';
|
|
6
|
+
export interface Reading {
|
|
7
|
+
objectId: string;
|
|
8
|
+
position: Position;
|
|
9
|
+
/** ISO 8601 observation time. */
|
|
10
|
+
timestamp: string;
|
|
11
|
+
layerId?: string;
|
|
12
|
+
properties?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
export declare function validateGeofence(value: unknown): ValidationResult;
|
|
15
|
+
export declare function watches(g: Geofence, r: Reading): boolean;
|
|
16
|
+
export declare class GeofenceEvaluator {
|
|
17
|
+
private fences;
|
|
18
|
+
private readonly state;
|
|
19
|
+
constructor(geofences?: Geofence[]);
|
|
20
|
+
/** Replaces the geofences. State is kept for unchanged ones and dropped for removed or changed ones. */
|
|
21
|
+
setGeofences(geofences: Geofence[]): void;
|
|
22
|
+
geofences(): Geofence[];
|
|
23
|
+
/**
|
|
24
|
+
* One reading → zero or more events. The first reading for an object sets its state silently (no "enter"
|
|
25
|
+
* storm when a map opens). Readings older than the last one for that object are ignored.
|
|
26
|
+
*/
|
|
27
|
+
observe(r: Reading): GeofenceEvent[];
|
|
28
|
+
/** Objects currently inside each geofence (settled state). */
|
|
29
|
+
occupancy(): Record<string, string[]>;
|
|
30
|
+
reset(): void;
|
|
31
|
+
/** Inside test with hysteresis: once inside, an object leaves only when farther than the margin outside. */
|
|
32
|
+
private isInside;
|
|
33
|
+
}
|
|
34
|
+
/** Readings from point objects (e.g. a layer's current data). */
|
|
35
|
+
export declare function readingsFrom(objects: SpatialObject[], layerId: string, fallbackTimestamp: string): Reading[];
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { deepEqual } from '../core/equal.js';
|
|
2
|
+
import { validateGeometry } from '../spatial/geometry.js';
|
|
3
|
+
import { distanceToGeometryMeters, within } from '../spatial/operations.js';
|
|
4
|
+
import { matchesCondition, validateConditions } from '../spatial/query.js';
|
|
5
|
+
export function validateGeofence(value) {
|
|
6
|
+
if (typeof value !== 'object' || value === null)
|
|
7
|
+
return { valid: false, reason: 'geofence is not an object' };
|
|
8
|
+
const g = value;
|
|
9
|
+
if (typeof g.id !== 'string' || !g.id)
|
|
10
|
+
return { valid: false, reason: 'geofence.id is required' };
|
|
11
|
+
if (!g.geometry || !['Polygon', 'MultiPolygon', 'Circle'].includes(g.geometry.type))
|
|
12
|
+
return { valid: false, reason: `geofence ${g.id}: geometry must be an area (Polygon, MultiPolygon or Circle)` };
|
|
13
|
+
const v = validateGeometry(g.geometry);
|
|
14
|
+
if (!v.valid)
|
|
15
|
+
return { valid: false, reason: `geofence ${g.id}: ${v.reason}` };
|
|
16
|
+
if (typeof g.enabled !== 'boolean')
|
|
17
|
+
return { valid: false, reason: `geofence ${g.id}: enabled must be a boolean` };
|
|
18
|
+
if (g.hysteresisMeters !== undefined && !(g.hysteresisMeters >= 0))
|
|
19
|
+
return { valid: false, reason: `geofence ${g.id}: hysteresisMeters must be >= 0` };
|
|
20
|
+
if (g.debounceSamples !== undefined && !(Number.isInteger(g.debounceSamples) && g.debounceSamples >= 1))
|
|
21
|
+
return { valid: false, reason: `geofence ${g.id}: debounceSamples must be a whole number >= 1` };
|
|
22
|
+
if (g.dwellSeconds !== undefined && !(g.dwellSeconds > 0))
|
|
23
|
+
return { valid: false, reason: `geofence ${g.id}: dwellSeconds must be > 0` };
|
|
24
|
+
for (const k of ['minAltitude', 'maxAltitude']) {
|
|
25
|
+
if (g[k] !== undefined && !(typeof g[k] === 'number' && Number.isFinite(g[k])))
|
|
26
|
+
return { valid: false, reason: `geofence ${g.id}: ${k} must be a number of metres` };
|
|
27
|
+
}
|
|
28
|
+
if (g.minAltitude !== undefined && g.maxAltitude !== undefined && !(g.minAltitude < g.maxAltitude))
|
|
29
|
+
return { valid: false, reason: `geofence ${g.id}: minAltitude must be below maxAltitude` };
|
|
30
|
+
if (g.watch?.where !== undefined) {
|
|
31
|
+
const w = validateConditions(g.watch.where, `geofence ${g.id}: watch.where`);
|
|
32
|
+
if (!w.valid)
|
|
33
|
+
return w;
|
|
34
|
+
}
|
|
35
|
+
return { valid: true };
|
|
36
|
+
}
|
|
37
|
+
export function watches(g, r) {
|
|
38
|
+
const w = g.watch;
|
|
39
|
+
if (!w)
|
|
40
|
+
return true;
|
|
41
|
+
if (w.layerIds && (!r.layerId || !w.layerIds.includes(r.layerId)))
|
|
42
|
+
return false;
|
|
43
|
+
if (w.objectIds && !w.objectIds.includes(r.objectId))
|
|
44
|
+
return false;
|
|
45
|
+
if (w.filter && !Object.entries(w.filter).every(([k, v]) => deepEqual(r.properties?.[k], v)))
|
|
46
|
+
return false;
|
|
47
|
+
if (w.where && !w.where.every((c) => matchesCondition(r.properties?.[c.property], c)))
|
|
48
|
+
return false;
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
export class GeofenceEvaluator {
|
|
52
|
+
fences = new Map();
|
|
53
|
+
state = new Map();
|
|
54
|
+
constructor(geofences = []) {
|
|
55
|
+
this.setGeofences(geofences);
|
|
56
|
+
}
|
|
57
|
+
/** Replaces the geofences. State is kept for unchanged ones and dropped for removed or changed ones. */
|
|
58
|
+
setGeofences(geofences) {
|
|
59
|
+
const next = new Map(geofences.map((g) => [g.id, structuredClone(g)]));
|
|
60
|
+
for (const key of [...this.state.keys()]) {
|
|
61
|
+
const id = key.slice(0, key.indexOf('\u0000'));
|
|
62
|
+
const before = this.fences.get(id);
|
|
63
|
+
const after = next.get(id);
|
|
64
|
+
if (!after || !before || !deepEqual(before.geometry, after.geometry) || before.hysteresisMeters !== after.hysteresisMeters || before.minAltitude !== after.minAltitude || before.maxAltitude !== after.maxAltitude)
|
|
65
|
+
this.state.delete(key);
|
|
66
|
+
}
|
|
67
|
+
this.fences = next;
|
|
68
|
+
}
|
|
69
|
+
geofences() {
|
|
70
|
+
return [...this.fences.values()].map((g) => structuredClone(g));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* One reading → zero or more events. The first reading for an object sets its state silently (no "enter"
|
|
74
|
+
* storm when a map opens). Readings older than the last one for that object are ignored.
|
|
75
|
+
*/
|
|
76
|
+
observe(r) {
|
|
77
|
+
const ms = Date.parse(r.timestamp);
|
|
78
|
+
if (!Number.isFinite(ms))
|
|
79
|
+
return [];
|
|
80
|
+
const events = [];
|
|
81
|
+
for (const g of this.fences.values()) {
|
|
82
|
+
if (!g.enabled || !watches(g, r))
|
|
83
|
+
continue;
|
|
84
|
+
const key = `${g.id}\u0000${r.objectId}`;
|
|
85
|
+
let s = this.state.get(key);
|
|
86
|
+
if (!s) {
|
|
87
|
+
s = { inside: undefined, pending: undefined, pendingCount: 0, enteredAtMs: undefined, dwellEmitted: false, lastMs: -Infinity };
|
|
88
|
+
this.state.set(key, s);
|
|
89
|
+
}
|
|
90
|
+
if (ms < s.lastMs)
|
|
91
|
+
continue; // out of order: the newer state already counted
|
|
92
|
+
s.lastMs = ms;
|
|
93
|
+
const raw = this.isInside(g, r.position, s.inside === true);
|
|
94
|
+
if (s.inside === undefined) {
|
|
95
|
+
s.inside = raw;
|
|
96
|
+
s.enteredAtMs = raw ? ms : undefined;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (raw !== s.inside) {
|
|
100
|
+
s.pendingCount = s.pending === raw ? s.pendingCount + 1 : 1;
|
|
101
|
+
s.pending = raw;
|
|
102
|
+
if (s.pendingCount >= (g.debounceSamples ?? 1)) {
|
|
103
|
+
s.inside = raw;
|
|
104
|
+
s.pending = undefined;
|
|
105
|
+
s.pendingCount = 0;
|
|
106
|
+
s.enteredAtMs = raw ? ms : undefined;
|
|
107
|
+
s.dwellEmitted = false;
|
|
108
|
+
events.push({ geofenceId: g.id, objectId: r.objectId, type: raw ? 'enter' : 'exit', timestamp: r.timestamp, position: r.position });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
s.pending = undefined;
|
|
113
|
+
s.pendingCount = 0;
|
|
114
|
+
}
|
|
115
|
+
if (s.inside && g.dwellSeconds !== undefined && !s.dwellEmitted && s.enteredAtMs !== undefined && ms - s.enteredAtMs >= g.dwellSeconds * 1000) {
|
|
116
|
+
s.dwellEmitted = true;
|
|
117
|
+
events.push({ geofenceId: g.id, objectId: r.objectId, type: 'dwell', timestamp: r.timestamp, position: r.position });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return events;
|
|
121
|
+
}
|
|
122
|
+
/** Objects currently inside each geofence (settled state). */
|
|
123
|
+
occupancy() {
|
|
124
|
+
const out = {};
|
|
125
|
+
for (const g of this.fences.values())
|
|
126
|
+
out[g.id] = [];
|
|
127
|
+
for (const [key, s] of this.state) {
|
|
128
|
+
if (!s.inside)
|
|
129
|
+
continue;
|
|
130
|
+
const sep = key.indexOf('\u0000');
|
|
131
|
+
const id = key.slice(0, sep);
|
|
132
|
+
if (out[id])
|
|
133
|
+
out[id].push(key.slice(sep + 1));
|
|
134
|
+
}
|
|
135
|
+
for (const id of Object.keys(out))
|
|
136
|
+
out[id].sort();
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
reset() {
|
|
140
|
+
this.state.clear();
|
|
141
|
+
}
|
|
142
|
+
/** Inside test with hysteresis: once inside, an object leaves only when farther than the margin outside. */
|
|
143
|
+
isInside(g, p, wasInside) {
|
|
144
|
+
const margin = g.hysteresisMeters ?? 0;
|
|
145
|
+
// A volume: the altitude band first (cheap), with the same exit margin vertically.
|
|
146
|
+
if (g.minAltitude !== undefined || g.maxAltitude !== undefined) {
|
|
147
|
+
if (p.altitude === undefined)
|
|
148
|
+
return false;
|
|
149
|
+
const slack = wasInside ? margin : 0;
|
|
150
|
+
if (g.minAltitude !== undefined && p.altitude < g.minAltitude - slack)
|
|
151
|
+
return false;
|
|
152
|
+
if (g.maxAltitude !== undefined && p.altitude > g.maxAltitude + slack)
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
const point = { type: 'Point', coordinates: p };
|
|
156
|
+
if (within(point, g.geometry))
|
|
157
|
+
return true;
|
|
158
|
+
return wasInside && margin > 0 && distanceToGeometryMeters(p, g.geometry) <= margin;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/** Readings from point objects (e.g. a layer's current data). */
|
|
162
|
+
export function readingsFrom(objects, layerId, fallbackTimestamp) {
|
|
163
|
+
return objects
|
|
164
|
+
.filter((o) => o.geometry.type === 'Point')
|
|
165
|
+
.map((o) => ({
|
|
166
|
+
objectId: o.objectId,
|
|
167
|
+
position: o.geometry.coordinates,
|
|
168
|
+
timestamp: o.observedAt ?? fallbackTimestamp,
|
|
169
|
+
layerId,
|
|
170
|
+
...(o.properties ? { properties: o.properties } : {}),
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Geofence events over history (doc 15: "historical/replay evaluation must use the state at the relevant time").
|
|
3
|
+
* Merges every track's readings in time order and runs a fresh evaluator over them.
|
|
4
|
+
*/
|
|
5
|
+
import type { Geofence, GeofenceEvent, Track } from '../core/types.js';
|
|
6
|
+
export declare function evaluateTracks(geofences: Geofence[], tracks: Array<{
|
|
7
|
+
track: Track;
|
|
8
|
+
layerId?: string;
|
|
9
|
+
}>): GeofenceEvent[];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { GeofenceEvaluator } from './evaluator.js';
|
|
2
|
+
export function evaluateTracks(geofences, tracks) {
|
|
3
|
+
const readings = [];
|
|
4
|
+
for (const { track, layerId } of tracks) {
|
|
5
|
+
for (const p of track.points) {
|
|
6
|
+
readings.push({
|
|
7
|
+
objectId: track.objectId,
|
|
8
|
+
position: { latitude: p.latitude, longitude: p.longitude },
|
|
9
|
+
timestamp: p.timestamp,
|
|
10
|
+
ms: Date.parse(p.timestamp),
|
|
11
|
+
...(layerId ? { layerId } : {}),
|
|
12
|
+
...(track.properties ? { properties: track.properties } : {}),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
readings.sort((a, b) => a.ms - b.ms || a.objectId.localeCompare(b.objectId));
|
|
17
|
+
const evaluator = new GeofenceEvaluator(geofences);
|
|
18
|
+
return readings.flatMap((r) => evaluator.observe(r));
|
|
19
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @faclon-labs/map-engine — public API.
|
|
3
|
+
*
|
|
4
|
+
* Entry points:
|
|
5
|
+
* "." runtime, contracts, spatial API (this file)
|
|
6
|
+
* "./testing" mock provider, test renderer, fixtures
|
|
7
|
+
* "./maplibre" (Phase 1B) MapLibre renderer adapter
|
|
8
|
+
* "./react" (Phase 1C) React bindings
|
|
9
|
+
*/
|
|
10
|
+
export type * from './core/types.js';
|
|
11
|
+
export { MapEngineError, type MapEngineErrorCode, type MapEngineErrorSource } from './core/errors.js';
|
|
12
|
+
export { COMMAND_TYPES, COMMAND_VERSION, commandProblem, type CommandResult, type MapCommand, type MapCommandType } from './core/commands.js';
|
|
13
|
+
export { AGE, ALTERNATIVES, CONFIDENCE, ageOf, isValidAt, presentObject, scaled, scaleValue, type AgeState } from './present/index.js';
|
|
14
|
+
export { decorationObjects, decorationOwner, footprintOf, formatDistance } from './present/index.js';
|
|
15
|
+
export { createPostMessageBridge, connectToMap, mapWebMcpTools, type PostMessageBridgeOptions, type WebMcpTool } from './commands/index.js';
|
|
16
|
+
export { type Measurement } from './spatial/index.js';
|
|
17
|
+
export { spatial, RBushSpatialIndex, type SpatialIndex, matchesCondition, matchesQuery, rankByRelation, validateConditions, judgeSight, pathSamples, type SightResult, type SightProfilePoint, objectsFromGeoJSON, objectsFromRows, guessCoordinateColumns, type ImportResult } from './spatial/index.js';
|
|
18
|
+
export { computeBounds, zoomToFit, validateViewport, MAX_ZOOM, MIN_ZOOM } from './viewport/index.js';
|
|
19
|
+
export { validateLayer } from './layers/index.js';
|
|
20
|
+
export { annotationsOnProvider, describeProperties, hasCatalog, isAuthAware, isMissingCapability, isWritableProvider } from './data/index.js';
|
|
21
|
+
export type { AnnotationProvider, AuthAware, AuthContext, JournalEntry, JournalProvider, Link, LinkProvider, DataCapabilities, DatasetCatalog, DatasetInfo, ElevationProvider, PropertySchema, MissingCapability, OntologySpatialResolver, RealtimeProvider, SpatialBinding, SpatialDataProvider, SpatialPatch, TrackProvider, WritableSpatialProvider, } from './data/index.js';
|
|
22
|
+
export { appendPoint, bearing, groupJournal, journalStateAt, normalizeTrack, Playback, stateAt, trailBetween, validateTrack, type PlaybackOptions, type StateAt } from './temporal/index.js';
|
|
23
|
+
export type { MapClickEvent, PickEvent, Renderer, RendererCapabilities, RendererOptions } from './render/index.js';
|
|
24
|
+
export { createMapRuntime } from './runtime/index.js';
|
|
25
|
+
export { offlineViolations, isLocalUrl } from './runtime/index.js';
|
|
26
|
+
export type { DrawingState, DrawKind, FlyToOptions, LayerFilter, LineOfSightOptions, MapRuntime, MapRuntimeDeps, MapRuntimeEvents, MapRuntimeOptions, ObjectInspection, ResolvedReference, RuntimeState } from './runtime/index.js';
|
|
27
|
+
export { GeofenceEvaluator, evaluateTracks, validateGeofence } from './geofence/index.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { MapEngineError } from './core/errors.js';
|
|
2
|
+
export { COMMAND_TYPES, COMMAND_VERSION, commandProblem } from './core/commands.js';
|
|
3
|
+
export { AGE, ALTERNATIVES, CONFIDENCE, ageOf, isValidAt, presentObject, scaled, scaleValue } from './present/index.js';
|
|
4
|
+
export { decorationObjects, decorationOwner, footprintOf, formatDistance } from './present/index.js';
|
|
5
|
+
export { createPostMessageBridge, connectToMap, mapWebMcpTools } from './commands/index.js';
|
|
6
|
+
export {} from './spatial/index.js';
|
|
7
|
+
export { spatial, RBushSpatialIndex, matchesCondition, matchesQuery, rankByRelation, validateConditions, judgeSight, pathSamples, objectsFromGeoJSON, objectsFromRows, guessCoordinateColumns } from './spatial/index.js';
|
|
8
|
+
export { computeBounds, zoomToFit, validateViewport, MAX_ZOOM, MIN_ZOOM } from './viewport/index.js';
|
|
9
|
+
export { validateLayer } from './layers/index.js';
|
|
10
|
+
export { annotationsOnProvider, describeProperties, hasCatalog, isAuthAware, isMissingCapability, isWritableProvider } from './data/index.js';
|
|
11
|
+
export { appendPoint, bearing, groupJournal, journalStateAt, normalizeTrack, Playback, stateAt, trailBetween, validateTrack } from './temporal/index.js';
|
|
12
|
+
export { createMapRuntime } from './runtime/index.js';
|
|
13
|
+
export { offlineViolations, isLocalUrl } from './runtime/index.js';
|
|
14
|
+
export { GeofenceEvaluator, evaluateTracks, validateGeofence } from './geofence/index.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { drawable, GEOMETRY_FOR, SOURCE_GEOMETRY_FOR, LayerRegistry, layerNeeds, layerQuery, tokenFor, validateLayer, volumeOf, type QueryHints, type ResolvedVolume } from './layers.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { drawable, GEOMETRY_FOR, SOURCE_GEOMETRY_FOR, LayerRegistry, layerNeeds, layerQuery, tokenFor, validateLayer, volumeOf } from './layers.js';
|