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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xiboplayer/xmds

v0.7.19

Published

XMDS SOAP client for Xibo CMS communication

Downloads

3,541

Readme

@xiboplayer/xmds

XMDS/REST dual-transport CMS client for Xibo digital signage -- auto-detects REST or SOAP based on CMS capabilities.

Overview

Unified abstraction over Xibo's two communication protocols:

  • REST API v2 -- JSON-based, JWT auth, ETag caching, ~30% smaller payloads
  • XMDS SOAP (v3-v7) -- XML-based, universal compatibility with all Xibo CMS versions

Both expose an identical public API. At startup, ProtocolDetector probes the CMS to select the optimal transport -- fallback to SOAP if REST is unavailable.

Capabilities

  • Dual-transport abstraction -- RestClient and XmdsClient implement the same interface
  • Auto-detection -- quick health probe (3s timeout) to select REST or SOAP
  • HTTP caching -- REST client uses ETags to avoid redundant GETs
  • Retry & backoff -- exponential backoff with jitter (default: 2 retries, 2s base delay)
  • JWT auth -- REST client auto-refreshes tokens 60s before expiry
  • CRC checksums -- checkRf and checkSchedule allow skipping unchanged data
  • Delegated reporting -- stats/logs can be submitted on behalf of other displays (follower -> lead delegation)

Architecture

Player Core                        Transport Selection                CMS
-----------                       --------------------              -----

registerDisplay()                  Is REST available?
requiredFiles()     Same API       (GET /api/v2/player/health)
schedule()                 Yes --> RestClient (JWT, ETag)   --> /api/v2/player/*
getResource()              No  --> XmdsClient (SOAP XML)    --> /xmds.php
notify()
submitStats()
submitLog()

Both clients share the same return types. The scheduler, renderer, and sync modules consume only the CmsClient interface -- they're transport-agnostic.

Installation

npm install @xiboplayer/xmds

Usage

Auto-detect and instantiate

import { ProtocolDetector, RestClient, XmdsClient } from '@xiboplayer/xmds';

const detector = new ProtocolDetector(cmsUrl, RestClient, XmdsClient);
const { client, protocol } = await detector.detect({
  cmsUrl: 'https://cms.example.com',
  cmsKey: 'your-server-key',
  hardwareKey: 'display-123',
  displayName: 'Main Screen',
});

console.log(`Using ${protocol} transport`);

const display = await client.registerDisplay();
const files = await client.requiredFiles();
const schedule = await client.schedule();

Force a specific transport

const { client } = await detector.detect(config, 'xmds');  // Force SOAP
const { client } = await detector.detect(config, 'rest');   // Force REST

Direct RestClient usage

import { RestClient } from '@xiboplayer/xmds';

const client = new RestClient({
  cmsUrl: 'https://cms.example.com',
  cmsKey: 'server-key',
  hardwareKey: 'display-key',
  displayName: 'Display 1',
});

const { code, message, settings, syncConfig } = await client.registerDisplay();
const { files, purge } = await client.requiredFiles();

Direct XmdsClient usage

import { XmdsClient } from '@xiboplayer/xmds';

const client = new XmdsClient({
  cmsUrl: 'https://cms.example.com',
  cmsKey: 'server-key',
  hardwareKey: 'display-key',
  displayName: 'Display 1',
  xmrChannel: 'ch-123',
  xmrPubKey: '-----BEGIN PUBLIC KEY-----\n...',
});

const display = await client.registerDisplay();

Parse schedule without network call

import { parseScheduleResponse } from '@xiboplayer/xmds';

const parsed = parseScheduleResponse(scheduleXml);
// { default, layouts, campaigns, overlays, actions, commands, dataConnectors }

Methods

All methods available on both RestClient and XmdsClient with identical signatures:

| Method | Parameters | Returns | Description | |--------|------------|---------|-------------| | registerDisplay() | -- | RegisterDisplayResult | Authenticate, get settings, tags, commands, sync config | | requiredFiles() | -- | RequiredFilesResult | Get media, layouts, widgets, and files to purge | | schedule() | -- | ScheduleObject | Get complete schedule | | getResource(layoutId, regionId, mediaId) | number x 3 | string | Get rendered widget HTML | | notifyStatus(status) | Object | JSON/XML | Report display status | | mediaInventory(inventoryXml) | string/Array | JSON/XML | Report cached media | | submitStats(statsXml, hardwareKeyOverride?) | string, string? | boolean | Submit proof-of-play (optional override for delegated reporting) | | submitLog(logXml, hardwareKeyOverride?) | string, string? | boolean | Submit logs (optional override for delegated reporting) | | submitScreenShot(base64Image) | string | boolean | Upload screenshot | | reportFaults(faultJson) | string/Object | boolean | Report hardware/software faults | | blackList(mediaId, type, reason) | string, string, string | boolean | Blacklist broken media | | getWeather() | -- | JSON/XML | Get weather data for schedule criteria |

Key Response Types

RegisterDisplayResult:

{
  code: 'READY' | 'WRONG_SCHEDULE_KEY' | 'DISPLAY_NOT_LICENSED' | ...,
  message: string,
  settings: { [key: string]: any },
  tags: string[],
  commands: Array<{ commandCode, commandString }>,
  checkRf: string,         // CRC32 of RequiredFiles (skip if unchanged)
  checkSchedule: string,   // CRC32 of Schedule (skip if unchanged)
  syncConfig: {             // Multi-display sync (null if not enabled)
    syncGroup: string,
    syncPublisherPort: number,
    syncSwitchDelay: number,
    isLead: boolean
  } | null
}

Transport Comparison

| Aspect | REST (v2) | XMDS (SOAP) | |--------|-----------|-------------| | Protocol | JSON over HTTP | XML-RPC over HTTP | | Auth | JWT (Bearer token) | Per-request params (serverKey) | | Payload size | ~30% smaller | Baseline | | Caching | ETags + response cache | No caching | | Availability | Custom CMS images (Xibo 3.0+) | All Xibo versions (v3-v7+) | | Fallback | SOAP (automatic) | None |

Error Handling

Retry: Both clients use fetchWithRetry() with exponential backoff (2 retries, 2s base delay).

Token expiry (REST): 401 response triggers automatic re-authentication and request retry.

SOAP faults: XmdsClient parses <soap:Fault> and throws with fault message.

Custom retry strategy:

const client = new RestClient({
  ...config,
  retryOptions: { maxRetries: 5, baseDelayMs: 5000 }
});

Constructor Options

{
  cmsUrl: string,                // Base URL of Xibo CMS
  cmsKey: string,                // Server authentication key
  hardwareKey: string,           // Unique display identifier
  displayName?: string,          // Human-readable display name
  clientVersion?: string,        // Default: '0.1.0'
  clientType?: string,           // Default: 'linux'
  xmrChannel?: string,           // XMR channel ID
  xmrPubKey?: string,            // XMR public key (PEM)
  retryOptions?: {
    maxRetries?: number,         // Default: 2
    baseDelayMs?: number         // Default: 2000
  }
}

Dependencies

  • @xiboplayer/utils -- logger, fetchWithRetry

xiboplayer.org · Part of the XiboPlayer SDK