@sourceregistry/node-ovsdb 1.0.1 → 1.0.3

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.
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,47 +1,63 @@
1
1
  {
2
2
  "name": "@sourceregistry/node-ovsdb",
3
- "version": "1.0.1",
4
- "description": "Open vSwitch Database Management Protocol typescript client",
3
+ "version": "1.0.3",
4
+ "description": "TypeScript OVSDB client for Node.js",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.es.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
10
  "import": "./dist/index.es.js",
11
+ "types": "./dist/index.d.ts",
11
12
  "require": "./dist/index.cjs"
12
13
  }
13
14
  },
15
+ "bin": {
16
+ "ovsdb-generate": "./bin/ovsdb-generate.cjs"
17
+ },
14
18
  "files": [
15
- "dist"
19
+ "bin",
20
+ "dist",
21
+ "dist-cli"
16
22
  ],
17
23
  "scripts": {
18
24
  "dev": "vite",
19
- "build": "tsc && vite build",
25
+ "build": "tsc && vite build && tsc -p tsconfig.cli.json",
20
26
  "preview": "vite preview",
21
- "test": "vitest"
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "test:integration": "OVSDB_INTEGRATION=1 vitest run tests/integration/ovsdb.integration.test.ts",
30
+ "test:ui": "vitest --ui",
31
+ "test:coverage": "vitest run --coverage",
32
+ "docs:build": "typedoc src/index.ts --out generated/docs --name \"node-ovsdb\" --tsconfig tsconfig.json --readme README.md --excludePrivate --excludeProtected"
22
33
  },
23
34
  "repository": {
24
35
  "type": "git",
25
36
  "url": "git+https://github.com/SourceRegistry/node-ovsdb.git"
26
37
  },
27
38
  "devDependencies": {
28
- "@types/node": "^24.3.0",
29
- "typescript": "^5.9.2",
30
- "vite": "^7.1.3",
39
+ "@types/node": "^25.3.3",
40
+ "@vitest/coverage-v8": "^4.0.18",
41
+ "@vitest/ui": "^4.0.18",
42
+ "typescript": "^5.9.3",
43
+ "vite": "^7.3.1",
31
44
  "vite-plugin-dts": "^4.5.4",
32
- "vitest": "^3.2.4",
45
+ "vitest": "^4.0.18",
46
+ "typedoc": "^0.28.17",
33
47
  "@semantic-release/commit-analyzer": "^13.0.1",
34
- "@semantic-release/release-notes-generator": "^14.0.3",
48
+ "@semantic-release/release-notes-generator": "^14.1.0",
35
49
  "@semantic-release/changelog": "^6.0.3",
36
- "@semantic-release/npm": "^12.0.2",
50
+ "@semantic-release/npm": "^13.1.5",
37
51
  "@semantic-release/git": "^10.0.1"
38
52
  },
39
53
  "keywords": [
40
54
  "networking",
41
55
  "ovs",
42
- "Open vSwitch",
56
+ "openvswitch",
57
+ "ovsdb",
43
58
  "RFC7047",
44
- "ISSN2070-1721 "
59
+ "unix-socket",
60
+ "typescript"
45
61
  ],
46
62
  "author": "A.P.A. Slaa (a.p.a.slaa@projectsource.nl)",
47
63
  "license": "Apache-2.0",
@@ -52,6 +68,9 @@
52
68
  "publishConfig": {
53
69
  "access": "public"
54
70
  },
71
+ "engines": {
72
+ "node": ">=18.18"
73
+ },
55
74
  "release": {
56
75
  "branches": [
57
76
  "main"
package/dist/index.cjs.js DELETED
@@ -1,4 +0,0 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("net"),u=require("fs");class l{constructor(e={}){this.socket=null,this.requestId=1,this.pendingRequests=new Map,this.isConnected=!1,this.socketPath=e.socketPath||"/var/run/openvswitch/db.sock",this.timeout=e.timeout||5e3}connect(){return new Promise((e,r)=>{if(this.isConnected){e(this);return}if(!u.existsSync(this.socketPath)){r(new Error(`OVSDB socket not found: ${this.socketPath}`));return}this.socket=a.createConnection(this.socketPath);const t=setTimeout(()=>{this._cleanup(),r(new Error(`Connection timeout after ${this.timeout}ms`))},this.timeout);this.socket.on("connect",()=>{clearTimeout(t),this.isConnected=!0,e(this)}),this.socket.on("error",o=>{clearTimeout(t),this._cleanup(),r(o)}),this.socket.on("close",()=>{this._cleanup()}),this.socket.on("data",o=>{this._handleData(o)})})}request(e,r){return new Promise((t,o)=>{if(!this.isConnected){o(new Error("Not connected to OVSDB"));return}const s=this.requestId++,c=JSON.stringify({method:e,params:r,id:s})+`
2
- `,n=setTimeout(()=>{this.pendingRequests.delete(s),o(new Error(`Request timeout for method: ${e}`))},this.timeout);this.pendingRequests.set(s,{resolve:t,reject:o,timeoutId:n}),this.socket.write(c,i=>{i&&(clearTimeout(n),this.pendingRequests.delete(s),o(i))})})}async listDbs(){const e=await this.request("list_dbs",[]);if("error"in e&&e.error!==null)throw new Error(`RPC Error: ${e.error}`);const r=e.result;if("error"in r)throw new Error(`OVSDB Error: ${r.error}`);return r}async getSchema(e="Open_vSwitch"){const r=await this.request("get_schema",[e]);if("error"in r&&r.error!==null)throw new Error(`RPC Error: ${r.error}`);const t=r.result;if("error"in t)throw new Error(`OVSDB Error: ${t.error}`);return t}async transact(e,r){const t=await this.request("transact",[e,...r]);if("error"in t&&t.error!==null)throw new Error(`RPC Error: ${t.error}`);return t.result}async monitor(e,r,t){const o=await this.request("monitor",[e,r,t]);if("error"in o&&o.error!==null)throw new Error(`RPC Error: ${o.error}`);const s=o.result;if("error"in s)throw new Error(`OVSDB Error: ${s.error}`);return s}async monitorCancel(e){const r=await this.request("monitor_cancel",[e]);if("error"in r&&r.error!==null)throw new Error(`RPC Error: ${r.error}`);const t=r.result;if("error"in t)throw new Error(`OVSDB Error: ${t.error}`);return t}async echo(e="ping"){const r=await this.request("echo",Array.isArray(e)?e:[e]);if("error"in r&&r.error!==null)throw new Error(`RPC Error: ${r.error}`);const t=r.result;if("error"in t)throw new Error(`OVSDB Error: ${t.error}`);return t}async close(){await this[Symbol.asyncDispose]()}async[Symbol.asyncDispose](){if(this.isConnected){const e=new Promise(r=>{if(this.socket){if(this.socket.destroyed||this.socket.readyState==="closed"){r();return}this.socket.once("close",()=>{r()})}else r()});this._cleanup(),await e}}_cleanup(){this.isConnected=!1,this.socket&&(this.socket.destroy(),this.socket=null),this.pendingRequests.forEach(({reject:e,timeoutId:r})=>{clearTimeout(r),e(new Error("Connection closed"))}),this.pendingRequests.clear()}_handleData(e){e.toString().trim().split(`
3
- `).forEach(t=>{if(t)try{const o=JSON.parse(t);this._handleResponse(o)}catch(o){console.error("Failed to parse JSON:",o)}})}_handleResponse(e){if(typeof e!="object"||e===null||!("id"in e)){console.error("Invalid response format:",e);return}const r=e.id,t=this.pendingRequests.get(r);if(!t){this._handleNotification(e);return}this.pendingRequests.delete(r),clearTimeout(t.timeoutId),"error"in e&&e.error!==null?t.reject(new Error(`RPC Error: ${e.error}`)):t.resolve(e)}_handleNotification(e){if(typeof e!="object"||e===null||!("method"in e)){console.error("Invalid notification format:",e);return}const r=e.method;switch(r){case"update":console.log("Received update notification:",e.params[0]);break;case"locked":console.log("Received locked notification:",e.params[0]);break;case"stolen":console.log("Received stolen notification:",e.params[0]);break;default:console.log("Received notification:",r)}}}exports.OVSDBClient=l;
4
- //# sourceMappingURL=index.cjs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/index.ts"],"sourcesContent":["import {createConnection, Socket} from \"net\";\nimport {existsSync} from \"fs\";\n\nimport {\n DatabaseOperation,\n DatabaseSchema, EchoResponse,\n GetSchemaResponse,\n JsonValue,\n ListDbsResponse, LockedNotification, MonitorCancelResponse, MonitorConfig, MonitorResponse, OvsdbResponse,\n OvsdbResult, StolenNotification, TableUpdate,\n TransactResponse, UpdateNotification\n} from \"./types\";\n\n/**\n * Options for configuring the OVSDBClient.\n */\nexport interface OvsdbClientOptions {\n socketPath?: string;\n timeout?: number;\n}\n\n/**\n * A lightweight, typesafe client for interacting with the OVSDB over a Unix socket.\n * Implements the AsyncDisposable interface for resource management.\n * No extra functionality should be added to this client than only interact with the low-level database functions of ovs\n */\nexport class OVSDBClient implements AsyncDisposable {\n private readonly socketPath: string;\n private readonly timeout: number;\n private socket: Socket | null = null;\n private requestId = 1;\n private pendingRequests = new Map<number, {\n resolve: (value: any) => void;\n reject: (reason?: any) => void;\n timeoutId: NodeJS.Timeout;\n }>();\n private isConnected = false;\n\n /**\n * Creates a new OVSDBClient instance.\n * @param options - Configuration options for the client.\n */\n constructor(options: OvsdbClientOptions = {}) {\n this.socketPath = options.socketPath || '/var/run/openvswitch/db.sock';\n this.timeout = options.timeout || 5000;\n }\n\n /**\n * Connects to the OVSDB Unix socket.\n * @returns A promise that resolves when connected.\n * @throws An error if the socket file does not exist or the connection fails.\n */\n public connect(): Promise<this> {\n return new Promise((resolve, reject) => {\n if (this.isConnected) {\n resolve(this);\n return;\n }\n\n if (!existsSync(this.socketPath)) {\n reject(new Error(`OVSDB socket not found: ${this.socketPath}`));\n return;\n }\n\n this.socket = createConnection(this.socketPath);\n\n const timeoutId = setTimeout(() => {\n this._cleanup();\n reject(new Error(`Connection timeout after ${this.timeout}ms`));\n }, this.timeout);\n\n this.socket.on('connect', () => {\n clearTimeout(timeoutId);\n this.isConnected = true;\n resolve(this);\n });\n\n this.socket.on('error', (err) => {\n clearTimeout(timeoutId);\n this._cleanup();\n reject(err);\n });\n\n this.socket.on('close', () => {\n this._cleanup();\n });\n\n this.socket.on('data', (data) => {\n this._handleData(data);\n });\n });\n }\n\n /**\n * Sends a JSON-RPC request to the OVSDB server.\n * @param method - The RPC method name.\n * @param params - The parameters for the RPC method.\n * @returns A promise that resolves with the result.\n * @throws An error if not connected, if the request times out, or if there is a network error.\n */\n public request<T>(method: string, params: JsonValue[]): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.isConnected) {\n reject(new Error('Not connected to OVSDB'));\n return;\n }\n\n const id = this.requestId++;\n const request = JSON.stringify({\n method,\n params,\n id\n }) + '\\n';\n\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, {resolve, reject, timeoutId});\n\n this.socket!.write(request, (err) => {\n if (err) {\n clearTimeout(timeoutId);\n this.pendingRequests.delete(id);\n reject(err);\n }\n });\n });\n }\n\n // --- Core OVSDB RPC Methods (Fixed to handle the response structure) ---\n\n public async listDbs(): Promise<string[]> {\n const response = await this.request<ListDbsResponse>('list_dbs', []);\n // Check if the response is an error object\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n const result = response.result;\n // Check if the OvsdbResult itself is an error\n if ('error' in result) {\n throw new Error(`OVSDB Error: ${result.error}`);\n }\n return result;\n }\n\n public async getSchema(dbName: string = 'Open_vSwitch'): Promise<DatabaseSchema> {\n const response = await this.request<GetSchemaResponse>('get_schema', [dbName]);\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n const result = response.result;\n if ('error' in result) {\n throw new Error(`OVSDB Error: ${result.error}`);\n }\n return result;\n }\n\n public async transact(dbName: string, operations: DatabaseOperation[]): Promise<Array<OvsdbResult<unknown>>> {\n const response = await this.request<TransactResponse>('transact', [dbName, ...operations]);\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n return response.result as Array<OvsdbResult<unknown>>;\n // Note: The result here is already an array of OvsdbResult<unknown>.\n // The caller is responsible for checking each element for errors.\n }\n\n public async monitor(dbName: string, monitorId: JsonValue, monitorRequests: Record<string, MonitorConfig[]>): Promise<Record<string, TableUpdate>> {\n const response = await this.request<MonitorResponse>('monitor', [dbName, monitorId, monitorRequests as JsonValue]);\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n const result = response.result;\n if ('error' in result) {\n throw new Error(`OVSDB Error: ${result.error}`);\n }\n return result;\n }\n\n public async monitorCancel(monitorId: JsonValue): Promise<Record<string, never>> {\n const response = await this.request<MonitorCancelResponse>('monitor_cancel', [monitorId]);\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n const result = response.result;\n if ('error' in result) {\n throw new Error(`OVSDB Error: ${result.error}`);\n }\n return result;\n }\n\n public async echo(payload: JsonValue = 'ping'): Promise<JsonValue[]> {\n const response = await this.request<EchoResponse>('echo', Array.isArray(payload) ? payload : [payload]);\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n const result = response.result;\n if ('error' in result) {\n throw new Error(`OVSDB Error: ${result.error}`);\n }\n return result;\n }\n\n /**\n * Closes the connection to the OVSDB server.\n * @returns A promise that resolves when the connection is closed.\n */\n public async close(): Promise<void> {\n await this[Symbol.asyncDispose]();\n }\n\n /**\n * Implements the AsyncDisposable interface for use with 'using' statements.\n * This method is called automatically when exiting a 'using' block.\n * @returns A promise that resolves when cleanup is complete.\n */\n public async [Symbol.asyncDispose](): Promise<void> {\n if (this.isConnected) {\n const closePromise = new Promise<void>((resolve) => {\n if (this.socket) {\n if (this.socket.destroyed || this.socket.readyState === 'closed') {\n resolve();\n return;\n }\n this.socket.once('close', () => {\n resolve();\n });\n } else {\n resolve();\n }\n });\n\n this._cleanup();\n await closePromise;\n }\n }\n\n /**\n * Cleans up the connection and pending requests.\n * @private\n */\n private _cleanup(): void {\n this.isConnected = false;\n if (this.socket) {\n this.socket.destroy();\n this.socket = null;\n }\n this.pendingRequests.forEach(({reject, timeoutId}) => {\n clearTimeout(timeoutId);\n reject(new Error('Connection closed'));\n });\n this.pendingRequests.clear();\n }\n\n /**\n * Handles incoming data from the socket.\n * @private\n * @param data - The raw data received.\n */\n private _handleData(data: Buffer): void {\n const messages = data.toString().trim().split('\\n');\n messages.forEach(message => {\n if (!message) return;\n try {\n const response = JSON.parse(message);\n this._handleResponse(response);\n } catch (err) {\n console.error('Failed to parse JSON:', err);\n }\n });\n }\n\n /**\n * Handles a parsed JSON-RPC response.\n * @private\n * @param response - The JSON-RPC response object.\n */\n private _handleResponse(response: JsonValue): void {\n if (typeof response !== 'object' || response === null || !('id' in response)) {\n console.error('Invalid response format:', response);\n return;\n }\n\n const id = response.id as number;\n const request = this.pendingRequests.get(id);\n\n if (!request) {\n // This is a notification (e.g., \"update\", \"locked\", \"stolen\")\n this._handleNotification(response);\n return;\n }\n\n this.pendingRequests.delete(id);\n clearTimeout(request.timeoutId);\n\n if ('error' in response && response.error !== null) {\n request.reject(new Error(`RPC Error: ${response.error}`));\n } else {\n request.resolve((response as unknown as OvsdbResponse));\n }\n }\n\n /**\n * Handles JSON-RPC notifications (e.g., \"update\", \"locked\", \"stolen\").\n * This can be overridden by subclasses or event listeners.\n * @private\n * @param notification - The notification object.\n */\n private _handleNotification(notification: JsonValue): void {\n if (typeof notification !== 'object' || notification === null || !('method' in notification)) {\n console.error('Invalid notification format:', notification);\n return;\n }\n\n const method = (notification as { method: string }).method;\n\n switch (method) {\n case 'update':\n console.log('Received update notification:', (notification as UpdateNotification).params[0]);\n break;\n case 'locked':\n console.log('Received locked notification:', (notification as LockedNotification).params[0]);\n break;\n case 'stolen':\n console.log('Received stolen notification:', (notification as StolenNotification).params[0]);\n break;\n default:\n console.log('Received notification:', method);\n }\n }\n}\n\nexport * from \"./types\"\n"],"names":["OVSDBClient","options","resolve","reject","existsSync","createConnection","timeoutId","err","data","method","params","id","request","response","result","dbName","operations","monitorId","monitorRequests","payload","closePromise","message","notification"],"mappings":"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"}
package/dist/index.es.js DELETED
@@ -1,221 +0,0 @@
1
- import { createConnection as a } from "net";
2
- import { existsSync as h } from "fs";
3
- class m {
4
- /**
5
- * Creates a new OVSDBClient instance.
6
- * @param options - Configuration options for the client.
7
- */
8
- constructor(r = {}) {
9
- this.socket = null, this.requestId = 1, this.pendingRequests = /* @__PURE__ */ new Map(), this.isConnected = !1, this.socketPath = r.socketPath || "/var/run/openvswitch/db.sock", this.timeout = r.timeout || 5e3;
10
- }
11
- /**
12
- * Connects to the OVSDB Unix socket.
13
- * @returns A promise that resolves when connected.
14
- * @throws An error if the socket file does not exist or the connection fails.
15
- */
16
- connect() {
17
- return new Promise((r, e) => {
18
- if (this.isConnected) {
19
- r(this);
20
- return;
21
- }
22
- if (!h(this.socketPath)) {
23
- e(new Error(`OVSDB socket not found: ${this.socketPath}`));
24
- return;
25
- }
26
- this.socket = a(this.socketPath);
27
- const t = setTimeout(() => {
28
- this._cleanup(), e(new Error(`Connection timeout after ${this.timeout}ms`));
29
- }, this.timeout);
30
- this.socket.on("connect", () => {
31
- clearTimeout(t), this.isConnected = !0, r(this);
32
- }), this.socket.on("error", (o) => {
33
- clearTimeout(t), this._cleanup(), e(o);
34
- }), this.socket.on("close", () => {
35
- this._cleanup();
36
- }), this.socket.on("data", (o) => {
37
- this._handleData(o);
38
- });
39
- });
40
- }
41
- /**
42
- * Sends a JSON-RPC request to the OVSDB server.
43
- * @param method - The RPC method name.
44
- * @param params - The parameters for the RPC method.
45
- * @returns A promise that resolves with the result.
46
- * @throws An error if not connected, if the request times out, or if there is a network error.
47
- */
48
- request(r, e) {
49
- return new Promise((t, o) => {
50
- if (!this.isConnected) {
51
- o(new Error("Not connected to OVSDB"));
52
- return;
53
- }
54
- const s = this.requestId++, c = JSON.stringify({
55
- method: r,
56
- params: e,
57
- id: s
58
- }) + `
59
- `, n = setTimeout(() => {
60
- this.pendingRequests.delete(s), o(new Error(`Request timeout for method: ${r}`));
61
- }, this.timeout);
62
- this.pendingRequests.set(s, { resolve: t, reject: o, timeoutId: n }), this.socket.write(c, (i) => {
63
- i && (clearTimeout(n), this.pendingRequests.delete(s), o(i));
64
- });
65
- });
66
- }
67
- // --- Core OVSDB RPC Methods (Fixed to handle the response structure) ---
68
- async listDbs() {
69
- const r = await this.request("list_dbs", []);
70
- if ("error" in r && r.error !== null)
71
- throw new Error(`RPC Error: ${r.error}`);
72
- const e = r.result;
73
- if ("error" in e)
74
- throw new Error(`OVSDB Error: ${e.error}`);
75
- return e;
76
- }
77
- async getSchema(r = "Open_vSwitch") {
78
- const e = await this.request("get_schema", [r]);
79
- if ("error" in e && e.error !== null)
80
- throw new Error(`RPC Error: ${e.error}`);
81
- const t = e.result;
82
- if ("error" in t)
83
- throw new Error(`OVSDB Error: ${t.error}`);
84
- return t;
85
- }
86
- async transact(r, e) {
87
- const t = await this.request("transact", [r, ...e]);
88
- if ("error" in t && t.error !== null)
89
- throw new Error(`RPC Error: ${t.error}`);
90
- return t.result;
91
- }
92
- async monitor(r, e, t) {
93
- const o = await this.request("monitor", [r, e, t]);
94
- if ("error" in o && o.error !== null)
95
- throw new Error(`RPC Error: ${o.error}`);
96
- const s = o.result;
97
- if ("error" in s)
98
- throw new Error(`OVSDB Error: ${s.error}`);
99
- return s;
100
- }
101
- async monitorCancel(r) {
102
- const e = await this.request("monitor_cancel", [r]);
103
- if ("error" in e && e.error !== null)
104
- throw new Error(`RPC Error: ${e.error}`);
105
- const t = e.result;
106
- if ("error" in t)
107
- throw new Error(`OVSDB Error: ${t.error}`);
108
- return t;
109
- }
110
- async echo(r = "ping") {
111
- const e = await this.request("echo", Array.isArray(r) ? r : [r]);
112
- if ("error" in e && e.error !== null)
113
- throw new Error(`RPC Error: ${e.error}`);
114
- const t = e.result;
115
- if ("error" in t)
116
- throw new Error(`OVSDB Error: ${t.error}`);
117
- return t;
118
- }
119
- /**
120
- * Closes the connection to the OVSDB server.
121
- * @returns A promise that resolves when the connection is closed.
122
- */
123
- async close() {
124
- await this[Symbol.asyncDispose]();
125
- }
126
- /**
127
- * Implements the AsyncDisposable interface for use with 'using' statements.
128
- * This method is called automatically when exiting a 'using' block.
129
- * @returns A promise that resolves when cleanup is complete.
130
- */
131
- async [Symbol.asyncDispose]() {
132
- if (this.isConnected) {
133
- const r = new Promise((e) => {
134
- if (this.socket) {
135
- if (this.socket.destroyed || this.socket.readyState === "closed") {
136
- e();
137
- return;
138
- }
139
- this.socket.once("close", () => {
140
- e();
141
- });
142
- } else
143
- e();
144
- });
145
- this._cleanup(), await r;
146
- }
147
- }
148
- /**
149
- * Cleans up the connection and pending requests.
150
- * @private
151
- */
152
- _cleanup() {
153
- this.isConnected = !1, this.socket && (this.socket.destroy(), this.socket = null), this.pendingRequests.forEach(({ reject: r, timeoutId: e }) => {
154
- clearTimeout(e), r(new Error("Connection closed"));
155
- }), this.pendingRequests.clear();
156
- }
157
- /**
158
- * Handles incoming data from the socket.
159
- * @private
160
- * @param data - The raw data received.
161
- */
162
- _handleData(r) {
163
- r.toString().trim().split(`
164
- `).forEach((t) => {
165
- if (t)
166
- try {
167
- const o = JSON.parse(t);
168
- this._handleResponse(o);
169
- } catch (o) {
170
- console.error("Failed to parse JSON:", o);
171
- }
172
- });
173
- }
174
- /**
175
- * Handles a parsed JSON-RPC response.
176
- * @private
177
- * @param response - The JSON-RPC response object.
178
- */
179
- _handleResponse(r) {
180
- if (typeof r != "object" || r === null || !("id" in r)) {
181
- console.error("Invalid response format:", r);
182
- return;
183
- }
184
- const e = r.id, t = this.pendingRequests.get(e);
185
- if (!t) {
186
- this._handleNotification(r);
187
- return;
188
- }
189
- this.pendingRequests.delete(e), clearTimeout(t.timeoutId), "error" in r && r.error !== null ? t.reject(new Error(`RPC Error: ${r.error}`)) : t.resolve(r);
190
- }
191
- /**
192
- * Handles JSON-RPC notifications (e.g., "update", "locked", "stolen").
193
- * This can be overridden by subclasses or event listeners.
194
- * @private
195
- * @param notification - The notification object.
196
- */
197
- _handleNotification(r) {
198
- if (typeof r != "object" || r === null || !("method" in r)) {
199
- console.error("Invalid notification format:", r);
200
- return;
201
- }
202
- const e = r.method;
203
- switch (e) {
204
- case "update":
205
- console.log("Received update notification:", r.params[0]);
206
- break;
207
- case "locked":
208
- console.log("Received locked notification:", r.params[0]);
209
- break;
210
- case "stolen":
211
- console.log("Received stolen notification:", r.params[0]);
212
- break;
213
- default:
214
- console.log("Received notification:", e);
215
- }
216
- }
217
- }
218
- export {
219
- m as OVSDBClient
220
- };
221
- //# sourceMappingURL=index.es.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.es.js","sources":["../src/index.ts"],"sourcesContent":["import {createConnection, Socket} from \"net\";\nimport {existsSync} from \"fs\";\n\nimport {\n DatabaseOperation,\n DatabaseSchema, EchoResponse,\n GetSchemaResponse,\n JsonValue,\n ListDbsResponse, LockedNotification, MonitorCancelResponse, MonitorConfig, MonitorResponse, OvsdbResponse,\n OvsdbResult, StolenNotification, TableUpdate,\n TransactResponse, UpdateNotification\n} from \"./types\";\n\n/**\n * Options for configuring the OVSDBClient.\n */\nexport interface OvsdbClientOptions {\n socketPath?: string;\n timeout?: number;\n}\n\n/**\n * A lightweight, typesafe client for interacting with the OVSDB over a Unix socket.\n * Implements the AsyncDisposable interface for resource management.\n * No extra functionality should be added to this client than only interact with the low-level database functions of ovs\n */\nexport class OVSDBClient implements AsyncDisposable {\n private readonly socketPath: string;\n private readonly timeout: number;\n private socket: Socket | null = null;\n private requestId = 1;\n private pendingRequests = new Map<number, {\n resolve: (value: any) => void;\n reject: (reason?: any) => void;\n timeoutId: NodeJS.Timeout;\n }>();\n private isConnected = false;\n\n /**\n * Creates a new OVSDBClient instance.\n * @param options - Configuration options for the client.\n */\n constructor(options: OvsdbClientOptions = {}) {\n this.socketPath = options.socketPath || '/var/run/openvswitch/db.sock';\n this.timeout = options.timeout || 5000;\n }\n\n /**\n * Connects to the OVSDB Unix socket.\n * @returns A promise that resolves when connected.\n * @throws An error if the socket file does not exist or the connection fails.\n */\n public connect(): Promise<this> {\n return new Promise((resolve, reject) => {\n if (this.isConnected) {\n resolve(this);\n return;\n }\n\n if (!existsSync(this.socketPath)) {\n reject(new Error(`OVSDB socket not found: ${this.socketPath}`));\n return;\n }\n\n this.socket = createConnection(this.socketPath);\n\n const timeoutId = setTimeout(() => {\n this._cleanup();\n reject(new Error(`Connection timeout after ${this.timeout}ms`));\n }, this.timeout);\n\n this.socket.on('connect', () => {\n clearTimeout(timeoutId);\n this.isConnected = true;\n resolve(this);\n });\n\n this.socket.on('error', (err) => {\n clearTimeout(timeoutId);\n this._cleanup();\n reject(err);\n });\n\n this.socket.on('close', () => {\n this._cleanup();\n });\n\n this.socket.on('data', (data) => {\n this._handleData(data);\n });\n });\n }\n\n /**\n * Sends a JSON-RPC request to the OVSDB server.\n * @param method - The RPC method name.\n * @param params - The parameters for the RPC method.\n * @returns A promise that resolves with the result.\n * @throws An error if not connected, if the request times out, or if there is a network error.\n */\n public request<T>(method: string, params: JsonValue[]): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.isConnected) {\n reject(new Error('Not connected to OVSDB'));\n return;\n }\n\n const id = this.requestId++;\n const request = JSON.stringify({\n method,\n params,\n id\n }) + '\\n';\n\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, {resolve, reject, timeoutId});\n\n this.socket!.write(request, (err) => {\n if (err) {\n clearTimeout(timeoutId);\n this.pendingRequests.delete(id);\n reject(err);\n }\n });\n });\n }\n\n // --- Core OVSDB RPC Methods (Fixed to handle the response structure) ---\n\n public async listDbs(): Promise<string[]> {\n const response = await this.request<ListDbsResponse>('list_dbs', []);\n // Check if the response is an error object\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n const result = response.result;\n // Check if the OvsdbResult itself is an error\n if ('error' in result) {\n throw new Error(`OVSDB Error: ${result.error}`);\n }\n return result;\n }\n\n public async getSchema(dbName: string = 'Open_vSwitch'): Promise<DatabaseSchema> {\n const response = await this.request<GetSchemaResponse>('get_schema', [dbName]);\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n const result = response.result;\n if ('error' in result) {\n throw new Error(`OVSDB Error: ${result.error}`);\n }\n return result;\n }\n\n public async transact(dbName: string, operations: DatabaseOperation[]): Promise<Array<OvsdbResult<unknown>>> {\n const response = await this.request<TransactResponse>('transact', [dbName, ...operations]);\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n return response.result as Array<OvsdbResult<unknown>>;\n // Note: The result here is already an array of OvsdbResult<unknown>.\n // The caller is responsible for checking each element for errors.\n }\n\n public async monitor(dbName: string, monitorId: JsonValue, monitorRequests: Record<string, MonitorConfig[]>): Promise<Record<string, TableUpdate>> {\n const response = await this.request<MonitorResponse>('monitor', [dbName, monitorId, monitorRequests as JsonValue]);\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n const result = response.result;\n if ('error' in result) {\n throw new Error(`OVSDB Error: ${result.error}`);\n }\n return result;\n }\n\n public async monitorCancel(monitorId: JsonValue): Promise<Record<string, never>> {\n const response = await this.request<MonitorCancelResponse>('monitor_cancel', [monitorId]);\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n const result = response.result;\n if ('error' in result) {\n throw new Error(`OVSDB Error: ${result.error}`);\n }\n return result;\n }\n\n public async echo(payload: JsonValue = 'ping'): Promise<JsonValue[]> {\n const response = await this.request<EchoResponse>('echo', Array.isArray(payload) ? payload : [payload]);\n if ('error' in response && response.error !== null) {\n throw new Error(`RPC Error: ${response.error}`);\n }\n const result = response.result;\n if ('error' in result) {\n throw new Error(`OVSDB Error: ${result.error}`);\n }\n return result;\n }\n\n /**\n * Closes the connection to the OVSDB server.\n * @returns A promise that resolves when the connection is closed.\n */\n public async close(): Promise<void> {\n await this[Symbol.asyncDispose]();\n }\n\n /**\n * Implements the AsyncDisposable interface for use with 'using' statements.\n * This method is called automatically when exiting a 'using' block.\n * @returns A promise that resolves when cleanup is complete.\n */\n public async [Symbol.asyncDispose](): Promise<void> {\n if (this.isConnected) {\n const closePromise = new Promise<void>((resolve) => {\n if (this.socket) {\n if (this.socket.destroyed || this.socket.readyState === 'closed') {\n resolve();\n return;\n }\n this.socket.once('close', () => {\n resolve();\n });\n } else {\n resolve();\n }\n });\n\n this._cleanup();\n await closePromise;\n }\n }\n\n /**\n * Cleans up the connection and pending requests.\n * @private\n */\n private _cleanup(): void {\n this.isConnected = false;\n if (this.socket) {\n this.socket.destroy();\n this.socket = null;\n }\n this.pendingRequests.forEach(({reject, timeoutId}) => {\n clearTimeout(timeoutId);\n reject(new Error('Connection closed'));\n });\n this.pendingRequests.clear();\n }\n\n /**\n * Handles incoming data from the socket.\n * @private\n * @param data - The raw data received.\n */\n private _handleData(data: Buffer): void {\n const messages = data.toString().trim().split('\\n');\n messages.forEach(message => {\n if (!message) return;\n try {\n const response = JSON.parse(message);\n this._handleResponse(response);\n } catch (err) {\n console.error('Failed to parse JSON:', err);\n }\n });\n }\n\n /**\n * Handles a parsed JSON-RPC response.\n * @private\n * @param response - The JSON-RPC response object.\n */\n private _handleResponse(response: JsonValue): void {\n if (typeof response !== 'object' || response === null || !('id' in response)) {\n console.error('Invalid response format:', response);\n return;\n }\n\n const id = response.id as number;\n const request = this.pendingRequests.get(id);\n\n if (!request) {\n // This is a notification (e.g., \"update\", \"locked\", \"stolen\")\n this._handleNotification(response);\n return;\n }\n\n this.pendingRequests.delete(id);\n clearTimeout(request.timeoutId);\n\n if ('error' in response && response.error !== null) {\n request.reject(new Error(`RPC Error: ${response.error}`));\n } else {\n request.resolve((response as unknown as OvsdbResponse));\n }\n }\n\n /**\n * Handles JSON-RPC notifications (e.g., \"update\", \"locked\", \"stolen\").\n * This can be overridden by subclasses or event listeners.\n * @private\n * @param notification - The notification object.\n */\n private _handleNotification(notification: JsonValue): void {\n if (typeof notification !== 'object' || notification === null || !('method' in notification)) {\n console.error('Invalid notification format:', notification);\n return;\n }\n\n const method = (notification as { method: string }).method;\n\n switch (method) {\n case 'update':\n console.log('Received update notification:', (notification as UpdateNotification).params[0]);\n break;\n case 'locked':\n console.log('Received locked notification:', (notification as LockedNotification).params[0]);\n break;\n case 'stolen':\n console.log('Received stolen notification:', (notification as StolenNotification).params[0]);\n break;\n default:\n console.log('Received notification:', method);\n }\n }\n}\n\nexport * from \"./types\"\n"],"names":["OVSDBClient","options","resolve","reject","existsSync","createConnection","timeoutId","err","data","method","params","id","request","response","result","dbName","operations","monitorId","monitorRequests","payload","closePromise","message","notification"],"mappings":"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"}