@geolonia/geonicdb-sdk 0.11.1 → 0.12.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 +49 -0
- package/ngsi-v2/index.cjs +92 -0
- package/ngsi-v2/index.cjs.map +7 -0
- package/ngsi-v2/index.d.ts +58 -0
- package/ngsi-v2/index.mjs +73 -0
- package/ngsi-v2/index.mjs.map +7 -0
- package/package.json +36 -1
- package/react/index.cjs +266 -0
- package/react/index.cjs.map +7 -0
- package/react/index.d.ts +551 -0
- package/react/index.mjs +233 -0
- package/react/index.mjs.map +7 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/sdk/react/index.ts", "../../../src/sdk/react/hooks.ts", "../../../src/sdk/react/GeonicDbMap.tsx"],
|
|
4
|
+
"sourcesContent": ["// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 Geolonia Inc.\n// See LICENSE in src/sdk/ for full license text.\n\n/**\n * @geolonia/geonicdb-sdk/react \u2014 React hooks and map component\n *\n * Requires React 18 or 19 as an optional peer dependency.\n * Import only from this subpath to avoid pulling React into core consumers.\n */\nexport { useLdEntities, useTemporalData } from './hooks.js';\nexport { GeonicDbMap } from './GeonicDbMap.js';\nexport type { GeonicDbMapProps } from './GeonicDbMap.js';\nexport type {\n LdEntity,\n LdAttribute,\n LdProperty,\n LdGeoProperty,\n LdRelationship,\n LdQueryOptions,\n NgsiEntity,\n NgsiAttribute,\n GeoJsonPoint,\n GeoJsonPolygon,\n GeoJsonGeometry,\n} from './types.js';\n", "// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 Geolonia Inc.\n// See LICENSE in src/sdk/ for full license text.\n\n/**\n * NGSI-LD React hooks \u2014 built on top of GeonicDB SDK core.\n */\n\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport type GeonicDB from '../index.js';\nimport type { GetEntitiesParams, GetTemporalEntitiesParams } from '../types.js';\nimport type { LdEntity, LdQueryOptions } from './types.js';\n\n/**\n * Fetch NGSI-LD entities using the GeonicDB SDK client.\n *\n * The official SDK core handles DPoP / auth transparently.\n */\nexport function useLdEntities(\n client: GeonicDB,\n options?: LdQueryOptions,\n): {\n entities: LdEntity[];\n loading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n} {\n const [entities, setEntities] = useState<LdEntity[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n // \u30EA\u30AF\u30A8\u30B9\u30C8\u4E16\u4EE3\u30AB\u30A6\u30F3\u30BF\u3002deps \u5909\u5316\u30FBrefetch\u30FB\u30A2\u30F3\u30DE\u30A6\u30F3\u30C8\u6642\u306B\u5897\u3084\u3057\u3001\n // \u53E4\u3044 in-flight \u30EC\u30B9\u30DD\u30F3\u30B9\u304C\u65B0\u3057\u3044\u7D50\u679C\u3092\u4E0A\u66F8\u304D\u3059\u308B race \u3068\u3001\n // \u30A2\u30F3\u30DE\u30A6\u30F3\u30C8\u5F8C\u306E setState \u3092\u9632\u3050\u3002\n const genRef = useRef(0);\n\n const params: GetEntitiesParams = {};\n if (options?.type) params.type = options.type;\n if (options?.limit) params.limit = options.limit;\n if (options?.attrs) params.attrs = options.attrs.join(',');\n if (options?.q) params.q = options.q;\n if (options?.scopeQ) params.scopeQ = options.scopeQ;\n\n const paramsKey = JSON.stringify(params);\n\n const fetchEntities = useCallback(async () => {\n const gen = ++genRef.current;\n setLoading(true);\n setError(null);\n try {\n const data = await client.getEntities(params);\n if (genRef.current === gen) setEntities(data as LdEntity[]);\n } catch (err) {\n if (genRef.current === gen) setError(err instanceof Error ? err : new Error('Unknown error'));\n } finally {\n if (genRef.current === gen) setLoading(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, paramsKey]);\n\n useEffect(() => {\n void fetchEntities();\n // \u30A2\u30F3\u30DE\u30A6\u30F3\u30C8 / deps \u5909\u5316\u3067 in-flight \u3092\u7121\u52B9\u5316\u3059\u308B\n return () => {\n genRef.current++;\n };\n }, [fetchEntities]);\n\n return { entities, loading, error, refetch: fetchEntities };\n}\n\n/**\n * Fetch NGSI-LD temporal (time-series) data using the GeonicDB SDK client.\n */\nexport function useTemporalData(\n client: GeonicDB | undefined,\n options: GetTemporalEntitiesParams & { enabled?: boolean },\n): {\n data: Record<string, unknown>[];\n loading: boolean;\n error: Error | null;\n refetch: () => Promise<void>;\n} {\n const [data, setData] = useState<Record<string, unknown>[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // useLdEntities \u3068\u540C\u3058\u304F\u3001\u53E4\u3044 in-flight \u30EC\u30B9\u30DD\u30F3\u30B9\u3068\u30A2\u30F3\u30DE\u30A6\u30F3\u30C8\u5F8C setState \u3092\u9632\u3050\u4E16\u4EE3\u30AB\u30A6\u30F3\u30BF\u3002\n const genRef = useRef(0);\n\n const enabled = options.enabled !== false;\n\n // Serialize all options as a stable cache key so that any param change triggers re-fetch.\n const optionsKey = JSON.stringify(options);\n\n const fetchData = useCallback(async () => {\n const gen = ++genRef.current;\n if (!enabled || !client) {\n setData([]);\n return;\n }\n\n setLoading(true);\n setError(null);\n try {\n if (options.id) {\n const entity = await client.getTemporalEntity(options.id);\n if (genRef.current === gen) setData([entity]);\n } else {\n const entities = await client.getTemporalEntities(options);\n if (genRef.current === gen) setData(entities);\n }\n } catch (err) {\n if (genRef.current === gen) setError(err instanceof Error ? err : new Error('Unknown error'));\n } finally {\n if (genRef.current === gen) setLoading(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [client, optionsKey]);\n\n useEffect(() => {\n void fetchData();\n // \u30A2\u30F3\u30DE\u30A6\u30F3\u30C8 / deps \u5909\u5316\u3067 in-flight \u3092\u7121\u52B9\u5316\u3059\u308B\n return () => {\n genRef.current++;\n };\n }, [fetchData]);\n\n return { data, loading, error, refetch: fetchData };\n}\n", "// SPDX-License-Identifier: MIT\n// Copyright (c) 2026 Geolonia Inc.\n// See LICENSE in src/sdk/ for full license text.\n\n/**\n * GeonicDbMap \u2014 Geolonia embed-based map component for GeonicDB entities.\n *\n * Ported from geonicdb-demo-app/packages/shared/src/components/GeonicDbMap.tsx.\n * @geolonia/embed is an optional peer dependency (required only when using this component).\n */\n\nimport { useEffect, useRef, useCallback, type CSSProperties } from 'react';\nimport type { Map as EmbedMap, Marker as EmbedMarker } from '@geolonia/embed';\nimport type { LdEntity, NgsiEntity, GeoJsonPoint } from './types.js';\n\nexport interface GeonicDbMapProps {\n center?: [number, number];\n zoom?: number;\n styleUrl?: string;\n /** Entities to display. Accepts both LdEntity (NGSI-LD) and NgsiEntity (NGSIv2). */\n entities?: (LdEntity | NgsiEntity)[];\n onEntityClick?: (entity: LdEntity | NgsiEntity) => void;\n onMapClick?: (lngLat: [number, number]) => void;\n className?: string;\n style?: CSSProperties;\n showPopups?: boolean;\n fitToMarkers?: boolean;\n}\n\nconst DEFAULT_STYLE = 'geolonia/basic';\n\nfunction escapeHtml(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n}\n\nfunction getEntityLocation(entity: LdEntity | NgsiEntity): [number, number] | null {\n const location = entity.location;\n if (!location || typeof location === 'string') return null;\n\n // NGSI-LD GeoProperty normalized: { type: \"GeoProperty\", value: { type: \"Point\", coordinates: [...] } }\n const ldLoc = location as { type?: string; value?: GeoJsonPoint };\n if (ldLoc.type === 'GeoProperty' && ldLoc.value?.type === 'Point' && Array.isArray(ldLoc.value.coordinates)) {\n return ldLoc.value.coordinates;\n }\n\n // NGSIv2 normalized: { type: \"geo:json\", value: { type: \"Point\", coordinates: [...] } }\n const v2Loc = location as { type?: string; value?: GeoJsonPoint };\n if (v2Loc.value?.type === 'Point' && Array.isArray(v2Loc.value.coordinates)) {\n return v2Loc.value.coordinates;\n }\n\n // keyValues: { type: \"Point\", coordinates: [...] }\n const kv = location as unknown as GeoJsonPoint;\n if (kv.type === 'Point' && Array.isArray(kv.coordinates)) {\n return kv.coordinates;\n }\n\n return null;\n}\n\nfunction getMarkerColor(entityType: string): string {\n const colors: Record<string, string> = {\n Room: '#3b82f6',\n ParkingSpot: '#22c55e',\n AirQualitySensor: '#f59e0b',\n TrafficFlow: '#ef4444',\n EnvironmentSensor: '#8b5cf6',\n EnvSensor: '#8b5cf6',\n TemperatureSensor: '#f97316',\n GeoFeature: '#0ea5e9',\n };\n return colors[entityType] ?? '#6b7280';\n}\n\nexport function GeonicDbMap({\n center = [139.7671, 35.6812],\n zoom = 13,\n styleUrl,\n entities = [],\n onEntityClick,\n onMapClick,\n className = '',\n style: customStyle,\n showPopups = true,\n fitToMarkers = false,\n}: GeonicDbMapProps) {\n const mapContainerRef = useRef<HTMLDivElement>(null);\n const mapRef = useRef<EmbedMap | null>(null);\n const markersRef = useRef<EmbedMarker[]>([]);\n const mapLoadedRef = useRef(false);\n const pendingUpdateRef = useRef(false);\n\n useEffect(() => {\n if (!mapContainerRef.current) return;\n\n mapLoadedRef.current = false;\n\n // Dynamic import to avoid bundling @geolonia/embed for non-map consumers.\n // @geolonia/embed is an optional peer dependency.\n void import('@geolonia/embed').then(({ Map: GeoMap }) => {\n if (!mapContainerRef.current) return;\n\n const map = new GeoMap({\n container: mapContainerRef.current,\n style: styleUrl ?? DEFAULT_STYLE,\n center,\n zoom,\n });\n\n mapRef.current = map;\n\n const onReady = () => {\n mapLoadedRef.current = true;\n if (pendingUpdateRef.current) {\n pendingUpdateRef.current = false;\n window.dispatchEvent(new CustomEvent('geonicdb-map-ready'));\n }\n };\n\n map.on('load', onReady);\n map.once('idle', onReady);\n\n if (onMapClick) {\n (map as unknown as { on: (e: string, cb: (e: { lngLat: { lng: number; lat: number } }) => void) => void }).on('click', (e) => {\n onMapClick([e.lngLat.lng, e.lngLat.lat]);\n });\n }\n });\n\n return () => {\n if (mapRef.current) {\n mapRef.current.remove();\n mapRef.current = null;\n mapLoadedRef.current = false;\n }\n };\n // center/zoom are intentionally excluded: the map is initialized once per styleUrl change.\n // Subsequent center/zoom updates should use imperative map methods (flyTo/jumpTo),\n // not re-mount the map. Markers/entities are updated via the doUpdate effect below.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [styleUrl]);\n\n const doUpdate = useCallback(() => {\n const map = mapRef.current;\n if (!map) return;\n\n markersRef.current.forEach((marker) => marker.remove());\n markersRef.current = [];\n\n void import('@geolonia/embed').then(({ Marker, geolonia }) => {\n entities.forEach((entity) => {\n const coords = getEntityLocation(entity);\n if (!coords) return;\n\n const color = getMarkerColor(entity.type);\n const el = document.createElement('div');\n el.style.cssText = `width:24px;height:24px;background-color:${color};border:2px solid white;border-radius:50%;cursor:pointer;box-shadow:0 2px 4px rgba(0,0,0,0.3);`;\n\n const marker = new Marker({ element: el }).setLngLat(coords).addTo(map);\n\n if (showPopups && geolonia?.Popup) {\n const popup = new geolonia.Popup({ closeButton: false, closeOnClick: false, offset: 15 })\n .setHTML(`<div style=\"font-family:sans-serif;font-size:12px;\"><strong>${escapeHtml(entity.id)}</strong><br/><span style=\"color:#666\">${escapeHtml(entity.type)}</span></div>`);\n el.addEventListener('mouseenter', () => { marker.setPopup(popup); popup.addTo(map); });\n el.addEventListener('mouseleave', () => { popup.remove(); });\n }\n\n if (onEntityClick) {\n el.addEventListener('click', (e) => { e.stopPropagation(); onEntityClick(entity); });\n }\n\n markersRef.current.push(marker);\n });\n\n if (fitToMarkers && markersRef.current.length > 0) {\n const allCoords = entities.map(getEntityLocation).filter((c): c is [number, number] => c !== null);\n if (allCoords.length === 1 && allCoords[0]) {\n map.flyTo({ center: allCoords[0], zoom: 14 });\n } else if (allCoords.length > 1) {\n const bounds = allCoords.reduce(\n (b, coord) => [[Math.min(b[0][0], coord[0]), Math.min(b[0][1], coord[1])], [Math.max(b[1][0], coord[0]), Math.max(b[1][1], coord[1])]] as [[number, number], [number, number]],\n [[allCoords[0]![0], allCoords[0]![1]], [allCoords[0]![0], allCoords[0]![1]]] as [[number, number], [number, number]]\n );\n map.fitBounds(bounds, { padding: 30 });\n }\n }\n });\n }, [entities, onEntityClick, showPopups, fitToMarkers]);\n\n useEffect(() => {\n if (mapLoadedRef.current) {\n doUpdate();\n } else {\n pendingUpdateRef.current = true;\n const handler = () => doUpdate();\n window.addEventListener('geonicdb-map-ready', handler, { once: true });\n return () => window.removeEventListener('geonicdb-map-ready', handler);\n }\n }, [doUpdate]);\n\n const defaultStyle: CSSProperties = { width: '100%', height: '100%', minHeight: '400px' };\n\n return (\n <div\n ref={mapContainerRef}\n className={className}\n style={{ ...defaultStyle, ...customStyle }}\n />\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_react"]
|
|
7
|
+
}
|
package/react/index.d.ts
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
+
|
|
3
|
+
import { CSSProperties } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Copyright (c) 2026 Geolonia Inc.
|
|
7
|
+
* Released under the MIT License. See src/sdk/LICENSE for details.
|
|
8
|
+
*/
|
|
9
|
+
/** Options for the GeonicDB SDK constructor. */
|
|
10
|
+
export interface GeonicDBOptions {
|
|
11
|
+
/** API key (or use data-api-key attribute on script tag) */
|
|
12
|
+
apiKey?: string;
|
|
13
|
+
/** Tenant name (or use data-tenant attribute on script tag) */
|
|
14
|
+
tenant?: string;
|
|
15
|
+
/** API base URL (auto-detected from script src if omitted) */
|
|
16
|
+
baseUrl?: string;
|
|
17
|
+
/** WebSocket endpoint URL (auto-detected from baseUrl if omitted) */
|
|
18
|
+
wsEndpoint?: string;
|
|
19
|
+
/** Enable debug logging to console (default: false) */
|
|
20
|
+
debug?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Enable in-memory client-side cache with automatic ETag/If-None-Match
|
|
23
|
+
* handling and request deduplication. (Phase A, default: true)
|
|
24
|
+
*/
|
|
25
|
+
cache?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Maximum number of cached entries (LRU eviction beyond this size).
|
|
28
|
+
* Only meaningful when `cache` is enabled. Default: 1000.
|
|
29
|
+
*/
|
|
30
|
+
cacheMaxEntries?: number;
|
|
31
|
+
/**
|
|
32
|
+
* #1105: Anonymous mode. When true, the SDK skips token acquisition and
|
|
33
|
+
* sends requests without an `Authorization` header. The server treats
|
|
34
|
+
* such requests as `role: 'anonymous'` and lets the XACML policy engine
|
|
35
|
+
* decide whether to permit them.
|
|
36
|
+
*
|
|
37
|
+
* - Cannot be combined with `apiKey` (constructor throws).
|
|
38
|
+
* - `login()` / `setCredentials()` switches the SDK out of anonymous mode
|
|
39
|
+
* for subsequent requests.
|
|
40
|
+
* - `logout()` reverts to anonymous mode.
|
|
41
|
+
* - WebSocket `connect()` is not supported in anonymous mode and throws.
|
|
42
|
+
*/
|
|
43
|
+
anonymous?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** Options for the SDK polling helper. */
|
|
46
|
+
export interface PollOptions<T = unknown> {
|
|
47
|
+
/** Polling interval in milliseconds (default: 5000). */
|
|
48
|
+
interval?: number;
|
|
49
|
+
/** Called when fresh data is received from the server (200). */
|
|
50
|
+
onData?: (data: T) => void;
|
|
51
|
+
/** Called when the server responded 304 (no change since last poll). */
|
|
52
|
+
onNoChange?: () => void;
|
|
53
|
+
/** Called on transport / HTTP errors. Polling continues unless the handler stops it. */
|
|
54
|
+
onError?: (error: unknown) => void;
|
|
55
|
+
}
|
|
56
|
+
/** Handle returned by `db.poll(...)` to control the polling loop. */
|
|
57
|
+
export interface PollHandle {
|
|
58
|
+
/** Stop the polling loop. Idempotent. */
|
|
59
|
+
stop(): void;
|
|
60
|
+
}
|
|
61
|
+
/** Options for setting credentials externally. */
|
|
62
|
+
export interface CredentialsOptions {
|
|
63
|
+
/** Access token (JWT) */
|
|
64
|
+
token: string;
|
|
65
|
+
/** Token type — default: 'Bearer' */
|
|
66
|
+
tokenType?: "Bearer" | "DPoP";
|
|
67
|
+
/** Token lifetime in seconds (default: 3600) */
|
|
68
|
+
expiresIn?: number;
|
|
69
|
+
/** Refresh token for auto-renewal */
|
|
70
|
+
refreshToken?: string;
|
|
71
|
+
}
|
|
72
|
+
/** Credentials returned after a token refresh. */
|
|
73
|
+
export interface RefreshedCredentials {
|
|
74
|
+
/** New access token */
|
|
75
|
+
token: string;
|
|
76
|
+
/** Token type */
|
|
77
|
+
tokenType: string;
|
|
78
|
+
/** Token lifetime in seconds */
|
|
79
|
+
expiresIn: number;
|
|
80
|
+
/** New refresh token */
|
|
81
|
+
refreshToken: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Parameters for querying entities.
|
|
85
|
+
*
|
|
86
|
+
* NGSI-LD 1.6 §5.7.2 Query Entities が定める主要パラメータを網羅する (#1132)。
|
|
87
|
+
* 以前はサーバ側が georel / scopeQ / attrs / pick / omit / lang などを実装
|
|
88
|
+
* しているのに SDK 側で型と URL builder が `type / limit / offset / q` の
|
|
89
|
+
* 4 つしか持たず、`db.request()` に逃げる必要があった。
|
|
90
|
+
*/
|
|
91
|
+
export interface GetEntitiesParams {
|
|
92
|
+
/** Entity type filter */
|
|
93
|
+
type?: string;
|
|
94
|
+
/** Max results */
|
|
95
|
+
limit?: number;
|
|
96
|
+
/** Pagination offset */
|
|
97
|
+
offset?: number;
|
|
98
|
+
/** NGSI-LD query expression */
|
|
99
|
+
q?: string;
|
|
100
|
+
/** NGSI-LD scope query expression (`/foo`, `/foo/#`, `/foo/+`, `;` で OR) */
|
|
101
|
+
scopeQ?: string;
|
|
102
|
+
/** Geo-relation: `near`, `within`, `contains`, `intersects`, `disjoint`, `equals` */
|
|
103
|
+
georel?: string;
|
|
104
|
+
/** Geometry type: `Point`, `Polygon`, `LineString`, ... */
|
|
105
|
+
geometry?: string;
|
|
106
|
+
/** Coordinates string (semicolon-delimited pairs or flat comma-separated) */
|
|
107
|
+
coordinates?: string;
|
|
108
|
+
/** Comma-separated attribute names to retrieve */
|
|
109
|
+
attrs?: string;
|
|
110
|
+
/** Comma-separated attribute names to keep (alternative to attrs) */
|
|
111
|
+
pick?: string;
|
|
112
|
+
/** Comma-separated attribute names to remove */
|
|
113
|
+
omit?: string;
|
|
114
|
+
/** Language tag for LanguageProperty filtering */
|
|
115
|
+
lang?: string;
|
|
116
|
+
/** Order by field */
|
|
117
|
+
orderBy?: string;
|
|
118
|
+
/** Order direction: `asc` (default) or `desc` */
|
|
119
|
+
orderDirection?: "asc" | "desc";
|
|
120
|
+
/** Sort points by distance from a `near` query */
|
|
121
|
+
orderByDistance?: boolean;
|
|
122
|
+
/** Whether the response should include a count (server returns `NGSILD-Results-Count` header) */
|
|
123
|
+
count?: boolean;
|
|
124
|
+
/** GeoProperty key to use (default `location`) */
|
|
125
|
+
geoproperty?: string;
|
|
126
|
+
/**
|
|
127
|
+
* NGSI-LD representation options (`options` query param)。カンマ区切りで複数指定可。
|
|
128
|
+
* - `sysAttrs` — システム属性 (`createdAt` / `modifiedAt`) を含める
|
|
129
|
+
* - `keyValues` — 簡易表現 (属性を値だけに圧縮)
|
|
130
|
+
* - `concise` — concise 表現
|
|
131
|
+
* - `normalized` — 正規化表現 (デフォルト)
|
|
132
|
+
*
|
|
133
|
+
* 例: `'sysAttrs'`, `'keyValues,sysAttrs'`。
|
|
134
|
+
*/
|
|
135
|
+
options?: string;
|
|
136
|
+
}
|
|
137
|
+
/** Parameters for counting entities. */
|
|
138
|
+
export interface CountEntitiesParams {
|
|
139
|
+
/** Entity type filter */
|
|
140
|
+
type?: string;
|
|
141
|
+
/** NGSI-LD query expression */
|
|
142
|
+
q?: string;
|
|
143
|
+
/** NGSI-LD scope query expression (#1132) */
|
|
144
|
+
scopeQ?: string;
|
|
145
|
+
}
|
|
146
|
+
/** Options for subscribing to entity events via WebSocket. */
|
|
147
|
+
export interface SubscribeOptions {
|
|
148
|
+
/** Entity types to subscribe to */
|
|
149
|
+
entityTypes?: string[];
|
|
150
|
+
/** Entity ID regex pattern */
|
|
151
|
+
idPattern?: string;
|
|
152
|
+
/** NGSI-LD scope query expression (#1132). Server-side filter; only events whose entity scope matches are delivered. */
|
|
153
|
+
scopeQ?: string;
|
|
154
|
+
}
|
|
155
|
+
/** Entity event received via WebSocket. */
|
|
156
|
+
export interface EntityEvent {
|
|
157
|
+
/** Event type */
|
|
158
|
+
type: "entityCreated" | "entityUpdated" | "entityDeleted";
|
|
159
|
+
/** Tenant name */
|
|
160
|
+
tenant: string;
|
|
161
|
+
/** Service path */
|
|
162
|
+
servicePath: string;
|
|
163
|
+
/** Entity ID */
|
|
164
|
+
entityId: string;
|
|
165
|
+
/** Entity type */
|
|
166
|
+
entityType: string;
|
|
167
|
+
/** Entity attributes */
|
|
168
|
+
data: Record<string, unknown>;
|
|
169
|
+
/** Complete NGSI-LD entity (id + type + attributes from data). Undefined when data is unavailable (e.g. some delete events). */
|
|
170
|
+
entity?: Record<string, unknown>;
|
|
171
|
+
/** Changed attribute names (update only) */
|
|
172
|
+
changedAttributes?: string[];
|
|
173
|
+
/** ISO 8601 timestamp */
|
|
174
|
+
timestamp: string;
|
|
175
|
+
}
|
|
176
|
+
/** Event fired when a reconnection attempt is starting. */
|
|
177
|
+
export interface ReconnectingEvent {
|
|
178
|
+
/** Current reconnection attempt number */
|
|
179
|
+
attempt: number;
|
|
180
|
+
/** Delay in ms before this attempt */
|
|
181
|
+
delay: number;
|
|
182
|
+
}
|
|
183
|
+
/** Options for `db.login(...)`. */
|
|
184
|
+
export interface LoginOptions {
|
|
185
|
+
/**
|
|
186
|
+
* If true, keep the user signed in across page reloads by persisting the
|
|
187
|
+
* session to IndexedDB. After a reload, call `db.restoreSession()` to
|
|
188
|
+
* rehydrate the session; `db.logout()` clears the persisted entry.
|
|
189
|
+
*
|
|
190
|
+
* The session is bound to a non-extractable key (DPoP, RFC 9449) stored via
|
|
191
|
+
* the structured clone algorithm — `extractable: false` is preserved, so the
|
|
192
|
+
* key cannot be read back as JWK / PEM even with full DOM access. A token
|
|
193
|
+
* leaked from localStorage stays unusable without this origin's IndexedDB.
|
|
194
|
+
*
|
|
195
|
+
* Default: false. Opt-out by design: shared-device flows should not enable
|
|
196
|
+
* this. Has no effect when the runtime lacks Web Crypto — the session cannot
|
|
197
|
+
* be sender-constrained, so it is not persisted.
|
|
198
|
+
*/
|
|
199
|
+
rememberSession?: boolean;
|
|
200
|
+
}
|
|
201
|
+
/** Response from the login endpoint. */
|
|
202
|
+
export interface LoginResponse {
|
|
203
|
+
accessToken: string;
|
|
204
|
+
refreshToken: string;
|
|
205
|
+
expiresIn: number;
|
|
206
|
+
/**
|
|
207
|
+
* Token scheme: `Bearer` (default) or `DPoP` when the session has been
|
|
208
|
+
* sender-constrained via `/auth/dpop-bind` (RFC 9449). Optional for
|
|
209
|
+
* backward compatibility with older server responses.
|
|
210
|
+
*/
|
|
211
|
+
tokenType?: "Bearer" | "DPoP";
|
|
212
|
+
}
|
|
213
|
+
/** Cache event payloads. */
|
|
214
|
+
export interface CacheEvent {
|
|
215
|
+
/** Cache key (typically `${method}:${path}` form). */
|
|
216
|
+
key: string;
|
|
217
|
+
/** Resource path (without method prefix). */
|
|
218
|
+
path: string;
|
|
219
|
+
}
|
|
220
|
+
/** Map of event names to their payload types. */
|
|
221
|
+
export interface GeonicDBEventMap {
|
|
222
|
+
entityCreated: EntityEvent;
|
|
223
|
+
entityUpdated: EntityEvent;
|
|
224
|
+
entityDeleted: EntityEvent;
|
|
225
|
+
open: undefined;
|
|
226
|
+
connected: undefined;
|
|
227
|
+
close: {
|
|
228
|
+
code: number;
|
|
229
|
+
reason: string;
|
|
230
|
+
};
|
|
231
|
+
disconnected: undefined;
|
|
232
|
+
reconnecting: ReconnectingEvent;
|
|
233
|
+
error: Error;
|
|
234
|
+
message: Record<string, unknown>;
|
|
235
|
+
tokenRefresh: RefreshedCredentials;
|
|
236
|
+
/** Fired when a request is served from the in-memory cache (304 received). */
|
|
237
|
+
cacheHit: CacheEvent;
|
|
238
|
+
/** Fired when a request misses cache and is fetched from the origin. */
|
|
239
|
+
cacheMiss: CacheEvent;
|
|
240
|
+
/** Fired when a cache entry is invalidated (e.g. by a WebSocket entity event). */
|
|
241
|
+
cacheInvalidated: CacheEvent;
|
|
242
|
+
}
|
|
243
|
+
/** Parameters for querying temporal entities. */
|
|
244
|
+
export interface GetTemporalEntitiesParams {
|
|
245
|
+
/** Entity type filter */
|
|
246
|
+
type?: string;
|
|
247
|
+
/** Entity ID */
|
|
248
|
+
id?: string;
|
|
249
|
+
/** Entity ID pattern (regex) */
|
|
250
|
+
idPattern?: string;
|
|
251
|
+
/** Attribute names to retrieve */
|
|
252
|
+
attrs?: string;
|
|
253
|
+
/** NGSI-LD query expression */
|
|
254
|
+
q?: string;
|
|
255
|
+
/** Time property to use (observedAt, createdAt, modifiedAt) */
|
|
256
|
+
timeproperty?: string;
|
|
257
|
+
/** Start time (ISO 8601) */
|
|
258
|
+
timeAt?: string;
|
|
259
|
+
/** End time (ISO 8601) */
|
|
260
|
+
endTimeAt?: string;
|
|
261
|
+
/** Temporal relation (before, after, between) */
|
|
262
|
+
timerel?: string;
|
|
263
|
+
/** NGSI-LD scope query expression (#1132) */
|
|
264
|
+
scopeQ?: string;
|
|
265
|
+
/** Max results */
|
|
266
|
+
limit?: number;
|
|
267
|
+
/** Pagination offset */
|
|
268
|
+
offset?: number;
|
|
269
|
+
/**
|
|
270
|
+
* NGSI-LD representation options (`options` query param)。カンマ区切りで複数指定可。
|
|
271
|
+
* - `sysAttrs` — システム属性 (`createdAt` / `modifiedAt`) を含める
|
|
272
|
+
* - `temporalValues` — 時系列を簡易配列表現で返す
|
|
273
|
+
* - `aggregatedValues` — 集約表現で返す
|
|
274
|
+
*
|
|
275
|
+
* 例: `'sysAttrs'`, `'temporalValues'`。
|
|
276
|
+
*/
|
|
277
|
+
options?: string;
|
|
278
|
+
}
|
|
279
|
+
export type Listener<T> = (data: T) => void;
|
|
280
|
+
declare class EventEmitter {
|
|
281
|
+
private _listeners;
|
|
282
|
+
on<K extends keyof GeonicDBEventMap>(event: K, callback: Listener<GeonicDBEventMap[K]>): this;
|
|
283
|
+
on(event: string, callback: Listener<unknown>): this;
|
|
284
|
+
off<K extends keyof GeonicDBEventMap>(event: K, callback?: Listener<GeonicDBEventMap[K]>): this;
|
|
285
|
+
off(event: string, callback?: Listener<unknown>): this;
|
|
286
|
+
protected emit<K extends keyof GeonicDBEventMap>(event: K, data?: GeonicDBEventMap[K]): void;
|
|
287
|
+
protected emit(event: string, data?: unknown): void;
|
|
288
|
+
}
|
|
289
|
+
declare class GeonicDB extends EventEmitter {
|
|
290
|
+
private _auth;
|
|
291
|
+
private _ws;
|
|
292
|
+
/**
|
|
293
|
+
* Legacy callback for token refresh events.
|
|
294
|
+
* Prefer `db.on('tokenRefresh', callback)` for new code.
|
|
295
|
+
* @deprecated Use `db.on('tokenRefresh', callback)` instead.
|
|
296
|
+
*/
|
|
297
|
+
onTokenRefresh: ((creds: RefreshedCredentials) => void) | null;
|
|
298
|
+
constructor(options?: GeonicDBOptions);
|
|
299
|
+
/**
|
|
300
|
+
* Drop every cached response. Useful in tests and on manual auth changes.
|
|
301
|
+
*
|
|
302
|
+
* Emits a `cacheInvalidated` event for each removed entry so listeners can
|
|
303
|
+
* track explicit flushes (the WebSocket-driven auto-invalidation was removed
|
|
304
|
+
* in #1060 to preserve the ETag/304 revalidation path; `clearCache()` is now
|
|
305
|
+
* the only path that emits this event).
|
|
306
|
+
*/
|
|
307
|
+
clearCache(): void;
|
|
308
|
+
/**
|
|
309
|
+
* Login with email and password.
|
|
310
|
+
*
|
|
311
|
+
* The session is sender-constrained with DPoP (RFC 9449) automatically and
|
|
312
|
+
* transparently — there is no DPoP option to set. A token leaked from
|
|
313
|
+
* storage (e.g. localStorage XSS) is therefore unusable from another origin.
|
|
314
|
+
* On runtimes without Web Crypto, the SDK silently keeps a plain Bearer
|
|
315
|
+
* session and login still succeeds.
|
|
316
|
+
*
|
|
317
|
+
* @example
|
|
318
|
+
* ```ts
|
|
319
|
+
* // Standard login — DPoP applied transparently when supported.
|
|
320
|
+
* await db.login('user@example.com', 'password');
|
|
321
|
+
*
|
|
322
|
+
* // Keep the user signed in across page reloads (browser SPA UX).
|
|
323
|
+
* await db.login('user@example.com', 'password', { rememberSession: true });
|
|
324
|
+
* ```
|
|
325
|
+
*/
|
|
326
|
+
login(email: string, password: string, options?: LoginOptions): Promise<LoginResponse>;
|
|
327
|
+
/**
|
|
328
|
+
* Rehydrate a session previously persisted via
|
|
329
|
+
* `login(email, password, { rememberSession: true })`.
|
|
330
|
+
*
|
|
331
|
+
* Returns true if a session for this tenant was found and loaded; false
|
|
332
|
+
* if there was no entry, IndexedDB is unavailable, or the persisted
|
|
333
|
+
* session was malformed. Call this at app startup before deciding
|
|
334
|
+
* whether to render the login form.
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* ```ts
|
|
338
|
+
* const db = new GeonicDB({ baseUrl, tenant });
|
|
339
|
+
* if (await db.restoreSession()) {
|
|
340
|
+
* // Session (tokens + non-extractable key) recovered — boot the app.
|
|
341
|
+
* } else {
|
|
342
|
+
* // No session; show the login form.
|
|
343
|
+
* }
|
|
344
|
+
* ```
|
|
345
|
+
*/
|
|
346
|
+
restoreSession(): Promise<boolean>;
|
|
347
|
+
/**
|
|
348
|
+
* Whether the SDK is currently operating in anonymous mode (no token held).
|
|
349
|
+
* Returns true only when `anonymous: true` was passed to the constructor
|
|
350
|
+
* AND no credentials have been set via `login()` / `setCredentials()`.
|
|
351
|
+
*/
|
|
352
|
+
isAnonymous(): boolean;
|
|
353
|
+
/**
|
|
354
|
+
* Set credentials externally (e.g. from a login API response).
|
|
355
|
+
* When tokenType is 'Bearer' with a refreshToken, DPoP/PoW is bypassed entirely.
|
|
356
|
+
*/
|
|
357
|
+
setCredentials(opts: CredentialsOptions): this;
|
|
358
|
+
/** Clear all credentials and disconnect. */
|
|
359
|
+
logout(): void;
|
|
360
|
+
/** Create a new entity. */
|
|
361
|
+
createEntity(entity: Record<string, unknown>): Promise<{
|
|
362
|
+
created: true;
|
|
363
|
+
}>;
|
|
364
|
+
/** Get a single entity by ID. */
|
|
365
|
+
getEntity(entityId: string): Promise<Record<string, unknown>>;
|
|
366
|
+
/** Query entities with optional filters. */
|
|
367
|
+
getEntities(params?: GetEntitiesParams): Promise<Record<string, unknown>[]>;
|
|
368
|
+
/**
|
|
369
|
+
* Poll for entity list changes using ETag-based revalidation (#991 Phase A).
|
|
370
|
+
*
|
|
371
|
+
* The handle's `stop()` ends the loop. Each tick performs a normal
|
|
372
|
+
* `getEntities()` call; the SDK's cache layer issues `If-None-Match`
|
|
373
|
+
* automatically. The poll detects "no change" by comparing the previous
|
|
374
|
+
* ETag with the response's ETag (the cache exposes the cached ETag on 304
|
|
375
|
+
* replays as well, so the comparison stays valid in both 200 and 304
|
|
376
|
+
* paths).
|
|
377
|
+
*
|
|
378
|
+
* @example
|
|
379
|
+
* ```typescript
|
|
380
|
+
* const handle = db.poll({ type: 'Room' }, {
|
|
381
|
+
* interval: 5000,
|
|
382
|
+
* onData: (rooms) => render(rooms),
|
|
383
|
+
* onNoChange: () => {},
|
|
384
|
+
* });
|
|
385
|
+
* // ...later
|
|
386
|
+
* handle.stop();
|
|
387
|
+
* ```
|
|
388
|
+
*/
|
|
389
|
+
poll(params: GetEntitiesParams | undefined, options: PollOptions<Record<string, unknown>[]>): PollHandle;
|
|
390
|
+
/** Count entities matching the given filters. */
|
|
391
|
+
count(params?: CountEntitiesParams): Promise<number>;
|
|
392
|
+
/** Update entity attributes (partial). */
|
|
393
|
+
updateEntity(entityId: string, attrs: Record<string, unknown>): Promise<{
|
|
394
|
+
updated: true;
|
|
395
|
+
}>;
|
|
396
|
+
/** Delete an entity. */
|
|
397
|
+
deleteEntity(entityId: string): Promise<{
|
|
398
|
+
deleted: true;
|
|
399
|
+
}>;
|
|
400
|
+
/** List all entity types. */
|
|
401
|
+
getTypes(): Promise<Record<string, unknown>[]>;
|
|
402
|
+
/** Get details for a specific entity type. */
|
|
403
|
+
getType(typeName: string): Promise<Record<string, unknown>>;
|
|
404
|
+
/** List all attributes. */
|
|
405
|
+
getAttributes(): Promise<Record<string, unknown>[]>;
|
|
406
|
+
/** Get details for a specific attribute. */
|
|
407
|
+
getAttribute(attrName: string): Promise<Record<string, unknown>>;
|
|
408
|
+
/** Query temporal entities. */
|
|
409
|
+
getTemporalEntities(params?: GetTemporalEntitiesParams): Promise<Record<string, unknown>[]>;
|
|
410
|
+
/** Get temporal representation of a single entity. */
|
|
411
|
+
getTemporalEntity(entityId: string): Promise<Record<string, unknown>>;
|
|
412
|
+
/** Create multiple entities in a single request. */
|
|
413
|
+
batchCreate(entities: Record<string, unknown>[]): Promise<Record<string, unknown>>;
|
|
414
|
+
/** Upsert multiple entities in a single request. */
|
|
415
|
+
batchUpsert(entities: Record<string, unknown>[]): Promise<Record<string, unknown>>;
|
|
416
|
+
/** Update multiple entities in a single request. */
|
|
417
|
+
batchUpdate(entities: Record<string, unknown>[]): Promise<Record<string, unknown>>;
|
|
418
|
+
/** Delete multiple entities by ID. */
|
|
419
|
+
batchDelete(entityIds: string[]): Promise<Record<string, unknown>>;
|
|
420
|
+
/** GET request that returns parsed JSON or throws. */
|
|
421
|
+
private _jsonGet;
|
|
422
|
+
/** POST request that returns parsed JSON or throws. */
|
|
423
|
+
private _jsonPost;
|
|
424
|
+
/**
|
|
425
|
+
* Make an authenticated API request.
|
|
426
|
+
* Automatically checks response status, parses JSON, and throws on error.
|
|
427
|
+
*
|
|
428
|
+
* Empty bodies (`Content-Length: 0` 含む) は Content-Type に関係なく `null`
|
|
429
|
+
* を返す (#1145)。NGSI-LD の POST / DELETE / PATCH 系は仕様上ボディが
|
|
430
|
+
* 空だが、サーバ実装が `Content-Type: application/ld+json` を付けて返す
|
|
431
|
+
* ケースがあり、そこで `res.json()` が SyntaxError を投げて止まっていた。
|
|
432
|
+
*/
|
|
433
|
+
request(method: string, path: string, body?: unknown): Promise<unknown>;
|
|
434
|
+
/**
|
|
435
|
+
* Make an authenticated API request and return the raw Response object.
|
|
436
|
+
* Use this when you need access to response headers (e.g. NGSILD-Results-Count).
|
|
437
|
+
*/
|
|
438
|
+
requestRaw(method: string, path: string, body?: unknown): Promise<Response>;
|
|
439
|
+
/** Establish WebSocket connection (authentication is automatic). */
|
|
440
|
+
connect(): Promise<void>;
|
|
441
|
+
/** Force-reconnect (closes existing connection, preserves subscriptions). */
|
|
442
|
+
reconnect(): Promise<void>;
|
|
443
|
+
/** Disconnect WebSocket (does not fire 'disconnected' event). */
|
|
444
|
+
disconnect(): void;
|
|
445
|
+
/** Check if WebSocket is currently open. */
|
|
446
|
+
isConnected(): boolean;
|
|
447
|
+
/** Subscribe to entity events (can be called before or after connect). */
|
|
448
|
+
subscribe(options?: SubscribeOptions): void;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* NGSI-LD and GeoJSON types for the ./react subpath.
|
|
452
|
+
*/
|
|
453
|
+
export interface GeoJsonPoint {
|
|
454
|
+
type: "Point";
|
|
455
|
+
coordinates: [
|
|
456
|
+
number,
|
|
457
|
+
number
|
|
458
|
+
];
|
|
459
|
+
}
|
|
460
|
+
export interface GeoJsonPolygon {
|
|
461
|
+
type: "Polygon";
|
|
462
|
+
coordinates: number[][][];
|
|
463
|
+
}
|
|
464
|
+
export type GeoJsonGeometry = GeoJsonPoint | GeoJsonPolygon;
|
|
465
|
+
/** NGSI-LD Property */
|
|
466
|
+
export interface LdProperty {
|
|
467
|
+
type: "Property";
|
|
468
|
+
value: string | number | boolean | null;
|
|
469
|
+
observedAt?: string;
|
|
470
|
+
}
|
|
471
|
+
/** NGSI-LD GeoProperty */
|
|
472
|
+
export interface LdGeoProperty {
|
|
473
|
+
type: "GeoProperty";
|
|
474
|
+
value: GeoJsonGeometry;
|
|
475
|
+
observedAt?: string;
|
|
476
|
+
}
|
|
477
|
+
/** NGSI-LD Relationship */
|
|
478
|
+
export interface LdRelationship {
|
|
479
|
+
type: "Relationship";
|
|
480
|
+
object: string;
|
|
481
|
+
observedAt?: string;
|
|
482
|
+
}
|
|
483
|
+
export type LdAttribute = LdProperty | LdGeoProperty | LdRelationship;
|
|
484
|
+
/** NGSI-LD Entity */
|
|
485
|
+
export interface LdEntity {
|
|
486
|
+
id: string;
|
|
487
|
+
type: string;
|
|
488
|
+
[key: string]: string | LdAttribute | undefined;
|
|
489
|
+
}
|
|
490
|
+
/** Options for querying NGSI-LD entities */
|
|
491
|
+
export interface LdQueryOptions {
|
|
492
|
+
type?: string;
|
|
493
|
+
limit?: number;
|
|
494
|
+
attrs?: string[];
|
|
495
|
+
q?: string;
|
|
496
|
+
scopeQ?: string;
|
|
497
|
+
}
|
|
498
|
+
/** NGSIv2 Entity for map display */
|
|
499
|
+
export interface NgsiEntity {
|
|
500
|
+
id: string;
|
|
501
|
+
type: string;
|
|
502
|
+
[key: string]: string | NgsiAttribute | undefined;
|
|
503
|
+
}
|
|
504
|
+
export interface NgsiAttribute {
|
|
505
|
+
type: string;
|
|
506
|
+
value: string | number | boolean | object | null;
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Fetch NGSI-LD entities using the GeonicDB SDK client.
|
|
510
|
+
*
|
|
511
|
+
* The official SDK core handles DPoP / auth transparently.
|
|
512
|
+
*/
|
|
513
|
+
export declare function useLdEntities(client: GeonicDB, options?: LdQueryOptions): {
|
|
514
|
+
entities: LdEntity[];
|
|
515
|
+
loading: boolean;
|
|
516
|
+
error: Error | null;
|
|
517
|
+
refetch: () => Promise<void>;
|
|
518
|
+
};
|
|
519
|
+
/**
|
|
520
|
+
* Fetch NGSI-LD temporal (time-series) data using the GeonicDB SDK client.
|
|
521
|
+
*/
|
|
522
|
+
export declare function useTemporalData(client: GeonicDB | undefined, options: GetTemporalEntitiesParams & {
|
|
523
|
+
enabled?: boolean;
|
|
524
|
+
}): {
|
|
525
|
+
data: Record<string, unknown>[];
|
|
526
|
+
loading: boolean;
|
|
527
|
+
error: Error | null;
|
|
528
|
+
refetch: () => Promise<void>;
|
|
529
|
+
};
|
|
530
|
+
export interface GeonicDbMapProps {
|
|
531
|
+
center?: [
|
|
532
|
+
number,
|
|
533
|
+
number
|
|
534
|
+
];
|
|
535
|
+
zoom?: number;
|
|
536
|
+
styleUrl?: string;
|
|
537
|
+
/** Entities to display. Accepts both LdEntity (NGSI-LD) and NgsiEntity (NGSIv2). */
|
|
538
|
+
entities?: (LdEntity | NgsiEntity)[];
|
|
539
|
+
onEntityClick?: (entity: LdEntity | NgsiEntity) => void;
|
|
540
|
+
onMapClick?: (lngLat: [
|
|
541
|
+
number,
|
|
542
|
+
number
|
|
543
|
+
]) => void;
|
|
544
|
+
className?: string;
|
|
545
|
+
style?: CSSProperties;
|
|
546
|
+
showPopups?: boolean;
|
|
547
|
+
fitToMarkers?: boolean;
|
|
548
|
+
}
|
|
549
|
+
export declare function GeonicDbMap({ center, zoom, styleUrl, entities, onEntityClick, onMapClick, className, style: customStyle, showPopups, fitToMarkers, }: GeonicDbMapProps): import("react").JSX.Element;
|
|
550
|
+
|
|
551
|
+
export {};
|