Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved Interface Generator #52

Merged
merged 18 commits into from
Mar 23, 2020
Merged

Improved Interface Generator #52

merged 18 commits into from
Mar 23, 2020

Conversation

Niels-Be
Copy link
Contributor

@Niels-Be Niels-Be commented Mar 12, 2020

This will add an interface generator for client interfaces.
It is similar to the existing generator but with several improvements.

  1. It lets you generate an interface directly from a dbus object
  2. Has more Handlebar functions
  3. Customizable templates
  4. Example templates for:
  • A client interface wrapper (TS and JS)
  • Typescript client interface definitions
  • Service class stub (JS only, like in original generator)

Let me know if you want this in this project, otherwise I would create an separate project for this generator.

Usage:

Usage: generate-client-interfaces [options] <destination> <objectPath>

Generate an interface from a DBus object

Options:
  -V, --version          output the version number
  --system               Use the system bus
  --session              Use the session bus
  -t, --template [path]  Template to use for interface generation
  --full                 Do not exclude DBus standard interfaces
  -p, --prefix           Prefix class names with full interface path
  -o, --output [path]    The output file path (default: stdout)
  -h, --help             output usage information

Example:
Generate a Typescript class that wraps all DBus calls into a high level interface.

./generate-client-interfaces.js --system -t ../templates/typescript-class.hbs org.bluez /org/bluez/hci0

import * as DBus from 'dbus-next';
import { EventEmitter } from 'events';

/*
 * Generated by dbus-next interface generator
 */

/**
 * org.bluez.Adapter1
 */
export class Adapter1 extends EventEmitter {

    public readonly dbusInterfaceName = 'org.bluez.Adapter1';
    public dbusObject: DBus.ProxyObject;
    public propertiesDBusInterface: DBus.ClientInterface;
    public thisDBusInterface: DBus.ClientInterface;

    constructor(dbusObject: DBus.ProxyObject) {
        super();
        this.dbusObject = dbusObject;
        this.thisDBusInterface = dbusObject.getInterface('org.bluez.Adapter1');
        this.propertiesDBusInterface = dbusObject.getInterface('org.freedesktop.DBus.Properties');

        // forward property change events
        this.propertiesDBusInterface.on('PropertiesChanged', (iface: string, changed: any, invalidated: any) => {
            if(iface === this.dbusInterfaceName) {
                this.emit('PropertiesChanged', iface, changed, invalidated);
            }
        });
        // forward all signals
        this.on("newListener", this.thisDBusInterface.on.bind(this.thisDBusInterface));
        this.on("removeListener", this.thisDBusInterface.removeListener.bind(this.thisDBusInterface));
    }

    /***** Properties *****/

    public getProperties(): Promise<{[name: string]: DBus.Variant}> {
        return this.propertiesDBusInterface.GetAll(this.dbusInterfaceName);
    }

    public getProperty(name: string): Promise<DBus.Variant> {
        return this.propertiesDBusInterface.Get(this.dbusInterfaceName, name);
    }

    public setProperty(name: string, value: DBus.Variant): Promise<void> {
        return this.propertiesDBusInterface.Set(this.dbusInterfaceName, name, value);
    }

    //@property({ name: 'Address', signature: 's', access: ACCESS_READ })
    public Address(): Promise<string> {
        return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'Address');
    }

    //@property({ name: 'AddressType', signature: 's', access: ACCESS_READ })
    public AddressType(): Promise<string> {
        return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'AddressType');
    }

    //@property({ name: 'Name', signature: 's', access: ACCESS_READ })
    public Name(): Promise<string> {
        return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'Name');
    }

    //@property({ name: 'Alias', signature: 's', access: ACCESS_READWRITE })
    public Alias(): Promise<string>;
    public Alias(value: string): Promise<void>;
    public Alias(value?: string): Promise<any> {
        if(value !== undefined) {
            return this.propertiesDBusInterface.Set(this.dbusInterfaceName, 'Alias', value);
        } else {
            return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'Alias');
        }
    }

    //@property({ name: 'Class', signature: 'u', access: ACCESS_READ })
    public Class(): Promise<number> {
        return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'Class');
    }

    //@property({ name: 'Powered', signature: 'b', access: ACCESS_READWRITE })
    public Powered(): Promise<boolean>;
    public Powered(value: boolean): Promise<void>;
    public Powered(value?: boolean): Promise<any> {
        if(value !== undefined) {
            return this.propertiesDBusInterface.Set(this.dbusInterfaceName, 'Powered', value);
        } else {
            return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'Powered');
        }
    }

    //@property({ name: 'Discoverable', signature: 'b', access: ACCESS_READWRITE })
    public Discoverable(): Promise<boolean>;
    public Discoverable(value: boolean): Promise<void>;
    public Discoverable(value?: boolean): Promise<any> {
        if(value !== undefined) {
            return this.propertiesDBusInterface.Set(this.dbusInterfaceName, 'Discoverable', value);
        } else {
            return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'Discoverable');
        }
    }

    //@property({ name: 'DiscoverableTimeout', signature: 'u', access: ACCESS_READWRITE })
    public DiscoverableTimeout(): Promise<number>;
    public DiscoverableTimeout(value: number): Promise<void>;
    public DiscoverableTimeout(value?: number): Promise<any> {
        if(value !== undefined) {
            return this.propertiesDBusInterface.Set(this.dbusInterfaceName, 'DiscoverableTimeout', value);
        } else {
            return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'DiscoverableTimeout');
        }
    }

    //@property({ name: 'Pairable', signature: 'b', access: ACCESS_READWRITE })
    public Pairable(): Promise<boolean>;
    public Pairable(value: boolean): Promise<void>;
    public Pairable(value?: boolean): Promise<any> {
        if(value !== undefined) {
            return this.propertiesDBusInterface.Set(this.dbusInterfaceName, 'Pairable', value);
        } else {
            return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'Pairable');
        }
    }

    //@property({ name: 'PairableTimeout', signature: 'u', access: ACCESS_READWRITE })
    public PairableTimeout(): Promise<number>;
    public PairableTimeout(value: number): Promise<void>;
    public PairableTimeout(value?: number): Promise<any> {
        if(value !== undefined) {
            return this.propertiesDBusInterface.Set(this.dbusInterfaceName, 'PairableTimeout', value);
        } else {
            return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'PairableTimeout');
        }
    }

    //@property({ name: 'Discovering', signature: 'b', access: ACCESS_READ })
    public Discovering(): Promise<boolean> {
        return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'Discovering');
    }

    //@property({ name: 'UUIDs', signature: 'as', access: ACCESS_READ })
    public UUIDs(): Promise<Array<string>> {
        return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'UUIDs');
    }

    //@property({ name: 'Modalias', signature: 's', access: ACCESS_READ })
    public Modalias(): Promise<string> {
        return this.propertiesDBusInterface.Get(this.dbusInterfaceName, 'Modalias');
    }


    /***** Methods *****/

    //@method({ name: 'StartDiscovery', inSignature: '', outSignature: '' })
    public StartDiscovery(): Promise<void> {
        return this.thisDBusInterface.StartDiscovery();
    }

    //@method({ name: 'SetDiscoveryFilter', inSignature: 'a{sv}', outSignature: '' })
    public SetDiscoveryFilter(properties: {[key: string]: DBus.Variant}): Promise<void> {
        return this.thisDBusInterface.SetDiscoveryFilter(properties);
    }

    //@method({ name: 'StopDiscovery', inSignature: '', outSignature: '' })
    public StopDiscovery(): Promise<void> {
        return this.thisDBusInterface.StopDiscovery();
    }

    //@method({ name: 'RemoveDevice', inSignature: 'o', outSignature: '' })
    public RemoveDevice(device: DBus.ObjectPath): Promise<void> {
        return this.thisDBusInterface.RemoveDevice(device);
    }

    //@method({ name: 'GetDiscoveryFilters', inSignature: '', outSignature: 'as' })
    public GetDiscoveryFilters(): Promise<Array<string>> {
        return this.thisDBusInterface.GetDiscoveryFilters();
    }

}


/* [....] */

This is a rewrite of the interface generator. It will enhance its
capabilities with cusomizeable templates, allow generation directly from
live dbus objects and adds example templates for javascript-classes,
typescript-classes and typescript-dts interfaces.
@acrisci
Copy link
Member

acrisci commented Mar 13, 2020

The JavaScript version makes a service interface and the TypeScript version makes a client interface. That should be explicit somewhere, probably in the name of the template.

@Niels-Be
Copy link
Contributor Author

Niels-Be commented Mar 13, 2020

The JavaScript version makes a service interface and the TypeScript version makes a client interface. That should be explicit somewhere, probably in the name of the template.

Right it should only generate client interfaces.
Is there any use case for generating interfaces for a service?

@acrisci
Copy link
Member

acrisci commented Mar 13, 2020

Is there any use case for generating interfaces for a service?

Yeah, this was written to generate the boilerplate for mpris-service. It's more useful for clients, but it can easily do both because they use the same kinds of abstractions.

@Niels-Be
Copy link
Contributor Author

I did some updates and also added a recursive option to generate classes for an entire service at once. Each interface will be generated into its own file.

See node-dbus-network-manager for an example of a fully generated project.

@acrisci
Copy link
Member

acrisci commented Mar 23, 2020

👍

@acrisci acrisci merged commit a04a265 into dbusjs:master Mar 23, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants