@geolonia/geonicdb-sdk 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 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 * 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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",
3
+ "sources": ["../../src/sdk/index.ts", "../../src/sdk/events.ts", "../../src/sdk/dpop.ts", "../../src/sdk/pow.ts", "../../src/sdk/constants.ts", "../../src/sdk/errors.ts", "../../src/sdk/auth.ts", "../../src/sdk/websocket.ts"],
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 { createErrorFromResponse } from './errors';\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// Re-export error classes for consumers\nexport {\n GeonicDBError,\n AuthenticationError,\n AuthorizationError,\n NotFoundError,\n ConflictError,\n ValidationError,\n RateLimitError,\n NetworkError,\n} from './errors';\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, opts.debug);\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 createErrorFromResponse(res.status, e as Record<string, string>, 'Create failed');\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 createErrorFromResponse(res.status, e as Record<string, string>, 'Not found');\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 createErrorFromResponse(res.status, e as Record<string, string>, 'Query failed');\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 createErrorFromResponse(res.status, e as Record<string, string>, 'Count failed');\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 createErrorFromResponse(res.status, e as Record<string, string>, 'Update failed');\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 createErrorFromResponse(res.status, e as Record<string, string>, 'Delete failed');\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 createErrorFromResponse(res.status, e as Record<string, string>, fallbackError);\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 createErrorFromResponse(res.status, e as Record<string, string>, fallbackError);\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 createErrorFromResponse(res.status, e as Record<string, string>, 'Request failed: ' + res.status);\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\n/**\n * Base error class for GeonicDB SDK.\n * All SDK errors extend this class, allowing `instanceof GeonicDBError` checks.\n */\nexport class GeonicDBError extends Error {\n /** HTTP status code (if applicable) */\n readonly statusCode: number;\n\n constructor(message: string, statusCode = 0) {\n super(message);\n this.name = 'GeonicDBError';\n this.statusCode = statusCode;\n }\n}\n\n/** 401 \u2014 Authentication failed (invalid credentials, expired token). */\nexport class AuthenticationError extends GeonicDBError {\n constructor(message = 'Authentication failed') {\n super(message, 401);\n this.name = 'AuthenticationError';\n }\n}\n\n/** 403 \u2014 Authorization denied (insufficient permissions). */\nexport class AuthorizationError extends GeonicDBError {\n constructor(message = 'Access denied') {\n super(message, 403);\n this.name = 'AuthorizationError';\n }\n}\n\n/** 404 \u2014 Resource not found. */\nexport class NotFoundError extends GeonicDBError {\n constructor(message = 'Not found') {\n super(message, 404);\n this.name = 'NotFoundError';\n }\n}\n\n/** 409 \u2014 Conflict (e.g. entity already exists). */\nexport class ConflictError extends GeonicDBError {\n constructor(message = 'Conflict') {\n super(message, 409);\n this.name = 'ConflictError';\n }\n}\n\n/** 422 \u2014 Validation error (bad request payload). */\nexport class ValidationError extends GeonicDBError {\n constructor(message = 'Validation failed') {\n super(message, 422);\n this.name = 'ValidationError';\n }\n}\n\n/** 429 \u2014 Rate limited. */\nexport class RateLimitError extends GeonicDBError {\n /** Seconds to wait before retrying (from Retry-After header) */\n readonly retryAfter: number;\n\n constructor(message = 'Rate limit exceeded', retryAfter = 1) {\n super(message, 429);\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/** Network error (fetch failed, DNS resolution, timeout). */\nexport class NetworkError extends GeonicDBError {\n constructor(message = 'Network error') {\n super(message, 0);\n this.name = 'NetworkError';\n }\n}\n\n/**\n * Create a typed error from an HTTP response status and error body.\n * Used internally by SDK methods to throw the appropriate error class.\n */\nexport function createErrorFromResponse(\n status: number,\n body: Record<string, string>,\n fallbackMessage: string,\n): GeonicDBError {\n const message = body.detail || body.description || fallbackMessage;\n switch (status) {\n case 401:\n return new AuthenticationError(message);\n case 403:\n return new AuthorizationError(message);\n case 404:\n return new NotFoundError(message);\n case 409:\n return new ConflictError(message);\n case 422:\n return new ValidationError(message);\n case 429:\n return new RateLimitError(message);\n default:\n return new GeonicDBError(message, status);\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, dpopSupported, generateDPoPKeyPair } from './dpop';\nimport { solvePoW } from './pow';\nimport { DEFAULT_TOKEN_TTL_SEC } from './constants';\nimport { AuthenticationError, GeonicDBError } from './errors';\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 _debug: boolean;\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, debug = false) {\n this._baseUrl = baseUrl;\n this._apiKey = apiKey;\n this._tenant = tenant;\n this._debug = debug;\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 private _log(...args: unknown[]): void {\n if (this._debug) console.log('[GeonicDB]', ...args);\n }\n\n /** Login with email and password (Bearer JWT). */\n async login(email: string, password: string): Promise<LoginResponse> {\n this._log('login', email);\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 AuthenticationError(\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 this._log('refreshing Bearer token');\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 AuthenticationError('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 AuthenticationError('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 AuthenticationError('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 GeonicDBError(\n 'Token request failed: ' +\n (errBody.error_description || errBody.error),\n 400,\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 this._log(method, path);\n const token = await this.ensureToken();\n const res = await this._doAuthenticatedRequest(method, path, body, token);\n this._log(method, path, '\u2192', res.status);\n return res;\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 private _log(...args: unknown[]): void {\n if (this._auth._debug) console.log('[GeonicDB:WS]', ...args);\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 this._log('connecting', wsUrl);\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._log('connected');\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._log('event', msg.type, msg.entityId || '');\n\n // Entity events: build a complete NGSI-LD entity from id + type + data\n if (msg.entityId && msg.data && typeof msg.data === 'object') {\n msg.entity = {\n id: msg.entityId,\n type: msg.entityType,\n ...(msg.data as Record<string, unknown>),\n };\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
  }