@geolonia/geonicdb-sdk 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -0
- package/geonicdb.cjs +310 -18
- package/geonicdb.cjs.map +4 -4
- package/geonicdb.iife.js +310 -18
- package/geonicdb.iife.js.map +4 -4
- package/geonicdb.mjs +310 -18
- package/geonicdb.mjs.map +4 -4
- package/package.json +1 -1
package/geonicdb.iife.js.map
CHANGED
|
@@ -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/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
|
-
"names": []
|
|
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/cache.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 { SdkCache } from './cache';\nimport { SDK_CACHE_MAX_ENTRIES_DEFAULT, SDK_POLL_INTERVAL_MS_DEFAULT } from './constants';\nimport type {\n GeonicDBOptions,\n CredentialsOptions,\n CountEntitiesParams,\n GetEntitiesParams,\n GetTemporalEntitiesParams,\n PollHandle,\n PollOptions,\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 CacheEvent,\n PollOptions,\n PollHandle,\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\n // #1043 Phase A: client-side cache. Enabled by default. Pass `cache: false` to opt out.\n if (opts.cache !== false) {\n const cache = new SdkCache(opts.cacheMaxEntries ?? SDK_CACHE_MAX_ENTRIES_DEFAULT);\n this._auth.setCache(cache);\n this._auth.setCacheEventEmitter((name, payload) => this.emit(name, payload));\n }\n\n this._ws = new WebSocketManager(\n this._auth,\n baseUrl,\n tenant,\n (event, data) => {\n this.emit(event, data);\n // \u6CE8: \u65E7\u5B9F\u88C5\u3067\u306F entityCreated / entityUpdated / entityDeleted \u3067\n // \u30AD\u30E3\u30C3\u30B7\u30E5\u30A8\u30F3\u30C8\u30EA\u3092\u524A\u9664\u3057\u3066\u3044\u305F\u304C\u3001`Cache-Control: private, no-cache`\n // \u306B\u3088\u308A\u6BCE\u8AAD\u307F\u53D6\u308A\u3067 `If-None-Match` revalidation \u304C\u8D70\u308B\u8A2D\u8A08\u306E\u305F\u3081\u3001\n // \u524A\u9664\u3059\u308B\u3068 ETag \u3092\u5931\u3063\u3066\u6BCE\u56DE full 200 \u306B\u306A\u308A 304 \u5E2F\u57DF\u7BC0\u7D04\u304C\u7121\u52B9\u5316\u3055\u308C\u3066\u3044\u305F\n // (incident 2026-04-28 \u3067 pulse \u306E\u4F53\u611F\u901F\u5EA6\u52A3\u5316\u3068\u3057\u3066\u9855\u5728\u5316)\u3002\n // \u30AD\u30E3\u30C3\u30B7\u30E5\u30A8\u30F3\u30C8\u30EA\u306F\u4FDD\u6301\u3057\u3001\u30B5\u30FC\u30D0\u5074\u306E ETag \u30DE\u30C3\u30C1\u3067\u81EA\u52D5\u7684\u306B\n // 304 (=fresh cache hit) / 200 (=\u672C\u5F53\u306B\u5909\u66F4\u3042\u308A\u306E\u307F full body) \u304C\n // \u632F\u308A\u5206\u3051\u3089\u308C\u308B\u3002\u610F\u56F3\u7684\u306A\u5168\u6D88\u53BB\u306F `clearCache()` \u3092\u4F7F\u3046\u3053\u3068\u3002\n },\n opts.wsEndpoint,\n );\n }\n\n /**\n * Drop every cached response. Useful in tests and on manual auth changes.\n *\n * Emits a `cacheInvalidated` event for each removed entry so listeners can\n * track explicit flushes (the WebSocket-driven auto-invalidation was removed\n * in #1060 to preserve the ETag/304 revalidation path; `clearCache()` is now\n * the only path that emits this event).\n */\n clearCache(): void {\n const cache = this._auth.getCache();\n if (!cache) return;\n const removed = cache.deleteWhere(() => true);\n for (const key of removed) {\n this._auth.emitCacheEvent('cacheInvalidated', { key, path: key.split(':').slice(1).join(':') });\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 const res = await this._auth.request('GET', buildEntitiesPath(params));\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 /**\n * Poll for entity list changes using ETag-based revalidation (#991 Phase A).\n *\n * The handle's `stop()` ends the loop. Each tick performs a normal\n * `getEntities()` call; the SDK's cache layer issues `If-None-Match`\n * automatically. The poll detects \"no change\" by comparing the previous\n * ETag with the response's ETag (the cache exposes the cached ETag on 304\n * replays as well, so the comparison stays valid in both 200 and 304\n * paths).\n *\n * @example\n * ```typescript\n * const handle = db.poll({ type: 'Room' }, {\n * interval: 5000,\n * onData: (rooms) => render(rooms),\n * onNoChange: () => {},\n * });\n * // ...later\n * handle.stop();\n * ```\n */\n poll(\n params: GetEntitiesParams | undefined,\n options: PollOptions<Record<string, unknown>[]>,\n ): PollHandle {\n const interval = options.interval ?? SDK_POLL_INTERVAL_MS_DEFAULT;\n if (!Number.isFinite(interval) || interval <= 0) {\n throw new Error(`poll interval must be a positive number (got ${String(interval)})`);\n }\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n let prevEtag: string | undefined;\n let prevPath: string | undefined;\n\n const buildPath = (): string => buildEntitiesPath(params);\n\n const tick = async (): Promise<void> => {\n if (stopped) return;\n try {\n const path = (prevPath ??= buildPath());\n const res = await this._auth.request('GET', path);\n if (stopped) return;\n const etag = res.headers.get('etag') ?? undefined;\n if (prevEtag !== undefined && etag !== undefined && prevEtag === etag) {\n options.onNoChange?.();\n } else {\n if (!res.ok) {\n throw createErrorFromResponse(res.status, {}, 'Poll request failed');\n }\n const data = (await res.json()) as Record<string, unknown>[];\n prevEtag = etag;\n options.onData?.(data);\n }\n } catch (err) {\n options.onError?.(err);\n } finally {\n if (!stopped) {\n timer = setTimeout(() => { void tick(); }, interval);\n }\n }\n };\n\n void tick();\n\n return {\n stop(): void {\n stopped = true;\n if (timer !== null) {\n clearTimeout(timer);\n timer = null;\n }\n },\n };\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/**\n * Build the NGSI-LD entities query path from `GetEntitiesParams`.\n * Shared by `getEntities()` and `poll()` so both stay in sync as parameters\n * are added (review #1043: query-string duplication).\n */\nfunction buildEntitiesPath(params?: GetEntitiesParams): string {\n if (!params) return '/ngsi-ld/v1/entities';\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 return parts.length > 0 ? '/ngsi-ld/v1/entities?' + parts.join('&') : '/ngsi-ld/v1/entities';\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 // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\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, @typescript-eslint/no-unnecessary-type-assertion */\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, @typescript-eslint/no-unnecessary-type-assertion */\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// ============================================================\n// SDK Client Cache (#1043 Phase A)\n// Mirrors `SDK_CACHE` in src/config/defaults.ts. Update both when changing.\n// ============================================================\n\n/** In-memory cache LRU capacity (entries). */\nexport const SDK_CACHE_MAX_ENTRIES_DEFAULT = 1_000;\n\n/** Default polling interval for `db.poll()` in milliseconds. */\nexport const SDK_POLL_INTERVAL_MS_DEFAULT = 5_000;\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 { SDK_CACHE_MAX_ENTRIES_DEFAULT } from './constants';\n\n/**\n * In-memory client-side cache for the GeonicDB SDK (#991 Phase A).\n *\n * Stores ETag / Last-Modified / response body / response headers per\n * `${method}:${path}` key. The cache layer is opt-out (enabled by default) and\n * driven by the SDK's `request()` method:\n *\n * 1. On a cacheable GET, the SDK looks up the cache and adds `If-None-Match` /\n * `If-Modified-Since` to the outgoing request.\n * 2. If the server returns `304 Not Modified`, the cached body is returned to\n * the caller (transparent to the consumer).\n * 3. On `200 OK`, the cache entry is replaced with the fresh body and ETag.\n * 4. WebSocket entity events do **not** auto-invalidate the cache. Because\n * data endpoints respond with `Cache-Control: private, no-cache`, every\n * cached read already revalidates with the origin via `If-None-Match`,\n * so the server returns `304` if data is unchanged or `200` with the\n * fresh body if it changed. Keeping the cache entries during WebSocket\n * activity preserves the bandwidth-saving `304` path; deleting them\n * forces a full `200` body on the next read with no benefit.\n * 5. Use `clearCache()` for explicit, full invalidation (e.g. on auth change).\n *\n * Eviction is LRU based on `maxEntries`. There is no TTL \u2014 freshness is\n * delegated entirely to the server's RFC 7234 `Cache-Control` directives,\n * which the SDK respects via revalidation (the server returns\n * `private, no-cache` for data endpoints \u2014 `private` blocks shared / CDN\n * caches and `no-cache` forces revalidation from the SDK's private cache,\n * so every cached lookup re-validates with the origin).\n */\n\nexport interface CacheEntry {\n /** ETag captured from the previous response. */\n etag?: string;\n /** Last-Modified captured from the previous response (RFC 1123 HTTP-date). */\n lastModified?: string;\n /**\n * Cached response body. Stored as the parsed JSON value (or string for\n * non-JSON responses) so subsequent 304 hits can hand the same shape back to\n * the caller without re-parsing.\n */\n data: unknown;\n /**\n * Selected response headers worth replaying on a 304 hit (e.g.\n * `NGSILD-Results-Count`, `Fiware-Total-Count`, `Link`). Stored as a plain\n * record because `Headers` instances are not serialisable.\n */\n headers: Record<string, string>;\n /** Cache insertion timestamp (epoch ms). Used for LRU only. */\n cachedAt: number;\n}\n\n/**\n * Minimal LRU cache for SDK responses.\n *\n * The implementation relies on `Map`'s insertion-order property (ES2015+):\n * deleting and re-inserting an entry moves it to the most-recent position, so\n * eviction simply removes the head of the iterator when capacity is exceeded.\n */\nexport class SdkCache {\n private readonly _store = new Map<string, CacheEntry>();\n private readonly _maxEntries: number;\n\n constructor(maxEntries: number = SDK_CACHE_MAX_ENTRIES_DEFAULT) {\n if (!Number.isInteger(maxEntries) || maxEntries <= 0) {\n throw new Error(`SdkCache maxEntries must be a positive integer, got ${String(maxEntries)}`);\n }\n this._maxEntries = maxEntries;\n }\n\n /** Build a stable cache key. Method is upper-cased so casing differences do not produce duplicate entries. */\n static keyFor(method: string, path: string): string {\n return `${method.toUpperCase()}:${path}`;\n }\n\n /** Returns the entry and bumps it to most-recent position, or `undefined`. */\n get(key: string): CacheEntry | undefined {\n const entry = this._store.get(key);\n if (!entry) return undefined;\n // Bump LRU position\n this._store.delete(key);\n this._store.set(key, entry);\n return entry;\n }\n\n /** Insert or replace an entry. Evicts the LRU entry when over capacity. */\n set(key: string, entry: CacheEntry): void {\n if (this._store.has(key)) {\n this._store.delete(key);\n }\n this._store.set(key, entry);\n while (this._store.size > this._maxEntries) {\n const oldest = this._store.keys().next().value;\n if (oldest === undefined) break;\n this._store.delete(oldest);\n }\n }\n\n /** Delete a specific entry. Returns whether anything was removed. */\n delete(key: string): boolean {\n return this._store.delete(key);\n }\n\n /**\n * Delete every entry whose key matches a predicate. Returns the array of\n * removed keys so callers can emit `cacheInvalidated` events.\n */\n deleteWhere(predicate: (key: string, entry: CacheEntry) => boolean): string[] {\n const removed: string[] = [];\n for (const [key, entry] of this._store) {\n if (predicate(key, entry)) {\n this._store.delete(key);\n removed.push(key);\n }\n }\n return removed;\n }\n\n /** Drop everything. */\n clear(): void {\n this._store.clear();\n }\n\n /** Current entry count. Useful for tests / metrics. */\n size(): number {\n return this._store.size;\n }\n}\n\n/**\n * Pull a small set of response headers worth retaining on a 304 replay.\n * Stripping unknown headers keeps memory bounded and avoids leaking transport\n * details (e.g. `set-cookie`) into the SDK consumer.\n */\nconst HEADERS_TO_PERSIST = [\n 'content-type',\n 'etag',\n 'last-modified',\n 'cache-control',\n 'vary',\n 'link',\n 'ngsild-results-count',\n 'fiware-total-count',\n 'x-total-count',\n 'ngsild-next',\n 'fiware-next-token',\n] as const;\n\nexport function snapshotHeaders(headers: Headers): Record<string, string> {\n const out: Record<string, string> = {};\n for (const name of HEADERS_TO_PERSIST) {\n const value = headers.get(name);\n if (value !== null) out[name] = value;\n }\n return out;\n}\n\n/** Whether a request method is cacheable per RFC 7234 \u00A74.2.1 (safe + idempotent + no body changes). */\nexport function isCacheableMethod(method: string): boolean {\n const upper = method.toUpperCase();\n return upper === 'GET' || upper === 'HEAD';\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 { SdkCache, snapshotHeaders, isCacheableMethod } from './cache';\nimport type {\n CacheEvent,\n CredentialsOptions,\n DPoPKeyPair,\n LoginResponse,\n RefreshedCredentials,\n} from './types';\n\ntype CacheEventName = 'cacheHit' | 'cacheMiss' | 'cacheInvalidated';\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 /**\n * SDK-level cache (#991 Phase A). When set, cacheable GET requests are\n * served via ETag/304 with automatic If-None-Match negotiation, and\n * concurrent requests to the same path are deduplicated.\n */\n private _cache: SdkCache | null = null;\n\n /** Emitter for cacheHit / cacheMiss / cacheInvalidated events. */\n private _emitCacheEvent: ((name: CacheEventName, payload: CacheEvent) => void) | null = null;\n\n /** In-flight request map keyed by `${METHOD}:${path}` for request deduplication. */\n private readonly _inFlight = new Map<string, Promise<Response>>();\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 /** Wire an SdkCache instance (called by GeonicDB constructor when caching is enabled). */\n setCache(cache: SdkCache | null): void {\n this._cache = cache;\n }\n\n /** Provide the cache event emitter (forwarded to the GeonicDB EventEmitter). */\n setCacheEventEmitter(\n emitter: ((name: CacheEventName, payload: CacheEvent) => void) | null,\n ): void {\n this._emitCacheEvent = emitter;\n }\n\n /** Expose the cache for invalidation (e.g. WebSocket entity events). */\n getCache(): SdkCache | null {\n return this._cache;\n }\n\n /** Emit a cache event if a listener is wired. */\n emitCacheEvent(name: CacheEventName, payload: CacheEvent): void {\n this._emitCacheEvent?.(name, payload);\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 // #1043 review (Critical): drop cache + dedup state from any previous identity.\n this._invalidateAuthScopedState();\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 // #1043 review (Critical): cache + in-flight dedup is keyed only by\n // METHOD:path, so credentials changes must invalidate them to prevent\n // cross-user response reuse.\n this._invalidateAuthScopedState();\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 this._invalidateAuthScopedState();\n }\n\n /**\n * Drop everything that may have been associated with the previous auth\n * context. Called on `login()` (after token assignment), `setCredentials()`,\n * and `logout()`. Without this, a cached body or in-flight Response from\n * user A could be returned to user B after a credentials swap.\n */\n private _invalidateAuthScopedState(): void {\n this._cache?.clear();\n this._inFlight.clear();\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 * When the SDK cache is enabled and the request is cacheable\n * (GET / HEAD without a body), this method:\n * - Sends `If-None-Match` / `If-Modified-Since` derived from a previously\n * cached entry, if any.\n * - Returns the cached body wrapped in a synthesized `200` Response when\n * the server replies `304 Not Modified`.\n * - Persists fresh `200` responses (with their ETag/Last-Modified) into\n * the cache.\n * - Deduplicates concurrent in-flight requests to the same path.\n */\n async request(\n method: string,\n path: string,\n body?: unknown,\n ): Promise<Response> {\n this._log(method, path);\n\n if (!this._cache || !isCacheableMethod(method) || body !== undefined) {\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 const key = SdkCache.keyFor(method, path);\n\n // Request deduplication: if the same path is already in flight,\n // return the same Response (cloned) so concurrent callers share the result.\n const inFlight = this._inFlight.get(key);\n if (inFlight) {\n return inFlight.then((res) => res.clone());\n }\n\n const promise = this._cachedRequest(method, path, key);\n this._inFlight.set(key, promise);\n try {\n return await promise;\n } finally {\n this._inFlight.delete(key);\n }\n }\n\n private async _cachedRequest(\n method: string,\n path: string,\n key: string,\n ): Promise<Response> {\n const cache = this._cache;\n if (!cache) {\n // Defensive: caller already checked, but TS narrowing prefers an explicit guard.\n const token = await this.ensureToken();\n return this._doAuthenticatedRequest(method, path, undefined, token);\n }\n const cached = cache.get(key);\n const conditional: Record<string, string> = {};\n if (cached?.etag) conditional['If-None-Match'] = cached.etag;\n if (cached?.lastModified) conditional['If-Modified-Since'] = cached.lastModified;\n\n const token = await this.ensureToken();\n const res = await this._doAuthenticatedRequest(method, path, undefined, token, 0, conditional);\n this._log(method, path, '\u2192', res.status);\n\n // 304 Not Modified \u2014 replay the cached body as a synthetic 200.\n // The SDK consumer should be unaware of conditional negotiation.\n //\n // The 304 response itself may carry refreshed validators (ETag /\n // Last-Modified rotation, updated Cache-Control etc.). Merge them into\n // the cached entry so the next request sends the latest If-None-Match.\n if (res.status === 304 && cached) {\n const refreshedHeaders = { ...cached.headers, ...snapshotHeaders(res.headers) };\n const refreshedEtag = res.headers.get('etag') ?? cached.etag;\n const refreshedLastModified = res.headers.get('last-modified') ?? cached.lastModified;\n cache.set(key, {\n ...cached,\n etag: refreshedEtag,\n lastModified: refreshedLastModified,\n headers: refreshedHeaders,\n cachedAt: Date.now(),\n });\n this.emitCacheEvent('cacheHit', { key, path });\n const body = typeof cached.data === 'string' ? cached.data : JSON.stringify(cached.data);\n return new Response(body, { status: 200, headers: refreshedHeaders });\n }\n\n // Persist fresh 200 responses that carry a validator.\n if (res.status === 200) {\n const etag = res.headers.get('etag') ?? undefined;\n const lastModified = res.headers.get('last-modified') ?? undefined;\n if (etag || lastModified) {\n const text = await res.clone().text();\n let data: unknown = text;\n try {\n data = JSON.parse(text);\n } catch {\n // not JSON \u2014 keep the raw text\n }\n cache.set(key, {\n etag,\n lastModified,\n data,\n headers: snapshotHeaders(res.headers),\n cachedAt: Date.now(),\n });\n this.emitCacheEvent('cacheMiss', { key, path });\n }\n }\n\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 extraHeaders: Record<string, string> = {},\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 ...extraHeaders,\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, extraHeaders);\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
|
+
"names": ["token"]
|
|
7
7
|
}
|