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

roon-kit

v0.1.0

Published

Collection of utility classes that simplify building extensions for Roon.

Downloads

14

Readme

Roon Kit

A collection of utility classes that simplify building extensions for Roon. Roon Kit modernizes the existing node-roon-api and adds the following features:

  • Promises and async/await support. Most of the callback based functions of the RoonApiBrowse, RoonApiImage, and RoonApiTransport services have been modified to return promises instead of taking a callback.
  • TypeScript definitions for everything. This adds type checking when building your app with TypeScript and enables better VSCode intellisense even for JavaScript based apps.
  • New RoonExtension class to simplify initializing the RoonApi and subscribing to zones or outputs.
  • Node.js style events for things like zone pairing and subscription callbacks. This lets multiple components subscribe to the same set of API notifications.
  • The paired RoonCore is wrapped with a Revocable Proxy for added safety. This prevents apps from trying to use a core after its be unpaired and helps eliminate a whole class of bugs.

Usage

To use Roon Kit in your project simply install it using your favorite package manager:

$ npm install roon-kit --save

or using Yarn:

$ yarn add roon-kit

Create a RoonExtension class instead of the RoonApi class. You can tell the services you'd like to use and if you'd like the extension to subscribe to output or zones:

const { RoonExtension } = require('roon-kit');

const extension = new RoonExtension({
        description: {
        extension_id:        'roon-kit-now-playing',
        display_name:        "Roon Kit Now Playing Test",
        display_version:     "0.1.0",
        publisher:           'roon-kit',
        email:               '[email protected]',
        website:             'https://github.com/Stevenic/roon-kit'
    },
    RoonApiBrowse: 'not_required',
    RoonApiImage: 'not_required',
    RoonApiTransport: 'required',
    subscribe_outputs: false,
    subscribe_zones: true,
    log_level: 'none'
});

Next you can listen for subscription events if you've enabled those option(s):

extension.on("subscribe_zones", (core, response, body) => {
    // Print new subscriptions
    const addedZones = body.zones ?? body.zones_added ?? [];
    addedZones.forEach(zone => {
        console.log(`Zone['${zone.zone_id}'] subscribed to "${zone.display_name}"`);
        console.log(`Zone['${zone.zone_id}'] "${zone.now_playing?.one_line.line1 ?? 'zone'}" is ${zone.state}`);
    });

    // Print removed subscriptions
    const removedZones = body.zones_removed ?? [];
    removedZones.forEach(zone => {
        console.log(`Zone['${zone.zone_id}'] unsubscribed from "${zone.display_name}"`);
    }); 

    // Print zone state changes
    const changedZones = body.zones_changed ?? [];
    changedZones.forEach(zone => {
        console.log(`Zone['${zone.zone_id}'] "${zone.now_playing?.one_line.line1 ?? 'zone'}" is ${zone.state}`);
    });

    // Print zone seeks
    const seekedZones = body.zones_seek_changed ?? [];
    seekedZones.forEach(zone => {
        console.log(`Zone['${zone.zone_id}'] time remaining: ${zone.queue_time_remaining} seconds`);
    });
});

You can then start discovery and wait for a RoonCore to pair. There's no need to initialize the services as that's managed by the extension class:

extension.start_discovery();
extension.set_status(`extension starting`);

You can get a handled to the current paired core by either subscribing to the "core_paired" event before your start discovery or by calling extension.get_core() after you start discovery. The get_core() method is asynchronous so you can wait for the core using either:

extension.get_core().then((core) => {
    extension.set_status(`core paired`);
});

Or using a more modern async/await pattern:

(async () => {
    const core = await extension.get_core();
    extension.set_status(`core paired`);
})();