npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@acaprojects/ts-composer

v2.1.4

Published

Composer is a typescript API for ACAEngine

Downloads

54

Readme

TypeScript Composer Library

Composer is a typescript API for ACAEngine

Compilation

You can build the library from source after installing the dependencies with the command

npm run build

Usage

API docs can be found here

You can install Typescript composer with the npm command

npm install --save-dev @acaprojects/ts-composer

After the package is installed you can import Composer into your application

import { Composer } from '@acaprojects/ts-composer'

Before using composer it will need to be intialised.

Composer.init(config);

The init method takes a config object with the following properties

|Property|Description|Optional|Type|Example| |--------|-----------|--------|----|-------| |host|Host name and port of the ACAEngine server|Yes|string|"dev.acaprojects.com:8080"| |mock|Whether to initialise composer with mock services|Yes|boolean|true| |auth_uri|URI for authorising users session|No|string|"/auth/oauth/authorize"| |token_uri|URI for generating new auth tokens|No|string|"/auth/token"| |redirect_uri|URI to redirect user to after authorising session|No|string|"/oauth-resp.html"| |scope|Scope of the user permissions needed by the application|No|string|"admin"| |storage|Browser storage to use for storing user credentials|Yes|"local" \| "session"| | |handle_login|Whether composer should handle user login|Yes|boolean|true|

Once initialised the Composer object will expose interfaces to ACAEngine's websocket and http APIs

Websocket API

Composer exposes ACAEngine's websocket API through the bindings service.

The bindings service is used to provide real-time interaction with modules running on ACAEngine. It provides an interface to build efficient, responsive user interfaces, monitoring systems and other extensions which require live, two-way or asynchronous interaction.

Once composer has initialised you can listen to values on modules

const my_mod = Composer.bindings.module('sys-death-star', 'TestModule', 3);
const my_variable = my_mod.binding('power');
const unbind = my_variable.bind();
const sub = my_variable.listen((value) => doSomething(value));

This binds to the power status variable on the 3rd TestModule in the system sys-death-star. Any changes to the value of power on ACAEngine will then be emitted to the function passed to listen.

Other than listening to changes of values you can also remotely execute methods on modules.

const my_mod = Composer.bindings.module('sys-death-star', 'DemoModule', 2);
my_mod.exec('power_off').then(
    (resp) => handleSuccess(resp)
    (err) => handleError(err)
);

This will execute the method power_off on the 2nd DemoModule in the system sys-death-star. If the method doesn't exist or the system is turned off it will return an error. The response from ACAEngine can be handled using the promise returned by the exec method.

HTTP API

For the HTTP API, Composer provides a service for each of the root endpoints available on ACAEngine's RESTful API.

Docs for the API can be found here https://docs.acaengine.com/api/control

Services are provided for drivers, modules, systems, users, and zones

Each service except for users provides CRUD methods. users provides _RUD.

// Drivers CRUD
Composer.drivers.add(driver_data).then((new_driver) => doSomething(new_driver));
Composer.drivers.show(driver_id).then((driver) => doSomething(driver));
Composer.drivers.update(driver_id, driver_data).then((updated_driver) => doSomething(updated_driver));
Composer.drivers.delete(driver_id).then(() => doSomething());

// Modules CRUD
Composer.modules.add(module_data).then((new_module) => doSomething(new_module));
Composer.modules.show(module_id).then((mod) => doSomething(mod));
Composer.modules.update(module_id, module_data).then((updated_module) => doSomething(updated_module));
Composer.modules.delete(module_id).then(() => doSomething());

// Systems CRUD
Composer.systems.add(system_data).then((new_system) => doSomething(new_system));
Composer.systems.show(system_id).then((system) => doSomething(system));
Composer.systems.update(system_id, system_data).then((updated_system) => doSomething(updated_system));
Composer.systems.delete(system_id).then(() => doSomething());

// Users CRUD
Composer.users.add(user_data).then((new_user) => doSomething(new_user)); // This will error
Composer.users.show(user_id).then((user) => doSomething(user));
Composer.users.update(user_id, user_data).then((updated_user) => doSomething(updated_user));
Composer.users.delete(user_id).then(() => doSomething());

// Zones CRUD
Composer.zones.add(zone_data).then((new_zone) => doSomething(new_zone));
Composer.zones.show(zone_id).then((zone) => doSomething(zone));
Composer.zones.update(zone_id, zone_data).then((updated_zone) => doSomething(updated_zone));
Composer.zones.delete(zone_id).then(() => doSomething());

The services also provide methods for the various item action endpoints

// Driver Actions
Composer.drivers.reload(driver_id);

// Module Actions
Composer.module.start(module_id);
Composer.module.stop(module_id);
Composer.module.ping(module_id);
Composer.module.lookup(module_id, lookup);
Composer.module.internalState(module_id);

// System Actions
Composer.system.remove(system_id, module_name);
Composer.system.start(system_id);
Composer.system.stop(system_id);
Composer.system.execute(system_id, module_name, index, args);
Composer.system.state(system_id, module_name, index, lookup);
Composer.system.functionList(system_id, module_name, index);
Composer.system.types(system_id, module_name);
Composer.system.count(system_id);

// User Actions
Composer.users.current();

Objects returned by show and query methods are immutable, though when reassigning value it will be saved under the changes property of that object. These changes can be saved using the save method which will return a promise for the new object.

Composer.zones.show(zone_id).then((zone) => {
    console.log(zone.description); // Prints the current description
    zone.description = 'New description';
    console.log(zone.description); // Same a previous print
    cosnole.log(zone.changes.description) // New description
    zone.save().then((updated_zone) => {
        cosnole.log(updated_zone.description) // New description
    });
});

You can find more details about endpoint action on the API docs

https://app.swaggerhub.com/apis/ACAprojects/ACAEngine/3.5.0#/

Writing mocks

If you don't have access to an ACAEngine server you can also write mocks so that you can still develop interfaces for ACAEngine.

To use the mock services you can pass mock: true into the initialisation object.

Websockets

To write mocks for the the realtime(websocket) API you'll need to add your systems to window.control.systems before initialising composer.

window.control.systems = {
    "my-system": {
        "MyModule": [
            {
                power: true,
                $power_on: function () { this.power = true },
                $power_off: function () { this.power = false }
            }
        ]
    }
}

Note that executable methods on mock systems are namespaced with $ as real systems in engine allow for methods to have the same name as variables.

Once initialised interactions with a system are performed in the same manner as the live system.

const my_mod = Composer.bindings.module('my-system', 'MyModule', 1);
const my_variable = my_mod.binding('power');
const unbind = my_variable.bind();
const sub = my_variable.listen((value) => doSomething(value)); // Emits true
my_mod.exec('power_off'); // The listen callback will now emit false

Some methods may need access to other modules within the system, for this a property is appended on runtime called _system which allows for access to the parent system

window.control.systems = {
    "my-system": {
        "MyModule": [
            {
                $lights_off: function () { this._system.MyOtherModule[0].lights = false; }
            }
        ]
        "MyOtherModule": [
            {
                lights: true,
            }
        ]
    }
}

HTTP Requests

HTTP API Requests can be mocked in a similar way to the realtime API by adding handlers to window.control.handlers

window.control.handlers = [
    {
        path: '/api/engine/v2/systems',
        metadata: {},
        method: 'GET',
        callback: (request) => my_mock_systems
    }
]

Paths allow for route parameters and will pass the value in the callback input.

window.control.handlers = [
    {
        path: '/api/engine/v2/systems/:system_id',
        ...
        callback: (request) =>
            my_mock_systems.find(sys => sys.id === request.route_params.system_id)
    }
]

Query parameters are also available on the callback input.

GET, POST, PUT, PATCH and DELETE requests can be mocked out.

If a request is made and there are no handlers it will attempt to make the live request.