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
JavaScript
"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;