{"version":3,"file":"index.es","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {existsSync} from \"node:fs\";\nimport {createConnection as createNetConnection, Socket} from \"node:net\";\nimport {EventEmitter} from \"node:events\";\nimport {Duplex} from \"node:stream\";\nimport {connect as connectTls, TLSSocket} from \"node:tls\";\nimport type {ConnectionOptions as TlsConnectionOptions} from \"node:tls\";\n\nimport type {\n    AbortOperation,\n    AssertOperation,\n    CommentOperation,\n    CommitOperation,\n    DatabaseOperation,\n    DatabaseSchema,\n    DatabaseTableMap,\n    DeleteOperation,\n    InsertOperation,\n    JsonObject,\n    JsonValue,\n    ListDbsResult,\n    LockedNotification,\n    MutateOperation,\n    MonitorCondRequest,\n    MonitorCondSinceResult,\n    MonitorRequest,\n    OperationResult,\n    OperationResults,\n    OvsdbError,\n    OvsdbNotification,\n    OvsdbResponse,\n    OvsdbValue,\n    SelectOperation,\n    StolenNotification,\n    TableUpdates,\n    TableUpdates2,\n    Update2Notification,\n    Update3Notification,\n    UpdateNotification,\n    UpdateOperation,\n    WaitOperation\n} from \"./types\";\n\n/**\n * A socket-compatible stream used by the client transport.\n */\nexport type OvsdbStream = Duplex | Socket | TLSSocket;\n\n/**\n * Supported connection modes for the OVSDB transport.\n */\nexport type OvsdbTransportKind = \"unix\" | \"tcp\" | \"tls\";\n\n/**\n * Resolved Unix socket transport settings.\n */\nexport interface OvsdbUnixConnectionOptions {\n    transport: \"unix\";\n    socketPath: string;\n}\n\n/**\n * Resolved TCP transport settings.\n */\nexport interface OvsdbTcpConnectionOptions {\n    transport: \"tcp\";\n    host: string;\n    port: number;\n}\n\n/**\n * Resolved TLS transport settings.\n */\nexport interface OvsdbTlsTransportOptions {\n    transport: \"tls\";\n    host: string;\n    port: number;\n    tlsOptions: TlsConnectionOptions;\n}\n\n/**\n * Fully resolved transport settings used by the client.\n */\nexport type OvsdbResolvedConnectionOptions =\n    | OvsdbUnixConnectionOptions\n    | OvsdbTcpConnectionOptions\n    | OvsdbTlsTransportOptions;\n\n/**\n * Typed events emitted by {@link OVSDBClient}.\n */\nexport interface OvsdbClientEvents<TDatabase extends DatabaseTableMap = DatabaseTableMap> {\n    connect: [];\n    close: [];\n    notification: [OvsdbNotification<TDatabase>];\n    update: [UpdateNotification<TDatabase>];\n    update2: [Update2Notification<TDatabase>];\n    update3: [Update3Notification<TDatabase>];\n    locked: [LockedNotification];\n    stolen: [StolenNotification];\n    protocolError: [Error, unknown];\n    transportError: [Error];\n}\n\n/**\n * Options for configuring an {@link OVSDBClient}.\n */\nexport interface OvsdbClientOptions {\n    /**\n     * Path to the OVSDB Unix domain socket.\n     *\n     * @defaultValue `\"/var/run/openvswitch/db.sock\"`\n     */\n    socketPath?: string;\n\n    /**\n     * Hostname for TCP or TLS connections.\n     *\n     * When set, the client uses a network socket instead of a Unix socket.\n     */\n    host?: string;\n\n    /**\n     * Port for TCP or TLS connections.\n     *\n     * @defaultValue `6640`\n     */\n    port?: number;\n\n    /**\n     * Enables TLS for network connections.\n     *\n     * @defaultValue `false`\n     */\n    tls?: boolean;\n\n    /**\n     * Extra TLS connection options forwarded to `node:tls`.\n     *\n     * These options are only used when `tls` is enabled.\n     */\n    tlsOptions?: TlsConnectionOptions;\n\n    /**\n     * Request and connection timeout in milliseconds.\n     *\n     * @defaultValue `5000`\n     */\n    timeout?: number;\n\n    /**\n     * Optional stream factory used for testing or custom transports.\n     * When set, the client skips the socket path existence check.\n     */\n    connectionFactory?: (options: OvsdbResolvedConnectionOptions) => OvsdbStream;\n}\n\n/**\n * JSON-RPC transport error returned by the OVSDB server.\n */\nexport class OvsdbRpcError extends Error {\n    /**\n     * The error payload returned by the server.\n     */\n    public readonly response: OvsdbError;\n\n    /**\n     * Creates a new RPC error wrapper.\n     */\n    constructor(response: OvsdbError) {\n        super(response.details ? `${response.error}: ${response.details}` : response.error);\n        this.name = \"OvsdbRpcError\";\n        this.response = response;\n    }\n}\n\n/**\n * Raised when a message does not match the expected JSON-RPC envelope.\n */\nexport class OvsdbProtocolError extends Error {\n    /**\n     * The raw payload that failed validation.\n     */\n    public readonly payload: unknown;\n\n    /**\n     * Creates a new protocol error wrapper.\n     */\n    constructor(message: string, payload: unknown) {\n        super(message);\n        this.name = \"OvsdbProtocolError\";\n        this.payload = payload;\n    }\n}\n\n/**\n * Raised when an OVSDB transaction response contains an operation-level error.\n */\nexport class OvsdbTransactionError<\n    TDatabase extends DatabaseTableMap = DatabaseTableMap\n> extends Error {\n    /**\n     * Zero-based index of the failed operation in the submitted transaction.\n     */\n    public readonly operationIndex: number;\n\n    /**\n     * Operation that produced the error.\n     */\n    public readonly operation: DatabaseOperation<TDatabase>;\n\n    /**\n     * OVSDB error payload returned for the failed operation.\n     */\n    public readonly result: OvsdbError;\n\n    /**\n     * Raw transaction results returned by the server.\n     */\n    public readonly results: Array<OperationResult<TDatabase, DatabaseOperation<TDatabase>> | OvsdbError>;\n\n    /**\n     * Creates a new transaction error wrapper.\n     */\n    constructor(options: {\n        operationIndex: number;\n        operation: DatabaseOperation<TDatabase>;\n        result: OvsdbError;\n        results: Array<OperationResult<TDatabase, DatabaseOperation<TDatabase>> | OvsdbError>;\n    }) {\n        super(`Transaction operation ${options.operationIndex} failed: ${options.result.error}`);\n        this.name = \"OvsdbTransactionError\";\n        this.operationIndex = options.operationIndex;\n        this.operation = options.operation;\n        this.result = options.result;\n        this.results = options.results;\n    }\n}\n\ninterface PendingRequest {\n    resolve: (value: unknown) => void;\n    reject: (reason?: unknown) => void;\n    timeoutId: NodeJS.Timeout;\n}\n\n/**\n * Result payload returned by a staged transaction helper.\n */\nexport interface OvsdbTransactionOutcome<\n    TDatabase extends DatabaseTableMap = DatabaseTableMap,\n    TValue = void\n> {\n    /**\n     * Value returned by the transaction callback.\n     */\n    value: TValue;\n\n    /**\n     * Operations that were submitted to OVSDB.\n     */\n    operations: readonly DatabaseOperation<TDatabase>[];\n\n    /**\n     * Per-operation OVSDB results in submission order.\n     */\n    results: Array<OperationResult<TDatabase, DatabaseOperation<TDatabase>>>;\n}\n\n/**\n * Options for the staged transaction helper.\n */\nexport interface OvsdbTransactionOptions {\n    /**\n     * Appends a trailing `commit` operation when the callback succeeds and the\n     * staged operations do not already include `commit` or `abort`.\n     *\n     * @defaultValue `true`\n     */\n    autoCommit?: boolean;\n\n    /**\n     * Durable flag used by the auto-generated `commit` operation.\n     *\n     * @defaultValue `false`\n     */\n    durable?: boolean;\n}\n\n/**\n * Stages OVSDB operations before sending them as a single `transact` request.\n */\nexport class OvsdbTransaction<TDatabase extends DatabaseTableMap = DatabaseTableMap> {\n    private readonly stagedOperations: DatabaseOperation<TDatabase>[] = [];\n\n    /**\n     * Returns the currently staged operations.\n     */\n    public get operations(): readonly DatabaseOperation<TDatabase>[] {\n        return this.stagedOperations;\n    }\n\n    /**\n     * Adds an operation to the transaction.\n     */\n    public add<TOperation extends DatabaseOperation<TDatabase>>(operation: TOperation): TOperation {\n        this.stagedOperations.push(operation);\n        return operation;\n    }\n\n    /**\n     * Stages an insert operation.\n     */\n    public insert<TOperation extends InsertOperation<TDatabase>>(operation: TOperation): TOperation {\n        return this.add(operation);\n    }\n\n    /**\n     * Stages a select operation.\n     */\n    public select<TOperation extends SelectOperation<TDatabase>>(operation: TOperation): TOperation {\n        return this.add(operation);\n    }\n\n    /**\n     * Stages an update operation.\n     */\n    public update<TOperation extends UpdateOperation<TDatabase>>(operation: TOperation): TOperation {\n        return this.add(operation);\n    }\n\n    /**\n     * Stages a mutate operation.\n     */\n    public mutate<TOperation extends MutateOperation<TDatabase>>(operation: TOperation): TOperation {\n        return this.add(operation);\n    }\n\n    /**\n     * Stages a delete operation.\n     */\n    public delete<TOperation extends DeleteOperation<TDatabase>>(operation: TOperation): TOperation {\n        return this.add(operation);\n    }\n\n    /**\n     * Stages a wait operation.\n     */\n    public wait<TOperation extends WaitOperation<TDatabase>>(operation: TOperation): TOperation {\n        return this.add(operation);\n    }\n\n    /**\n     * Stages a comment operation.\n     */\n    public comment(comment: string): CommentOperation {\n        return this.add({\n            op: \"comment\",\n            comment\n        });\n    }\n\n    /**\n     * Stages an assert operation.\n     */\n    public assert(lock: string): AssertOperation {\n        return this.add({\n            op: \"assert\",\n            lock\n        });\n    }\n\n    /**\n     * Stages a commit operation.\n     */\n    public commit(durable = false): CommitOperation {\n        return this.add({\n            op: \"commit\",\n            durable\n        });\n    }\n\n    /**\n     * Stages an abort operation.\n     */\n    public abort(): AbortOperation {\n        return this.add({\n            op: \"abort\"\n        });\n    }\n}\n\n/**\n * A low-level, event-driven OVSDB client for Unix sockets, TCP, or TLS.\n *\n * The client exposes the RFC 7047 primitives together with common\n * Open vSwitch protocol extensions while keeping the API small and predictable.\n */\nexport class OVSDBClient<\n    TDatabase extends DatabaseTableMap = DatabaseTableMap\n> extends EventEmitter<OvsdbClientEvents<TDatabase>> implements AsyncDisposable {\n    private readonly timeout: number;\n    private readonly connectionOptions: OvsdbResolvedConnectionOptions;\n    private readonly connectionFactory?: (options: OvsdbResolvedConnectionOptions) => OvsdbStream;\n\n    private socket: OvsdbStream | null = null;\n    private requestId = 1;\n    private receiveBuffer = \"\";\n    private pendingRequests = new Map<JsonValue, PendingRequest>();\n    private connected = false;\n    private closeEmitted = false;\n\n    /**\n     * Creates a new OVSDB client instance.\n     */\n    constructor(options: OvsdbClientOptions = {}) {\n        super();\n        this.timeout = options.timeout ?? 5000;\n        this.connectionOptions = resolveConnectionOptions(options);\n        this.connectionFactory = options.connectionFactory;\n    }\n\n    /**\n     * Returns `true` when the underlying socket is currently connected.\n     */\n    public get isConnected(): boolean {\n        return this.connected;\n    }\n\n    /**\n     * Opens the transport connection.\n     *\n     * @returns The connected client instance for chaining.\n     */\n    public async connect(): Promise<this> {\n        if (this.connected) {\n            return this;\n        }\n\n        if (\n            !this.connectionFactory &&\n            this.connectionOptions.transport === \"unix\" &&\n            !existsSync(this.connectionOptions.socketPath)\n        ) {\n            throw new Error(`OVSDB socket not found: ${this.connectionOptions.socketPath}`);\n        }\n\n        const socket = this.connectionFactory\n            ? this.connectionFactory(this.connectionOptions)\n            : createTransport(this.connectionOptions);\n        this.attachSocket(socket);\n        const connectEvent = this.connectionOptions.transport === \"tls\" ? \"secureConnect\" : \"connect\";\n\n        await new Promise<void>((resolve, reject) => {\n            const timeoutId = setTimeout(() => {\n                cleanup();\n                this.disposeTransport(new Error(`Connection timeout after ${this.timeout}ms`));\n                reject(new Error(`Connection timeout after ${this.timeout}ms`));\n            }, this.timeout);\n\n            const onConnect = () => {\n                cleanup();\n                this.connected = true;\n                this.closeEmitted = false;\n                this.emit(\"connect\");\n                resolve();\n            };\n\n            const onError = (error: Error) => {\n                cleanup();\n                reject(error);\n            };\n\n            const cleanup = () => {\n                clearTimeout(timeoutId);\n                socket.off(connectEvent, onConnect);\n                socket.off(\"error\", onError);\n            };\n\n            socket.once(connectEvent, onConnect);\n            socket.once(\"error\", onError);\n        });\n\n        return this;\n    }\n\n    /**\n     * Sends a raw JSON-RPC request and resolves with its `result` payload.\n     *\n     * @param method RPC method name.\n     * @param params RPC parameters.\n     */\n    public async request<TResult>(method: string, params: JsonValue[] = []): Promise<TResult> {\n        this.assertConnected();\n\n        const id = this.requestId++;\n        const payload = {\n            method,\n            params,\n            id\n        };\n\n        return await new Promise<TResult>((resolve, reject) => {\n            const timeoutId = setTimeout(() => {\n                this.pendingRequests.delete(id);\n                reject(new Error(`Request timeout for method: ${method}`));\n            }, this.timeout);\n\n            this.pendingRequests.set(id, {\n                resolve: (value) => resolve(value as TResult),\n                reject,\n                timeoutId\n            });\n\n            this.writeMessage(payload).catch((error) => {\n                clearTimeout(timeoutId);\n                this.pendingRequests.delete(id);\n                reject(error);\n            });\n        });\n    }\n\n    /**\n     * Sends a JSON-RPC notification without waiting for a response.\n     *\n     * @param method RPC method name.\n     * @param params RPC parameters.\n     */\n    public async notify(method: string, params: JsonValue[] = []): Promise<void> {\n        this.assertConnected();\n        await this.writeMessage({method, params});\n    }\n\n    /**\n     * Returns the database names exposed by the connected OVSDB server.\n     */\n    public async listDbs(): Promise<ListDbsResult> {\n        return await this.request<ListDbsResult>(\"list_dbs\", []);\n    }\n\n    /**\n     * Returns the schema definition for a database.\n     *\n     * @param dbName Database name.\n     */\n    public async getSchema(dbName = \"Open_vSwitch\"): Promise<DatabaseSchema> {\n        return await this.request<DatabaseSchema>(\"get_schema\", [dbName]);\n    }\n\n    /**\n     * Executes a single transaction.\n     *\n     * The response preserves operation ordering, so tuple inputs infer tuple outputs.\n     *\n     * @param dbName Database name.\n     * @param operations Transaction operations.\n     */\n    public async transact<TOperations extends readonly DatabaseOperation<TDatabase>[]>(\n        dbName: string,\n        operations: [...TOperations]\n    ): Promise<OperationResults<TDatabase, TOperations>> {\n        return await this.request<OperationResults<TDatabase, TOperations>>(\n            \"transact\",\n            [dbName, ...operations] as JsonValue[]\n        );\n    }\n\n    /**\n     * Stages a transaction in a callback and submits it only if the callback\n     * completes successfully.\n     *\n     * This helper is convenient when you want a scoped, imperative API while\n     * still sending exactly one OVSDB `transact` request.\n     *\n     * @param dbName Database name.\n     * @param callback Callback that stages operations on the transaction object.\n     * @param options Auto-commit behavior for the staged transaction.\n     */\n    public async transaction<TValue>(\n        dbName: string,\n        callback: (transaction: OvsdbTransaction<TDatabase>) => Promise<TValue> | TValue,\n        options: OvsdbTransactionOptions = {}\n    ): Promise<OvsdbTransactionOutcome<TDatabase, TValue>> {\n        const transaction = new OvsdbTransaction<TDatabase>();\n        const value = await callback(transaction);\n\n        const operations = [...transaction.operations];\n        const autoCommit = options.autoCommit ?? true;\n        const hasFinalizer = operations.some((operation) => operation.op === \"commit\" || operation.op === \"abort\");\n        if (autoCommit && !hasFinalizer) {\n            operations.push({\n                op: \"commit\",\n                durable: options.durable ?? false\n            });\n        }\n\n        if (operations.length === 0) {\n            return {\n                value,\n                operations,\n                results: []\n            };\n        }\n\n        const results = await this.request<Array<OperationResult<TDatabase, DatabaseOperation<TDatabase>> | OvsdbError>>(\n            \"transact\",\n            [dbName, ...operations] as JsonValue[]\n        );\n\n        for (const [index, result] of results.entries()) {\n            if (isOvsdbError(result)) {\n                throw new OvsdbTransactionError<TDatabase>({\n                    operationIndex: index,\n                    operation: operations[index] as DatabaseOperation<TDatabase>,\n                    result,\n                    results\n                });\n            }\n        }\n\n        return {\n            value,\n            operations,\n            results: results as Array<OperationResult<TDatabase, DatabaseOperation<TDatabase>>>\n        };\n    }\n\n    /**\n     * Cancels a previously issued request by id.\n     *\n     * @param requestId JSON-RPC request id to cancel.\n     */\n    public async cancel(requestId: JsonValue): Promise<null | JsonObject> {\n        return await this.request<null | JsonObject>(\"cancel\", [requestId]);\n    }\n\n    /**\n     * Starts a standard RFC 7047 monitor.\n     *\n     * @param dbName Database name.\n     * @param monitorId Application-defined monitor id.\n     * @param monitorRequests Per-table monitor definitions.\n     */\n    public async monitor(\n        dbName: string,\n        monitorId: JsonValue,\n        monitorRequests: Record<string, MonitorRequest<TDatabase>>\n    ): Promise<TableUpdates<TDatabase>> {\n        return await this.request<TableUpdates<TDatabase>>(\"monitor\", [\n            dbName,\n            monitorId,\n            monitorRequests as JsonValue\n        ]);\n    }\n\n    /**\n     * Starts an Open vSwitch conditional monitor.\n     *\n     * @param dbName Database name.\n     * @param monitorId Application-defined monitor id.\n     * @param monitorRequests Per-table conditional monitor definitions.\n     */\n    public async monitorCond(\n        dbName: string,\n        monitorId: JsonValue,\n        monitorRequests: Record<string, MonitorCondRequest<TDatabase>>\n    ): Promise<TableUpdates2<TDatabase>> {\n        return await this.request<TableUpdates2<TDatabase>>(\"monitor_cond\", [\n            dbName,\n            monitorId,\n            monitorRequests as JsonValue\n        ]);\n    }\n\n    /**\n     * Starts an Open vSwitch conditional monitor from a known transaction id.\n     *\n     * @param dbName Database name.\n     * @param monitorId Application-defined monitor id.\n     * @param monitorRequests Per-table conditional monitor definitions.\n     * @param lastTransactionId Last seen transaction id, or `null` for a fresh snapshot.\n     */\n    public async monitorCondSince(\n        dbName: string,\n        monitorId: JsonValue,\n        monitorRequests: Record<string, MonitorCondRequest<TDatabase>>,\n        lastTransactionId: string | null = null\n    ): Promise<MonitorCondSinceResult<TDatabase>> {\n        return await this.request<MonitorCondSinceResult<TDatabase>>(\"monitor_cond_since\", [\n            dbName,\n            monitorId,\n            monitorRequests as JsonValue,\n            lastTransactionId\n        ]);\n    }\n\n    /**\n     * Cancels a monitor by its monitor id.\n     *\n     * @param monitorId Monitor id used when the monitor was created.\n     */\n    public async monitorCancel(monitorId: JsonValue): Promise<null | JsonObject> {\n        return await this.request<null | JsonObject>(\"monitor_cancel\", [monitorId]);\n    }\n\n    /**\n     * Acquires a named database lock.\n     *\n     * @param lockId Lock identifier.\n     */\n    public async lock(lockId: string): Promise<null | JsonObject> {\n        return await this.request<null | JsonObject>(\"lock\", [lockId]);\n    }\n\n    /**\n     * Forces ownership of a named database lock.\n     *\n     * @param lockId Lock identifier.\n     */\n    public async steal(lockId: string): Promise<null | JsonObject> {\n        return await this.request<null | JsonObject>(\"steal\", [lockId]);\n    }\n\n    /**\n     * Releases a previously acquired named database lock.\n     *\n     * @param lockId Lock identifier.\n     */\n    public async unlock(lockId: string): Promise<null | JsonObject> {\n        return await this.request<null | JsonObject>(\"unlock\", [lockId]);\n    }\n\n    /**\n     * Sends an echo request to validate transport liveness.\n     *\n     * @param payload Values to be echoed back by the server.\n     */\n    public async echo<TPayload extends OvsdbValue[]>(...payload: TPayload): Promise<TPayload> {\n        return await this.request<TPayload>(\"echo\", payload as JsonValue[]);\n    }\n\n    /**\n     * Enables or disables Open vSwitch database change awareness.\n     *\n     * @param enabled Whether the server should report change awareness metadata.\n     */\n    public async setDbChangeAware(enabled = true): Promise<boolean | null> {\n        return await this.request<boolean | null>(\"set_db_change_aware\", [enabled]);\n    }\n\n    /**\n     * Closes the connection and rejects all pending requests.\n     */\n    public async close(): Promise<void> {\n        this.disposeTransport();\n    }\n\n    /**\n     * Implements `AsyncDisposable`.\n     */\n    public async [Symbol.asyncDispose](): Promise<void> {\n        await this.close();\n    }\n\n    private attachSocket(socket: OvsdbStream): void {\n        this.socket = socket;\n        this.receiveBuffer = \"\";\n\n        socket.on(\"data\", this.handleData);\n        socket.on(\"error\", this.handleSocketError);\n        socket.on(\"close\", this.handleSocketClose);\n    }\n\n    private readonly handleData = (chunk: Buffer | string): void => {\n        this.receiveBuffer += typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\");\n\n        let frame = extractJsonFrame(this.receiveBuffer);\n        while (frame) {\n            this.receiveBuffer = frame.rest;\n            this.parseFrame(frame.frame);\n            frame = extractJsonFrame(this.receiveBuffer);\n        }\n\n        const trimmed = this.receiveBuffer.trimStart();\n        if (trimmed && trimmed[0] !== \"{\" && trimmed[0] !== \"[\") {\n            this.emitProtocolError(\"Received non-JSON data on the transport\", this.receiveBuffer);\n            this.receiveBuffer = \"\";\n        }\n    };\n\n    private readonly handleSocketError = (error: Error): void => {\n        this.emit(\"transportError\", error);\n        this.disposeTransport(error);\n    };\n\n    private readonly handleSocketClose = (): void => {\n        this.disposeTransport();\n    };\n\n    private parseFrame(frame: string): void {\n        try {\n            const payload = JSON.parse(frame) as unknown;\n            this.handleMessage(payload);\n        } catch (error) {\n            const protocolError = new OvsdbProtocolError(\"Failed to parse JSON message\", frame);\n            this.emit(\"protocolError\", protocolError, frame);\n            if (error instanceof Error) {\n                void error;\n            }\n        }\n    }\n\n    private handleMessage(payload: unknown): void {\n        if (!payload || typeof payload !== \"object\") {\n            this.emitProtocolError(\"Expected a JSON object message\", payload);\n            return;\n        }\n\n        if (\"method\" in payload && typeof payload.method === \"string\") {\n            const message = payload as {method: string; params?: JsonValue[]; id?: JsonValue | null};\n\n            if (message.id !== undefined && message.id !== null) {\n                void this.handleIncomingRequest(message.method, message.params ?? [], message.id);\n                return;\n            }\n\n            this.handleNotification(payload as OvsdbNotification<TDatabase>);\n            return;\n        }\n\n        if (\"id\" in payload) {\n            this.handleResponse(payload as OvsdbResponse<unknown>);\n            return;\n        }\n\n        this.emitProtocolError(\"Received message without method or id\", payload);\n    }\n\n    private handleResponse(response: OvsdbResponse<unknown>): void {\n        const pendingRequest = this.pendingRequests.get(response.id);\n        if (!pendingRequest) {\n            this.emitProtocolError(\"Received response for an unknown request id\", response);\n            return;\n        }\n\n        this.pendingRequests.delete(response.id);\n        clearTimeout(pendingRequest.timeoutId);\n\n        if (response.error) {\n            pendingRequest.reject(new OvsdbRpcError(response.error));\n            return;\n        }\n\n        pendingRequest.resolve(response.result);\n    }\n\n    private async handleIncomingRequest(method: string, params: JsonValue[], id: JsonValue): Promise<void> {\n        if (method === \"echo\") {\n            await this.writeMessage({\n                id,\n                result: params,\n                error: null\n            });\n            return;\n        }\n\n        await this.writeMessage({\n            id,\n            result: null,\n            error: {\n                error: \"not supported\",\n                details: `Unsupported server request: ${method}`\n            }\n        });\n    }\n\n    private handleNotification(notification: OvsdbNotification<TDatabase>): void {\n        this.emit(\"notification\", notification);\n\n        switch (notification.method) {\n            case \"update\":\n                this.emit(\"update\", notification);\n                break;\n            case \"update2\":\n                this.emit(\"update2\", notification);\n                break;\n            case \"update3\":\n                this.emit(\"update3\", notification);\n                break;\n            case \"locked\":\n                this.emit(\"locked\", notification);\n                break;\n            case \"stolen\":\n                this.emit(\"stolen\", notification);\n                break;\n            default:\n                this.emitProtocolError(\"Received an unknown notification method\", notification);\n                break;\n        }\n    }\n\n    private emitProtocolError(message: string, payload: unknown): void {\n        const error = new OvsdbProtocolError(message, payload);\n        this.emit(\"protocolError\", error, payload);\n    }\n\n    private async writeMessage(payload: JsonObject): Promise<void> {\n        this.assertConnected();\n\n        await new Promise<void>((resolve, reject) => {\n            this.socket?.write(`${JSON.stringify(payload)}\\n`, (error) => {\n                if (error) {\n                    reject(error);\n                    return;\n                }\n                resolve();\n            });\n        });\n    }\n\n    private assertConnected(): void {\n        if (!this.connected || !this.socket) {\n            throw new Error(\"Not connected to OVSDB\");\n        }\n    }\n\n    private disposeTransport(reason?: Error): void {\n        const socket = this.socket;\n        this.socket = null;\n        this.connected = false;\n        this.receiveBuffer = \"\";\n\n        if (socket) {\n            socket.off(\"data\", this.handleData);\n            socket.off(\"error\", this.handleSocketError);\n            socket.off(\"close\", this.handleSocketClose);\n            if (!socket.destroyed) {\n                socket.destroy();\n            }\n        }\n\n        const closeError = reason ?? new Error(\"Connection closed\");\n        for (const pendingRequest of this.pendingRequests.values()) {\n            clearTimeout(pendingRequest.timeoutId);\n            pendingRequest.reject(closeError);\n        }\n        this.pendingRequests.clear();\n\n        if (!this.closeEmitted) {\n            this.closeEmitted = true;\n            this.emit(\"close\");\n        }\n    }\n}\n\nexport * from \"./types\";\n\n/**\n * Resolves the user-supplied transport options into an explicit connection mode.\n */\nexport function resolveConnectionOptions(options: OvsdbClientOptions = {}): OvsdbResolvedConnectionOptions {\n    if (options.host) {\n        const port = options.port ?? 6640;\n        if (options.tls) {\n            return {\n                transport: \"tls\",\n                host: options.host,\n                port,\n                tlsOptions: {\n                    host: options.host,\n                    port,\n                    ...options.tlsOptions\n                }\n            };\n        }\n\n        return {\n            transport: \"tcp\",\n            host: options.host,\n            port\n        };\n    }\n\n    return {\n        transport: \"unix\",\n        socketPath: options.socketPath ?? \"/var/run/openvswitch/db.sock\"\n    };\n}\n\nfunction createTransport(options: OvsdbResolvedConnectionOptions): OvsdbStream {\n    switch (options.transport) {\n        case \"unix\":\n            return createNetConnection(options.socketPath);\n        case \"tcp\":\n            return createNetConnection(options.port, options.host);\n        case \"tls\":\n            return connectTls(options.tlsOptions);\n    }\n}\n\nfunction isOvsdbError(value: unknown): value is OvsdbError {\n    return typeof value === \"object\" && value !== null && \"error\" in value && typeof value.error === \"string\";\n}\n\nfunction extractJsonFrame(buffer: string): {frame: string; rest: string} | null {\n    let startIndex = 0;\n    while (startIndex < buffer.length && /\\s/u.test(buffer[startIndex])) {\n        startIndex += 1;\n    }\n\n    if (startIndex >= buffer.length) {\n        return null;\n    }\n\n    const opening = buffer[startIndex];\n    const closing = opening === \"{\" ? \"}\" : opening === \"[\" ? \"]\" : null;\n    if (!closing) {\n        return null;\n    }\n\n    let depth = 0;\n    let inString = false;\n    let escaping = false;\n\n    for (let index = startIndex; index < buffer.length; index += 1) {\n        const char = buffer[index];\n\n        if (inString) {\n            if (escaping) {\n                escaping = false;\n                continue;\n            }\n\n            if (char === \"\\\\\") {\n                escaping = true;\n                continue;\n            }\n\n            if (char === \"\\\"\") {\n                inString = false;\n            }\n            continue;\n        }\n\n        if (char === \"\\\"\") {\n            inString = true;\n            continue;\n        }\n\n        if (char === \"{\" || char === \"[\") {\n            depth += 1;\n            continue;\n        }\n\n        if (char === \"}\" || char === \"]\") {\n            depth -= 1;\n            if (depth === 0) {\n                return {\n                    frame: buffer.slice(startIndex, index + 1),\n                    rest: buffer.slice(index + 1)\n                };\n            }\n        }\n    }\n\n    return null;\n}\n"],"mappings":"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"}