UNPKG

dbus-sdk

Version:

A Node.js SDK for interacting with DBus, enabling seamless service calling and exposure with TypeScript support

149 lines (148 loc) 7.08 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DBusObject = void 0; const DBusInterface_1 = require("./DBusInterface"); const xml2js_1 = require("xml2js"); const Errors_1 = require("./lib/Errors"); const DBusTypeClass_1 = require("./lib/DBusTypeClass"); class DBusObject { #shareIntrospect = false; #shareIntrospectInterfaces = []; /** * Constructor for DBusObject. * Initializes the DBus object with the provided options and sets up references to the DBus connection * and service. * @param opts - Configuration options for the DBus object. */ constructor(opts) { this.opts = opts; this.dbus = this.opts.dbus; this.service = this.opts.dbusService; this.name = this.opts.objectPath; } /** * Internal method to get a DBus interface by name. * Retrieves or caches introspection data for the specified interface and creates a DBusInterface instance. * @param iface - The name of the interface to retrieve. * @param shareIntrospect - Whether to use shared introspection data to avoid multiple introspections. * @returns A Promise resolving to a DBusInterface instance for the specified interface. * @throws InterfaceNotFoundError if the specified interface is not found. */ async internalGetInterface(iface, shareIntrospect = false) { let introspectInterfaces; if (shareIntrospect) { introspectInterfaces = this.#shareIntrospectInterfaces; } else { introspectInterfaces = (await this.introspect()).interface; } const introspectInterface = introspectInterfaces.find((introspectInterface) => introspectInterface.name === iface); if (!introspectInterface) throw new Errors_1.InterfaceNotFoundError(`Interface ${iface} not found`); return new DBusInterface_1.DBusInterface({ ...this.opts, iface: iface, dbusObject: this, introspectInterface: introspectInterface }); } /** * Introspects the DBus object to retrieve its structure and metadata. * Invokes the Introspect method on the DBus object to get XML data, parses it, and constructs * an IntrospectNode object with details about interfaces, methods, properties, and signals. * @returns A Promise resolving to an IntrospectNode object representing the object's introspection data. */ async introspect() { const [introspectXML] = await this.dbus.invoke({ service: this.service.name, objectPath: this.name, interface: 'org.freedesktop.DBus.Introspectable', method: 'Introspect' }); const introspectObject = await (0, xml2js_1.parseStringPromise)(introspectXML instanceof DBusTypeClass_1.DBusTypeClass ? introspectXML.value : introspectXML); const node = introspectObject.node; const interfaces = node.interface ? node.interface : []; return { interface: interfaces.map(interfaceInfo => { const method = interfaceInfo.method ? interfaceInfo.method : []; const property = interfaceInfo.property ? interfaceInfo.property : []; const signal = interfaceInfo.signal ? interfaceInfo.signal : []; const introspectInterface = { name: interfaceInfo.$.name, method: method.map(methodInfo => { const arg = methodInfo.arg ? methodInfo.arg : []; const introspectMethod = { name: methodInfo.$.name, arg: arg.map(methodArgInfo => { const introspectMethodArgument = { name: methodArgInfo.$.name, type: methodArgInfo.$.type, direction: methodArgInfo.$.direction }; return introspectMethodArgument; }) }; return introspectMethod; }), property: property.map(propertyInfo => { const introspectProperty = { name: propertyInfo.$.name, type: propertyInfo.$.type, access: propertyInfo.$.access }; return introspectProperty; }), signal: signal.map(signalInfo => { const arg = signalInfo.arg ? signalInfo.arg : []; const introspectSignal = { name: signalInfo.$.name, arg: arg.map(signalArgInfo => { const introspectSignalArgument = { name: signalArgInfo.$.name, type: signalArgInfo.$.type }; return introspectSignalArgument; }) }; return introspectSignal; }) }; return introspectInterface; }) }; } /** * Lists all interface names available on this DBus object. * Performs introspection to retrieve the list of interfaces and optionally caches the result. * @returns A Promise resolving to an array of interface names as strings. */ async listInterfaces() { const introspectResult = await this.introspect(); if (this.#shareIntrospect) this.#shareIntrospectInterfaces = introspectResult.interface; return introspectResult.interface.map((iface) => iface.name); } /** * Retrieves all DBus interfaces available on this object. * Uses shared introspection data to efficiently create DBusInterface instances for all interfaces. * @returns A Promise resolving to an array of DBusInterface instances for all interfaces on this object. */ async getInterfaces() { this.#shareIntrospect = true; const interfaceNames = await this.listInterfaces(); const dbusInterfaces = await Promise.all(interfaceNames.map((interfaceName) => this.internalGetInterface(interfaceName, true))); this.#shareIntrospectInterfaces = []; this.#shareIntrospect = false; return dbusInterfaces; } /** * Retrieves a specific DBus interface by name from this object. * @param iface - The name of the interface to retrieve. * @returns A Promise resolving to a DBusInterface instance for the specified interface. * @throws InterfaceNotFoundError if the specified interface is not found. */ async getInterface(iface) { return await this.internalGetInterface(iface, false); } } exports.DBusObject = DBusObject;