@geolonia/geonicdb-sdk 0.2.0 → 0.2.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Geolonia Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -47,19 +47,6 @@ await db.createEntity({
47
47
  </script>
48
48
  ```
49
49
 
50
- ### Browser (direct distribution from GeonicDB)
51
-
52
- ```html
53
- <script src="https://your-geonicdb.example.com/sdk/v1/geonicdb.js"
54
- data-api-key="your-api-key"
55
- data-tenant="your-tenant"
56
- data-base-url="https://your-geonicdb.example.com"></script>
57
- <script>
58
- var db = new GeonicDB(); // auto-initialized from data-* attributes
59
- db.getEntities({ type: 'Room' }).then(console.log);
60
- </script>
61
- ```
62
-
63
50
  ## Authentication
64
51
 
65
52
  ### API Key (DPoP + Proof of Work)
@@ -189,6 +176,130 @@ await db.connect();
189
176
  | `error` | `Error` | Error occurred |
190
177
  | `tokenRefresh` | `RefreshedCredentials` | Bearer token was refreshed |
191
178
 
179
+ ## API Reference
180
+
181
+ ### Constructor
182
+
183
+ | Method | Parameters | Returns | Description |
184
+ |--------|-----------|---------|-------------|
185
+ | `new GeonicDB(options?)` | `GeonicDBOptions` | `GeonicDB` | Create a new SDK instance |
186
+
187
+ #### `GeonicDBOptions`
188
+
189
+ | Property | Type | Required | Description |
190
+ |----------|------|----------|-------------|
191
+ | `apiKey` | `string` | No | API key (or use `data-api-key` attribute on script tag) |
192
+ | `tenant` | `string` | No | Tenant name (or use `data-tenant` attribute on script tag) |
193
+ | `baseUrl` | `string` | No | API base URL (auto-detected from script `src` if omitted) |
194
+ | `wsEndpoint` | `string` | No | WebSocket endpoint URL (auto-detected from `baseUrl` if omitted) |
195
+
196
+ ### Authentication
197
+
198
+ | Method | Parameters | Returns | Description |
199
+ |--------|-----------|---------|-------------|
200
+ | `login(email, password)` | `string, string` | `Promise<LoginResponse>` | Login with email and password (Bearer JWT) |
201
+ | `setCredentials(opts)` | `CredentialsOptions` | `this` | Set credentials externally (e.g. from a login API response) |
202
+ | `logout()` | — | `void` | Clear all credentials and disconnect WebSocket |
203
+
204
+ ### Entity CRUD
205
+
206
+ | Method | Parameters | Returns | Description |
207
+ |--------|-----------|---------|-------------|
208
+ | `createEntity(entity)` | `Record<string, unknown>` | `Promise<{ created: true }>` | Create a new entity |
209
+ | `getEntity(entityId)` | `string` | `Promise<Record<string, unknown>>` | Get a single entity by ID |
210
+ | `getEntities(params?)` | `GetEntitiesParams` | `Promise<Record<string, unknown>[]>` | Query entities with optional filters |
211
+ | `count(params?)` | `CountEntitiesParams` | `Promise<number>` | Count entities matching the given filters |
212
+ | `updateEntity(entityId, attrs)` | `string, Record<string, unknown>` | `Promise<{ updated: true }>` | Update entity attributes (partial) |
213
+ | `deleteEntity(entityId)` | `string` | `Promise<{ deleted: true }>` | Delete an entity |
214
+
215
+ #### `GetEntitiesParams`
216
+
217
+ | Property | Type | Description |
218
+ |----------|------|-------------|
219
+ | `type` | `string` | Entity type filter |
220
+ | `limit` | `number` | Max results |
221
+ | `offset` | `number` | Pagination offset |
222
+ | `q` | `string` | NGSI-LD query expression |
223
+
224
+ #### `CountEntitiesParams`
225
+
226
+ | Property | Type | Description |
227
+ |----------|------|-------------|
228
+ | `type` | `string` | Entity type filter |
229
+ | `q` | `string` | NGSI-LD query expression |
230
+
231
+ ### Types / Attributes Discovery
232
+
233
+ | Method | Parameters | Returns | Description |
234
+ |--------|-----------|---------|-------------|
235
+ | `getTypes()` | — | `Promise<Record<string, unknown>[]>` | List all entity types |
236
+ | `getType(typeName)` | `string` | `Promise<Record<string, unknown>>` | Get details for a specific entity type |
237
+ | `getAttributes()` | — | `Promise<Record<string, unknown>[]>` | List all attributes |
238
+ | `getAttribute(attrName)` | `string` | `Promise<Record<string, unknown>>` | Get details for a specific attribute |
239
+
240
+ ### Temporal API
241
+
242
+ | Method | Parameters | Returns | Description |
243
+ |--------|-----------|---------|-------------|
244
+ | `getTemporalEntities(params?)` | `GetTemporalEntitiesParams` | `Promise<Record<string, unknown>[]>` | Query temporal entities |
245
+ | `getTemporalEntity(entityId)` | `string` | `Promise<Record<string, unknown>>` | Get temporal representation of a single entity |
246
+
247
+ #### `GetTemporalEntitiesParams`
248
+
249
+ | Property | Type | Description |
250
+ |----------|------|-------------|
251
+ | `type` | `string` | Entity type filter |
252
+ | `id` | `string` | Entity ID |
253
+ | `idPattern` | `string` | Entity ID pattern (regex) |
254
+ | `attrs` | `string` | Attribute names to retrieve |
255
+ | `q` | `string` | NGSI-LD query expression |
256
+ | `timeproperty` | `string` | Time property (`observedAt`, `createdAt`, `modifiedAt`) |
257
+ | `timeAt` | `string` | Start time (ISO 8601) |
258
+ | `endTimeAt` | `string` | End time (ISO 8601) |
259
+ | `timerel` | `string` | Temporal relation (`before`, `after`, `between`) |
260
+ | `limit` | `number` | Max results |
261
+ | `offset` | `number` | Pagination offset |
262
+
263
+ ### Batch Operations
264
+
265
+ | Method | Parameters | Returns | Description |
266
+ |--------|-----------|---------|-------------|
267
+ | `batchCreate(entities)` | `Record<string, unknown>[]` | `Promise<Record<string, unknown>>` | Create multiple entities |
268
+ | `batchUpsert(entities)` | `Record<string, unknown>[]` | `Promise<Record<string, unknown>>` | Upsert multiple entities |
269
+ | `batchUpdate(entities)` | `Record<string, unknown>[]` | `Promise<Record<string, unknown>>` | Update multiple entities |
270
+ | `batchDelete(entityIds)` | `string[]` | `Promise<Record<string, unknown>>` | Delete multiple entities by ID |
271
+
272
+ ### Generic Request
273
+
274
+ | Method | Parameters | Returns | Description |
275
+ |--------|-----------|---------|-------------|
276
+ | `request(method, path, body?)` | `string, string, unknown` | `Promise<unknown>` | Authenticated request with automatic JSON parsing |
277
+ | `requestRaw(method, path, body?)` | `string, string, unknown` | `Promise<Response>` | Authenticated request returning raw `Response` (for accessing headers) |
278
+
279
+ ### WebSocket
280
+
281
+ | Method | Parameters | Returns | Description |
282
+ |--------|-----------|---------|-------------|
283
+ | `connect()` | — | `Promise<void>` | Establish WebSocket connection |
284
+ | `reconnect()` | — | `Promise<void>` | Force-reconnect (preserves subscriptions) |
285
+ | `disconnect()` | — | `void` | Disconnect WebSocket |
286
+ | `isConnected()` | — | `boolean` | Check if WebSocket is currently open |
287
+ | `subscribe(options?)` | `SubscribeOptions` | `void` | Subscribe to entity events |
288
+
289
+ #### `SubscribeOptions`
290
+
291
+ | Property | Type | Description |
292
+ |----------|------|-------------|
293
+ | `entityTypes` | `string[]` | Entity types to subscribe to |
294
+ | `idPattern` | `string` | Entity ID regex pattern |
295
+
296
+ ### Event Handling
297
+
298
+ | Method | Parameters | Returns | Description |
299
+ |--------|-----------|---------|-------------|
300
+ | `on(event, listener)` | `string, Function` | `this` | Register an event listener |
301
+ | `off(event, listener)` | `string, Function` | `this` | Remove an event listener |
302
+
192
303
  ## License
193
304
 
194
- AGPL-3.0-or-later
305
+ MIT
package/geonicdb.cjs.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/sdk/index.ts", "../../src/sdk/events.ts", "../../src/sdk/dpop.ts", "../../src/sdk/pow.ts", "../../src/sdk/constants.ts", "../../src/sdk/auth.ts", "../../src/sdk/websocket.ts"],
4
- "sourcesContent": ["/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\n/**\n * GeonicDB JavaScript SDK\n *\n * NGSI-LD Context Broker client for browser and Node.js.\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ndeclare const document: any;\ndeclare const window: any;\n\nimport { EventEmitter } from './events';\nimport { AuthManager } from './auth';\nimport { WebSocketManager } from './websocket';\nimport type {\n GeonicDBOptions,\n CredentialsOptions,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n// Re-export types for consumers\nexport type {\n GeonicDBOptions,\n CredentialsOptions,\n RefreshedCredentials,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n EntityEvent,\n ReconnectingEvent,\n LoginResponse,\n GeonicDBEventMap,\n} from './types';\n\n/**\n * GeonicDB SDK client.\n *\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n *\n * @example\n * ```typescript\n * import GeonicDB from '@geolonia/geonicdb-sdk';\n *\n * const db = new GeonicDB({\n * apiKey: 'your-api-key',\n * tenant: 'your-tenant',\n * baseUrl: 'https://your-geonicdb.example.com',\n * });\n *\n * const entities = await db.getEntities({ type: 'Room' });\n * ```\n */\nexport class GeonicDB extends EventEmitter {\n private _auth: AuthManager;\n private _ws: WebSocketManager;\n\n /**\n * Legacy callback for token refresh events.\n * Prefer `db.on('tokenRefresh', callback)` for new code.\n * @deprecated Use `db.on('tokenRefresh', callback)` instead.\n */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(options?: GeonicDBOptions) {\n super();\n const opts = options || {};\n\n // Auto-detect from script tag in browser\n let apiKey = opts.apiKey || '';\n let tenant = opts.tenant || '';\n let baseUrl = opts.baseUrl || '';\n\n /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n if (typeof document !== 'undefined' && document.currentScript) {\n const script = document.currentScript;\n if (!apiKey) apiKey = script?.getAttribute?.('data-api-key') || '';\n if (!tenant) tenant = script?.getAttribute?.('data-tenant') || '';\n if (!baseUrl) baseUrl = script?.getAttribute?.('data-base-url') || '';\n }\n /* eslint-enable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n\n this._auth = new AuthManager(baseUrl, apiKey, tenant);\n this._auth.onTokenRefresh = (creds): void => {\n this.onTokenRefresh?.(creds);\n this.emit('tokenRefresh', creds);\n };\n this._ws = new WebSocketManager(\n this._auth,\n baseUrl,\n tenant,\n (event, data) => this.emit(event, data),\n opts.wsEndpoint,\n );\n }\n\n // --- Authentication ---\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n return this._auth.login(email, password);\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' with a refreshToken, DPoP/PoW is bypassed entirely.\n */\n setCredentials(opts: CredentialsOptions): this {\n this._auth.setCredentials(opts);\n return this;\n }\n\n /** Clear all credentials and disconnect. */\n logout(): void {\n this._ws.disconnect();\n this._auth.logout();\n }\n\n // --- Entity CRUD (NGSI-LD) ---\n\n /** Create a new entity. */\n async createEntity(\n entity: Record<string, unknown>,\n ): Promise<{ created: true }> {\n const res = await this._auth.request('POST', '/ngsi-ld/v1/entities', entity);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Create failed',\n );\n }\n return { created: true };\n }\n\n /** Get a single entity by ID. */\n async getEntity(entityId: string): Promise<Record<string, unknown>> {\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Not found',\n );\n }\n return (await res.json()) as Record<string, unknown>;\n }\n\n /** Query entities with optional filters. */\n async getEntities(\n params?: GetEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (parts.length) qs = '?' + parts.join('&');\n }\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Query failed',\n );\n }\n return (await res.json()) as Record<string, unknown>[];\n }\n\n /** Count entities matching the given filters. */\n async count(\n params?: CountEntitiesParams,\n ): Promise<number> {\n const parts: string[] = ['count=true', 'limit=0'];\n if (params?.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params?.q) parts.push('q=' + encodeURIComponent(params.q));\n const qs = '?' + parts.join('&');\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Count failed',\n );\n }\n const countHeader = res.headers.get('NGSILD-Results-Count');\n return countHeader ? parseInt(countHeader, 10) : 0;\n }\n\n /** Update entity attributes (partial). */\n async updateEntity(\n entityId: string,\n attrs: Record<string, unknown>,\n ): Promise<{ updated: true }> {\n const res = await this._auth.request(\n 'PATCH',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId) + '/attrs',\n attrs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Update failed',\n );\n }\n return { updated: true };\n }\n\n /** Delete an entity. */\n async deleteEntity(entityId: string): Promise<{ deleted: true }> {\n const res = await this._auth.request(\n 'DELETE',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Delete failed',\n );\n }\n return { deleted: true };\n }\n\n // --- Types / Attributes Discovery ---\n\n /** List all entity types. */\n async getTypes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/types', 'Types query failed');\n }\n\n /** Get details for a specific entity type. */\n async getType(typeName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/types/' + encodeURIComponent(typeName),\n 'Type not found',\n );\n }\n\n /** List all attributes. */\n async getAttributes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/attributes', 'Attributes query failed');\n }\n\n /** Get details for a specific attribute. */\n async getAttribute(attrName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/attributes/' + encodeURIComponent(attrName),\n 'Attribute not found',\n );\n }\n\n // --- Temporal API ---\n\n /** Query temporal entities. */\n async getTemporalEntities(\n params?: GetTemporalEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.id) parts.push('id=' + encodeURIComponent(params.id));\n if (params.idPattern) parts.push('idPattern=' + encodeURIComponent(params.idPattern));\n if (params.attrs) parts.push('attrs=' + encodeURIComponent(params.attrs));\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (params.timeproperty) parts.push('timeproperty=' + encodeURIComponent(params.timeproperty));\n if (params.timeAt) parts.push('timeAt=' + encodeURIComponent(params.timeAt));\n if (params.endTimeAt) parts.push('endTimeAt=' + encodeURIComponent(params.endTimeAt));\n if (params.timerel) parts.push('timerel=' + encodeURIComponent(params.timerel));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (parts.length) qs = '?' + parts.join('&');\n }\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities' + qs,\n 'Temporal query failed',\n );\n }\n\n /** Get temporal representation of a single entity. */\n async getTemporalEntity(entityId: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities/' + encodeURIComponent(entityId),\n 'Temporal entity not found',\n );\n }\n\n // --- Batch Operations ---\n\n /** Create multiple entities in a single request. */\n async batchCreate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/create',\n entities,\n 'Batch create failed',\n );\n }\n\n /** Upsert multiple entities in a single request. */\n async batchUpsert(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/upsert',\n entities,\n 'Batch upsert failed',\n );\n }\n\n /** Update multiple entities in a single request. */\n async batchUpdate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/update',\n entities,\n 'Batch update failed',\n );\n }\n\n /** Delete multiple entities by ID. */\n async batchDelete(entityIds: string[]): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/delete',\n entityIds,\n 'Batch delete failed',\n );\n }\n\n // --- Internal helpers ---\n\n /** GET request that returns parsed JSON or throws. */\n private async _jsonGet<T>(path: string, fallbackError: string): Promise<T> {\n const res = await this._auth.request('GET', path);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n return (await res.json()) as T;\n }\n\n /** POST request that returns parsed JSON or throws. */\n private async _jsonPost<T>(\n path: string,\n body: unknown,\n fallbackError: string,\n ): Promise<T> {\n const res = await this._auth.request('POST', path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n if (res.status === 204) return {} as T;\n return (await res.json()) as T;\n }\n\n // --- Generic Request ---\n\n /**\n * Make an authenticated API request.\n * Automatically checks response status, parses JSON, and throws on error.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<unknown> {\n const res = await this._auth.request(method, path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Request failed: ' + res.status,\n );\n }\n const ct = res.headers.get('Content-Type') || '';\n if (res.status === 204 || !ct) return null;\n if (ct.indexOf('json') !== -1) return res.json();\n return res.text();\n }\n\n /**\n * Make an authenticated API request and return the raw Response object.\n * Use this when you need access to response headers (e.g. NGSILD-Results-Count).\n */\n async requestRaw(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n return this._auth.request(method, path, body);\n }\n\n // --- WebSocket ---\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n return this._ws.connect();\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n return this._ws.reconnect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._ws.disconnect();\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return this._ws.isConnected();\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: SubscribeOptions): void {\n this._ws.subscribe(options);\n }\n}\n\n// Default export for convenient importing\nexport default GeonicDB;\n\n// UMD-style global assignment for browser script tag usage\nif (typeof window !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n window.GeonicDB = GeonicDB;\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport type { GeonicDBEventMap } from './types';\n\ntype Listener<T> = (data: T) => void;\n\n/**\n * Minimal typed event emitter for GeonicDB SDK.\n */\nexport class EventEmitter {\n private _listeners: Record<string, Listener<unknown>[]> =\n Object.create(null) as Record<string, Listener<unknown>[]>;\n\n on<K extends keyof GeonicDBEventMap>(\n event: K,\n callback: Listener<GeonicDBEventMap[K]>,\n ): this;\n on(event: string, callback: Listener<unknown>): this;\n on(event: string, callback: Listener<unknown>): this {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n this._listeners[event].push(callback);\n return this;\n }\n\n off<K extends keyof GeonicDBEventMap>(\n event: K,\n callback?: Listener<GeonicDBEventMap[K]>,\n ): this;\n off(event: string, callback?: Listener<unknown>): this;\n off(event: string, callback?: Listener<unknown>): this {\n if (!this._listeners[event]) return this;\n if (!callback) {\n delete this._listeners[event];\n } else {\n this._listeners[event] = this._listeners[event].filter(\n (cb) => cb !== callback,\n );\n }\n return this;\n }\n\n protected emit<K extends keyof GeonicDBEventMap>(\n event: K,\n data?: GeonicDBEventMap[K],\n ): void;\n protected emit(event: string, data?: unknown): void;\n protected emit(event: string, data?: unknown): void {\n const cbs = this._listeners[event];\n if (!cbs) return;\n const snapshot = cbs.slice();\n for (const cb of snapshot) {\n try {\n cb(data);\n } catch {\n // listener error \u2014 swallow silently\n }\n }\n }\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport type { DPoPKeyPair } from './types';\n\n/** Whether the Web Crypto DPoP API is available in the current environment. */\nexport const dpopSupported =\n typeof crypto !== 'undefined' &&\n !!crypto.subtle &&\n !!crypto.subtle.generateKey;\n\n/** Base64url-encode an ArrayBuffer or Uint8Array. */\nfunction b64url(buf: ArrayBuffer | Uint8Array): string {\n const arr = buf instanceof ArrayBuffer ? new Uint8Array(buf) : buf;\n let str = '';\n for (let i = 0; i < arr.length; i++) {\n str += String.fromCharCode(arr[i]);\n }\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** Encode a string to Uint8Array. */\nfunction strToUint8(s: string): Uint8Array {\n return new TextEncoder().encode(s);\n}\n\n/** Generate an ECDSA P-256 key pair for DPoP proof creation. */\nexport async function generateDPoPKeyPair(): Promise<DPoPKeyPair | null> {\n if (!dpopSupported) return null;\n const kp = await crypto.subtle.generateKey(\n { name: 'ECDSA', namedCurve: 'P-256' },\n false,\n ['sign'],\n );\n const pubJwk = await crypto.subtle.exportKey(\n 'jwk',\n kp.publicKey,\n );\n return {\n privateKey: kp.privateKey,\n publicJwk: {\n kty: pubJwk.kty!,\n crv: pubJwk.crv!,\n x: pubJwk.x!,\n y: pubJwk.y!,\n },\n };\n}\n\n/**\n * Create a DPoP proof JWT (RFC 9449).\n *\n * @param keyPair - The DPoP key pair\n * @param htm - HTTP method\n * @param htu - HTTP target URI\n * @param accessToken - Optional access token for ath claim\n * @param nonce - Optional server-provided nonce\n * @returns Signed DPoP proof JWT or null if keyPair is null\n */\nexport async function createDPoPProof(\n keyPair: DPoPKeyPair | null,\n htm: string,\n htu: string,\n accessToken?: string | null,\n nonce?: string | null,\n): Promise<string | null> {\n if (!keyPair) return null;\n\n const header = { alg: 'ES256', typ: 'dpop+jwt', jwk: keyPair.publicJwk };\n const payload: Record<string, unknown> = {\n jti:\n typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : Date.now().toString(36) + Math.random().toString(36).substr(2),\n htm,\n htu,\n iat: Math.floor(Date.now() / 1000),\n };\n if (nonce) payload.nonce = nonce;\n\n if (accessToken) {\n const hash = await crypto.subtle.digest('SHA-256', strToUint8(accessToken) as unknown as ArrayBuffer);\n payload.ath = b64url(hash);\n }\n\n const headerB64 = b64url(strToUint8(JSON.stringify(header)));\n const payloadB64 = b64url(strToUint8(JSON.stringify(payload)));\n const signingInput = headerB64 + '.' + payloadB64;\n\n /* eslint-disable @typescript-eslint/no-unsafe-argument */\n const sigBuf = await crypto.subtle.sign(\n { name: 'ECDSA', hash: 'SHA-256' },\n keyPair.privateKey,\n strToUint8(signingInput) as unknown as ArrayBuffer,\n );\n /* eslint-enable @typescript-eslint/no-unsafe-argument */\n // WebCrypto ECDSA returns IEEE P1363 r||s format (64 bytes for P-256)\n return signingInput + '.' + b64url(new Uint8Array(sigBuf));\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nconst BATCH_SIZE = 1000;\nconst MAX_ITERATIONS = 1_000_000;\n\n/** Check whether the first `bits` bits of a hash are zero. */\nfunction checkZeros(hash: Uint8Array, bits: number): boolean {\n const fullBytes = Math.floor(bits / 8);\n const remainBits = bits % 8;\n for (let k = 0; k < fullBytes; k++) {\n if (hash[k] !== 0) return false;\n }\n if (remainBits > 0) {\n const mask = 0xff << (8 - remainBits);\n if ((hash[fullBytes] & mask) !== 0) return false;\n }\n return true;\n}\n\n/**\n * Solve a Proof of Work challenge asynchronously using Web Crypto.\n *\n * Hashes `challenge + nonce` (SHA-256) in batches and checks for\n * the required number of leading zero bits.\n *\n * @param challenge - The challenge string from the server\n * @param difficulty - Number of leading zero bits required\n * @returns The nonce that satisfies the difficulty\n */\nexport async function solvePoW(\n challenge: string,\n difficulty: number,\n): Promise<number> {\n if (!Number.isInteger(difficulty) || difficulty < 0 || difficulty > 256) {\n throw new Error('difficulty must be an integer between 0 and 256');\n }\n const encoder = new TextEncoder();\n let i = 0;\n\n async function tryBatch(): Promise<number> {\n const batchEnd = Math.min(i + BATCH_SIZE, MAX_ITERATIONS);\n const promises: Promise<{ idx: number; hash: Uint8Array }>[] = [];\n\n for (; i < batchEnd; i++) {\n const idx = i;\n promises.push(\n crypto.subtle\n .digest('SHA-256', encoder.encode(challenge + String(idx)))\n .then((buf) => ({ idx, hash: new Uint8Array(buf) })),\n );\n }\n\n const results = await Promise.all(promises);\n for (const result of results) {\n if (checkZeros(result.hash, difficulty)) {\n return result.idx;\n }\n }\n if (i >= MAX_ITERATIONS) throw new Error('PoW solution not found');\n return tryBatch();\n }\n\n return tryBatch();\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\n/** Default token TTL in seconds when expiresIn is not specified in setCredentials(). */\nexport const DEFAULT_TOKEN_TTL_SEC = 3_600;\n\n/** Token refresh leeway in ms \u2014 refresh 2 minutes before expiry. */\nexport const TOKEN_REFRESH_LEEWAY_MS = 120_000;\n\n/** Minimum wait time in ms before refreshing a token. */\nexport const TOKEN_REFRESH_MIN_MS = 10_000;\n\n/** Maximum WebSocket reconnection attempts. */\nexport const RECONNECT_MAX_ATTEMPTS = 10;\n\n/** Base delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_BASE_MS = 1_000;\n\n/** Maximum delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_MAX_DELAY_MS = 30_000;\n\n/** WebSocket sub-protocol name for browser authentication. */\nexport const SUB_PROTOCOL = 'access_token';\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport { createDPoPProof, dpopSupported, generateDPoPKeyPair } from './dpop';\nimport { solvePoW } from './pow';\nimport { DEFAULT_TOKEN_TTL_SEC } from './constants';\nimport type {\n CredentialsOptions,\n DPoPKeyPair,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n/** Internal authentication state for the GeonicDB SDK. */\nexport class AuthManager {\n private _baseUrl: string;\n private _apiKey: string;\n private _tenant: string;\n\n _token: string | null = null;\n _tokenExpiry = 0;\n _tokenType: 'Bearer' | 'DPoP' = 'Bearer';\n _refreshToken: string | null = null;\n _dpopKeyPair: DPoPKeyPair | null = null;\n _dpopReady: Promise<void> | null = null;\n _dpopNonce: string | null = null;\n private _tokenPromise: Promise<string> | null = null;\n\n /** Callback to emit tokenRefresh events. Set by GeonicDB class. */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(baseUrl: string, apiKey: string, tenant: string) {\n this._baseUrl = baseUrl;\n this._apiKey = apiKey;\n this._tenant = tenant;\n\n if (dpopSupported) {\n this._dpopReady = generateDPoPKeyPair()\n .then((kp) => {\n this._dpopKeyPair = kp;\n })\n .catch(() => {\n this._dpopKeyPair = null;\n });\n }\n }\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (this._tenant) headers['NGSILD-Tenant'] = this._tenant;\n\n const res = await fetch(this._baseUrl + '/auth/login', {\n method: 'POST',\n headers,\n body: JSON.stringify({ email, password }),\n });\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Login failed: ' + res.status,\n );\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n return data;\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' and refreshToken is provided, all subsequent\n * API calls and connect() bypass DPoP/PoW entirely.\n */\n setCredentials(opts: CredentialsOptions): void {\n if (!opts || !opts.token) throw new Error('token is required');\n this._token = opts.token;\n this._tokenType = opts.tokenType || 'Bearer';\n this._tokenExpiry = opts.expiresIn != null\n ? Date.now() + (opts.expiresIn - 60) * 1000\n : Date.now() + DEFAULT_TOKEN_TTL_SEC * 1000;\n this._refreshToken = opts.refreshToken || null;\n this._tokenPromise = null;\n }\n\n /** Clear all credentials. */\n logout(): void {\n this._token = null;\n this._tokenExpiry = 0;\n this._refreshToken = null;\n this._tokenPromise = null;\n }\n\n /** Ensure a valid token is available, refreshing or acquiring as needed. */\n async ensureToken(): Promise<string> {\n if (this._token && Date.now() < this._tokenExpiry) {\n return this._token;\n }\n\n // Deduplicate concurrent calls\n if (this._tokenPromise) {\n return this._tokenPromise;\n }\n\n // Bearer JWT refresh path \u2014 skip DPoP/PoW\n if (this._refreshToken) {\n this._tokenPromise = this._refreshBearerToken();\n return this._tokenPromise;\n }\n\n // API key + DPoP/PoW path\n this._tokenPromise = this._acquireTokenViaPow();\n return this._tokenPromise;\n }\n\n private async _refreshBearerToken(): Promise<string> {\n try {\n const res = await fetch(this._baseUrl + '/auth/refresh', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ refreshToken: this._refreshToken }),\n });\n if (!res.ok) {\n this._refreshToken = null;\n this._token = null;\n this._tokenPromise = null;\n throw new Error('Token refresh failed: ' + res.status);\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n this._tokenPromise = null;\n this.onTokenRefresh?.({\n token: this._token,\n tokenType: this._tokenType,\n expiresIn: data.expiresIn,\n refreshToken: this._refreshToken,\n });\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private async _acquireTokenViaPow(): Promise<string> {\n try {\n if (this._dpopReady) await this._dpopReady;\n\n // Step 1: Get nonce + PoW challenge\n const nonceRes = await fetch(this._baseUrl + '/auth/nonce', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ api_key: this._apiKey }),\n });\n if (!nonceRes.ok)\n throw new Error('Nonce request failed: ' + nonceRes.status);\n const nonceData = (await nonceRes.json()) as {\n nonce: string;\n challenge: string;\n difficulty: number;\n dpop_nonce?: string;\n };\n\n // RFC 9449 \u00A78: store pre-issued DPoP-Nonce\n if (nonceData.dpop_nonce) this._dpopNonce = nonceData.dpop_nonce;\n\n // Step 2: Solve PoW\n const proof = await solvePoW(nonceData.challenge, nonceData.difficulty);\n\n // Step 3: Exchange for token\n const tokenUrl = this._baseUrl + '/oauth/token';\n const tokenBody = JSON.stringify({\n grant_type: 'api_key',\n api_key: this._apiKey,\n nonce: nonceData.nonce,\n proof: String(proof),\n });\n\n const res = await this._doTokenExchange(tokenUrl, tokenBody, this._dpopNonce);\n\n if (!res.ok)\n throw new Error('Token request failed: ' + res.status);\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n const data = (await res.json()) as {\n access_token: string;\n expires_in: number;\n token_type?: string;\n };\n this._token = data.access_token;\n this._tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;\n this._tokenType = (data.token_type as 'Bearer' | 'DPoP') || 'Bearer';\n this._tokenPromise = null;\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private static readonly MAX_DPOP_RETRIES = 3;\n\n private async _doTokenExchange(\n tokenUrl: string,\n tokenBody: string,\n dpopNonce: string | null,\n retryCount = 0,\n ): Promise<Response> {\n const reqHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n const dpopProof = await createDPoPProof(\n this._dpopKeyPair,\n 'POST',\n tokenUrl,\n null,\n dpopNonce,\n );\n if (dpopProof) reqHeaders['DPoP'] = dpopProof;\n\n const res = await fetch(tokenUrl, {\n method: 'POST',\n headers: reqHeaders,\n body: tokenBody,\n });\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 400 && this._dpopKeyPair) {\n const errBody = await res.json().catch(() => ({})) as Record<string, string>;\n if (errBody.error === 'use_dpop_nonce') {\n const serverNonce = res.headers.get('DPoP-Nonce');\n if (serverNonce && serverNonce !== dpopNonce && retryCount < AuthManager.MAX_DPOP_RETRIES) {\n this._dpopNonce = serverNonce;\n return this._doTokenExchange(tokenUrl, tokenBody, serverNonce, retryCount + 1);\n }\n }\n throw new Error(\n 'Token request failed: ' +\n (errBody.error_description || errBody.error),\n );\n }\n\n return res;\n }\n\n /**\n * Make an authenticated HTTP request with automatic token refresh and DPoP.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const token = await this.ensureToken();\n return this._doAuthenticatedRequest(method, path, body, token);\n }\n\n private static readonly MAX_REQUEST_RETRIES = 3;\n\n private async _doAuthenticatedRequest(\n method: string,\n path: string,\n body: unknown,\n token: string,\n retryCount = 0,\n ): Promise<Response> {\n const url = this._baseUrl + path;\n const isDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const bodyStr = body !== undefined ? JSON.stringify(body) : undefined;\n\n const doRequest = async (\n reqToken: string,\n dpopNonce: string | null,\n ): Promise<Response> => {\n const reqIsDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const dpopProof = reqIsDPoP\n ? await createDPoPProof(\n this._dpopKeyPair,\n method,\n url,\n reqToken,\n dpopNonce,\n )\n : null;\n\n const headers: Record<string, string> = {\n Authorization: (reqIsDPoP ? 'DPoP ' : 'Bearer ') + reqToken,\n 'Content-Type': 'application/ld+json',\n Accept: 'application/ld+json',\n };\n if (dpopProof) headers['DPoP'] = dpopProof;\n if (this._tenant) headers['Fiware-Service'] = this._tenant;\n\n return fetch(url, { method, headers, body: bodyStr });\n };\n\n let currentToken = token;\n let res = await doRequest(currentToken, this._dpopNonce);\n const previousNonce = this._dpopNonce;\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 401 && isDPoP && newNonce && newNonce !== previousNonce) {\n res = await doRequest(currentToken, newNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const fn = res.headers.get('DPoP-Nonce');\n if (fn) this._dpopNonce = fn;\n }\n } else if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n }\n\n if (res.status === 429 && retryCount < AuthManager.MAX_REQUEST_RETRIES) {\n const retryNonce = res.headers.get('DPoP-Nonce');\n if (retryNonce) this._dpopNonce = retryNonce;\n const delay =\n parseInt(res.headers.get('Retry-After') || '1', 10) * 1000;\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\n return this._doAuthenticatedRequest(method, path, body, currentToken, retryCount + 1);\n }\n\n return res;\n }\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport { createDPoPProof } from './dpop';\nimport type { AuthManager } from './auth';\nimport {\n TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n RECONNECT_MAX_ATTEMPTS,\n RECONNECT_BASE_MS,\n RECONNECT_MAX_DELAY_MS,\n SUB_PROTOCOL,\n} from './constants';\nimport type { SubscriptionMessage } from './types';\n\ntype EmitFn = (event: string, data?: unknown) => void;\n\n/**\n * WebSocket connection manager for the GeonicDB SDK.\n *\n * Handles connection lifecycle, DPoP binding, token refresh,\n * automatic reconnection with exponential backoff, and subscriptions.\n */\nexport class WebSocketManager {\n private _auth: AuthManager;\n private _tenant: string;\n private _wsEndpointOverride: string | null;\n private _baseUrl: string;\n private _emit: EmitFn;\n\n private _ws: WebSocket | null = null;\n private _wsEndpoint: string | null = null;\n private _wsIntentionalClose = false;\n private _reconnectAttempts = 0;\n private _tokenRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private _subscription: SubscriptionMessage | null = null;\n private _pendingSubscription = false;\n\n constructor(\n auth: AuthManager,\n baseUrl: string,\n tenant: string,\n emit: EmitFn,\n wsEndpointOverride?: string,\n ) {\n this._auth = auth;\n this._baseUrl = baseUrl;\n this._tenant = tenant;\n this._emit = emit;\n this._wsEndpointOverride = wsEndpointOverride || null;\n }\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n this._wsIntentionalClose = false;\n this._reconnectAttempts = 0;\n\n try {\n const token = await this._auth.ensureToken();\n await this._openWebSocket(token);\n } catch (err) {\n this._emit('error', err);\n }\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n this._wsIntentionalClose = true;\n this._clearTimers();\n if (this._ws) {\n this._ws.close(1000, 'Client reconnect');\n this._ws = null;\n }\n return this.connect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._wsIntentionalClose = true;\n this._clearTimers();\n this._subscription = null;\n this._pendingSubscription = false;\n if (this._ws) {\n this._ws.close(1000, 'Client disconnect');\n this._ws = null;\n }\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return !!(this._ws && this._ws.readyState === WebSocket.OPEN);\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: { entityTypes?: string[]; idPattern?: string }): void {\n const msg: SubscriptionMessage = { action: 'subscribe' };\n if (options) {\n if (options.entityTypes) msg.entityTypes = options.entityTypes;\n if (options.idPattern) msg.idPattern = options.idPattern;\n }\n this._subscription = msg;\n // If DPoP pending verification, store subscription but don't send yet\n if (this._pendingSubscription) return;\n if (this._ws && this._ws.readyState === WebSocket.OPEN) {\n this._ws.send(JSON.stringify(msg));\n }\n }\n\n private async _discoverWsEndpoint(): Promise<string> {\n if (this._wsEndpointOverride) return this._wsEndpointOverride;\n if (this._wsEndpoint) return this._wsEndpoint;\n\n // Fetch endpoint from server discovery API\n try {\n const res = await fetch(this._baseUrl + '/sdk/v1/streaming');\n if (res.ok) {\n const info = (await res.json()) as {\n enabled: boolean;\n endpoint: string | null;\n };\n if (info.enabled && info.endpoint) {\n this._wsEndpoint = info.endpoint;\n return this._wsEndpoint;\n }\n }\n } catch {\n // Discovery failed \u2014 fall back to URL scheme conversion\n }\n\n // Fallback: convert http(s) baseUrl to ws(s)\n this._wsEndpoint = this._baseUrl.replace(/^http/, 'ws');\n return this._wsEndpoint;\n }\n\n private async _openWebSocket(token: string): Promise<void> {\n const endpoint = await this._discoverWsEndpoint();\n return new Promise<void>((resolve, reject) => {\n const wsUrl =\n endpoint +\n (endpoint.indexOf('?') === -1 ? '?' : '&') +\n 'tenant=' +\n encodeURIComponent(this._tenant);\n\n const ws = new WebSocket(wsUrl, [SUB_PROTOCOL, token]);\n this._ws = ws;\n\n ws.onopen = (): void => {\n if (this._ws !== ws) return;\n this._reconnectAttempts = 0;\n\n const isDPoP =\n this._auth._tokenType === 'DPoP' && !!this._auth._dpopKeyPair;\n\n const bindPromise = isDPoP\n ? createDPoPProof(this._auth._dpopKeyPair, 'GET', wsUrl, null).then(\n (proof) => {\n if (proof && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ action: 'dpop_bind', proof }));\n }\n },\n )\n : Promise.resolve();\n\n bindPromise\n .then(() => {\n this._scheduleTokenRefresh();\n\n if (isDPoP) {\n this._pendingSubscription = true;\n } else if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n\n this._emit('open');\n this._emit('connected');\n resolve();\n })\n .catch((err) => {\n this._emit('error', err);\n resolve();\n });\n };\n\n ws.onmessage = (event: MessageEvent): void => {\n if (this._ws !== ws) return;\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(event.data as string) as Record<string, unknown>;\n } catch {\n return;\n }\n\n if (msg.type === 'pong') return;\n\n if (msg.type === 'dpop_verified') {\n this._pendingSubscription = false;\n if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n return;\n }\n\n if (msg.type === 'error') {\n this._emit('error', new Error(msg.message as string));\n return;\n }\n\n this._emit(msg.type as string, msg);\n this._emit('message', msg);\n };\n\n ws.onclose = (event: CloseEvent): void => {\n if (this._ws !== ws) return;\n this._clearTimers();\n\n if (this._wsIntentionalClose) {\n this._emit('close', event);\n return;\n }\n\n this._emit('close', event);\n this._emit('disconnected');\n this._autoReconnect();\n };\n\n ws.onerror = (err: Event): void => {\n if (this._ws !== ws) return;\n this._emit('error', err);\n if (ws.readyState !== WebSocket.OPEN) {\n reject(new Error('WebSocket connection failed'));\n }\n };\n });\n }\n\n private _scheduleTokenRefresh(): void {\n if (this._tokenRefreshTimer) clearTimeout(this._tokenRefreshTimer);\n\n const remaining = this._auth._tokenExpiry - Date.now();\n const refreshIn = Math.max(\n remaining - TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n );\n\n this._tokenRefreshTimer = setTimeout(() => {\n const oldWs = this._ws;\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((newToken) => {\n if (!oldWs || oldWs.readyState !== WebSocket.OPEN) return;\n\n this._wsIntentionalClose = true;\n oldWs.close(1000, 'Token refresh');\n\n this._wsIntentionalClose = false;\n return this._openWebSocket(newToken);\n })\n .catch((err) => {\n this._emit('error', err);\n this._autoReconnect();\n });\n }, refreshIn);\n }\n\n private _autoReconnect(): void {\n if (this._wsIntentionalClose) return;\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n\n if (this._reconnectAttempts >= RECONNECT_MAX_ATTEMPTS) {\n this._emit('error', new Error('Max reconnection attempts reached'));\n return;\n }\n\n const delay = Math.min(\n RECONNECT_BASE_MS * Math.pow(2, this._reconnectAttempts),\n RECONNECT_MAX_DELAY_MS,\n );\n this._reconnectAttempts++;\n this._emit('reconnecting', {\n attempt: this._reconnectAttempts,\n delay,\n });\n\n this._reconnectTimer = setTimeout(() => {\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((token) => this._openWebSocket(token))\n .catch(() => this._autoReconnect());\n }, delay);\n }\n\n private _clearTimers(): void {\n if (this._tokenRefreshTimer) {\n clearTimeout(this._tokenRefreshTimer);\n this._tokenRefreshTimer = null;\n }\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\n/**\n * GeonicDB JavaScript SDK\n *\n * NGSI-LD Context Broker client for browser and Node.js.\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ndeclare const document: any;\ndeclare const window: any;\n\nimport { EventEmitter } from './events';\nimport { AuthManager } from './auth';\nimport { WebSocketManager } from './websocket';\nimport type {\n GeonicDBOptions,\n CredentialsOptions,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n// Re-export types for consumers\nexport type {\n GeonicDBOptions,\n CredentialsOptions,\n RefreshedCredentials,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n EntityEvent,\n ReconnectingEvent,\n LoginResponse,\n GeonicDBEventMap,\n} from './types';\n\n/**\n * GeonicDB SDK client.\n *\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n *\n * @example\n * ```typescript\n * import GeonicDB from '@geolonia/geonicdb-sdk';\n *\n * const db = new GeonicDB({\n * apiKey: 'your-api-key',\n * tenant: 'your-tenant',\n * baseUrl: 'https://your-geonicdb.example.com',\n * });\n *\n * const entities = await db.getEntities({ type: 'Room' });\n * ```\n */\nexport class GeonicDB extends EventEmitter {\n private _auth: AuthManager;\n private _ws: WebSocketManager;\n\n /**\n * Legacy callback for token refresh events.\n * Prefer `db.on('tokenRefresh', callback)` for new code.\n * @deprecated Use `db.on('tokenRefresh', callback)` instead.\n */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(options?: GeonicDBOptions) {\n super();\n const opts = options || {};\n\n // Auto-detect from script tag in browser\n let apiKey = opts.apiKey || '';\n let tenant = opts.tenant || '';\n let baseUrl = opts.baseUrl || '';\n\n /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n if (typeof document !== 'undefined' && document.currentScript) {\n const script = document.currentScript;\n if (!apiKey) apiKey = script?.getAttribute?.('data-api-key') || '';\n if (!tenant) tenant = script?.getAttribute?.('data-tenant') || '';\n if (!baseUrl) baseUrl = script?.getAttribute?.('data-base-url') || '';\n }\n /* eslint-enable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n\n this._auth = new AuthManager(baseUrl, apiKey, tenant);\n this._auth.onTokenRefresh = (creds): void => {\n this.onTokenRefresh?.(creds);\n this.emit('tokenRefresh', creds);\n };\n this._ws = new WebSocketManager(\n this._auth,\n baseUrl,\n tenant,\n (event, data) => this.emit(event, data),\n opts.wsEndpoint,\n );\n }\n\n // --- Authentication ---\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n return this._auth.login(email, password);\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' with a refreshToken, DPoP/PoW is bypassed entirely.\n */\n setCredentials(opts: CredentialsOptions): this {\n this._auth.setCredentials(opts);\n return this;\n }\n\n /** Clear all credentials and disconnect. */\n logout(): void {\n this._ws.disconnect();\n this._auth.logout();\n }\n\n // --- Entity CRUD (NGSI-LD) ---\n\n /** Create a new entity. */\n async createEntity(\n entity: Record<string, unknown>,\n ): Promise<{ created: true }> {\n const res = await this._auth.request('POST', '/ngsi-ld/v1/entities', entity);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Create failed',\n );\n }\n return { created: true };\n }\n\n /** Get a single entity by ID. */\n async getEntity(entityId: string): Promise<Record<string, unknown>> {\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Not found',\n );\n }\n return (await res.json()) as Record<string, unknown>;\n }\n\n /** Query entities with optional filters. */\n async getEntities(\n params?: GetEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (parts.length) qs = '?' + parts.join('&');\n }\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Query failed',\n );\n }\n return (await res.json()) as Record<string, unknown>[];\n }\n\n /** Count entities matching the given filters. */\n async count(\n params?: CountEntitiesParams,\n ): Promise<number> {\n const parts: string[] = ['count=true', 'limit=0'];\n if (params?.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params?.q) parts.push('q=' + encodeURIComponent(params.q));\n const qs = '?' + parts.join('&');\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Count failed',\n );\n }\n const countHeader = res.headers.get('NGSILD-Results-Count');\n return countHeader ? parseInt(countHeader, 10) : 0;\n }\n\n /** Update entity attributes (partial). */\n async updateEntity(\n entityId: string,\n attrs: Record<string, unknown>,\n ): Promise<{ updated: true }> {\n const res = await this._auth.request(\n 'PATCH',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId) + '/attrs',\n attrs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Update failed',\n );\n }\n return { updated: true };\n }\n\n /** Delete an entity. */\n async deleteEntity(entityId: string): Promise<{ deleted: true }> {\n const res = await this._auth.request(\n 'DELETE',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Delete failed',\n );\n }\n return { deleted: true };\n }\n\n // --- Types / Attributes Discovery ---\n\n /** List all entity types. */\n async getTypes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/types', 'Types query failed');\n }\n\n /** Get details for a specific entity type. */\n async getType(typeName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/types/' + encodeURIComponent(typeName),\n 'Type not found',\n );\n }\n\n /** List all attributes. */\n async getAttributes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/attributes', 'Attributes query failed');\n }\n\n /** Get details for a specific attribute. */\n async getAttribute(attrName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/attributes/' + encodeURIComponent(attrName),\n 'Attribute not found',\n );\n }\n\n // --- Temporal API ---\n\n /** Query temporal entities. */\n async getTemporalEntities(\n params?: GetTemporalEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.id) parts.push('id=' + encodeURIComponent(params.id));\n if (params.idPattern) parts.push('idPattern=' + encodeURIComponent(params.idPattern));\n if (params.attrs) parts.push('attrs=' + encodeURIComponent(params.attrs));\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (params.timeproperty) parts.push('timeproperty=' + encodeURIComponent(params.timeproperty));\n if (params.timeAt) parts.push('timeAt=' + encodeURIComponent(params.timeAt));\n if (params.endTimeAt) parts.push('endTimeAt=' + encodeURIComponent(params.endTimeAt));\n if (params.timerel) parts.push('timerel=' + encodeURIComponent(params.timerel));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (parts.length) qs = '?' + parts.join('&');\n }\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities' + qs,\n 'Temporal query failed',\n );\n }\n\n /** Get temporal representation of a single entity. */\n async getTemporalEntity(entityId: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities/' + encodeURIComponent(entityId),\n 'Temporal entity not found',\n );\n }\n\n // --- Batch Operations ---\n\n /** Create multiple entities in a single request. */\n async batchCreate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/create',\n entities,\n 'Batch create failed',\n );\n }\n\n /** Upsert multiple entities in a single request. */\n async batchUpsert(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/upsert',\n entities,\n 'Batch upsert failed',\n );\n }\n\n /** Update multiple entities in a single request. */\n async batchUpdate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/update',\n entities,\n 'Batch update failed',\n );\n }\n\n /** Delete multiple entities by ID. */\n async batchDelete(entityIds: string[]): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/delete',\n entityIds,\n 'Batch delete failed',\n );\n }\n\n // --- Internal helpers ---\n\n /** GET request that returns parsed JSON or throws. */\n private async _jsonGet<T>(path: string, fallbackError: string): Promise<T> {\n const res = await this._auth.request('GET', path);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n return (await res.json()) as T;\n }\n\n /** POST request that returns parsed JSON or throws. */\n private async _jsonPost<T>(\n path: string,\n body: unknown,\n fallbackError: string,\n ): Promise<T> {\n const res = await this._auth.request('POST', path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n if (res.status === 204) return {} as T;\n return (await res.json()) as T;\n }\n\n // --- Generic Request ---\n\n /**\n * Make an authenticated API request.\n * Automatically checks response status, parses JSON, and throws on error.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<unknown> {\n const res = await this._auth.request(method, path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Request failed: ' + res.status,\n );\n }\n const ct = res.headers.get('Content-Type') || '';\n if (res.status === 204 || !ct) return null;\n if (ct.indexOf('json') !== -1) return res.json();\n return res.text();\n }\n\n /**\n * Make an authenticated API request and return the raw Response object.\n * Use this when you need access to response headers (e.g. NGSILD-Results-Count).\n */\n async requestRaw(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n return this._auth.request(method, path, body);\n }\n\n // --- WebSocket ---\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n return this._ws.connect();\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n return this._ws.reconnect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._ws.disconnect();\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return this._ws.isConnected();\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: SubscribeOptions): void {\n this._ws.subscribe(options);\n }\n}\n\n// Default export for convenient importing\nexport default GeonicDB;\n\n// UMD-style global assignment for browser script tag usage\nif (typeof window !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n window.GeonicDB = GeonicDB;\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport type { GeonicDBEventMap } from './types';\n\ntype Listener<T> = (data: T) => void;\n\n/**\n * Minimal typed event emitter for GeonicDB SDK.\n */\nexport class EventEmitter {\n private _listeners: Record<string, Listener<unknown>[]> =\n Object.create(null) as Record<string, Listener<unknown>[]>;\n\n on<K extends keyof GeonicDBEventMap>(\n event: K,\n callback: Listener<GeonicDBEventMap[K]>,\n ): this;\n on(event: string, callback: Listener<unknown>): this;\n on(event: string, callback: Listener<unknown>): this {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n this._listeners[event].push(callback);\n return this;\n }\n\n off<K extends keyof GeonicDBEventMap>(\n event: K,\n callback?: Listener<GeonicDBEventMap[K]>,\n ): this;\n off(event: string, callback?: Listener<unknown>): this;\n off(event: string, callback?: Listener<unknown>): this {\n if (!this._listeners[event]) return this;\n if (!callback) {\n delete this._listeners[event];\n } else {\n this._listeners[event] = this._listeners[event].filter(\n (cb) => cb !== callback,\n );\n }\n return this;\n }\n\n protected emit<K extends keyof GeonicDBEventMap>(\n event: K,\n data?: GeonicDBEventMap[K],\n ): void;\n protected emit(event: string, data?: unknown): void;\n protected emit(event: string, data?: unknown): void {\n const cbs = this._listeners[event];\n if (!cbs) return;\n const snapshot = cbs.slice();\n for (const cb of snapshot) {\n try {\n cb(data);\n } catch {\n // listener error \u2014 swallow silently\n }\n }\n }\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport type { DPoPKeyPair } from './types';\n\n/** Whether the Web Crypto DPoP API is available in the current environment. */\nexport const dpopSupported =\n typeof crypto !== 'undefined' &&\n !!crypto.subtle &&\n !!crypto.subtle.generateKey;\n\n/** Base64url-encode an ArrayBuffer or Uint8Array. */\nfunction b64url(buf: ArrayBuffer | Uint8Array): string {\n const arr = buf instanceof ArrayBuffer ? new Uint8Array(buf) : buf;\n let str = '';\n for (let i = 0; i < arr.length; i++) {\n str += String.fromCharCode(arr[i]);\n }\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** Encode a string to Uint8Array. */\nfunction strToUint8(s: string): Uint8Array {\n return new TextEncoder().encode(s);\n}\n\n/** Generate an ECDSA P-256 key pair for DPoP proof creation. */\nexport async function generateDPoPKeyPair(): Promise<DPoPKeyPair | null> {\n if (!dpopSupported) return null;\n const kp = await crypto.subtle.generateKey(\n { name: 'ECDSA', namedCurve: 'P-256' },\n false,\n ['sign'],\n );\n const pubJwk = await crypto.subtle.exportKey(\n 'jwk',\n kp.publicKey,\n );\n return {\n privateKey: kp.privateKey,\n publicJwk: {\n kty: pubJwk.kty!,\n crv: pubJwk.crv!,\n x: pubJwk.x!,\n y: pubJwk.y!,\n },\n };\n}\n\n/**\n * Create a DPoP proof JWT (RFC 9449).\n *\n * @param keyPair - The DPoP key pair\n * @param htm - HTTP method\n * @param htu - HTTP target URI\n * @param accessToken - Optional access token for ath claim\n * @param nonce - Optional server-provided nonce\n * @returns Signed DPoP proof JWT or null if keyPair is null\n */\nexport async function createDPoPProof(\n keyPair: DPoPKeyPair | null,\n htm: string,\n htu: string,\n accessToken?: string | null,\n nonce?: string | null,\n): Promise<string | null> {\n if (!keyPair) return null;\n\n const header = { alg: 'ES256', typ: 'dpop+jwt', jwk: keyPair.publicJwk };\n const payload: Record<string, unknown> = {\n jti:\n typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : Date.now().toString(36) + Math.random().toString(36).substr(2),\n htm,\n htu,\n iat: Math.floor(Date.now() / 1000),\n };\n if (nonce) payload.nonce = nonce;\n\n if (accessToken) {\n const hash = await crypto.subtle.digest('SHA-256', strToUint8(accessToken) as unknown as ArrayBuffer);\n payload.ath = b64url(hash);\n }\n\n const headerB64 = b64url(strToUint8(JSON.stringify(header)));\n const payloadB64 = b64url(strToUint8(JSON.stringify(payload)));\n const signingInput = headerB64 + '.' + payloadB64;\n\n /* eslint-disable @typescript-eslint/no-unsafe-argument */\n const sigBuf = await crypto.subtle.sign(\n { name: 'ECDSA', hash: 'SHA-256' },\n keyPair.privateKey,\n strToUint8(signingInput) as unknown as ArrayBuffer,\n );\n /* eslint-enable @typescript-eslint/no-unsafe-argument */\n // WebCrypto ECDSA returns IEEE P1363 r||s format (64 bytes for P-256)\n return signingInput + '.' + b64url(new Uint8Array(sigBuf));\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nconst BATCH_SIZE = 1000;\nconst MAX_ITERATIONS = 1_000_000;\n\n/** Check whether the first `bits` bits of a hash are zero. */\nfunction checkZeros(hash: Uint8Array, bits: number): boolean {\n const fullBytes = Math.floor(bits / 8);\n const remainBits = bits % 8;\n for (let k = 0; k < fullBytes; k++) {\n if (hash[k] !== 0) return false;\n }\n if (remainBits > 0) {\n const mask = 0xff << (8 - remainBits);\n if ((hash[fullBytes] & mask) !== 0) return false;\n }\n return true;\n}\n\n/**\n * Solve a Proof of Work challenge asynchronously using Web Crypto.\n *\n * Hashes `challenge + nonce` (SHA-256) in batches and checks for\n * the required number of leading zero bits.\n *\n * @param challenge - The challenge string from the server\n * @param difficulty - Number of leading zero bits required\n * @returns The nonce that satisfies the difficulty\n */\nexport async function solvePoW(\n challenge: string,\n difficulty: number,\n): Promise<number> {\n if (!Number.isInteger(difficulty) || difficulty < 0 || difficulty > 256) {\n throw new Error('difficulty must be an integer between 0 and 256');\n }\n const encoder = new TextEncoder();\n let i = 0;\n\n async function tryBatch(): Promise<number> {\n const batchEnd = Math.min(i + BATCH_SIZE, MAX_ITERATIONS);\n const promises: Promise<{ idx: number; hash: Uint8Array }>[] = [];\n\n for (; i < batchEnd; i++) {\n const idx = i;\n promises.push(\n crypto.subtle\n .digest('SHA-256', encoder.encode(challenge + String(idx)))\n .then((buf) => ({ idx, hash: new Uint8Array(buf) })),\n );\n }\n\n const results = await Promise.all(promises);\n for (const result of results) {\n if (checkZeros(result.hash, difficulty)) {\n return result.idx;\n }\n }\n if (i >= MAX_ITERATIONS) throw new Error('PoW solution not found');\n return tryBatch();\n }\n\n return tryBatch();\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\n/** Default token TTL in seconds when expiresIn is not specified in setCredentials(). */\nexport const DEFAULT_TOKEN_TTL_SEC = 3_600;\n\n/** Token refresh leeway in ms \u2014 refresh 2 minutes before expiry. */\nexport const TOKEN_REFRESH_LEEWAY_MS = 120_000;\n\n/** Minimum wait time in ms before refreshing a token. */\nexport const TOKEN_REFRESH_MIN_MS = 10_000;\n\n/** Maximum WebSocket reconnection attempts. */\nexport const RECONNECT_MAX_ATTEMPTS = 10;\n\n/** Base delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_BASE_MS = 1_000;\n\n/** Maximum delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_MAX_DELAY_MS = 30_000;\n\n/** WebSocket sub-protocol name for browser authentication. */\nexport const SUB_PROTOCOL = 'access_token';\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport { createDPoPProof, dpopSupported, generateDPoPKeyPair } from './dpop';\nimport { solvePoW } from './pow';\nimport { DEFAULT_TOKEN_TTL_SEC } from './constants';\nimport type {\n CredentialsOptions,\n DPoPKeyPair,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n/** Internal authentication state for the GeonicDB SDK. */\nexport class AuthManager {\n private _baseUrl: string;\n private _apiKey: string;\n private _tenant: string;\n\n _token: string | null = null;\n _tokenExpiry = 0;\n _tokenType: 'Bearer' | 'DPoP' = 'Bearer';\n _refreshToken: string | null = null;\n _dpopKeyPair: DPoPKeyPair | null = null;\n _dpopReady: Promise<void> | null = null;\n _dpopNonce: string | null = null;\n private _tokenPromise: Promise<string> | null = null;\n\n /** Callback to emit tokenRefresh events. Set by GeonicDB class. */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(baseUrl: string, apiKey: string, tenant: string) {\n this._baseUrl = baseUrl;\n this._apiKey = apiKey;\n this._tenant = tenant;\n\n if (dpopSupported) {\n this._dpopReady = generateDPoPKeyPair()\n .then((kp) => {\n this._dpopKeyPair = kp;\n })\n .catch(() => {\n this._dpopKeyPair = null;\n });\n }\n }\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (this._tenant) headers['NGSILD-Tenant'] = this._tenant;\n\n const res = await fetch(this._baseUrl + '/auth/login', {\n method: 'POST',\n headers,\n body: JSON.stringify({ email, password }),\n });\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Login failed: ' + res.status,\n );\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n return data;\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' and refreshToken is provided, all subsequent\n * API calls and connect() bypass DPoP/PoW entirely.\n */\n setCredentials(opts: CredentialsOptions): void {\n if (!opts || !opts.token) throw new Error('token is required');\n this._token = opts.token;\n this._tokenType = opts.tokenType || 'Bearer';\n this._tokenExpiry = opts.expiresIn != null\n ? Date.now() + (opts.expiresIn - 60) * 1000\n : Date.now() + DEFAULT_TOKEN_TTL_SEC * 1000;\n this._refreshToken = opts.refreshToken || null;\n this._tokenPromise = null;\n }\n\n /** Clear all credentials. */\n logout(): void {\n this._token = null;\n this._tokenExpiry = 0;\n this._refreshToken = null;\n this._tokenPromise = null;\n }\n\n /** Ensure a valid token is available, refreshing or acquiring as needed. */\n async ensureToken(): Promise<string> {\n if (this._token && Date.now() < this._tokenExpiry) {\n return this._token;\n }\n\n // Deduplicate concurrent calls\n if (this._tokenPromise) {\n return this._tokenPromise;\n }\n\n // Bearer JWT refresh path \u2014 skip DPoP/PoW\n if (this._refreshToken) {\n this._tokenPromise = this._refreshBearerToken();\n return this._tokenPromise;\n }\n\n // API key + DPoP/PoW path\n this._tokenPromise = this._acquireTokenViaPow();\n return this._tokenPromise;\n }\n\n private async _refreshBearerToken(): Promise<string> {\n try {\n const res = await fetch(this._baseUrl + '/auth/refresh', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ refreshToken: this._refreshToken }),\n });\n if (!res.ok) {\n this._refreshToken = null;\n this._token = null;\n this._tokenPromise = null;\n throw new Error('Token refresh failed: ' + res.status);\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n this._tokenPromise = null;\n this.onTokenRefresh?.({\n token: this._token,\n tokenType: this._tokenType,\n expiresIn: data.expiresIn,\n refreshToken: this._refreshToken,\n });\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private async _acquireTokenViaPow(): Promise<string> {\n try {\n if (this._dpopReady) await this._dpopReady;\n\n // Step 1: Get nonce + PoW challenge\n const nonceRes = await fetch(this._baseUrl + '/auth/nonce', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ api_key: this._apiKey }),\n });\n if (!nonceRes.ok)\n throw new Error('Nonce request failed: ' + nonceRes.status);\n const nonceData = (await nonceRes.json()) as {\n nonce: string;\n challenge: string;\n difficulty: number;\n dpop_nonce?: string;\n };\n\n // RFC 9449 \u00A78: store pre-issued DPoP-Nonce\n if (nonceData.dpop_nonce) this._dpopNonce = nonceData.dpop_nonce;\n\n // Step 2: Solve PoW\n const proof = await solvePoW(nonceData.challenge, nonceData.difficulty);\n\n // Step 3: Exchange for token\n const tokenUrl = this._baseUrl + '/oauth/token';\n const tokenBody = JSON.stringify({\n grant_type: 'api_key',\n api_key: this._apiKey,\n nonce: nonceData.nonce,\n proof: String(proof),\n });\n\n const res = await this._doTokenExchange(tokenUrl, tokenBody, this._dpopNonce);\n\n if (!res.ok)\n throw new Error('Token request failed: ' + res.status);\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n const data = (await res.json()) as {\n access_token: string;\n expires_in: number;\n token_type?: string;\n };\n this._token = data.access_token;\n this._tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;\n this._tokenType = (data.token_type as 'Bearer' | 'DPoP') || 'Bearer';\n this._tokenPromise = null;\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private static readonly MAX_DPOP_RETRIES = 3;\n\n private async _doTokenExchange(\n tokenUrl: string,\n tokenBody: string,\n dpopNonce: string | null,\n retryCount = 0,\n ): Promise<Response> {\n const reqHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n const dpopProof = await createDPoPProof(\n this._dpopKeyPair,\n 'POST',\n tokenUrl,\n null,\n dpopNonce,\n );\n if (dpopProof) reqHeaders['DPoP'] = dpopProof;\n\n const res = await fetch(tokenUrl, {\n method: 'POST',\n headers: reqHeaders,\n body: tokenBody,\n });\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 400 && this._dpopKeyPair) {\n const errBody = await res.json().catch(() => ({})) as Record<string, string>;\n if (errBody.error === 'use_dpop_nonce') {\n const serverNonce = res.headers.get('DPoP-Nonce');\n if (serverNonce && serverNonce !== dpopNonce && retryCount < AuthManager.MAX_DPOP_RETRIES) {\n this._dpopNonce = serverNonce;\n return this._doTokenExchange(tokenUrl, tokenBody, serverNonce, retryCount + 1);\n }\n }\n throw new Error(\n 'Token request failed: ' +\n (errBody.error_description || errBody.error),\n );\n }\n\n return res;\n }\n\n /**\n * Make an authenticated HTTP request with automatic token refresh and DPoP.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const token = await this.ensureToken();\n return this._doAuthenticatedRequest(method, path, body, token);\n }\n\n private static readonly MAX_REQUEST_RETRIES = 3;\n\n private async _doAuthenticatedRequest(\n method: string,\n path: string,\n body: unknown,\n token: string,\n retryCount = 0,\n ): Promise<Response> {\n const url = this._baseUrl + path;\n const isDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const bodyStr = body !== undefined ? JSON.stringify(body) : undefined;\n\n const doRequest = async (\n reqToken: string,\n dpopNonce: string | null,\n ): Promise<Response> => {\n const reqIsDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const dpopProof = reqIsDPoP\n ? await createDPoPProof(\n this._dpopKeyPair,\n method,\n url,\n reqToken,\n dpopNonce,\n )\n : null;\n\n const headers: Record<string, string> = {\n Authorization: (reqIsDPoP ? 'DPoP ' : 'Bearer ') + reqToken,\n 'Content-Type': 'application/ld+json',\n Accept: 'application/ld+json',\n };\n if (dpopProof) headers['DPoP'] = dpopProof;\n if (this._tenant) headers['Fiware-Service'] = this._tenant;\n\n return fetch(url, { method, headers, body: bodyStr });\n };\n\n let currentToken = token;\n let res = await doRequest(currentToken, this._dpopNonce);\n const previousNonce = this._dpopNonce;\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 401 && isDPoP && newNonce && newNonce !== previousNonce) {\n res = await doRequest(currentToken, newNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const fn = res.headers.get('DPoP-Nonce');\n if (fn) this._dpopNonce = fn;\n }\n } else if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n }\n\n if (res.status === 429 && retryCount < AuthManager.MAX_REQUEST_RETRIES) {\n const retryNonce = res.headers.get('DPoP-Nonce');\n if (retryNonce) this._dpopNonce = retryNonce;\n const delay =\n parseInt(res.headers.get('Retry-After') || '1', 10) * 1000;\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\n return this._doAuthenticatedRequest(method, path, body, currentToken, retryCount + 1);\n }\n\n return res;\n }\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport { createDPoPProof } from './dpop';\nimport type { AuthManager } from './auth';\nimport {\n TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n RECONNECT_MAX_ATTEMPTS,\n RECONNECT_BASE_MS,\n RECONNECT_MAX_DELAY_MS,\n SUB_PROTOCOL,\n} from './constants';\nimport type { SubscriptionMessage } from './types';\n\ntype EmitFn = (event: string, data?: unknown) => void;\n\n/**\n * WebSocket connection manager for the GeonicDB SDK.\n *\n * Handles connection lifecycle, DPoP binding, token refresh,\n * automatic reconnection with exponential backoff, and subscriptions.\n */\nexport class WebSocketManager {\n private _auth: AuthManager;\n private _tenant: string;\n private _wsEndpointOverride: string | null;\n private _baseUrl: string;\n private _emit: EmitFn;\n\n private _ws: WebSocket | null = null;\n private _wsEndpoint: string | null = null;\n private _wsIntentionalClose = false;\n private _reconnectAttempts = 0;\n private _tokenRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private _subscription: SubscriptionMessage | null = null;\n private _pendingSubscription = false;\n\n constructor(\n auth: AuthManager,\n baseUrl: string,\n tenant: string,\n emit: EmitFn,\n wsEndpointOverride?: string,\n ) {\n this._auth = auth;\n this._baseUrl = baseUrl;\n this._tenant = tenant;\n this._emit = emit;\n this._wsEndpointOverride = wsEndpointOverride || null;\n }\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n this._wsIntentionalClose = false;\n this._reconnectAttempts = 0;\n\n try {\n const token = await this._auth.ensureToken();\n await this._openWebSocket(token);\n } catch (err) {\n this._emit('error', err);\n }\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n this._wsIntentionalClose = true;\n this._clearTimers();\n if (this._ws) {\n this._ws.close(1000, 'Client reconnect');\n this._ws = null;\n }\n return this.connect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._wsIntentionalClose = true;\n this._clearTimers();\n this._subscription = null;\n this._pendingSubscription = false;\n if (this._ws) {\n this._ws.close(1000, 'Client disconnect');\n this._ws = null;\n }\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return !!(this._ws && this._ws.readyState === WebSocket.OPEN);\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: { entityTypes?: string[]; idPattern?: string }): void {\n const msg: SubscriptionMessage = { action: 'subscribe' };\n if (options) {\n if (options.entityTypes) msg.entityTypes = options.entityTypes;\n if (options.idPattern) msg.idPattern = options.idPattern;\n }\n this._subscription = msg;\n // If DPoP pending verification, store subscription but don't send yet\n if (this._pendingSubscription) return;\n if (this._ws && this._ws.readyState === WebSocket.OPEN) {\n this._ws.send(JSON.stringify(msg));\n }\n }\n\n private async _discoverWsEndpoint(): Promise<string> {\n if (this._wsEndpointOverride) return this._wsEndpointOverride;\n if (this._wsEndpoint) return this._wsEndpoint;\n\n // Fetch endpoint from server discovery API\n try {\n const res = await fetch(this._baseUrl + '/sdk/v1/streaming');\n if (res.ok) {\n const info = (await res.json()) as {\n enabled: boolean;\n endpoint: string | null;\n };\n if (info.enabled && info.endpoint) {\n this._wsEndpoint = info.endpoint;\n return this._wsEndpoint;\n }\n }\n } catch {\n // Discovery failed \u2014 fall back to URL scheme conversion\n }\n\n // Fallback: convert http(s) baseUrl to ws(s)\n this._wsEndpoint = this._baseUrl.replace(/^http/, 'ws');\n return this._wsEndpoint;\n }\n\n private async _openWebSocket(token: string): Promise<void> {\n const endpoint = await this._discoverWsEndpoint();\n return new Promise<void>((resolve, reject) => {\n const wsUrl =\n endpoint +\n (endpoint.indexOf('?') === -1 ? '?' : '&') +\n 'tenant=' +\n encodeURIComponent(this._tenant);\n\n const ws = new WebSocket(wsUrl, [SUB_PROTOCOL, token]);\n this._ws = ws;\n\n ws.onopen = (): void => {\n if (this._ws !== ws) return;\n this._reconnectAttempts = 0;\n\n const isDPoP =\n this._auth._tokenType === 'DPoP' && !!this._auth._dpopKeyPair;\n\n const bindPromise = isDPoP\n ? createDPoPProof(this._auth._dpopKeyPair, 'GET', wsUrl, null).then(\n (proof) => {\n if (proof && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ action: 'dpop_bind', proof }));\n }\n },\n )\n : Promise.resolve();\n\n bindPromise\n .then(() => {\n this._scheduleTokenRefresh();\n\n if (isDPoP) {\n this._pendingSubscription = true;\n } else if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n\n this._emit('open');\n this._emit('connected');\n resolve();\n })\n .catch((err) => {\n this._emit('error', err);\n resolve();\n });\n };\n\n ws.onmessage = (event: MessageEvent): void => {\n if (this._ws !== ws) return;\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(event.data as string) as Record<string, unknown>;\n } catch {\n return;\n }\n\n if (msg.type === 'pong') return;\n\n if (msg.type === 'dpop_verified') {\n this._pendingSubscription = false;\n if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n return;\n }\n\n if (msg.type === 'error') {\n this._emit('error', new Error(msg.message as string));\n return;\n }\n\n this._emit(msg.type as string, msg);\n this._emit('message', msg);\n };\n\n ws.onclose = (event: CloseEvent): void => {\n if (this._ws !== ws) return;\n this._clearTimers();\n\n if (this._wsIntentionalClose) {\n this._emit('close', event);\n return;\n }\n\n this._emit('close', event);\n this._emit('disconnected');\n this._autoReconnect();\n };\n\n ws.onerror = (err: Event): void => {\n if (this._ws !== ws) return;\n this._emit('error', err);\n if (ws.readyState !== WebSocket.OPEN) {\n reject(new Error('WebSocket connection failed'));\n }\n };\n });\n }\n\n private _scheduleTokenRefresh(): void {\n if (this._tokenRefreshTimer) clearTimeout(this._tokenRefreshTimer);\n\n const remaining = this._auth._tokenExpiry - Date.now();\n const refreshIn = Math.max(\n remaining - TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n );\n\n this._tokenRefreshTimer = setTimeout(() => {\n const oldWs = this._ws;\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((newToken) => {\n if (!oldWs || oldWs.readyState !== WebSocket.OPEN) return;\n\n this._wsIntentionalClose = true;\n oldWs.close(1000, 'Token refresh');\n\n this._wsIntentionalClose = false;\n return this._openWebSocket(newToken);\n })\n .catch((err) => {\n this._emit('error', err);\n this._autoReconnect();\n });\n }, refreshIn);\n }\n\n private _autoReconnect(): void {\n if (this._wsIntentionalClose) return;\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n\n if (this._reconnectAttempts >= RECONNECT_MAX_ATTEMPTS) {\n this._emit('error', new Error('Max reconnection attempts reached'));\n return;\n }\n\n const delay = Math.min(\n RECONNECT_BASE_MS * Math.pow(2, this._reconnectAttempts),\n RECONNECT_MAX_DELAY_MS,\n );\n this._reconnectAttempts++;\n this._emit('reconnecting', {\n attempt: this._reconnectAttempts,\n delay,\n });\n\n this._reconnectTimer = setTimeout(() => {\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((token) => this._openWebSocket(token))\n .catch(() => this._autoReconnect());\n }, delay);\n }\n\n private _clearTimers(): void {\n if (this._tokenRefreshTimer) {\n clearTimeout(this._tokenRefreshTimer);\n this._tokenRefreshTimer = null;\n }\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/sdk/index.ts", "../../src/sdk/events.ts", "../../src/sdk/dpop.ts", "../../src/sdk/pow.ts", "../../src/sdk/constants.ts", "../../src/sdk/auth.ts", "../../src/sdk/websocket.ts"],
4
- "sourcesContent": ["/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\n/**\n * GeonicDB JavaScript SDK\n *\n * NGSI-LD Context Broker client for browser and Node.js.\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ndeclare const document: any;\ndeclare const window: any;\n\nimport { EventEmitter } from './events';\nimport { AuthManager } from './auth';\nimport { WebSocketManager } from './websocket';\nimport type {\n GeonicDBOptions,\n CredentialsOptions,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n// Re-export types for consumers\nexport type {\n GeonicDBOptions,\n CredentialsOptions,\n RefreshedCredentials,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n EntityEvent,\n ReconnectingEvent,\n LoginResponse,\n GeonicDBEventMap,\n} from './types';\n\n/**\n * GeonicDB SDK client.\n *\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n *\n * @example\n * ```typescript\n * import GeonicDB from '@geolonia/geonicdb-sdk';\n *\n * const db = new GeonicDB({\n * apiKey: 'your-api-key',\n * tenant: 'your-tenant',\n * baseUrl: 'https://your-geonicdb.example.com',\n * });\n *\n * const entities = await db.getEntities({ type: 'Room' });\n * ```\n */\nexport class GeonicDB extends EventEmitter {\n private _auth: AuthManager;\n private _ws: WebSocketManager;\n\n /**\n * Legacy callback for token refresh events.\n * Prefer `db.on('tokenRefresh', callback)` for new code.\n * @deprecated Use `db.on('tokenRefresh', callback)` instead.\n */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(options?: GeonicDBOptions) {\n super();\n const opts = options || {};\n\n // Auto-detect from script tag in browser\n let apiKey = opts.apiKey || '';\n let tenant = opts.tenant || '';\n let baseUrl = opts.baseUrl || '';\n\n /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n if (typeof document !== 'undefined' && document.currentScript) {\n const script = document.currentScript;\n if (!apiKey) apiKey = script?.getAttribute?.('data-api-key') || '';\n if (!tenant) tenant = script?.getAttribute?.('data-tenant') || '';\n if (!baseUrl) baseUrl = script?.getAttribute?.('data-base-url') || '';\n }\n /* eslint-enable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n\n this._auth = new AuthManager(baseUrl, apiKey, tenant);\n this._auth.onTokenRefresh = (creds): void => {\n this.onTokenRefresh?.(creds);\n this.emit('tokenRefresh', creds);\n };\n this._ws = new WebSocketManager(\n this._auth,\n baseUrl,\n tenant,\n (event, data) => this.emit(event, data),\n opts.wsEndpoint,\n );\n }\n\n // --- Authentication ---\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n return this._auth.login(email, password);\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' with a refreshToken, DPoP/PoW is bypassed entirely.\n */\n setCredentials(opts: CredentialsOptions): this {\n this._auth.setCredentials(opts);\n return this;\n }\n\n /** Clear all credentials and disconnect. */\n logout(): void {\n this._ws.disconnect();\n this._auth.logout();\n }\n\n // --- Entity CRUD (NGSI-LD) ---\n\n /** Create a new entity. */\n async createEntity(\n entity: Record<string, unknown>,\n ): Promise<{ created: true }> {\n const res = await this._auth.request('POST', '/ngsi-ld/v1/entities', entity);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Create failed',\n );\n }\n return { created: true };\n }\n\n /** Get a single entity by ID. */\n async getEntity(entityId: string): Promise<Record<string, unknown>> {\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Not found',\n );\n }\n return (await res.json()) as Record<string, unknown>;\n }\n\n /** Query entities with optional filters. */\n async getEntities(\n params?: GetEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (parts.length) qs = '?' + parts.join('&');\n }\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Query failed',\n );\n }\n return (await res.json()) as Record<string, unknown>[];\n }\n\n /** Count entities matching the given filters. */\n async count(\n params?: CountEntitiesParams,\n ): Promise<number> {\n const parts: string[] = ['count=true', 'limit=0'];\n if (params?.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params?.q) parts.push('q=' + encodeURIComponent(params.q));\n const qs = '?' + parts.join('&');\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Count failed',\n );\n }\n const countHeader = res.headers.get('NGSILD-Results-Count');\n return countHeader ? parseInt(countHeader, 10) : 0;\n }\n\n /** Update entity attributes (partial). */\n async updateEntity(\n entityId: string,\n attrs: Record<string, unknown>,\n ): Promise<{ updated: true }> {\n const res = await this._auth.request(\n 'PATCH',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId) + '/attrs',\n attrs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Update failed',\n );\n }\n return { updated: true };\n }\n\n /** Delete an entity. */\n async deleteEntity(entityId: string): Promise<{ deleted: true }> {\n const res = await this._auth.request(\n 'DELETE',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Delete failed',\n );\n }\n return { deleted: true };\n }\n\n // --- Types / Attributes Discovery ---\n\n /** List all entity types. */\n async getTypes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/types', 'Types query failed');\n }\n\n /** Get details for a specific entity type. */\n async getType(typeName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/types/' + encodeURIComponent(typeName),\n 'Type not found',\n );\n }\n\n /** List all attributes. */\n async getAttributes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/attributes', 'Attributes query failed');\n }\n\n /** Get details for a specific attribute. */\n async getAttribute(attrName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/attributes/' + encodeURIComponent(attrName),\n 'Attribute not found',\n );\n }\n\n // --- Temporal API ---\n\n /** Query temporal entities. */\n async getTemporalEntities(\n params?: GetTemporalEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.id) parts.push('id=' + encodeURIComponent(params.id));\n if (params.idPattern) parts.push('idPattern=' + encodeURIComponent(params.idPattern));\n if (params.attrs) parts.push('attrs=' + encodeURIComponent(params.attrs));\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (params.timeproperty) parts.push('timeproperty=' + encodeURIComponent(params.timeproperty));\n if (params.timeAt) parts.push('timeAt=' + encodeURIComponent(params.timeAt));\n if (params.endTimeAt) parts.push('endTimeAt=' + encodeURIComponent(params.endTimeAt));\n if (params.timerel) parts.push('timerel=' + encodeURIComponent(params.timerel));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (parts.length) qs = '?' + parts.join('&');\n }\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities' + qs,\n 'Temporal query failed',\n );\n }\n\n /** Get temporal representation of a single entity. */\n async getTemporalEntity(entityId: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities/' + encodeURIComponent(entityId),\n 'Temporal entity not found',\n );\n }\n\n // --- Batch Operations ---\n\n /** Create multiple entities in a single request. */\n async batchCreate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/create',\n entities,\n 'Batch create failed',\n );\n }\n\n /** Upsert multiple entities in a single request. */\n async batchUpsert(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/upsert',\n entities,\n 'Batch upsert failed',\n );\n }\n\n /** Update multiple entities in a single request. */\n async batchUpdate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/update',\n entities,\n 'Batch update failed',\n );\n }\n\n /** Delete multiple entities by ID. */\n async batchDelete(entityIds: string[]): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/delete',\n entityIds,\n 'Batch delete failed',\n );\n }\n\n // --- Internal helpers ---\n\n /** GET request that returns parsed JSON or throws. */\n private async _jsonGet<T>(path: string, fallbackError: string): Promise<T> {\n const res = await this._auth.request('GET', path);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n return (await res.json()) as T;\n }\n\n /** POST request that returns parsed JSON or throws. */\n private async _jsonPost<T>(\n path: string,\n body: unknown,\n fallbackError: string,\n ): Promise<T> {\n const res = await this._auth.request('POST', path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n if (res.status === 204) return {} as T;\n return (await res.json()) as T;\n }\n\n // --- Generic Request ---\n\n /**\n * Make an authenticated API request.\n * Automatically checks response status, parses JSON, and throws on error.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<unknown> {\n const res = await this._auth.request(method, path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Request failed: ' + res.status,\n );\n }\n const ct = res.headers.get('Content-Type') || '';\n if (res.status === 204 || !ct) return null;\n if (ct.indexOf('json') !== -1) return res.json();\n return res.text();\n }\n\n /**\n * Make an authenticated API request and return the raw Response object.\n * Use this when you need access to response headers (e.g. NGSILD-Results-Count).\n */\n async requestRaw(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n return this._auth.request(method, path, body);\n }\n\n // --- WebSocket ---\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n return this._ws.connect();\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n return this._ws.reconnect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._ws.disconnect();\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return this._ws.isConnected();\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: SubscribeOptions): void {\n this._ws.subscribe(options);\n }\n}\n\n// Default export for convenient importing\nexport default GeonicDB;\n\n// UMD-style global assignment for browser script tag usage\nif (typeof window !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n window.GeonicDB = GeonicDB;\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport type { GeonicDBEventMap } from './types';\n\ntype Listener<T> = (data: T) => void;\n\n/**\n * Minimal typed event emitter for GeonicDB SDK.\n */\nexport class EventEmitter {\n private _listeners: Record<string, Listener<unknown>[]> =\n Object.create(null) as Record<string, Listener<unknown>[]>;\n\n on<K extends keyof GeonicDBEventMap>(\n event: K,\n callback: Listener<GeonicDBEventMap[K]>,\n ): this;\n on(event: string, callback: Listener<unknown>): this;\n on(event: string, callback: Listener<unknown>): this {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n this._listeners[event].push(callback);\n return this;\n }\n\n off<K extends keyof GeonicDBEventMap>(\n event: K,\n callback?: Listener<GeonicDBEventMap[K]>,\n ): this;\n off(event: string, callback?: Listener<unknown>): this;\n off(event: string, callback?: Listener<unknown>): this {\n if (!this._listeners[event]) return this;\n if (!callback) {\n delete this._listeners[event];\n } else {\n this._listeners[event] = this._listeners[event].filter(\n (cb) => cb !== callback,\n );\n }\n return this;\n }\n\n protected emit<K extends keyof GeonicDBEventMap>(\n event: K,\n data?: GeonicDBEventMap[K],\n ): void;\n protected emit(event: string, data?: unknown): void;\n protected emit(event: string, data?: unknown): void {\n const cbs = this._listeners[event];\n if (!cbs) return;\n const snapshot = cbs.slice();\n for (const cb of snapshot) {\n try {\n cb(data);\n } catch {\n // listener error \u2014 swallow silently\n }\n }\n }\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport type { DPoPKeyPair } from './types';\n\n/** Whether the Web Crypto DPoP API is available in the current environment. */\nexport const dpopSupported =\n typeof crypto !== 'undefined' &&\n !!crypto.subtle &&\n !!crypto.subtle.generateKey;\n\n/** Base64url-encode an ArrayBuffer or Uint8Array. */\nfunction b64url(buf: ArrayBuffer | Uint8Array): string {\n const arr = buf instanceof ArrayBuffer ? new Uint8Array(buf) : buf;\n let str = '';\n for (let i = 0; i < arr.length; i++) {\n str += String.fromCharCode(arr[i]);\n }\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** Encode a string to Uint8Array. */\nfunction strToUint8(s: string): Uint8Array {\n return new TextEncoder().encode(s);\n}\n\n/** Generate an ECDSA P-256 key pair for DPoP proof creation. */\nexport async function generateDPoPKeyPair(): Promise<DPoPKeyPair | null> {\n if (!dpopSupported) return null;\n const kp = await crypto.subtle.generateKey(\n { name: 'ECDSA', namedCurve: 'P-256' },\n false,\n ['sign'],\n );\n const pubJwk = await crypto.subtle.exportKey(\n 'jwk',\n kp.publicKey,\n );\n return {\n privateKey: kp.privateKey,\n publicJwk: {\n kty: pubJwk.kty!,\n crv: pubJwk.crv!,\n x: pubJwk.x!,\n y: pubJwk.y!,\n },\n };\n}\n\n/**\n * Create a DPoP proof JWT (RFC 9449).\n *\n * @param keyPair - The DPoP key pair\n * @param htm - HTTP method\n * @param htu - HTTP target URI\n * @param accessToken - Optional access token for ath claim\n * @param nonce - Optional server-provided nonce\n * @returns Signed DPoP proof JWT or null if keyPair is null\n */\nexport async function createDPoPProof(\n keyPair: DPoPKeyPair | null,\n htm: string,\n htu: string,\n accessToken?: string | null,\n nonce?: string | null,\n): Promise<string | null> {\n if (!keyPair) return null;\n\n const header = { alg: 'ES256', typ: 'dpop+jwt', jwk: keyPair.publicJwk };\n const payload: Record<string, unknown> = {\n jti:\n typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : Date.now().toString(36) + Math.random().toString(36).substr(2),\n htm,\n htu,\n iat: Math.floor(Date.now() / 1000),\n };\n if (nonce) payload.nonce = nonce;\n\n if (accessToken) {\n const hash = await crypto.subtle.digest('SHA-256', strToUint8(accessToken) as unknown as ArrayBuffer);\n payload.ath = b64url(hash);\n }\n\n const headerB64 = b64url(strToUint8(JSON.stringify(header)));\n const payloadB64 = b64url(strToUint8(JSON.stringify(payload)));\n const signingInput = headerB64 + '.' + payloadB64;\n\n /* eslint-disable @typescript-eslint/no-unsafe-argument */\n const sigBuf = await crypto.subtle.sign(\n { name: 'ECDSA', hash: 'SHA-256' },\n keyPair.privateKey,\n strToUint8(signingInput) as unknown as ArrayBuffer,\n );\n /* eslint-enable @typescript-eslint/no-unsafe-argument */\n // WebCrypto ECDSA returns IEEE P1363 r||s format (64 bytes for P-256)\n return signingInput + '.' + b64url(new Uint8Array(sigBuf));\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nconst BATCH_SIZE = 1000;\nconst MAX_ITERATIONS = 1_000_000;\n\n/** Check whether the first `bits` bits of a hash are zero. */\nfunction checkZeros(hash: Uint8Array, bits: number): boolean {\n const fullBytes = Math.floor(bits / 8);\n const remainBits = bits % 8;\n for (let k = 0; k < fullBytes; k++) {\n if (hash[k] !== 0) return false;\n }\n if (remainBits > 0) {\n const mask = 0xff << (8 - remainBits);\n if ((hash[fullBytes] & mask) !== 0) return false;\n }\n return true;\n}\n\n/**\n * Solve a Proof of Work challenge asynchronously using Web Crypto.\n *\n * Hashes `challenge + nonce` (SHA-256) in batches and checks for\n * the required number of leading zero bits.\n *\n * @param challenge - The challenge string from the server\n * @param difficulty - Number of leading zero bits required\n * @returns The nonce that satisfies the difficulty\n */\nexport async function solvePoW(\n challenge: string,\n difficulty: number,\n): Promise<number> {\n if (!Number.isInteger(difficulty) || difficulty < 0 || difficulty > 256) {\n throw new Error('difficulty must be an integer between 0 and 256');\n }\n const encoder = new TextEncoder();\n let i = 0;\n\n async function tryBatch(): Promise<number> {\n const batchEnd = Math.min(i + BATCH_SIZE, MAX_ITERATIONS);\n const promises: Promise<{ idx: number; hash: Uint8Array }>[] = [];\n\n for (; i < batchEnd; i++) {\n const idx = i;\n promises.push(\n crypto.subtle\n .digest('SHA-256', encoder.encode(challenge + String(idx)))\n .then((buf) => ({ idx, hash: new Uint8Array(buf) })),\n );\n }\n\n const results = await Promise.all(promises);\n for (const result of results) {\n if (checkZeros(result.hash, difficulty)) {\n return result.idx;\n }\n }\n if (i >= MAX_ITERATIONS) throw new Error('PoW solution not found');\n return tryBatch();\n }\n\n return tryBatch();\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\n/** Default token TTL in seconds when expiresIn is not specified in setCredentials(). */\nexport const DEFAULT_TOKEN_TTL_SEC = 3_600;\n\n/** Token refresh leeway in ms \u2014 refresh 2 minutes before expiry. */\nexport const TOKEN_REFRESH_LEEWAY_MS = 120_000;\n\n/** Minimum wait time in ms before refreshing a token. */\nexport const TOKEN_REFRESH_MIN_MS = 10_000;\n\n/** Maximum WebSocket reconnection attempts. */\nexport const RECONNECT_MAX_ATTEMPTS = 10;\n\n/** Base delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_BASE_MS = 1_000;\n\n/** Maximum delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_MAX_DELAY_MS = 30_000;\n\n/** WebSocket sub-protocol name for browser authentication. */\nexport const SUB_PROTOCOL = 'access_token';\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport { createDPoPProof, dpopSupported, generateDPoPKeyPair } from './dpop';\nimport { solvePoW } from './pow';\nimport { DEFAULT_TOKEN_TTL_SEC } from './constants';\nimport type {\n CredentialsOptions,\n DPoPKeyPair,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n/** Internal authentication state for the GeonicDB SDK. */\nexport class AuthManager {\n private _baseUrl: string;\n private _apiKey: string;\n private _tenant: string;\n\n _token: string | null = null;\n _tokenExpiry = 0;\n _tokenType: 'Bearer' | 'DPoP' = 'Bearer';\n _refreshToken: string | null = null;\n _dpopKeyPair: DPoPKeyPair | null = null;\n _dpopReady: Promise<void> | null = null;\n _dpopNonce: string | null = null;\n private _tokenPromise: Promise<string> | null = null;\n\n /** Callback to emit tokenRefresh events. Set by GeonicDB class. */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(baseUrl: string, apiKey: string, tenant: string) {\n this._baseUrl = baseUrl;\n this._apiKey = apiKey;\n this._tenant = tenant;\n\n if (dpopSupported) {\n this._dpopReady = generateDPoPKeyPair()\n .then((kp) => {\n this._dpopKeyPair = kp;\n })\n .catch(() => {\n this._dpopKeyPair = null;\n });\n }\n }\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (this._tenant) headers['NGSILD-Tenant'] = this._tenant;\n\n const res = await fetch(this._baseUrl + '/auth/login', {\n method: 'POST',\n headers,\n body: JSON.stringify({ email, password }),\n });\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Login failed: ' + res.status,\n );\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n return data;\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' and refreshToken is provided, all subsequent\n * API calls and connect() bypass DPoP/PoW entirely.\n */\n setCredentials(opts: CredentialsOptions): void {\n if (!opts || !opts.token) throw new Error('token is required');\n this._token = opts.token;\n this._tokenType = opts.tokenType || 'Bearer';\n this._tokenExpiry = opts.expiresIn != null\n ? Date.now() + (opts.expiresIn - 60) * 1000\n : Date.now() + DEFAULT_TOKEN_TTL_SEC * 1000;\n this._refreshToken = opts.refreshToken || null;\n this._tokenPromise = null;\n }\n\n /** Clear all credentials. */\n logout(): void {\n this._token = null;\n this._tokenExpiry = 0;\n this._refreshToken = null;\n this._tokenPromise = null;\n }\n\n /** Ensure a valid token is available, refreshing or acquiring as needed. */\n async ensureToken(): Promise<string> {\n if (this._token && Date.now() < this._tokenExpiry) {\n return this._token;\n }\n\n // Deduplicate concurrent calls\n if (this._tokenPromise) {\n return this._tokenPromise;\n }\n\n // Bearer JWT refresh path \u2014 skip DPoP/PoW\n if (this._refreshToken) {\n this._tokenPromise = this._refreshBearerToken();\n return this._tokenPromise;\n }\n\n // API key + DPoP/PoW path\n this._tokenPromise = this._acquireTokenViaPow();\n return this._tokenPromise;\n }\n\n private async _refreshBearerToken(): Promise<string> {\n try {\n const res = await fetch(this._baseUrl + '/auth/refresh', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ refreshToken: this._refreshToken }),\n });\n if (!res.ok) {\n this._refreshToken = null;\n this._token = null;\n this._tokenPromise = null;\n throw new Error('Token refresh failed: ' + res.status);\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n this._tokenPromise = null;\n this.onTokenRefresh?.({\n token: this._token,\n tokenType: this._tokenType,\n expiresIn: data.expiresIn,\n refreshToken: this._refreshToken,\n });\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private async _acquireTokenViaPow(): Promise<string> {\n try {\n if (this._dpopReady) await this._dpopReady;\n\n // Step 1: Get nonce + PoW challenge\n const nonceRes = await fetch(this._baseUrl + '/auth/nonce', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ api_key: this._apiKey }),\n });\n if (!nonceRes.ok)\n throw new Error('Nonce request failed: ' + nonceRes.status);\n const nonceData = (await nonceRes.json()) as {\n nonce: string;\n challenge: string;\n difficulty: number;\n dpop_nonce?: string;\n };\n\n // RFC 9449 \u00A78: store pre-issued DPoP-Nonce\n if (nonceData.dpop_nonce) this._dpopNonce = nonceData.dpop_nonce;\n\n // Step 2: Solve PoW\n const proof = await solvePoW(nonceData.challenge, nonceData.difficulty);\n\n // Step 3: Exchange for token\n const tokenUrl = this._baseUrl + '/oauth/token';\n const tokenBody = JSON.stringify({\n grant_type: 'api_key',\n api_key: this._apiKey,\n nonce: nonceData.nonce,\n proof: String(proof),\n });\n\n const res = await this._doTokenExchange(tokenUrl, tokenBody, this._dpopNonce);\n\n if (!res.ok)\n throw new Error('Token request failed: ' + res.status);\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n const data = (await res.json()) as {\n access_token: string;\n expires_in: number;\n token_type?: string;\n };\n this._token = data.access_token;\n this._tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;\n this._tokenType = (data.token_type as 'Bearer' | 'DPoP') || 'Bearer';\n this._tokenPromise = null;\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private static readonly MAX_DPOP_RETRIES = 3;\n\n private async _doTokenExchange(\n tokenUrl: string,\n tokenBody: string,\n dpopNonce: string | null,\n retryCount = 0,\n ): Promise<Response> {\n const reqHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n const dpopProof = await createDPoPProof(\n this._dpopKeyPair,\n 'POST',\n tokenUrl,\n null,\n dpopNonce,\n );\n if (dpopProof) reqHeaders['DPoP'] = dpopProof;\n\n const res = await fetch(tokenUrl, {\n method: 'POST',\n headers: reqHeaders,\n body: tokenBody,\n });\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 400 && this._dpopKeyPair) {\n const errBody = await res.json().catch(() => ({})) as Record<string, string>;\n if (errBody.error === 'use_dpop_nonce') {\n const serverNonce = res.headers.get('DPoP-Nonce');\n if (serverNonce && serverNonce !== dpopNonce && retryCount < AuthManager.MAX_DPOP_RETRIES) {\n this._dpopNonce = serverNonce;\n return this._doTokenExchange(tokenUrl, tokenBody, serverNonce, retryCount + 1);\n }\n }\n throw new Error(\n 'Token request failed: ' +\n (errBody.error_description || errBody.error),\n );\n }\n\n return res;\n }\n\n /**\n * Make an authenticated HTTP request with automatic token refresh and DPoP.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const token = await this.ensureToken();\n return this._doAuthenticatedRequest(method, path, body, token);\n }\n\n private static readonly MAX_REQUEST_RETRIES = 3;\n\n private async _doAuthenticatedRequest(\n method: string,\n path: string,\n body: unknown,\n token: string,\n retryCount = 0,\n ): Promise<Response> {\n const url = this._baseUrl + path;\n const isDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const bodyStr = body !== undefined ? JSON.stringify(body) : undefined;\n\n const doRequest = async (\n reqToken: string,\n dpopNonce: string | null,\n ): Promise<Response> => {\n const reqIsDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const dpopProof = reqIsDPoP\n ? await createDPoPProof(\n this._dpopKeyPair,\n method,\n url,\n reqToken,\n dpopNonce,\n )\n : null;\n\n const headers: Record<string, string> = {\n Authorization: (reqIsDPoP ? 'DPoP ' : 'Bearer ') + reqToken,\n 'Content-Type': 'application/ld+json',\n Accept: 'application/ld+json',\n };\n if (dpopProof) headers['DPoP'] = dpopProof;\n if (this._tenant) headers['Fiware-Service'] = this._tenant;\n\n return fetch(url, { method, headers, body: bodyStr });\n };\n\n let currentToken = token;\n let res = await doRequest(currentToken, this._dpopNonce);\n const previousNonce = this._dpopNonce;\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 401 && isDPoP && newNonce && newNonce !== previousNonce) {\n res = await doRequest(currentToken, newNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const fn = res.headers.get('DPoP-Nonce');\n if (fn) this._dpopNonce = fn;\n }\n } else if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n }\n\n if (res.status === 429 && retryCount < AuthManager.MAX_REQUEST_RETRIES) {\n const retryNonce = res.headers.get('DPoP-Nonce');\n if (retryNonce) this._dpopNonce = retryNonce;\n const delay =\n parseInt(res.headers.get('Retry-After') || '1', 10) * 1000;\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\n return this._doAuthenticatedRequest(method, path, body, currentToken, retryCount + 1);\n }\n\n return res;\n }\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport { createDPoPProof } from './dpop';\nimport type { AuthManager } from './auth';\nimport {\n TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n RECONNECT_MAX_ATTEMPTS,\n RECONNECT_BASE_MS,\n RECONNECT_MAX_DELAY_MS,\n SUB_PROTOCOL,\n} from './constants';\nimport type { SubscriptionMessage } from './types';\n\ntype EmitFn = (event: string, data?: unknown) => void;\n\n/**\n * WebSocket connection manager for the GeonicDB SDK.\n *\n * Handles connection lifecycle, DPoP binding, token refresh,\n * automatic reconnection with exponential backoff, and subscriptions.\n */\nexport class WebSocketManager {\n private _auth: AuthManager;\n private _tenant: string;\n private _wsEndpointOverride: string | null;\n private _baseUrl: string;\n private _emit: EmitFn;\n\n private _ws: WebSocket | null = null;\n private _wsEndpoint: string | null = null;\n private _wsIntentionalClose = false;\n private _reconnectAttempts = 0;\n private _tokenRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private _subscription: SubscriptionMessage | null = null;\n private _pendingSubscription = false;\n\n constructor(\n auth: AuthManager,\n baseUrl: string,\n tenant: string,\n emit: EmitFn,\n wsEndpointOverride?: string,\n ) {\n this._auth = auth;\n this._baseUrl = baseUrl;\n this._tenant = tenant;\n this._emit = emit;\n this._wsEndpointOverride = wsEndpointOverride || null;\n }\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n this._wsIntentionalClose = false;\n this._reconnectAttempts = 0;\n\n try {\n const token = await this._auth.ensureToken();\n await this._openWebSocket(token);\n } catch (err) {\n this._emit('error', err);\n }\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n this._wsIntentionalClose = true;\n this._clearTimers();\n if (this._ws) {\n this._ws.close(1000, 'Client reconnect');\n this._ws = null;\n }\n return this.connect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._wsIntentionalClose = true;\n this._clearTimers();\n this._subscription = null;\n this._pendingSubscription = false;\n if (this._ws) {\n this._ws.close(1000, 'Client disconnect');\n this._ws = null;\n }\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return !!(this._ws && this._ws.readyState === WebSocket.OPEN);\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: { entityTypes?: string[]; idPattern?: string }): void {\n const msg: SubscriptionMessage = { action: 'subscribe' };\n if (options) {\n if (options.entityTypes) msg.entityTypes = options.entityTypes;\n if (options.idPattern) msg.idPattern = options.idPattern;\n }\n this._subscription = msg;\n // If DPoP pending verification, store subscription but don't send yet\n if (this._pendingSubscription) return;\n if (this._ws && this._ws.readyState === WebSocket.OPEN) {\n this._ws.send(JSON.stringify(msg));\n }\n }\n\n private async _discoverWsEndpoint(): Promise<string> {\n if (this._wsEndpointOverride) return this._wsEndpointOverride;\n if (this._wsEndpoint) return this._wsEndpoint;\n\n // Fetch endpoint from server discovery API\n try {\n const res = await fetch(this._baseUrl + '/sdk/v1/streaming');\n if (res.ok) {\n const info = (await res.json()) as {\n enabled: boolean;\n endpoint: string | null;\n };\n if (info.enabled && info.endpoint) {\n this._wsEndpoint = info.endpoint;\n return this._wsEndpoint;\n }\n }\n } catch {\n // Discovery failed \u2014 fall back to URL scheme conversion\n }\n\n // Fallback: convert http(s) baseUrl to ws(s)\n this._wsEndpoint = this._baseUrl.replace(/^http/, 'ws');\n return this._wsEndpoint;\n }\n\n private async _openWebSocket(token: string): Promise<void> {\n const endpoint = await this._discoverWsEndpoint();\n return new Promise<void>((resolve, reject) => {\n const wsUrl =\n endpoint +\n (endpoint.indexOf('?') === -1 ? '?' : '&') +\n 'tenant=' +\n encodeURIComponent(this._tenant);\n\n const ws = new WebSocket(wsUrl, [SUB_PROTOCOL, token]);\n this._ws = ws;\n\n ws.onopen = (): void => {\n if (this._ws !== ws) return;\n this._reconnectAttempts = 0;\n\n const isDPoP =\n this._auth._tokenType === 'DPoP' && !!this._auth._dpopKeyPair;\n\n const bindPromise = isDPoP\n ? createDPoPProof(this._auth._dpopKeyPair, 'GET', wsUrl, null).then(\n (proof) => {\n if (proof && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ action: 'dpop_bind', proof }));\n }\n },\n )\n : Promise.resolve();\n\n bindPromise\n .then(() => {\n this._scheduleTokenRefresh();\n\n if (isDPoP) {\n this._pendingSubscription = true;\n } else if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n\n this._emit('open');\n this._emit('connected');\n resolve();\n })\n .catch((err) => {\n this._emit('error', err);\n resolve();\n });\n };\n\n ws.onmessage = (event: MessageEvent): void => {\n if (this._ws !== ws) return;\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(event.data as string) as Record<string, unknown>;\n } catch {\n return;\n }\n\n if (msg.type === 'pong') return;\n\n if (msg.type === 'dpop_verified') {\n this._pendingSubscription = false;\n if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n return;\n }\n\n if (msg.type === 'error') {\n this._emit('error', new Error(msg.message as string));\n return;\n }\n\n this._emit(msg.type as string, msg);\n this._emit('message', msg);\n };\n\n ws.onclose = (event: CloseEvent): void => {\n if (this._ws !== ws) return;\n this._clearTimers();\n\n if (this._wsIntentionalClose) {\n this._emit('close', event);\n return;\n }\n\n this._emit('close', event);\n this._emit('disconnected');\n this._autoReconnect();\n };\n\n ws.onerror = (err: Event): void => {\n if (this._ws !== ws) return;\n this._emit('error', err);\n if (ws.readyState !== WebSocket.OPEN) {\n reject(new Error('WebSocket connection failed'));\n }\n };\n });\n }\n\n private _scheduleTokenRefresh(): void {\n if (this._tokenRefreshTimer) clearTimeout(this._tokenRefreshTimer);\n\n const remaining = this._auth._tokenExpiry - Date.now();\n const refreshIn = Math.max(\n remaining - TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n );\n\n this._tokenRefreshTimer = setTimeout(() => {\n const oldWs = this._ws;\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((newToken) => {\n if (!oldWs || oldWs.readyState !== WebSocket.OPEN) return;\n\n this._wsIntentionalClose = true;\n oldWs.close(1000, 'Token refresh');\n\n this._wsIntentionalClose = false;\n return this._openWebSocket(newToken);\n })\n .catch((err) => {\n this._emit('error', err);\n this._autoReconnect();\n });\n }, refreshIn);\n }\n\n private _autoReconnect(): void {\n if (this._wsIntentionalClose) return;\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n\n if (this._reconnectAttempts >= RECONNECT_MAX_ATTEMPTS) {\n this._emit('error', new Error('Max reconnection attempts reached'));\n return;\n }\n\n const delay = Math.min(\n RECONNECT_BASE_MS * Math.pow(2, this._reconnectAttempts),\n RECONNECT_MAX_DELAY_MS,\n );\n this._reconnectAttempts++;\n this._emit('reconnecting', {\n attempt: this._reconnectAttempts,\n delay,\n });\n\n this._reconnectTimer = setTimeout(() => {\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((token) => this._openWebSocket(token))\n .catch(() => this._autoReconnect());\n }, delay);\n }\n\n private _clearTimers(): void {\n if (this._tokenRefreshTimer) {\n clearTimeout(this._tokenRefreshTimer);\n this._tokenRefreshTimer = null;\n }\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\n/**\n * GeonicDB JavaScript SDK\n *\n * NGSI-LD Context Broker client for browser and Node.js.\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ndeclare const document: any;\ndeclare const window: any;\n\nimport { EventEmitter } from './events';\nimport { AuthManager } from './auth';\nimport { WebSocketManager } from './websocket';\nimport type {\n GeonicDBOptions,\n CredentialsOptions,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n// Re-export types for consumers\nexport type {\n GeonicDBOptions,\n CredentialsOptions,\n RefreshedCredentials,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n EntityEvent,\n ReconnectingEvent,\n LoginResponse,\n GeonicDBEventMap,\n} from './types';\n\n/**\n * GeonicDB SDK client.\n *\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n *\n * @example\n * ```typescript\n * import GeonicDB from '@geolonia/geonicdb-sdk';\n *\n * const db = new GeonicDB({\n * apiKey: 'your-api-key',\n * tenant: 'your-tenant',\n * baseUrl: 'https://your-geonicdb.example.com',\n * });\n *\n * const entities = await db.getEntities({ type: 'Room' });\n * ```\n */\nexport class GeonicDB extends EventEmitter {\n private _auth: AuthManager;\n private _ws: WebSocketManager;\n\n /**\n * Legacy callback for token refresh events.\n * Prefer `db.on('tokenRefresh', callback)` for new code.\n * @deprecated Use `db.on('tokenRefresh', callback)` instead.\n */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(options?: GeonicDBOptions) {\n super();\n const opts = options || {};\n\n // Auto-detect from script tag in browser\n let apiKey = opts.apiKey || '';\n let tenant = opts.tenant || '';\n let baseUrl = opts.baseUrl || '';\n\n /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n if (typeof document !== 'undefined' && document.currentScript) {\n const script = document.currentScript;\n if (!apiKey) apiKey = script?.getAttribute?.('data-api-key') || '';\n if (!tenant) tenant = script?.getAttribute?.('data-tenant') || '';\n if (!baseUrl) baseUrl = script?.getAttribute?.('data-base-url') || '';\n }\n /* eslint-enable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n\n this._auth = new AuthManager(baseUrl, apiKey, tenant);\n this._auth.onTokenRefresh = (creds): void => {\n this.onTokenRefresh?.(creds);\n this.emit('tokenRefresh', creds);\n };\n this._ws = new WebSocketManager(\n this._auth,\n baseUrl,\n tenant,\n (event, data) => this.emit(event, data),\n opts.wsEndpoint,\n );\n }\n\n // --- Authentication ---\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n return this._auth.login(email, password);\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' with a refreshToken, DPoP/PoW is bypassed entirely.\n */\n setCredentials(opts: CredentialsOptions): this {\n this._auth.setCredentials(opts);\n return this;\n }\n\n /** Clear all credentials and disconnect. */\n logout(): void {\n this._ws.disconnect();\n this._auth.logout();\n }\n\n // --- Entity CRUD (NGSI-LD) ---\n\n /** Create a new entity. */\n async createEntity(\n entity: Record<string, unknown>,\n ): Promise<{ created: true }> {\n const res = await this._auth.request('POST', '/ngsi-ld/v1/entities', entity);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Create failed',\n );\n }\n return { created: true };\n }\n\n /** Get a single entity by ID. */\n async getEntity(entityId: string): Promise<Record<string, unknown>> {\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Not found',\n );\n }\n return (await res.json()) as Record<string, unknown>;\n }\n\n /** Query entities with optional filters. */\n async getEntities(\n params?: GetEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (parts.length) qs = '?' + parts.join('&');\n }\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Query failed',\n );\n }\n return (await res.json()) as Record<string, unknown>[];\n }\n\n /** Count entities matching the given filters. */\n async count(\n params?: CountEntitiesParams,\n ): Promise<number> {\n const parts: string[] = ['count=true', 'limit=0'];\n if (params?.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params?.q) parts.push('q=' + encodeURIComponent(params.q));\n const qs = '?' + parts.join('&');\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Count failed',\n );\n }\n const countHeader = res.headers.get('NGSILD-Results-Count');\n return countHeader ? parseInt(countHeader, 10) : 0;\n }\n\n /** Update entity attributes (partial). */\n async updateEntity(\n entityId: string,\n attrs: Record<string, unknown>,\n ): Promise<{ updated: true }> {\n const res = await this._auth.request(\n 'PATCH',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId) + '/attrs',\n attrs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Update failed',\n );\n }\n return { updated: true };\n }\n\n /** Delete an entity. */\n async deleteEntity(entityId: string): Promise<{ deleted: true }> {\n const res = await this._auth.request(\n 'DELETE',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Delete failed',\n );\n }\n return { deleted: true };\n }\n\n // --- Types / Attributes Discovery ---\n\n /** List all entity types. */\n async getTypes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/types', 'Types query failed');\n }\n\n /** Get details for a specific entity type. */\n async getType(typeName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/types/' + encodeURIComponent(typeName),\n 'Type not found',\n );\n }\n\n /** List all attributes. */\n async getAttributes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/attributes', 'Attributes query failed');\n }\n\n /** Get details for a specific attribute. */\n async getAttribute(attrName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/attributes/' + encodeURIComponent(attrName),\n 'Attribute not found',\n );\n }\n\n // --- Temporal API ---\n\n /** Query temporal entities. */\n async getTemporalEntities(\n params?: GetTemporalEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.id) parts.push('id=' + encodeURIComponent(params.id));\n if (params.idPattern) parts.push('idPattern=' + encodeURIComponent(params.idPattern));\n if (params.attrs) parts.push('attrs=' + encodeURIComponent(params.attrs));\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (params.timeproperty) parts.push('timeproperty=' + encodeURIComponent(params.timeproperty));\n if (params.timeAt) parts.push('timeAt=' + encodeURIComponent(params.timeAt));\n if (params.endTimeAt) parts.push('endTimeAt=' + encodeURIComponent(params.endTimeAt));\n if (params.timerel) parts.push('timerel=' + encodeURIComponent(params.timerel));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (parts.length) qs = '?' + parts.join('&');\n }\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities' + qs,\n 'Temporal query failed',\n );\n }\n\n /** Get temporal representation of a single entity. */\n async getTemporalEntity(entityId: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities/' + encodeURIComponent(entityId),\n 'Temporal entity not found',\n );\n }\n\n // --- Batch Operations ---\n\n /** Create multiple entities in a single request. */\n async batchCreate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/create',\n entities,\n 'Batch create failed',\n );\n }\n\n /** Upsert multiple entities in a single request. */\n async batchUpsert(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/upsert',\n entities,\n 'Batch upsert failed',\n );\n }\n\n /** Update multiple entities in a single request. */\n async batchUpdate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/update',\n entities,\n 'Batch update failed',\n );\n }\n\n /** Delete multiple entities by ID. */\n async batchDelete(entityIds: string[]): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/delete',\n entityIds,\n 'Batch delete failed',\n );\n }\n\n // --- Internal helpers ---\n\n /** GET request that returns parsed JSON or throws. */\n private async _jsonGet<T>(path: string, fallbackError: string): Promise<T> {\n const res = await this._auth.request('GET', path);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n return (await res.json()) as T;\n }\n\n /** POST request that returns parsed JSON or throws. */\n private async _jsonPost<T>(\n path: string,\n body: unknown,\n fallbackError: string,\n ): Promise<T> {\n const res = await this._auth.request('POST', path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n if (res.status === 204) return {} as T;\n return (await res.json()) as T;\n }\n\n // --- Generic Request ---\n\n /**\n * Make an authenticated API request.\n * Automatically checks response status, parses JSON, and throws on error.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<unknown> {\n const res = await this._auth.request(method, path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Request failed: ' + res.status,\n );\n }\n const ct = res.headers.get('Content-Type') || '';\n if (res.status === 204 || !ct) return null;\n if (ct.indexOf('json') !== -1) return res.json();\n return res.text();\n }\n\n /**\n * Make an authenticated API request and return the raw Response object.\n * Use this when you need access to response headers (e.g. NGSILD-Results-Count).\n */\n async requestRaw(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n return this._auth.request(method, path, body);\n }\n\n // --- WebSocket ---\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n return this._ws.connect();\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n return this._ws.reconnect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._ws.disconnect();\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return this._ws.isConnected();\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: SubscribeOptions): void {\n this._ws.subscribe(options);\n }\n}\n\n// Default export for convenient importing\nexport default GeonicDB;\n\n// UMD-style global assignment for browser script tag usage\nif (typeof window !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n window.GeonicDB = GeonicDB;\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport type { GeonicDBEventMap } from './types';\n\ntype Listener<T> = (data: T) => void;\n\n/**\n * Minimal typed event emitter for GeonicDB SDK.\n */\nexport class EventEmitter {\n private _listeners: Record<string, Listener<unknown>[]> =\n Object.create(null) as Record<string, Listener<unknown>[]>;\n\n on<K extends keyof GeonicDBEventMap>(\n event: K,\n callback: Listener<GeonicDBEventMap[K]>,\n ): this;\n on(event: string, callback: Listener<unknown>): this;\n on(event: string, callback: Listener<unknown>): this {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n this._listeners[event].push(callback);\n return this;\n }\n\n off<K extends keyof GeonicDBEventMap>(\n event: K,\n callback?: Listener<GeonicDBEventMap[K]>,\n ): this;\n off(event: string, callback?: Listener<unknown>): this;\n off(event: string, callback?: Listener<unknown>): this {\n if (!this._listeners[event]) return this;\n if (!callback) {\n delete this._listeners[event];\n } else {\n this._listeners[event] = this._listeners[event].filter(\n (cb) => cb !== callback,\n );\n }\n return this;\n }\n\n protected emit<K extends keyof GeonicDBEventMap>(\n event: K,\n data?: GeonicDBEventMap[K],\n ): void;\n protected emit(event: string, data?: unknown): void;\n protected emit(event: string, data?: unknown): void {\n const cbs = this._listeners[event];\n if (!cbs) return;\n const snapshot = cbs.slice();\n for (const cb of snapshot) {\n try {\n cb(data);\n } catch {\n // listener error \u2014 swallow silently\n }\n }\n }\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport type { DPoPKeyPair } from './types';\n\n/** Whether the Web Crypto DPoP API is available in the current environment. */\nexport const dpopSupported =\n typeof crypto !== 'undefined' &&\n !!crypto.subtle &&\n !!crypto.subtle.generateKey;\n\n/** Base64url-encode an ArrayBuffer or Uint8Array. */\nfunction b64url(buf: ArrayBuffer | Uint8Array): string {\n const arr = buf instanceof ArrayBuffer ? new Uint8Array(buf) : buf;\n let str = '';\n for (let i = 0; i < arr.length; i++) {\n str += String.fromCharCode(arr[i]);\n }\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** Encode a string to Uint8Array. */\nfunction strToUint8(s: string): Uint8Array {\n return new TextEncoder().encode(s);\n}\n\n/** Generate an ECDSA P-256 key pair for DPoP proof creation. */\nexport async function generateDPoPKeyPair(): Promise<DPoPKeyPair | null> {\n if (!dpopSupported) return null;\n const kp = await crypto.subtle.generateKey(\n { name: 'ECDSA', namedCurve: 'P-256' },\n false,\n ['sign'],\n );\n const pubJwk = await crypto.subtle.exportKey(\n 'jwk',\n kp.publicKey,\n );\n return {\n privateKey: kp.privateKey,\n publicJwk: {\n kty: pubJwk.kty!,\n crv: pubJwk.crv!,\n x: pubJwk.x!,\n y: pubJwk.y!,\n },\n };\n}\n\n/**\n * Create a DPoP proof JWT (RFC 9449).\n *\n * @param keyPair - The DPoP key pair\n * @param htm - HTTP method\n * @param htu - HTTP target URI\n * @param accessToken - Optional access token for ath claim\n * @param nonce - Optional server-provided nonce\n * @returns Signed DPoP proof JWT or null if keyPair is null\n */\nexport async function createDPoPProof(\n keyPair: DPoPKeyPair | null,\n htm: string,\n htu: string,\n accessToken?: string | null,\n nonce?: string | null,\n): Promise<string | null> {\n if (!keyPair) return null;\n\n const header = { alg: 'ES256', typ: 'dpop+jwt', jwk: keyPair.publicJwk };\n const payload: Record<string, unknown> = {\n jti:\n typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : Date.now().toString(36) + Math.random().toString(36).substr(2),\n htm,\n htu,\n iat: Math.floor(Date.now() / 1000),\n };\n if (nonce) payload.nonce = nonce;\n\n if (accessToken) {\n const hash = await crypto.subtle.digest('SHA-256', strToUint8(accessToken) as unknown as ArrayBuffer);\n payload.ath = b64url(hash);\n }\n\n const headerB64 = b64url(strToUint8(JSON.stringify(header)));\n const payloadB64 = b64url(strToUint8(JSON.stringify(payload)));\n const signingInput = headerB64 + '.' + payloadB64;\n\n /* eslint-disable @typescript-eslint/no-unsafe-argument */\n const sigBuf = await crypto.subtle.sign(\n { name: 'ECDSA', hash: 'SHA-256' },\n keyPair.privateKey,\n strToUint8(signingInput) as unknown as ArrayBuffer,\n );\n /* eslint-enable @typescript-eslint/no-unsafe-argument */\n // WebCrypto ECDSA returns IEEE P1363 r||s format (64 bytes for P-256)\n return signingInput + '.' + b64url(new Uint8Array(sigBuf));\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nconst BATCH_SIZE = 1000;\nconst MAX_ITERATIONS = 1_000_000;\n\n/** Check whether the first `bits` bits of a hash are zero. */\nfunction checkZeros(hash: Uint8Array, bits: number): boolean {\n const fullBytes = Math.floor(bits / 8);\n const remainBits = bits % 8;\n for (let k = 0; k < fullBytes; k++) {\n if (hash[k] !== 0) return false;\n }\n if (remainBits > 0) {\n const mask = 0xff << (8 - remainBits);\n if ((hash[fullBytes] & mask) !== 0) return false;\n }\n return true;\n}\n\n/**\n * Solve a Proof of Work challenge asynchronously using Web Crypto.\n *\n * Hashes `challenge + nonce` (SHA-256) in batches and checks for\n * the required number of leading zero bits.\n *\n * @param challenge - The challenge string from the server\n * @param difficulty - Number of leading zero bits required\n * @returns The nonce that satisfies the difficulty\n */\nexport async function solvePoW(\n challenge: string,\n difficulty: number,\n): Promise<number> {\n if (!Number.isInteger(difficulty) || difficulty < 0 || difficulty > 256) {\n throw new Error('difficulty must be an integer between 0 and 256');\n }\n const encoder = new TextEncoder();\n let i = 0;\n\n async function tryBatch(): Promise<number> {\n const batchEnd = Math.min(i + BATCH_SIZE, MAX_ITERATIONS);\n const promises: Promise<{ idx: number; hash: Uint8Array }>[] = [];\n\n for (; i < batchEnd; i++) {\n const idx = i;\n promises.push(\n crypto.subtle\n .digest('SHA-256', encoder.encode(challenge + String(idx)))\n .then((buf) => ({ idx, hash: new Uint8Array(buf) })),\n );\n }\n\n const results = await Promise.all(promises);\n for (const result of results) {\n if (checkZeros(result.hash, difficulty)) {\n return result.idx;\n }\n }\n if (i >= MAX_ITERATIONS) throw new Error('PoW solution not found');\n return tryBatch();\n }\n\n return tryBatch();\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\n/** Default token TTL in seconds when expiresIn is not specified in setCredentials(). */\nexport const DEFAULT_TOKEN_TTL_SEC = 3_600;\n\n/** Token refresh leeway in ms \u2014 refresh 2 minutes before expiry. */\nexport const TOKEN_REFRESH_LEEWAY_MS = 120_000;\n\n/** Minimum wait time in ms before refreshing a token. */\nexport const TOKEN_REFRESH_MIN_MS = 10_000;\n\n/** Maximum WebSocket reconnection attempts. */\nexport const RECONNECT_MAX_ATTEMPTS = 10;\n\n/** Base delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_BASE_MS = 1_000;\n\n/** Maximum delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_MAX_DELAY_MS = 30_000;\n\n/** WebSocket sub-protocol name for browser authentication. */\nexport const SUB_PROTOCOL = 'access_token';\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport { createDPoPProof, dpopSupported, generateDPoPKeyPair } from './dpop';\nimport { solvePoW } from './pow';\nimport { DEFAULT_TOKEN_TTL_SEC } from './constants';\nimport type {\n CredentialsOptions,\n DPoPKeyPair,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n/** Internal authentication state for the GeonicDB SDK. */\nexport class AuthManager {\n private _baseUrl: string;\n private _apiKey: string;\n private _tenant: string;\n\n _token: string | null = null;\n _tokenExpiry = 0;\n _tokenType: 'Bearer' | 'DPoP' = 'Bearer';\n _refreshToken: string | null = null;\n _dpopKeyPair: DPoPKeyPair | null = null;\n _dpopReady: Promise<void> | null = null;\n _dpopNonce: string | null = null;\n private _tokenPromise: Promise<string> | null = null;\n\n /** Callback to emit tokenRefresh events. Set by GeonicDB class. */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(baseUrl: string, apiKey: string, tenant: string) {\n this._baseUrl = baseUrl;\n this._apiKey = apiKey;\n this._tenant = tenant;\n\n if (dpopSupported) {\n this._dpopReady = generateDPoPKeyPair()\n .then((kp) => {\n this._dpopKeyPair = kp;\n })\n .catch(() => {\n this._dpopKeyPair = null;\n });\n }\n }\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (this._tenant) headers['NGSILD-Tenant'] = this._tenant;\n\n const res = await fetch(this._baseUrl + '/auth/login', {\n method: 'POST',\n headers,\n body: JSON.stringify({ email, password }),\n });\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Login failed: ' + res.status,\n );\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n return data;\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' and refreshToken is provided, all subsequent\n * API calls and connect() bypass DPoP/PoW entirely.\n */\n setCredentials(opts: CredentialsOptions): void {\n if (!opts || !opts.token) throw new Error('token is required');\n this._token = opts.token;\n this._tokenType = opts.tokenType || 'Bearer';\n this._tokenExpiry = opts.expiresIn != null\n ? Date.now() + (opts.expiresIn - 60) * 1000\n : Date.now() + DEFAULT_TOKEN_TTL_SEC * 1000;\n this._refreshToken = opts.refreshToken || null;\n this._tokenPromise = null;\n }\n\n /** Clear all credentials. */\n logout(): void {\n this._token = null;\n this._tokenExpiry = 0;\n this._refreshToken = null;\n this._tokenPromise = null;\n }\n\n /** Ensure a valid token is available, refreshing or acquiring as needed. */\n async ensureToken(): Promise<string> {\n if (this._token && Date.now() < this._tokenExpiry) {\n return this._token;\n }\n\n // Deduplicate concurrent calls\n if (this._tokenPromise) {\n return this._tokenPromise;\n }\n\n // Bearer JWT refresh path \u2014 skip DPoP/PoW\n if (this._refreshToken) {\n this._tokenPromise = this._refreshBearerToken();\n return this._tokenPromise;\n }\n\n // API key + DPoP/PoW path\n this._tokenPromise = this._acquireTokenViaPow();\n return this._tokenPromise;\n }\n\n private async _refreshBearerToken(): Promise<string> {\n try {\n const res = await fetch(this._baseUrl + '/auth/refresh', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ refreshToken: this._refreshToken }),\n });\n if (!res.ok) {\n this._refreshToken = null;\n this._token = null;\n this._tokenPromise = null;\n throw new Error('Token refresh failed: ' + res.status);\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n this._tokenPromise = null;\n this.onTokenRefresh?.({\n token: this._token,\n tokenType: this._tokenType,\n expiresIn: data.expiresIn,\n refreshToken: this._refreshToken,\n });\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private async _acquireTokenViaPow(): Promise<string> {\n try {\n if (this._dpopReady) await this._dpopReady;\n\n // Step 1: Get nonce + PoW challenge\n const nonceRes = await fetch(this._baseUrl + '/auth/nonce', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ api_key: this._apiKey }),\n });\n if (!nonceRes.ok)\n throw new Error('Nonce request failed: ' + nonceRes.status);\n const nonceData = (await nonceRes.json()) as {\n nonce: string;\n challenge: string;\n difficulty: number;\n dpop_nonce?: string;\n };\n\n // RFC 9449 \u00A78: store pre-issued DPoP-Nonce\n if (nonceData.dpop_nonce) this._dpopNonce = nonceData.dpop_nonce;\n\n // Step 2: Solve PoW\n const proof = await solvePoW(nonceData.challenge, nonceData.difficulty);\n\n // Step 3: Exchange for token\n const tokenUrl = this._baseUrl + '/oauth/token';\n const tokenBody = JSON.stringify({\n grant_type: 'api_key',\n api_key: this._apiKey,\n nonce: nonceData.nonce,\n proof: String(proof),\n });\n\n const res = await this._doTokenExchange(tokenUrl, tokenBody, this._dpopNonce);\n\n if (!res.ok)\n throw new Error('Token request failed: ' + res.status);\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n const data = (await res.json()) as {\n access_token: string;\n expires_in: number;\n token_type?: string;\n };\n this._token = data.access_token;\n this._tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;\n this._tokenType = (data.token_type as 'Bearer' | 'DPoP') || 'Bearer';\n this._tokenPromise = null;\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private static readonly MAX_DPOP_RETRIES = 3;\n\n private async _doTokenExchange(\n tokenUrl: string,\n tokenBody: string,\n dpopNonce: string | null,\n retryCount = 0,\n ): Promise<Response> {\n const reqHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n const dpopProof = await createDPoPProof(\n this._dpopKeyPair,\n 'POST',\n tokenUrl,\n null,\n dpopNonce,\n );\n if (dpopProof) reqHeaders['DPoP'] = dpopProof;\n\n const res = await fetch(tokenUrl, {\n method: 'POST',\n headers: reqHeaders,\n body: tokenBody,\n });\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 400 && this._dpopKeyPair) {\n const errBody = await res.json().catch(() => ({})) as Record<string, string>;\n if (errBody.error === 'use_dpop_nonce') {\n const serverNonce = res.headers.get('DPoP-Nonce');\n if (serverNonce && serverNonce !== dpopNonce && retryCount < AuthManager.MAX_DPOP_RETRIES) {\n this._dpopNonce = serverNonce;\n return this._doTokenExchange(tokenUrl, tokenBody, serverNonce, retryCount + 1);\n }\n }\n throw new Error(\n 'Token request failed: ' +\n (errBody.error_description || errBody.error),\n );\n }\n\n return res;\n }\n\n /**\n * Make an authenticated HTTP request with automatic token refresh and DPoP.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const token = await this.ensureToken();\n return this._doAuthenticatedRequest(method, path, body, token);\n }\n\n private static readonly MAX_REQUEST_RETRIES = 3;\n\n private async _doAuthenticatedRequest(\n method: string,\n path: string,\n body: unknown,\n token: string,\n retryCount = 0,\n ): Promise<Response> {\n const url = this._baseUrl + path;\n const isDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const bodyStr = body !== undefined ? JSON.stringify(body) : undefined;\n\n const doRequest = async (\n reqToken: string,\n dpopNonce: string | null,\n ): Promise<Response> => {\n const reqIsDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const dpopProof = reqIsDPoP\n ? await createDPoPProof(\n this._dpopKeyPair,\n method,\n url,\n reqToken,\n dpopNonce,\n )\n : null;\n\n const headers: Record<string, string> = {\n Authorization: (reqIsDPoP ? 'DPoP ' : 'Bearer ') + reqToken,\n 'Content-Type': 'application/ld+json',\n Accept: 'application/ld+json',\n };\n if (dpopProof) headers['DPoP'] = dpopProof;\n if (this._tenant) headers['Fiware-Service'] = this._tenant;\n\n return fetch(url, { method, headers, body: bodyStr });\n };\n\n let currentToken = token;\n let res = await doRequest(currentToken, this._dpopNonce);\n const previousNonce = this._dpopNonce;\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 401 && isDPoP && newNonce && newNonce !== previousNonce) {\n res = await doRequest(currentToken, newNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const fn = res.headers.get('DPoP-Nonce');\n if (fn) this._dpopNonce = fn;\n }\n } else if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n }\n\n if (res.status === 429 && retryCount < AuthManager.MAX_REQUEST_RETRIES) {\n const retryNonce = res.headers.get('DPoP-Nonce');\n if (retryNonce) this._dpopNonce = retryNonce;\n const delay =\n parseInt(res.headers.get('Retry-After') || '1', 10) * 1000;\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\n return this._doAuthenticatedRequest(method, path, body, currentToken, retryCount + 1);\n }\n\n return res;\n }\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport { createDPoPProof } from './dpop';\nimport type { AuthManager } from './auth';\nimport {\n TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n RECONNECT_MAX_ATTEMPTS,\n RECONNECT_BASE_MS,\n RECONNECT_MAX_DELAY_MS,\n SUB_PROTOCOL,\n} from './constants';\nimport type { SubscriptionMessage } from './types';\n\ntype EmitFn = (event: string, data?: unknown) => void;\n\n/**\n * WebSocket connection manager for the GeonicDB SDK.\n *\n * Handles connection lifecycle, DPoP binding, token refresh,\n * automatic reconnection with exponential backoff, and subscriptions.\n */\nexport class WebSocketManager {\n private _auth: AuthManager;\n private _tenant: string;\n private _wsEndpointOverride: string | null;\n private _baseUrl: string;\n private _emit: EmitFn;\n\n private _ws: WebSocket | null = null;\n private _wsEndpoint: string | null = null;\n private _wsIntentionalClose = false;\n private _reconnectAttempts = 0;\n private _tokenRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private _subscription: SubscriptionMessage | null = null;\n private _pendingSubscription = false;\n\n constructor(\n auth: AuthManager,\n baseUrl: string,\n tenant: string,\n emit: EmitFn,\n wsEndpointOverride?: string,\n ) {\n this._auth = auth;\n this._baseUrl = baseUrl;\n this._tenant = tenant;\n this._emit = emit;\n this._wsEndpointOverride = wsEndpointOverride || null;\n }\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n this._wsIntentionalClose = false;\n this._reconnectAttempts = 0;\n\n try {\n const token = await this._auth.ensureToken();\n await this._openWebSocket(token);\n } catch (err) {\n this._emit('error', err);\n }\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n this._wsIntentionalClose = true;\n this._clearTimers();\n if (this._ws) {\n this._ws.close(1000, 'Client reconnect');\n this._ws = null;\n }\n return this.connect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._wsIntentionalClose = true;\n this._clearTimers();\n this._subscription = null;\n this._pendingSubscription = false;\n if (this._ws) {\n this._ws.close(1000, 'Client disconnect');\n this._ws = null;\n }\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return !!(this._ws && this._ws.readyState === WebSocket.OPEN);\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: { entityTypes?: string[]; idPattern?: string }): void {\n const msg: SubscriptionMessage = { action: 'subscribe' };\n if (options) {\n if (options.entityTypes) msg.entityTypes = options.entityTypes;\n if (options.idPattern) msg.idPattern = options.idPattern;\n }\n this._subscription = msg;\n // If DPoP pending verification, store subscription but don't send yet\n if (this._pendingSubscription) return;\n if (this._ws && this._ws.readyState === WebSocket.OPEN) {\n this._ws.send(JSON.stringify(msg));\n }\n }\n\n private async _discoverWsEndpoint(): Promise<string> {\n if (this._wsEndpointOverride) return this._wsEndpointOverride;\n if (this._wsEndpoint) return this._wsEndpoint;\n\n // Fetch endpoint from server discovery API\n try {\n const res = await fetch(this._baseUrl + '/sdk/v1/streaming');\n if (res.ok) {\n const info = (await res.json()) as {\n enabled: boolean;\n endpoint: string | null;\n };\n if (info.enabled && info.endpoint) {\n this._wsEndpoint = info.endpoint;\n return this._wsEndpoint;\n }\n }\n } catch {\n // Discovery failed \u2014 fall back to URL scheme conversion\n }\n\n // Fallback: convert http(s) baseUrl to ws(s)\n this._wsEndpoint = this._baseUrl.replace(/^http/, 'ws');\n return this._wsEndpoint;\n }\n\n private async _openWebSocket(token: string): Promise<void> {\n const endpoint = await this._discoverWsEndpoint();\n return new Promise<void>((resolve, reject) => {\n const wsUrl =\n endpoint +\n (endpoint.indexOf('?') === -1 ? '?' : '&') +\n 'tenant=' +\n encodeURIComponent(this._tenant);\n\n const ws = new WebSocket(wsUrl, [SUB_PROTOCOL, token]);\n this._ws = ws;\n\n ws.onopen = (): void => {\n if (this._ws !== ws) return;\n this._reconnectAttempts = 0;\n\n const isDPoP =\n this._auth._tokenType === 'DPoP' && !!this._auth._dpopKeyPair;\n\n const bindPromise = isDPoP\n ? createDPoPProof(this._auth._dpopKeyPair, 'GET', wsUrl, null).then(\n (proof) => {\n if (proof && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ action: 'dpop_bind', proof }));\n }\n },\n )\n : Promise.resolve();\n\n bindPromise\n .then(() => {\n this._scheduleTokenRefresh();\n\n if (isDPoP) {\n this._pendingSubscription = true;\n } else if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n\n this._emit('open');\n this._emit('connected');\n resolve();\n })\n .catch((err) => {\n this._emit('error', err);\n resolve();\n });\n };\n\n ws.onmessage = (event: MessageEvent): void => {\n if (this._ws !== ws) return;\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(event.data as string) as Record<string, unknown>;\n } catch {\n return;\n }\n\n if (msg.type === 'pong') return;\n\n if (msg.type === 'dpop_verified') {\n this._pendingSubscription = false;\n if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n return;\n }\n\n if (msg.type === 'error') {\n this._emit('error', new Error(msg.message as string));\n return;\n }\n\n this._emit(msg.type as string, msg);\n this._emit('message', msg);\n };\n\n ws.onclose = (event: CloseEvent): void => {\n if (this._ws !== ws) return;\n this._clearTimers();\n\n if (this._wsIntentionalClose) {\n this._emit('close', event);\n return;\n }\n\n this._emit('close', event);\n this._emit('disconnected');\n this._autoReconnect();\n };\n\n ws.onerror = (err: Event): void => {\n if (this._ws !== ws) return;\n this._emit('error', err);\n if (ws.readyState !== WebSocket.OPEN) {\n reject(new Error('WebSocket connection failed'));\n }\n };\n });\n }\n\n private _scheduleTokenRefresh(): void {\n if (this._tokenRefreshTimer) clearTimeout(this._tokenRefreshTimer);\n\n const remaining = this._auth._tokenExpiry - Date.now();\n const refreshIn = Math.max(\n remaining - TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n );\n\n this._tokenRefreshTimer = setTimeout(() => {\n const oldWs = this._ws;\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((newToken) => {\n if (!oldWs || oldWs.readyState !== WebSocket.OPEN) return;\n\n this._wsIntentionalClose = true;\n oldWs.close(1000, 'Token refresh');\n\n this._wsIntentionalClose = false;\n return this._openWebSocket(newToken);\n })\n .catch((err) => {\n this._emit('error', err);\n this._autoReconnect();\n });\n }, refreshIn);\n }\n\n private _autoReconnect(): void {\n if (this._wsIntentionalClose) return;\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n\n if (this._reconnectAttempts >= RECONNECT_MAX_ATTEMPTS) {\n this._emit('error', new Error('Max reconnection attempts reached'));\n return;\n }\n\n const delay = Math.min(\n RECONNECT_BASE_MS * Math.pow(2, this._reconnectAttempts),\n RECONNECT_MAX_DELAY_MS,\n );\n this._reconnectAttempts++;\n this._emit('reconnecting', {\n attempt: this._reconnectAttempts,\n delay,\n });\n\n this._reconnectTimer = setTimeout(() => {\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((token) => this._openWebSocket(token))\n .catch(() => this._autoReconnect());\n }, delay);\n }\n\n private _clearTimers(): void {\n if (this._tokenRefreshTimer) {\n clearTimeout(this._tokenRefreshTimer);\n this._tokenRefreshTimer = null;\n }\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/geonicdb.mjs.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/sdk/events.ts", "../../src/sdk/dpop.ts", "../../src/sdk/pow.ts", "../../src/sdk/constants.ts", "../../src/sdk/auth.ts", "../../src/sdk/websocket.ts", "../../src/sdk/index.ts"],
4
- "sourcesContent": ["/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport type { GeonicDBEventMap } from './types';\n\ntype Listener<T> = (data: T) => void;\n\n/**\n * Minimal typed event emitter for GeonicDB SDK.\n */\nexport class EventEmitter {\n private _listeners: Record<string, Listener<unknown>[]> =\n Object.create(null) as Record<string, Listener<unknown>[]>;\n\n on<K extends keyof GeonicDBEventMap>(\n event: K,\n callback: Listener<GeonicDBEventMap[K]>,\n ): this;\n on(event: string, callback: Listener<unknown>): this;\n on(event: string, callback: Listener<unknown>): this {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n this._listeners[event].push(callback);\n return this;\n }\n\n off<K extends keyof GeonicDBEventMap>(\n event: K,\n callback?: Listener<GeonicDBEventMap[K]>,\n ): this;\n off(event: string, callback?: Listener<unknown>): this;\n off(event: string, callback?: Listener<unknown>): this {\n if (!this._listeners[event]) return this;\n if (!callback) {\n delete this._listeners[event];\n } else {\n this._listeners[event] = this._listeners[event].filter(\n (cb) => cb !== callback,\n );\n }\n return this;\n }\n\n protected emit<K extends keyof GeonicDBEventMap>(\n event: K,\n data?: GeonicDBEventMap[K],\n ): void;\n protected emit(event: string, data?: unknown): void;\n protected emit(event: string, data?: unknown): void {\n const cbs = this._listeners[event];\n if (!cbs) return;\n const snapshot = cbs.slice();\n for (const cb of snapshot) {\n try {\n cb(data);\n } catch {\n // listener error \u2014 swallow silently\n }\n }\n }\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport type { DPoPKeyPair } from './types';\n\n/** Whether the Web Crypto DPoP API is available in the current environment. */\nexport const dpopSupported =\n typeof crypto !== 'undefined' &&\n !!crypto.subtle &&\n !!crypto.subtle.generateKey;\n\n/** Base64url-encode an ArrayBuffer or Uint8Array. */\nfunction b64url(buf: ArrayBuffer | Uint8Array): string {\n const arr = buf instanceof ArrayBuffer ? new Uint8Array(buf) : buf;\n let str = '';\n for (let i = 0; i < arr.length; i++) {\n str += String.fromCharCode(arr[i]);\n }\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** Encode a string to Uint8Array. */\nfunction strToUint8(s: string): Uint8Array {\n return new TextEncoder().encode(s);\n}\n\n/** Generate an ECDSA P-256 key pair for DPoP proof creation. */\nexport async function generateDPoPKeyPair(): Promise<DPoPKeyPair | null> {\n if (!dpopSupported) return null;\n const kp = await crypto.subtle.generateKey(\n { name: 'ECDSA', namedCurve: 'P-256' },\n false,\n ['sign'],\n );\n const pubJwk = await crypto.subtle.exportKey(\n 'jwk',\n kp.publicKey,\n );\n return {\n privateKey: kp.privateKey,\n publicJwk: {\n kty: pubJwk.kty!,\n crv: pubJwk.crv!,\n x: pubJwk.x!,\n y: pubJwk.y!,\n },\n };\n}\n\n/**\n * Create a DPoP proof JWT (RFC 9449).\n *\n * @param keyPair - The DPoP key pair\n * @param htm - HTTP method\n * @param htu - HTTP target URI\n * @param accessToken - Optional access token for ath claim\n * @param nonce - Optional server-provided nonce\n * @returns Signed DPoP proof JWT or null if keyPair is null\n */\nexport async function createDPoPProof(\n keyPair: DPoPKeyPair | null,\n htm: string,\n htu: string,\n accessToken?: string | null,\n nonce?: string | null,\n): Promise<string | null> {\n if (!keyPair) return null;\n\n const header = { alg: 'ES256', typ: 'dpop+jwt', jwk: keyPair.publicJwk };\n const payload: Record<string, unknown> = {\n jti:\n typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : Date.now().toString(36) + Math.random().toString(36).substr(2),\n htm,\n htu,\n iat: Math.floor(Date.now() / 1000),\n };\n if (nonce) payload.nonce = nonce;\n\n if (accessToken) {\n const hash = await crypto.subtle.digest('SHA-256', strToUint8(accessToken) as unknown as ArrayBuffer);\n payload.ath = b64url(hash);\n }\n\n const headerB64 = b64url(strToUint8(JSON.stringify(header)));\n const payloadB64 = b64url(strToUint8(JSON.stringify(payload)));\n const signingInput = headerB64 + '.' + payloadB64;\n\n /* eslint-disable @typescript-eslint/no-unsafe-argument */\n const sigBuf = await crypto.subtle.sign(\n { name: 'ECDSA', hash: 'SHA-256' },\n keyPair.privateKey,\n strToUint8(signingInput) as unknown as ArrayBuffer,\n );\n /* eslint-enable @typescript-eslint/no-unsafe-argument */\n // WebCrypto ECDSA returns IEEE P1363 r||s format (64 bytes for P-256)\n return signingInput + '.' + b64url(new Uint8Array(sigBuf));\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nconst BATCH_SIZE = 1000;\nconst MAX_ITERATIONS = 1_000_000;\n\n/** Check whether the first `bits` bits of a hash are zero. */\nfunction checkZeros(hash: Uint8Array, bits: number): boolean {\n const fullBytes = Math.floor(bits / 8);\n const remainBits = bits % 8;\n for (let k = 0; k < fullBytes; k++) {\n if (hash[k] !== 0) return false;\n }\n if (remainBits > 0) {\n const mask = 0xff << (8 - remainBits);\n if ((hash[fullBytes] & mask) !== 0) return false;\n }\n return true;\n}\n\n/**\n * Solve a Proof of Work challenge asynchronously using Web Crypto.\n *\n * Hashes `challenge + nonce` (SHA-256) in batches and checks for\n * the required number of leading zero bits.\n *\n * @param challenge - The challenge string from the server\n * @param difficulty - Number of leading zero bits required\n * @returns The nonce that satisfies the difficulty\n */\nexport async function solvePoW(\n challenge: string,\n difficulty: number,\n): Promise<number> {\n if (!Number.isInteger(difficulty) || difficulty < 0 || difficulty > 256) {\n throw new Error('difficulty must be an integer between 0 and 256');\n }\n const encoder = new TextEncoder();\n let i = 0;\n\n async function tryBatch(): Promise<number> {\n const batchEnd = Math.min(i + BATCH_SIZE, MAX_ITERATIONS);\n const promises: Promise<{ idx: number; hash: Uint8Array }>[] = [];\n\n for (; i < batchEnd; i++) {\n const idx = i;\n promises.push(\n crypto.subtle\n .digest('SHA-256', encoder.encode(challenge + String(idx)))\n .then((buf) => ({ idx, hash: new Uint8Array(buf) })),\n );\n }\n\n const results = await Promise.all(promises);\n for (const result of results) {\n if (checkZeros(result.hash, difficulty)) {\n return result.idx;\n }\n }\n if (i >= MAX_ITERATIONS) throw new Error('PoW solution not found');\n return tryBatch();\n }\n\n return tryBatch();\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\n/** Default token TTL in seconds when expiresIn is not specified in setCredentials(). */\nexport const DEFAULT_TOKEN_TTL_SEC = 3_600;\n\n/** Token refresh leeway in ms \u2014 refresh 2 minutes before expiry. */\nexport const TOKEN_REFRESH_LEEWAY_MS = 120_000;\n\n/** Minimum wait time in ms before refreshing a token. */\nexport const TOKEN_REFRESH_MIN_MS = 10_000;\n\n/** Maximum WebSocket reconnection attempts. */\nexport const RECONNECT_MAX_ATTEMPTS = 10;\n\n/** Base delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_BASE_MS = 1_000;\n\n/** Maximum delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_MAX_DELAY_MS = 30_000;\n\n/** WebSocket sub-protocol name for browser authentication. */\nexport const SUB_PROTOCOL = 'access_token';\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport { createDPoPProof, dpopSupported, generateDPoPKeyPair } from './dpop';\nimport { solvePoW } from './pow';\nimport { DEFAULT_TOKEN_TTL_SEC } from './constants';\nimport type {\n CredentialsOptions,\n DPoPKeyPair,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n/** Internal authentication state for the GeonicDB SDK. */\nexport class AuthManager {\n private _baseUrl: string;\n private _apiKey: string;\n private _tenant: string;\n\n _token: string | null = null;\n _tokenExpiry = 0;\n _tokenType: 'Bearer' | 'DPoP' = 'Bearer';\n _refreshToken: string | null = null;\n _dpopKeyPair: DPoPKeyPair | null = null;\n _dpopReady: Promise<void> | null = null;\n _dpopNonce: string | null = null;\n private _tokenPromise: Promise<string> | null = null;\n\n /** Callback to emit tokenRefresh events. Set by GeonicDB class. */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(baseUrl: string, apiKey: string, tenant: string) {\n this._baseUrl = baseUrl;\n this._apiKey = apiKey;\n this._tenant = tenant;\n\n if (dpopSupported) {\n this._dpopReady = generateDPoPKeyPair()\n .then((kp) => {\n this._dpopKeyPair = kp;\n })\n .catch(() => {\n this._dpopKeyPair = null;\n });\n }\n }\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (this._tenant) headers['NGSILD-Tenant'] = this._tenant;\n\n const res = await fetch(this._baseUrl + '/auth/login', {\n method: 'POST',\n headers,\n body: JSON.stringify({ email, password }),\n });\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Login failed: ' + res.status,\n );\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n return data;\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' and refreshToken is provided, all subsequent\n * API calls and connect() bypass DPoP/PoW entirely.\n */\n setCredentials(opts: CredentialsOptions): void {\n if (!opts || !opts.token) throw new Error('token is required');\n this._token = opts.token;\n this._tokenType = opts.tokenType || 'Bearer';\n this._tokenExpiry = opts.expiresIn != null\n ? Date.now() + (opts.expiresIn - 60) * 1000\n : Date.now() + DEFAULT_TOKEN_TTL_SEC * 1000;\n this._refreshToken = opts.refreshToken || null;\n this._tokenPromise = null;\n }\n\n /** Clear all credentials. */\n logout(): void {\n this._token = null;\n this._tokenExpiry = 0;\n this._refreshToken = null;\n this._tokenPromise = null;\n }\n\n /** Ensure a valid token is available, refreshing or acquiring as needed. */\n async ensureToken(): Promise<string> {\n if (this._token && Date.now() < this._tokenExpiry) {\n return this._token;\n }\n\n // Deduplicate concurrent calls\n if (this._tokenPromise) {\n return this._tokenPromise;\n }\n\n // Bearer JWT refresh path \u2014 skip DPoP/PoW\n if (this._refreshToken) {\n this._tokenPromise = this._refreshBearerToken();\n return this._tokenPromise;\n }\n\n // API key + DPoP/PoW path\n this._tokenPromise = this._acquireTokenViaPow();\n return this._tokenPromise;\n }\n\n private async _refreshBearerToken(): Promise<string> {\n try {\n const res = await fetch(this._baseUrl + '/auth/refresh', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ refreshToken: this._refreshToken }),\n });\n if (!res.ok) {\n this._refreshToken = null;\n this._token = null;\n this._tokenPromise = null;\n throw new Error('Token refresh failed: ' + res.status);\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n this._tokenPromise = null;\n this.onTokenRefresh?.({\n token: this._token,\n tokenType: this._tokenType,\n expiresIn: data.expiresIn,\n refreshToken: this._refreshToken,\n });\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private async _acquireTokenViaPow(): Promise<string> {\n try {\n if (this._dpopReady) await this._dpopReady;\n\n // Step 1: Get nonce + PoW challenge\n const nonceRes = await fetch(this._baseUrl + '/auth/nonce', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ api_key: this._apiKey }),\n });\n if (!nonceRes.ok)\n throw new Error('Nonce request failed: ' + nonceRes.status);\n const nonceData = (await nonceRes.json()) as {\n nonce: string;\n challenge: string;\n difficulty: number;\n dpop_nonce?: string;\n };\n\n // RFC 9449 \u00A78: store pre-issued DPoP-Nonce\n if (nonceData.dpop_nonce) this._dpopNonce = nonceData.dpop_nonce;\n\n // Step 2: Solve PoW\n const proof = await solvePoW(nonceData.challenge, nonceData.difficulty);\n\n // Step 3: Exchange for token\n const tokenUrl = this._baseUrl + '/oauth/token';\n const tokenBody = JSON.stringify({\n grant_type: 'api_key',\n api_key: this._apiKey,\n nonce: nonceData.nonce,\n proof: String(proof),\n });\n\n const res = await this._doTokenExchange(tokenUrl, tokenBody, this._dpopNonce);\n\n if (!res.ok)\n throw new Error('Token request failed: ' + res.status);\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n const data = (await res.json()) as {\n access_token: string;\n expires_in: number;\n token_type?: string;\n };\n this._token = data.access_token;\n this._tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;\n this._tokenType = (data.token_type as 'Bearer' | 'DPoP') || 'Bearer';\n this._tokenPromise = null;\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private static readonly MAX_DPOP_RETRIES = 3;\n\n private async _doTokenExchange(\n tokenUrl: string,\n tokenBody: string,\n dpopNonce: string | null,\n retryCount = 0,\n ): Promise<Response> {\n const reqHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n const dpopProof = await createDPoPProof(\n this._dpopKeyPair,\n 'POST',\n tokenUrl,\n null,\n dpopNonce,\n );\n if (dpopProof) reqHeaders['DPoP'] = dpopProof;\n\n const res = await fetch(tokenUrl, {\n method: 'POST',\n headers: reqHeaders,\n body: tokenBody,\n });\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 400 && this._dpopKeyPair) {\n const errBody = await res.json().catch(() => ({})) as Record<string, string>;\n if (errBody.error === 'use_dpop_nonce') {\n const serverNonce = res.headers.get('DPoP-Nonce');\n if (serverNonce && serverNonce !== dpopNonce && retryCount < AuthManager.MAX_DPOP_RETRIES) {\n this._dpopNonce = serverNonce;\n return this._doTokenExchange(tokenUrl, tokenBody, serverNonce, retryCount + 1);\n }\n }\n throw new Error(\n 'Token request failed: ' +\n (errBody.error_description || errBody.error),\n );\n }\n\n return res;\n }\n\n /**\n * Make an authenticated HTTP request with automatic token refresh and DPoP.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const token = await this.ensureToken();\n return this._doAuthenticatedRequest(method, path, body, token);\n }\n\n private static readonly MAX_REQUEST_RETRIES = 3;\n\n private async _doAuthenticatedRequest(\n method: string,\n path: string,\n body: unknown,\n token: string,\n retryCount = 0,\n ): Promise<Response> {\n const url = this._baseUrl + path;\n const isDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const bodyStr = body !== undefined ? JSON.stringify(body) : undefined;\n\n const doRequest = async (\n reqToken: string,\n dpopNonce: string | null,\n ): Promise<Response> => {\n const reqIsDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const dpopProof = reqIsDPoP\n ? await createDPoPProof(\n this._dpopKeyPair,\n method,\n url,\n reqToken,\n dpopNonce,\n )\n : null;\n\n const headers: Record<string, string> = {\n Authorization: (reqIsDPoP ? 'DPoP ' : 'Bearer ') + reqToken,\n 'Content-Type': 'application/ld+json',\n Accept: 'application/ld+json',\n };\n if (dpopProof) headers['DPoP'] = dpopProof;\n if (this._tenant) headers['Fiware-Service'] = this._tenant;\n\n return fetch(url, { method, headers, body: bodyStr });\n };\n\n let currentToken = token;\n let res = await doRequest(currentToken, this._dpopNonce);\n const previousNonce = this._dpopNonce;\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 401 && isDPoP && newNonce && newNonce !== previousNonce) {\n res = await doRequest(currentToken, newNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const fn = res.headers.get('DPoP-Nonce');\n if (fn) this._dpopNonce = fn;\n }\n } else if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n }\n\n if (res.status === 429 && retryCount < AuthManager.MAX_REQUEST_RETRIES) {\n const retryNonce = res.headers.get('DPoP-Nonce');\n if (retryNonce) this._dpopNonce = retryNonce;\n const delay =\n parseInt(res.headers.get('Retry-After') || '1', 10) * 1000;\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\n return this._doAuthenticatedRequest(method, path, body, currentToken, retryCount + 1);\n }\n\n return res;\n }\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport { createDPoPProof } from './dpop';\nimport type { AuthManager } from './auth';\nimport {\n TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n RECONNECT_MAX_ATTEMPTS,\n RECONNECT_BASE_MS,\n RECONNECT_MAX_DELAY_MS,\n SUB_PROTOCOL,\n} from './constants';\nimport type { SubscriptionMessage } from './types';\n\ntype EmitFn = (event: string, data?: unknown) => void;\n\n/**\n * WebSocket connection manager for the GeonicDB SDK.\n *\n * Handles connection lifecycle, DPoP binding, token refresh,\n * automatic reconnection with exponential backoff, and subscriptions.\n */\nexport class WebSocketManager {\n private _auth: AuthManager;\n private _tenant: string;\n private _wsEndpointOverride: string | null;\n private _baseUrl: string;\n private _emit: EmitFn;\n\n private _ws: WebSocket | null = null;\n private _wsEndpoint: string | null = null;\n private _wsIntentionalClose = false;\n private _reconnectAttempts = 0;\n private _tokenRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private _subscription: SubscriptionMessage | null = null;\n private _pendingSubscription = false;\n\n constructor(\n auth: AuthManager,\n baseUrl: string,\n tenant: string,\n emit: EmitFn,\n wsEndpointOverride?: string,\n ) {\n this._auth = auth;\n this._baseUrl = baseUrl;\n this._tenant = tenant;\n this._emit = emit;\n this._wsEndpointOverride = wsEndpointOverride || null;\n }\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n this._wsIntentionalClose = false;\n this._reconnectAttempts = 0;\n\n try {\n const token = await this._auth.ensureToken();\n await this._openWebSocket(token);\n } catch (err) {\n this._emit('error', err);\n }\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n this._wsIntentionalClose = true;\n this._clearTimers();\n if (this._ws) {\n this._ws.close(1000, 'Client reconnect');\n this._ws = null;\n }\n return this.connect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._wsIntentionalClose = true;\n this._clearTimers();\n this._subscription = null;\n this._pendingSubscription = false;\n if (this._ws) {\n this._ws.close(1000, 'Client disconnect');\n this._ws = null;\n }\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return !!(this._ws && this._ws.readyState === WebSocket.OPEN);\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: { entityTypes?: string[]; idPattern?: string }): void {\n const msg: SubscriptionMessage = { action: 'subscribe' };\n if (options) {\n if (options.entityTypes) msg.entityTypes = options.entityTypes;\n if (options.idPattern) msg.idPattern = options.idPattern;\n }\n this._subscription = msg;\n // If DPoP pending verification, store subscription but don't send yet\n if (this._pendingSubscription) return;\n if (this._ws && this._ws.readyState === WebSocket.OPEN) {\n this._ws.send(JSON.stringify(msg));\n }\n }\n\n private async _discoverWsEndpoint(): Promise<string> {\n if (this._wsEndpointOverride) return this._wsEndpointOverride;\n if (this._wsEndpoint) return this._wsEndpoint;\n\n // Fetch endpoint from server discovery API\n try {\n const res = await fetch(this._baseUrl + '/sdk/v1/streaming');\n if (res.ok) {\n const info = (await res.json()) as {\n enabled: boolean;\n endpoint: string | null;\n };\n if (info.enabled && info.endpoint) {\n this._wsEndpoint = info.endpoint;\n return this._wsEndpoint;\n }\n }\n } catch {\n // Discovery failed \u2014 fall back to URL scheme conversion\n }\n\n // Fallback: convert http(s) baseUrl to ws(s)\n this._wsEndpoint = this._baseUrl.replace(/^http/, 'ws');\n return this._wsEndpoint;\n }\n\n private async _openWebSocket(token: string): Promise<void> {\n const endpoint = await this._discoverWsEndpoint();\n return new Promise<void>((resolve, reject) => {\n const wsUrl =\n endpoint +\n (endpoint.indexOf('?') === -1 ? '?' : '&') +\n 'tenant=' +\n encodeURIComponent(this._tenant);\n\n const ws = new WebSocket(wsUrl, [SUB_PROTOCOL, token]);\n this._ws = ws;\n\n ws.onopen = (): void => {\n if (this._ws !== ws) return;\n this._reconnectAttempts = 0;\n\n const isDPoP =\n this._auth._tokenType === 'DPoP' && !!this._auth._dpopKeyPair;\n\n const bindPromise = isDPoP\n ? createDPoPProof(this._auth._dpopKeyPair, 'GET', wsUrl, null).then(\n (proof) => {\n if (proof && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ action: 'dpop_bind', proof }));\n }\n },\n )\n : Promise.resolve();\n\n bindPromise\n .then(() => {\n this._scheduleTokenRefresh();\n\n if (isDPoP) {\n this._pendingSubscription = true;\n } else if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n\n this._emit('open');\n this._emit('connected');\n resolve();\n })\n .catch((err) => {\n this._emit('error', err);\n resolve();\n });\n };\n\n ws.onmessage = (event: MessageEvent): void => {\n if (this._ws !== ws) return;\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(event.data as string) as Record<string, unknown>;\n } catch {\n return;\n }\n\n if (msg.type === 'pong') return;\n\n if (msg.type === 'dpop_verified') {\n this._pendingSubscription = false;\n if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n return;\n }\n\n if (msg.type === 'error') {\n this._emit('error', new Error(msg.message as string));\n return;\n }\n\n this._emit(msg.type as string, msg);\n this._emit('message', msg);\n };\n\n ws.onclose = (event: CloseEvent): void => {\n if (this._ws !== ws) return;\n this._clearTimers();\n\n if (this._wsIntentionalClose) {\n this._emit('close', event);\n return;\n }\n\n this._emit('close', event);\n this._emit('disconnected');\n this._autoReconnect();\n };\n\n ws.onerror = (err: Event): void => {\n if (this._ws !== ws) return;\n this._emit('error', err);\n if (ws.readyState !== WebSocket.OPEN) {\n reject(new Error('WebSocket connection failed'));\n }\n };\n });\n }\n\n private _scheduleTokenRefresh(): void {\n if (this._tokenRefreshTimer) clearTimeout(this._tokenRefreshTimer);\n\n const remaining = this._auth._tokenExpiry - Date.now();\n const refreshIn = Math.max(\n remaining - TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n );\n\n this._tokenRefreshTimer = setTimeout(() => {\n const oldWs = this._ws;\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((newToken) => {\n if (!oldWs || oldWs.readyState !== WebSocket.OPEN) return;\n\n this._wsIntentionalClose = true;\n oldWs.close(1000, 'Token refresh');\n\n this._wsIntentionalClose = false;\n return this._openWebSocket(newToken);\n })\n .catch((err) => {\n this._emit('error', err);\n this._autoReconnect();\n });\n }, refreshIn);\n }\n\n private _autoReconnect(): void {\n if (this._wsIntentionalClose) return;\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n\n if (this._reconnectAttempts >= RECONNECT_MAX_ATTEMPTS) {\n this._emit('error', new Error('Max reconnection attempts reached'));\n return;\n }\n\n const delay = Math.min(\n RECONNECT_BASE_MS * Math.pow(2, this._reconnectAttempts),\n RECONNECT_MAX_DELAY_MS,\n );\n this._reconnectAttempts++;\n this._emit('reconnecting', {\n attempt: this._reconnectAttempts,\n delay,\n });\n\n this._reconnectTimer = setTimeout(() => {\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((token) => this._openWebSocket(token))\n .catch(() => this._autoReconnect());\n }, delay);\n }\n\n private _clearTimers(): void {\n if (this._tokenRefreshTimer) {\n clearTimeout(this._tokenRefreshTimer);\n this._tokenRefreshTimer = null;\n }\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n }\n}\n", "/**\n * Copyright (C) 2026 Geolonia Inc.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\n/**\n * GeonicDB JavaScript SDK\n *\n * NGSI-LD Context Broker client for browser and Node.js.\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ndeclare const document: any;\ndeclare const window: any;\n\nimport { EventEmitter } from './events';\nimport { AuthManager } from './auth';\nimport { WebSocketManager } from './websocket';\nimport type {\n GeonicDBOptions,\n CredentialsOptions,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n// Re-export types for consumers\nexport type {\n GeonicDBOptions,\n CredentialsOptions,\n RefreshedCredentials,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n EntityEvent,\n ReconnectingEvent,\n LoginResponse,\n GeonicDBEventMap,\n} from './types';\n\n/**\n * GeonicDB SDK client.\n *\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n *\n * @example\n * ```typescript\n * import GeonicDB from '@geolonia/geonicdb-sdk';\n *\n * const db = new GeonicDB({\n * apiKey: 'your-api-key',\n * tenant: 'your-tenant',\n * baseUrl: 'https://your-geonicdb.example.com',\n * });\n *\n * const entities = await db.getEntities({ type: 'Room' });\n * ```\n */\nexport class GeonicDB extends EventEmitter {\n private _auth: AuthManager;\n private _ws: WebSocketManager;\n\n /**\n * Legacy callback for token refresh events.\n * Prefer `db.on('tokenRefresh', callback)` for new code.\n * @deprecated Use `db.on('tokenRefresh', callback)` instead.\n */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(options?: GeonicDBOptions) {\n super();\n const opts = options || {};\n\n // Auto-detect from script tag in browser\n let apiKey = opts.apiKey || '';\n let tenant = opts.tenant || '';\n let baseUrl = opts.baseUrl || '';\n\n /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n if (typeof document !== 'undefined' && document.currentScript) {\n const script = document.currentScript;\n if (!apiKey) apiKey = script?.getAttribute?.('data-api-key') || '';\n if (!tenant) tenant = script?.getAttribute?.('data-tenant') || '';\n if (!baseUrl) baseUrl = script?.getAttribute?.('data-base-url') || '';\n }\n /* eslint-enable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n\n this._auth = new AuthManager(baseUrl, apiKey, tenant);\n this._auth.onTokenRefresh = (creds): void => {\n this.onTokenRefresh?.(creds);\n this.emit('tokenRefresh', creds);\n };\n this._ws = new WebSocketManager(\n this._auth,\n baseUrl,\n tenant,\n (event, data) => this.emit(event, data),\n opts.wsEndpoint,\n );\n }\n\n // --- Authentication ---\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n return this._auth.login(email, password);\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' with a refreshToken, DPoP/PoW is bypassed entirely.\n */\n setCredentials(opts: CredentialsOptions): this {\n this._auth.setCredentials(opts);\n return this;\n }\n\n /** Clear all credentials and disconnect. */\n logout(): void {\n this._ws.disconnect();\n this._auth.logout();\n }\n\n // --- Entity CRUD (NGSI-LD) ---\n\n /** Create a new entity. */\n async createEntity(\n entity: Record<string, unknown>,\n ): Promise<{ created: true }> {\n const res = await this._auth.request('POST', '/ngsi-ld/v1/entities', entity);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Create failed',\n );\n }\n return { created: true };\n }\n\n /** Get a single entity by ID. */\n async getEntity(entityId: string): Promise<Record<string, unknown>> {\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Not found',\n );\n }\n return (await res.json()) as Record<string, unknown>;\n }\n\n /** Query entities with optional filters. */\n async getEntities(\n params?: GetEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (parts.length) qs = '?' + parts.join('&');\n }\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Query failed',\n );\n }\n return (await res.json()) as Record<string, unknown>[];\n }\n\n /** Count entities matching the given filters. */\n async count(\n params?: CountEntitiesParams,\n ): Promise<number> {\n const parts: string[] = ['count=true', 'limit=0'];\n if (params?.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params?.q) parts.push('q=' + encodeURIComponent(params.q));\n const qs = '?' + parts.join('&');\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Count failed',\n );\n }\n const countHeader = res.headers.get('NGSILD-Results-Count');\n return countHeader ? parseInt(countHeader, 10) : 0;\n }\n\n /** Update entity attributes (partial). */\n async updateEntity(\n entityId: string,\n attrs: Record<string, unknown>,\n ): Promise<{ updated: true }> {\n const res = await this._auth.request(\n 'PATCH',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId) + '/attrs',\n attrs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Update failed',\n );\n }\n return { updated: true };\n }\n\n /** Delete an entity. */\n async deleteEntity(entityId: string): Promise<{ deleted: true }> {\n const res = await this._auth.request(\n 'DELETE',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Delete failed',\n );\n }\n return { deleted: true };\n }\n\n // --- Types / Attributes Discovery ---\n\n /** List all entity types. */\n async getTypes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/types', 'Types query failed');\n }\n\n /** Get details for a specific entity type. */\n async getType(typeName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/types/' + encodeURIComponent(typeName),\n 'Type not found',\n );\n }\n\n /** List all attributes. */\n async getAttributes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/attributes', 'Attributes query failed');\n }\n\n /** Get details for a specific attribute. */\n async getAttribute(attrName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/attributes/' + encodeURIComponent(attrName),\n 'Attribute not found',\n );\n }\n\n // --- Temporal API ---\n\n /** Query temporal entities. */\n async getTemporalEntities(\n params?: GetTemporalEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.id) parts.push('id=' + encodeURIComponent(params.id));\n if (params.idPattern) parts.push('idPattern=' + encodeURIComponent(params.idPattern));\n if (params.attrs) parts.push('attrs=' + encodeURIComponent(params.attrs));\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (params.timeproperty) parts.push('timeproperty=' + encodeURIComponent(params.timeproperty));\n if (params.timeAt) parts.push('timeAt=' + encodeURIComponent(params.timeAt));\n if (params.endTimeAt) parts.push('endTimeAt=' + encodeURIComponent(params.endTimeAt));\n if (params.timerel) parts.push('timerel=' + encodeURIComponent(params.timerel));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (parts.length) qs = '?' + parts.join('&');\n }\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities' + qs,\n 'Temporal query failed',\n );\n }\n\n /** Get temporal representation of a single entity. */\n async getTemporalEntity(entityId: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities/' + encodeURIComponent(entityId),\n 'Temporal entity not found',\n );\n }\n\n // --- Batch Operations ---\n\n /** Create multiple entities in a single request. */\n async batchCreate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/create',\n entities,\n 'Batch create failed',\n );\n }\n\n /** Upsert multiple entities in a single request. */\n async batchUpsert(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/upsert',\n entities,\n 'Batch upsert failed',\n );\n }\n\n /** Update multiple entities in a single request. */\n async batchUpdate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/update',\n entities,\n 'Batch update failed',\n );\n }\n\n /** Delete multiple entities by ID. */\n async batchDelete(entityIds: string[]): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/delete',\n entityIds,\n 'Batch delete failed',\n );\n }\n\n // --- Internal helpers ---\n\n /** GET request that returns parsed JSON or throws. */\n private async _jsonGet<T>(path: string, fallbackError: string): Promise<T> {\n const res = await this._auth.request('GET', path);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n return (await res.json()) as T;\n }\n\n /** POST request that returns parsed JSON or throws. */\n private async _jsonPost<T>(\n path: string,\n body: unknown,\n fallbackError: string,\n ): Promise<T> {\n const res = await this._auth.request('POST', path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n if (res.status === 204) return {} as T;\n return (await res.json()) as T;\n }\n\n // --- Generic Request ---\n\n /**\n * Make an authenticated API request.\n * Automatically checks response status, parses JSON, and throws on error.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<unknown> {\n const res = await this._auth.request(method, path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Request failed: ' + res.status,\n );\n }\n const ct = res.headers.get('Content-Type') || '';\n if (res.status === 204 || !ct) return null;\n if (ct.indexOf('json') !== -1) return res.json();\n return res.text();\n }\n\n /**\n * Make an authenticated API request and return the raw Response object.\n * Use this when you need access to response headers (e.g. NGSILD-Results-Count).\n */\n async requestRaw(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n return this._auth.request(method, path, body);\n }\n\n // --- WebSocket ---\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n return this._ws.connect();\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n return this._ws.reconnect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._ws.disconnect();\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return this._ws.isConnected();\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: SubscribeOptions): void {\n this._ws.subscribe(options);\n }\n}\n\n// Default export for convenient importing\nexport default GeonicDB;\n\n// UMD-style global assignment for browser script tag usage\nif (typeof window !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n window.GeonicDB = GeonicDB;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport type { GeonicDBEventMap } from './types';\n\ntype Listener<T> = (data: T) => void;\n\n/**\n * Minimal typed event emitter for GeonicDB SDK.\n */\nexport class EventEmitter {\n private _listeners: Record<string, Listener<unknown>[]> =\n Object.create(null) as Record<string, Listener<unknown>[]>;\n\n on<K extends keyof GeonicDBEventMap>(\n event: K,\n callback: Listener<GeonicDBEventMap[K]>,\n ): this;\n on(event: string, callback: Listener<unknown>): this;\n on(event: string, callback: Listener<unknown>): this {\n if (!this._listeners[event]) {\n this._listeners[event] = [];\n }\n this._listeners[event].push(callback);\n return this;\n }\n\n off<K extends keyof GeonicDBEventMap>(\n event: K,\n callback?: Listener<GeonicDBEventMap[K]>,\n ): this;\n off(event: string, callback?: Listener<unknown>): this;\n off(event: string, callback?: Listener<unknown>): this {\n if (!this._listeners[event]) return this;\n if (!callback) {\n delete this._listeners[event];\n } else {\n this._listeners[event] = this._listeners[event].filter(\n (cb) => cb !== callback,\n );\n }\n return this;\n }\n\n protected emit<K extends keyof GeonicDBEventMap>(\n event: K,\n data?: GeonicDBEventMap[K],\n ): void;\n protected emit(event: string, data?: unknown): void;\n protected emit(event: string, data?: unknown): void {\n const cbs = this._listeners[event];\n if (!cbs) return;\n const snapshot = cbs.slice();\n for (const cb of snapshot) {\n try {\n cb(data);\n } catch {\n // listener error \u2014 swallow silently\n }\n }\n }\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport type { DPoPKeyPair } from './types';\n\n/** Whether the Web Crypto DPoP API is available in the current environment. */\nexport const dpopSupported =\n typeof crypto !== 'undefined' &&\n !!crypto.subtle &&\n !!crypto.subtle.generateKey;\n\n/** Base64url-encode an ArrayBuffer or Uint8Array. */\nfunction b64url(buf: ArrayBuffer | Uint8Array): string {\n const arr = buf instanceof ArrayBuffer ? new Uint8Array(buf) : buf;\n let str = '';\n for (let i = 0; i < arr.length; i++) {\n str += String.fromCharCode(arr[i]);\n }\n return btoa(str).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** Encode a string to Uint8Array. */\nfunction strToUint8(s: string): Uint8Array {\n return new TextEncoder().encode(s);\n}\n\n/** Generate an ECDSA P-256 key pair for DPoP proof creation. */\nexport async function generateDPoPKeyPair(): Promise<DPoPKeyPair | null> {\n if (!dpopSupported) return null;\n const kp = await crypto.subtle.generateKey(\n { name: 'ECDSA', namedCurve: 'P-256' },\n false,\n ['sign'],\n );\n const pubJwk = await crypto.subtle.exportKey(\n 'jwk',\n kp.publicKey,\n );\n return {\n privateKey: kp.privateKey,\n publicJwk: {\n kty: pubJwk.kty!,\n crv: pubJwk.crv!,\n x: pubJwk.x!,\n y: pubJwk.y!,\n },\n };\n}\n\n/**\n * Create a DPoP proof JWT (RFC 9449).\n *\n * @param keyPair - The DPoP key pair\n * @param htm - HTTP method\n * @param htu - HTTP target URI\n * @param accessToken - Optional access token for ath claim\n * @param nonce - Optional server-provided nonce\n * @returns Signed DPoP proof JWT or null if keyPair is null\n */\nexport async function createDPoPProof(\n keyPair: DPoPKeyPair | null,\n htm: string,\n htu: string,\n accessToken?: string | null,\n nonce?: string | null,\n): Promise<string | null> {\n if (!keyPair) return null;\n\n const header = { alg: 'ES256', typ: 'dpop+jwt', jwk: keyPair.publicJwk };\n const payload: Record<string, unknown> = {\n jti:\n typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID()\n : Date.now().toString(36) + Math.random().toString(36).substr(2),\n htm,\n htu,\n iat: Math.floor(Date.now() / 1000),\n };\n if (nonce) payload.nonce = nonce;\n\n if (accessToken) {\n const hash = await crypto.subtle.digest('SHA-256', strToUint8(accessToken) as unknown as ArrayBuffer);\n payload.ath = b64url(hash);\n }\n\n const headerB64 = b64url(strToUint8(JSON.stringify(header)));\n const payloadB64 = b64url(strToUint8(JSON.stringify(payload)));\n const signingInput = headerB64 + '.' + payloadB64;\n\n /* eslint-disable @typescript-eslint/no-unsafe-argument */\n const sigBuf = await crypto.subtle.sign(\n { name: 'ECDSA', hash: 'SHA-256' },\n keyPair.privateKey,\n strToUint8(signingInput) as unknown as ArrayBuffer,\n );\n /* eslint-enable @typescript-eslint/no-unsafe-argument */\n // WebCrypto ECDSA returns IEEE P1363 r||s format (64 bytes for P-256)\n return signingInput + '.' + b64url(new Uint8Array(sigBuf));\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nconst BATCH_SIZE = 1000;\nconst MAX_ITERATIONS = 1_000_000;\n\n/** Check whether the first `bits` bits of a hash are zero. */\nfunction checkZeros(hash: Uint8Array, bits: number): boolean {\n const fullBytes = Math.floor(bits / 8);\n const remainBits = bits % 8;\n for (let k = 0; k < fullBytes; k++) {\n if (hash[k] !== 0) return false;\n }\n if (remainBits > 0) {\n const mask = 0xff << (8 - remainBits);\n if ((hash[fullBytes] & mask) !== 0) return false;\n }\n return true;\n}\n\n/**\n * Solve a Proof of Work challenge asynchronously using Web Crypto.\n *\n * Hashes `challenge + nonce` (SHA-256) in batches and checks for\n * the required number of leading zero bits.\n *\n * @param challenge - The challenge string from the server\n * @param difficulty - Number of leading zero bits required\n * @returns The nonce that satisfies the difficulty\n */\nexport async function solvePoW(\n challenge: string,\n difficulty: number,\n): Promise<number> {\n if (!Number.isInteger(difficulty) || difficulty < 0 || difficulty > 256) {\n throw new Error('difficulty must be an integer between 0 and 256');\n }\n const encoder = new TextEncoder();\n let i = 0;\n\n async function tryBatch(): Promise<number> {\n const batchEnd = Math.min(i + BATCH_SIZE, MAX_ITERATIONS);\n const promises: Promise<{ idx: number; hash: Uint8Array }>[] = [];\n\n for (; i < batchEnd; i++) {\n const idx = i;\n promises.push(\n crypto.subtle\n .digest('SHA-256', encoder.encode(challenge + String(idx)))\n .then((buf) => ({ idx, hash: new Uint8Array(buf) })),\n );\n }\n\n const results = await Promise.all(promises);\n for (const result of results) {\n if (checkZeros(result.hash, difficulty)) {\n return result.idx;\n }\n }\n if (i >= MAX_ITERATIONS) throw new Error('PoW solution not found');\n return tryBatch();\n }\n\n return tryBatch();\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\n/** Default token TTL in seconds when expiresIn is not specified in setCredentials(). */\nexport const DEFAULT_TOKEN_TTL_SEC = 3_600;\n\n/** Token refresh leeway in ms \u2014 refresh 2 minutes before expiry. */\nexport const TOKEN_REFRESH_LEEWAY_MS = 120_000;\n\n/** Minimum wait time in ms before refreshing a token. */\nexport const TOKEN_REFRESH_MIN_MS = 10_000;\n\n/** Maximum WebSocket reconnection attempts. */\nexport const RECONNECT_MAX_ATTEMPTS = 10;\n\n/** Base delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_BASE_MS = 1_000;\n\n/** Maximum delay in ms for exponential backoff reconnection. */\nexport const RECONNECT_MAX_DELAY_MS = 30_000;\n\n/** WebSocket sub-protocol name for browser authentication. */\nexport const SUB_PROTOCOL = 'access_token';\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport { createDPoPProof, dpopSupported, generateDPoPKeyPair } from './dpop';\nimport { solvePoW } from './pow';\nimport { DEFAULT_TOKEN_TTL_SEC } from './constants';\nimport type {\n CredentialsOptions,\n DPoPKeyPair,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n/** Internal authentication state for the GeonicDB SDK. */\nexport class AuthManager {\n private _baseUrl: string;\n private _apiKey: string;\n private _tenant: string;\n\n _token: string | null = null;\n _tokenExpiry = 0;\n _tokenType: 'Bearer' | 'DPoP' = 'Bearer';\n _refreshToken: string | null = null;\n _dpopKeyPair: DPoPKeyPair | null = null;\n _dpopReady: Promise<void> | null = null;\n _dpopNonce: string | null = null;\n private _tokenPromise: Promise<string> | null = null;\n\n /** Callback to emit tokenRefresh events. Set by GeonicDB class. */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(baseUrl: string, apiKey: string, tenant: string) {\n this._baseUrl = baseUrl;\n this._apiKey = apiKey;\n this._tenant = tenant;\n\n if (dpopSupported) {\n this._dpopReady = generateDPoPKeyPair()\n .then((kp) => {\n this._dpopKeyPair = kp;\n })\n .catch(() => {\n this._dpopKeyPair = null;\n });\n }\n }\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (this._tenant) headers['NGSILD-Tenant'] = this._tenant;\n\n const res = await fetch(this._baseUrl + '/auth/login', {\n method: 'POST',\n headers,\n body: JSON.stringify({ email, password }),\n });\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Login failed: ' + res.status,\n );\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n return data;\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' and refreshToken is provided, all subsequent\n * API calls and connect() bypass DPoP/PoW entirely.\n */\n setCredentials(opts: CredentialsOptions): void {\n if (!opts || !opts.token) throw new Error('token is required');\n this._token = opts.token;\n this._tokenType = opts.tokenType || 'Bearer';\n this._tokenExpiry = opts.expiresIn != null\n ? Date.now() + (opts.expiresIn - 60) * 1000\n : Date.now() + DEFAULT_TOKEN_TTL_SEC * 1000;\n this._refreshToken = opts.refreshToken || null;\n this._tokenPromise = null;\n }\n\n /** Clear all credentials. */\n logout(): void {\n this._token = null;\n this._tokenExpiry = 0;\n this._refreshToken = null;\n this._tokenPromise = null;\n }\n\n /** Ensure a valid token is available, refreshing or acquiring as needed. */\n async ensureToken(): Promise<string> {\n if (this._token && Date.now() < this._tokenExpiry) {\n return this._token;\n }\n\n // Deduplicate concurrent calls\n if (this._tokenPromise) {\n return this._tokenPromise;\n }\n\n // Bearer JWT refresh path \u2014 skip DPoP/PoW\n if (this._refreshToken) {\n this._tokenPromise = this._refreshBearerToken();\n return this._tokenPromise;\n }\n\n // API key + DPoP/PoW path\n this._tokenPromise = this._acquireTokenViaPow();\n return this._tokenPromise;\n }\n\n private async _refreshBearerToken(): Promise<string> {\n try {\n const res = await fetch(this._baseUrl + '/auth/refresh', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ refreshToken: this._refreshToken }),\n });\n if (!res.ok) {\n this._refreshToken = null;\n this._token = null;\n this._tokenPromise = null;\n throw new Error('Token refresh failed: ' + res.status);\n }\n const data = (await res.json()) as LoginResponse;\n this._token = data.accessToken;\n this._tokenExpiry = Date.now() + (data.expiresIn - 60) * 1000;\n this._tokenType = 'Bearer';\n this._refreshToken = data.refreshToken;\n this._tokenPromise = null;\n this.onTokenRefresh?.({\n token: this._token,\n tokenType: this._tokenType,\n expiresIn: data.expiresIn,\n refreshToken: this._refreshToken,\n });\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private async _acquireTokenViaPow(): Promise<string> {\n try {\n if (this._dpopReady) await this._dpopReady;\n\n // Step 1: Get nonce + PoW challenge\n const nonceRes = await fetch(this._baseUrl + '/auth/nonce', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ api_key: this._apiKey }),\n });\n if (!nonceRes.ok)\n throw new Error('Nonce request failed: ' + nonceRes.status);\n const nonceData = (await nonceRes.json()) as {\n nonce: string;\n challenge: string;\n difficulty: number;\n dpop_nonce?: string;\n };\n\n // RFC 9449 \u00A78: store pre-issued DPoP-Nonce\n if (nonceData.dpop_nonce) this._dpopNonce = nonceData.dpop_nonce;\n\n // Step 2: Solve PoW\n const proof = await solvePoW(nonceData.challenge, nonceData.difficulty);\n\n // Step 3: Exchange for token\n const tokenUrl = this._baseUrl + '/oauth/token';\n const tokenBody = JSON.stringify({\n grant_type: 'api_key',\n api_key: this._apiKey,\n nonce: nonceData.nonce,\n proof: String(proof),\n });\n\n const res = await this._doTokenExchange(tokenUrl, tokenBody, this._dpopNonce);\n\n if (!res.ok)\n throw new Error('Token request failed: ' + res.status);\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n const data = (await res.json()) as {\n access_token: string;\n expires_in: number;\n token_type?: string;\n };\n this._token = data.access_token;\n this._tokenExpiry = Date.now() + (data.expires_in - 60) * 1000;\n this._tokenType = (data.token_type as 'Bearer' | 'DPoP') || 'Bearer';\n this._tokenPromise = null;\n return this._token;\n } catch (err) {\n this._tokenPromise = null;\n throw err;\n }\n }\n\n private static readonly MAX_DPOP_RETRIES = 3;\n\n private async _doTokenExchange(\n tokenUrl: string,\n tokenBody: string,\n dpopNonce: string | null,\n retryCount = 0,\n ): Promise<Response> {\n const reqHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n const dpopProof = await createDPoPProof(\n this._dpopKeyPair,\n 'POST',\n tokenUrl,\n null,\n dpopNonce,\n );\n if (dpopProof) reqHeaders['DPoP'] = dpopProof;\n\n const res = await fetch(tokenUrl, {\n method: 'POST',\n headers: reqHeaders,\n body: tokenBody,\n });\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 400 && this._dpopKeyPair) {\n const errBody = await res.json().catch(() => ({})) as Record<string, string>;\n if (errBody.error === 'use_dpop_nonce') {\n const serverNonce = res.headers.get('DPoP-Nonce');\n if (serverNonce && serverNonce !== dpopNonce && retryCount < AuthManager.MAX_DPOP_RETRIES) {\n this._dpopNonce = serverNonce;\n return this._doTokenExchange(tokenUrl, tokenBody, serverNonce, retryCount + 1);\n }\n }\n throw new Error(\n 'Token request failed: ' +\n (errBody.error_description || errBody.error),\n );\n }\n\n return res;\n }\n\n /**\n * Make an authenticated HTTP request with automatic token refresh and DPoP.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n const token = await this.ensureToken();\n return this._doAuthenticatedRequest(method, path, body, token);\n }\n\n private static readonly MAX_REQUEST_RETRIES = 3;\n\n private async _doAuthenticatedRequest(\n method: string,\n path: string,\n body: unknown,\n token: string,\n retryCount = 0,\n ): Promise<Response> {\n const url = this._baseUrl + path;\n const isDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const bodyStr = body !== undefined ? JSON.stringify(body) : undefined;\n\n const doRequest = async (\n reqToken: string,\n dpopNonce: string | null,\n ): Promise<Response> => {\n const reqIsDPoP = this._tokenType === 'DPoP' && !!this._dpopKeyPair;\n const dpopProof = reqIsDPoP\n ? await createDPoPProof(\n this._dpopKeyPair,\n method,\n url,\n reqToken,\n dpopNonce,\n )\n : null;\n\n const headers: Record<string, string> = {\n Authorization: (reqIsDPoP ? 'DPoP ' : 'Bearer ') + reqToken,\n 'Content-Type': 'application/ld+json',\n Accept: 'application/ld+json',\n };\n if (dpopProof) headers['DPoP'] = dpopProof;\n if (this._tenant) headers['Fiware-Service'] = this._tenant;\n\n return fetch(url, { method, headers, body: bodyStr });\n };\n\n let currentToken = token;\n let res = await doRequest(currentToken, this._dpopNonce);\n const previousNonce = this._dpopNonce;\n const newNonce = res.headers.get('DPoP-Nonce');\n if (newNonce) this._dpopNonce = newNonce;\n\n // RFC 9449 \u00A78: use_dpop_nonce \u2192 retry with server nonce\n if (res.status === 401 && isDPoP && newNonce && newNonce !== previousNonce) {\n res = await doRequest(currentToken, newNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const fn = res.headers.get('DPoP-Nonce');\n if (fn) this._dpopNonce = fn;\n }\n } else if (res.status === 401) {\n this._token = null;\n this._tokenPromise = null;\n currentToken = await this.ensureToken();\n res = await doRequest(currentToken, this._dpopNonce);\n const rn = res.headers.get('DPoP-Nonce');\n if (rn) this._dpopNonce = rn;\n }\n\n if (res.status === 429 && retryCount < AuthManager.MAX_REQUEST_RETRIES) {\n const retryNonce = res.headers.get('DPoP-Nonce');\n if (retryNonce) this._dpopNonce = retryNonce;\n const delay =\n parseInt(res.headers.get('Retry-After') || '1', 10) * 1000;\n await new Promise<void>((resolve) => setTimeout(resolve, delay));\n return this._doAuthenticatedRequest(method, path, body, currentToken, retryCount + 1);\n }\n\n return res;\n }\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\nimport { createDPoPProof } from './dpop';\nimport type { AuthManager } from './auth';\nimport {\n TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n RECONNECT_MAX_ATTEMPTS,\n RECONNECT_BASE_MS,\n RECONNECT_MAX_DELAY_MS,\n SUB_PROTOCOL,\n} from './constants';\nimport type { SubscriptionMessage } from './types';\n\ntype EmitFn = (event: string, data?: unknown) => void;\n\n/**\n * WebSocket connection manager for the GeonicDB SDK.\n *\n * Handles connection lifecycle, DPoP binding, token refresh,\n * automatic reconnection with exponential backoff, and subscriptions.\n */\nexport class WebSocketManager {\n private _auth: AuthManager;\n private _tenant: string;\n private _wsEndpointOverride: string | null;\n private _baseUrl: string;\n private _emit: EmitFn;\n\n private _ws: WebSocket | null = null;\n private _wsEndpoint: string | null = null;\n private _wsIntentionalClose = false;\n private _reconnectAttempts = 0;\n private _tokenRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private _subscription: SubscriptionMessage | null = null;\n private _pendingSubscription = false;\n\n constructor(\n auth: AuthManager,\n baseUrl: string,\n tenant: string,\n emit: EmitFn,\n wsEndpointOverride?: string,\n ) {\n this._auth = auth;\n this._baseUrl = baseUrl;\n this._tenant = tenant;\n this._emit = emit;\n this._wsEndpointOverride = wsEndpointOverride || null;\n }\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n this._wsIntentionalClose = false;\n this._reconnectAttempts = 0;\n\n try {\n const token = await this._auth.ensureToken();\n await this._openWebSocket(token);\n } catch (err) {\n this._emit('error', err);\n }\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n this._wsIntentionalClose = true;\n this._clearTimers();\n if (this._ws) {\n this._ws.close(1000, 'Client reconnect');\n this._ws = null;\n }\n return this.connect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._wsIntentionalClose = true;\n this._clearTimers();\n this._subscription = null;\n this._pendingSubscription = false;\n if (this._ws) {\n this._ws.close(1000, 'Client disconnect');\n this._ws = null;\n }\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return !!(this._ws && this._ws.readyState === WebSocket.OPEN);\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: { entityTypes?: string[]; idPattern?: string }): void {\n const msg: SubscriptionMessage = { action: 'subscribe' };\n if (options) {\n if (options.entityTypes) msg.entityTypes = options.entityTypes;\n if (options.idPattern) msg.idPattern = options.idPattern;\n }\n this._subscription = msg;\n // If DPoP pending verification, store subscription but don't send yet\n if (this._pendingSubscription) return;\n if (this._ws && this._ws.readyState === WebSocket.OPEN) {\n this._ws.send(JSON.stringify(msg));\n }\n }\n\n private async _discoverWsEndpoint(): Promise<string> {\n if (this._wsEndpointOverride) return this._wsEndpointOverride;\n if (this._wsEndpoint) return this._wsEndpoint;\n\n // Fetch endpoint from server discovery API\n try {\n const res = await fetch(this._baseUrl + '/sdk/v1/streaming');\n if (res.ok) {\n const info = (await res.json()) as {\n enabled: boolean;\n endpoint: string | null;\n };\n if (info.enabled && info.endpoint) {\n this._wsEndpoint = info.endpoint;\n return this._wsEndpoint;\n }\n }\n } catch {\n // Discovery failed \u2014 fall back to URL scheme conversion\n }\n\n // Fallback: convert http(s) baseUrl to ws(s)\n this._wsEndpoint = this._baseUrl.replace(/^http/, 'ws');\n return this._wsEndpoint;\n }\n\n private async _openWebSocket(token: string): Promise<void> {\n const endpoint = await this._discoverWsEndpoint();\n return new Promise<void>((resolve, reject) => {\n const wsUrl =\n endpoint +\n (endpoint.indexOf('?') === -1 ? '?' : '&') +\n 'tenant=' +\n encodeURIComponent(this._tenant);\n\n const ws = new WebSocket(wsUrl, [SUB_PROTOCOL, token]);\n this._ws = ws;\n\n ws.onopen = (): void => {\n if (this._ws !== ws) return;\n this._reconnectAttempts = 0;\n\n const isDPoP =\n this._auth._tokenType === 'DPoP' && !!this._auth._dpopKeyPair;\n\n const bindPromise = isDPoP\n ? createDPoPProof(this._auth._dpopKeyPair, 'GET', wsUrl, null).then(\n (proof) => {\n if (proof && ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify({ action: 'dpop_bind', proof }));\n }\n },\n )\n : Promise.resolve();\n\n bindPromise\n .then(() => {\n this._scheduleTokenRefresh();\n\n if (isDPoP) {\n this._pendingSubscription = true;\n } else if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n\n this._emit('open');\n this._emit('connected');\n resolve();\n })\n .catch((err) => {\n this._emit('error', err);\n resolve();\n });\n };\n\n ws.onmessage = (event: MessageEvent): void => {\n if (this._ws !== ws) return;\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(event.data as string) as Record<string, unknown>;\n } catch {\n return;\n }\n\n if (msg.type === 'pong') return;\n\n if (msg.type === 'dpop_verified') {\n this._pendingSubscription = false;\n if (this._subscription) {\n ws.send(JSON.stringify(this._subscription));\n }\n return;\n }\n\n if (msg.type === 'error') {\n this._emit('error', new Error(msg.message as string));\n return;\n }\n\n this._emit(msg.type as string, msg);\n this._emit('message', msg);\n };\n\n ws.onclose = (event: CloseEvent): void => {\n if (this._ws !== ws) return;\n this._clearTimers();\n\n if (this._wsIntentionalClose) {\n this._emit('close', event);\n return;\n }\n\n this._emit('close', event);\n this._emit('disconnected');\n this._autoReconnect();\n };\n\n ws.onerror = (err: Event): void => {\n if (this._ws !== ws) return;\n this._emit('error', err);\n if (ws.readyState !== WebSocket.OPEN) {\n reject(new Error('WebSocket connection failed'));\n }\n };\n });\n }\n\n private _scheduleTokenRefresh(): void {\n if (this._tokenRefreshTimer) clearTimeout(this._tokenRefreshTimer);\n\n const remaining = this._auth._tokenExpiry - Date.now();\n const refreshIn = Math.max(\n remaining - TOKEN_REFRESH_LEEWAY_MS,\n TOKEN_REFRESH_MIN_MS,\n );\n\n this._tokenRefreshTimer = setTimeout(() => {\n const oldWs = this._ws;\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((newToken) => {\n if (!oldWs || oldWs.readyState !== WebSocket.OPEN) return;\n\n this._wsIntentionalClose = true;\n oldWs.close(1000, 'Token refresh');\n\n this._wsIntentionalClose = false;\n return this._openWebSocket(newToken);\n })\n .catch((err) => {\n this._emit('error', err);\n this._autoReconnect();\n });\n }, refreshIn);\n }\n\n private _autoReconnect(): void {\n if (this._wsIntentionalClose) return;\n if (\n this._ws &&\n (this._ws.readyState === WebSocket.OPEN ||\n this._ws.readyState === WebSocket.CONNECTING)\n ) {\n return;\n }\n\n if (this._reconnectAttempts >= RECONNECT_MAX_ATTEMPTS) {\n this._emit('error', new Error('Max reconnection attempts reached'));\n return;\n }\n\n const delay = Math.min(\n RECONNECT_BASE_MS * Math.pow(2, this._reconnectAttempts),\n RECONNECT_MAX_DELAY_MS,\n );\n this._reconnectAttempts++;\n this._emit('reconnecting', {\n attempt: this._reconnectAttempts,\n delay,\n });\n\n this._reconnectTimer = setTimeout(() => {\n this._auth._token = null;\n this._auth\n .ensureToken()\n .then((token) => this._openWebSocket(token))\n .catch(() => this._autoReconnect());\n }, delay);\n }\n\n private _clearTimers(): void {\n if (this._tokenRefreshTimer) {\n clearTimeout(this._tokenRefreshTimer);\n this._tokenRefreshTimer = null;\n }\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n }\n}\n", "/**\n * Copyright (c) 2026 Geolonia Inc.\n * Released under the MIT License. See src/sdk/LICENSE for details.\n */\n\n/**\n * GeonicDB JavaScript SDK\n *\n * NGSI-LD Context Broker client for browser and Node.js.\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n */\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ndeclare const document: any;\ndeclare const window: any;\n\nimport { EventEmitter } from './events';\nimport { AuthManager } from './auth';\nimport { WebSocketManager } from './websocket';\nimport type {\n GeonicDBOptions,\n CredentialsOptions,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\n// Re-export types for consumers\nexport type {\n GeonicDBOptions,\n CredentialsOptions,\n RefreshedCredentials,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n SubscribeOptions,\n EntityEvent,\n ReconnectingEvent,\n LoginResponse,\n GeonicDBEventMap,\n} from './types';\n\n/**\n * GeonicDB SDK client.\n *\n * Handles API key auth (DPoP + PoW), Bearer JWT, entity CRUD,\n * WebSocket event streaming, and automatic reconnection.\n *\n * @example\n * ```typescript\n * import GeonicDB from '@geolonia/geonicdb-sdk';\n *\n * const db = new GeonicDB({\n * apiKey: 'your-api-key',\n * tenant: 'your-tenant',\n * baseUrl: 'https://your-geonicdb.example.com',\n * });\n *\n * const entities = await db.getEntities({ type: 'Room' });\n * ```\n */\nexport class GeonicDB extends EventEmitter {\n private _auth: AuthManager;\n private _ws: WebSocketManager;\n\n /**\n * Legacy callback for token refresh events.\n * Prefer `db.on('tokenRefresh', callback)` for new code.\n * @deprecated Use `db.on('tokenRefresh', callback)` instead.\n */\n onTokenRefresh: ((creds: RefreshedCredentials) => void) | null = null;\n\n constructor(options?: GeonicDBOptions) {\n super();\n const opts = options || {};\n\n // Auto-detect from script tag in browser\n let apiKey = opts.apiKey || '';\n let tenant = opts.tenant || '';\n let baseUrl = opts.baseUrl || '';\n\n /* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n if (typeof document !== 'undefined' && document.currentScript) {\n const script = document.currentScript;\n if (!apiKey) apiKey = script?.getAttribute?.('data-api-key') || '';\n if (!tenant) tenant = script?.getAttribute?.('data-tenant') || '';\n if (!baseUrl) baseUrl = script?.getAttribute?.('data-base-url') || '';\n }\n /* eslint-enable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call */\n\n this._auth = new AuthManager(baseUrl, apiKey, tenant);\n this._auth.onTokenRefresh = (creds): void => {\n this.onTokenRefresh?.(creds);\n this.emit('tokenRefresh', creds);\n };\n this._ws = new WebSocketManager(\n this._auth,\n baseUrl,\n tenant,\n (event, data) => this.emit(event, data),\n opts.wsEndpoint,\n );\n }\n\n // --- Authentication ---\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n return this._auth.login(email, password);\n }\n\n /**\n * Set credentials externally (e.g. from a login API response).\n * When tokenType is 'Bearer' with a refreshToken, DPoP/PoW is bypassed entirely.\n */\n setCredentials(opts: CredentialsOptions): this {\n this._auth.setCredentials(opts);\n return this;\n }\n\n /** Clear all credentials and disconnect. */\n logout(): void {\n this._ws.disconnect();\n this._auth.logout();\n }\n\n // --- Entity CRUD (NGSI-LD) ---\n\n /** Create a new entity. */\n async createEntity(\n entity: Record<string, unknown>,\n ): Promise<{ created: true }> {\n const res = await this._auth.request('POST', '/ngsi-ld/v1/entities', entity);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Create failed',\n );\n }\n return { created: true };\n }\n\n /** Get a single entity by ID. */\n async getEntity(entityId: string): Promise<Record<string, unknown>> {\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Not found',\n );\n }\n return (await res.json()) as Record<string, unknown>;\n }\n\n /** Query entities with optional filters. */\n async getEntities(\n params?: GetEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (parts.length) qs = '?' + parts.join('&');\n }\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Query failed',\n );\n }\n return (await res.json()) as Record<string, unknown>[];\n }\n\n /** Count entities matching the given filters. */\n async count(\n params?: CountEntitiesParams,\n ): Promise<number> {\n const parts: string[] = ['count=true', 'limit=0'];\n if (params?.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params?.q) parts.push('q=' + encodeURIComponent(params.q));\n const qs = '?' + parts.join('&');\n const res = await this._auth.request(\n 'GET',\n '/ngsi-ld/v1/entities' + qs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Count failed',\n );\n }\n const countHeader = res.headers.get('NGSILD-Results-Count');\n return countHeader ? parseInt(countHeader, 10) : 0;\n }\n\n /** Update entity attributes (partial). */\n async updateEntity(\n entityId: string,\n attrs: Record<string, unknown>,\n ): Promise<{ updated: true }> {\n const res = await this._auth.request(\n 'PATCH',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId) + '/attrs',\n attrs,\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Update failed',\n );\n }\n return { updated: true };\n }\n\n /** Delete an entity. */\n async deleteEntity(entityId: string): Promise<{ deleted: true }> {\n const res = await this._auth.request(\n 'DELETE',\n '/ngsi-ld/v1/entities/' + encodeURIComponent(entityId),\n );\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Delete failed',\n );\n }\n return { deleted: true };\n }\n\n // --- Types / Attributes Discovery ---\n\n /** List all entity types. */\n async getTypes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/types', 'Types query failed');\n }\n\n /** Get details for a specific entity type. */\n async getType(typeName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/types/' + encodeURIComponent(typeName),\n 'Type not found',\n );\n }\n\n /** List all attributes. */\n async getAttributes(): Promise<Record<string, unknown>[]> {\n return this._jsonGet('/ngsi-ld/v1/attributes', 'Attributes query failed');\n }\n\n /** Get details for a specific attribute. */\n async getAttribute(attrName: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/attributes/' + encodeURIComponent(attrName),\n 'Attribute not found',\n );\n }\n\n // --- Temporal API ---\n\n /** Query temporal entities. */\n async getTemporalEntities(\n params?: GetTemporalEntitiesParams,\n ): Promise<Record<string, unknown>[]> {\n let qs = '';\n if (params) {\n const parts: string[] = [];\n if (params.type) parts.push('type=' + encodeURIComponent(params.type));\n if (params.id) parts.push('id=' + encodeURIComponent(params.id));\n if (params.idPattern) parts.push('idPattern=' + encodeURIComponent(params.idPattern));\n if (params.attrs) parts.push('attrs=' + encodeURIComponent(params.attrs));\n if (params.q) parts.push('q=' + encodeURIComponent(params.q));\n if (params.timeproperty) parts.push('timeproperty=' + encodeURIComponent(params.timeproperty));\n if (params.timeAt) parts.push('timeAt=' + encodeURIComponent(params.timeAt));\n if (params.endTimeAt) parts.push('endTimeAt=' + encodeURIComponent(params.endTimeAt));\n if (params.timerel) parts.push('timerel=' + encodeURIComponent(params.timerel));\n if (params.limit != null) parts.push('limit=' + params.limit);\n if (params.offset != null) parts.push('offset=' + params.offset);\n if (parts.length) qs = '?' + parts.join('&');\n }\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities' + qs,\n 'Temporal query failed',\n );\n }\n\n /** Get temporal representation of a single entity. */\n async getTemporalEntity(entityId: string): Promise<Record<string, unknown>> {\n return this._jsonGet(\n '/ngsi-ld/v1/temporal/entities/' + encodeURIComponent(entityId),\n 'Temporal entity not found',\n );\n }\n\n // --- Batch Operations ---\n\n /** Create multiple entities in a single request. */\n async batchCreate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/create',\n entities,\n 'Batch create failed',\n );\n }\n\n /** Upsert multiple entities in a single request. */\n async batchUpsert(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/upsert',\n entities,\n 'Batch upsert failed',\n );\n }\n\n /** Update multiple entities in a single request. */\n async batchUpdate(\n entities: Record<string, unknown>[],\n ): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/update',\n entities,\n 'Batch update failed',\n );\n }\n\n /** Delete multiple entities by ID. */\n async batchDelete(entityIds: string[]): Promise<Record<string, unknown>> {\n return this._jsonPost(\n '/ngsi-ld/v1/entityOperations/delete',\n entityIds,\n 'Batch delete failed',\n );\n }\n\n // --- Internal helpers ---\n\n /** GET request that returns parsed JSON or throws. */\n private async _jsonGet<T>(path: string, fallbackError: string): Promise<T> {\n const res = await this._auth.request('GET', path);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n return (await res.json()) as T;\n }\n\n /** POST request that returns parsed JSON or throws. */\n private async _jsonPost<T>(\n path: string,\n body: unknown,\n fallbackError: string,\n ): Promise<T> {\n const res = await this._auth.request('POST', path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n fallbackError,\n );\n }\n if (res.status === 204) return {} as T;\n return (await res.json()) as T;\n }\n\n // --- Generic Request ---\n\n /**\n * Make an authenticated API request.\n * Automatically checks response status, parses JSON, and throws on error.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<unknown> {\n const res = await this._auth.request(method, path, body);\n if (!res.ok) {\n const e = await res.json().catch(() => ({}));\n throw new Error(\n (e as Record<string, string>).detail ||\n (e as Record<string, string>).description ||\n 'Request failed: ' + res.status,\n );\n }\n const ct = res.headers.get('Content-Type') || '';\n if (res.status === 204 || !ct) return null;\n if (ct.indexOf('json') !== -1) return res.json();\n return res.text();\n }\n\n /**\n * Make an authenticated API request and return the raw Response object.\n * Use this when you need access to response headers (e.g. NGSILD-Results-Count).\n */\n async requestRaw(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n return this._auth.request(method, path, body);\n }\n\n // --- WebSocket ---\n\n /** Establish WebSocket connection (authentication is automatic). */\n async connect(): Promise<void> {\n return this._ws.connect();\n }\n\n /** Force-reconnect (closes existing connection, preserves subscriptions). */\n async reconnect(): Promise<void> {\n return this._ws.reconnect();\n }\n\n /** Disconnect WebSocket (does not fire 'disconnected' event). */\n disconnect(): void {\n this._ws.disconnect();\n }\n\n /** Check if WebSocket is currently open. */\n isConnected(): boolean {\n return this._ws.isConnected();\n }\n\n /** Subscribe to entity events (can be called before or after connect). */\n subscribe(options?: SubscribeOptions): void {\n this._ws.subscribe(options);\n }\n}\n\n// Default export for convenient importing\nexport default GeonicDB;\n\n// UMD-style global assignment for browser script tag usage\nif (typeof window !== 'undefined') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n window.GeonicDB = GeonicDB;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geolonia/geonicdb-sdk",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "GeonicDB JavaScript SDK — NGSI-LD Context Broker client for browser and Node.js",
5
5
  "main": "geonicdb.cjs",
6
6
  "module": "geonicdb.mjs",
@@ -19,9 +19,10 @@
19
19
  }
20
20
  },
21
21
  "files": [
22
- "geonicdb.*"
22
+ "geonicdb.*",
23
+ "LICENSE"
23
24
  ],
24
- "license": "AGPL-3.0-or-later",
25
+ "license": "MIT",
25
26
  "publishConfig": {
26
27
  "access": "public"
27
28
  },