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

@timschrader/node-dbus

v1.0.0

Published

Modern, production-ready DBus library for Node.js with complete client and service support

Readme

@timschrader/node-dbus

Modern, production-ready DBus library for Node.js with TypeScript support.

Built on sd-bus (systemd) via C++ N-API — all DBus communication happens in native code for maximum performance and correctness.

License: MIT Node.js Version


Features

  • Full Client Support — Call methods, read/write properties, subscribe to signals
  • Service Export — Expose objects with methods, properties, and signals on the bus
  • Introspection — Discover interfaces, methods, and properties; generate introspection XML
  • Complete Type System — All DBus types (basic + containers), full validation in C++
  • Name Management — Request/release well-known names with queue & replace support
  • Signals — EventEmitter-based subscription with automatic match rule management
  • Connection Management — Auto-reconnect, disconnect detection, multiple connections
  • Variant Support — First-class Variant class with factories, JSON serialization, type guards
  • Retry & Timeouts — Per-call timeouts, AbortSignal cancellation, withRetry() helper
  • Advanced Service — Fallback vtables for dynamic paths, ObjectManager, PropertiesChanged signals
  • Property Caching — Optional sync property reads with auto-sync via PropertiesChanged
  • Call Tracing — Built-in debug logging with custom logger support
  • Service Templates — Pre-built MPRIS Player and Notification Daemon templates
  • Code Generation — Auto-generate typed TypeScript proxies from DBus introspection
  • Testing Utilities — MockBus for unit testing without a real DBus connection
  • TypeScript — Full type definitions, type-safe API

Quick Start

Prerequisites

# Arch Linux
sudo pacman -Syu systemd pkgconf base-devel

# Ubuntu/Debian
sudo apt-get install libsystemd-dev pkg-config build-essential

# Fedora/RHEL
sudo dnf install systemd-devel pkg-config gcc-c++

Install

npm install @timschrader/node-dbus

The native addon compiles automatically during install (requires the prerequisites above).

Install from Source

git clone https://github.com/Tim-Schrader/node-dbus.git
cd node-dbus
npm install
npm run build:all

Client Usage

import { Bus, DBusError } from '@timschrader/node-dbus';

// Connect to the session bus
const bus = Bus.session();

// Get a proxy object and interface
const obj = bus.getObject('org.freedesktop.DBus', '/org/freedesktop/DBus');
const iface = obj.getInterface('org.freedesktop.DBus');

// Call a method
const names = await iface.call<string[]>('ListNames', '', []);
console.log('Bus names:', names);

// Read a property
const features = await bus.getProperty<string[]>(
  'org.freedesktop.DBus', '/org/freedesktop/DBus',
  'org.freedesktop.DBus', 'Features'
);

// Subscribe to signals
iface.on('NameOwnerChanged', (name, oldOwner, newOwner) => {
  console.log(`${name}: ${oldOwner} → ${newOwner}`);
});

// Error handling
try {
  await bus.call('org.nonexistent.Service', '/path', 'iface', 'Method');
} catch (err) {
  if (DBusError.isDBusError(err)) {
    console.log(`DBus error: ${err.dbusName}`);
  }
}

bus.close();

Service Usage

import { Bus, ServiceBuilder, NameFlags } from '@timschrader/node-dbus';

const bus = Bus.session();

const builder = new ServiceBuilder('com.example.Calculator')
  .method('Add', 'ii', 'i', (a: number, b: number) => a + b)
  .method('Echo', 's', 's', (s: string) => s)
  .property('Version', 's', () => '1.0')
  .property('Counter', 'i', () => counter, (v: number) => { counter = v; })
  .signal('CounterChanged', 'i');

let counter = 0;

bus.exportObject('/com/example/Calculator', builder);
bus.requestName('com.example.Calculator', NameFlags.REPLACE_EXISTING);

// Emit signals
bus.emitSignal('/com/example/Calculator', 'com.example.Calculator',
  'CounterChanged', 'i', [counter]);

// Emit PropertiesChanged
bus.emitPropertiesChanged('/com/example/Calculator',
  'com.example.Calculator', ['Counter'], []);

API Overview

Connection

const bus = Bus.session();           // Session bus
const bus = Bus.system();            // System bus
const bus = Bus.connect(address);    // Custom address

bus.connected;     // boolean
bus.uniqueName;    // ":1.xxx"
bus.close();       // Disconnect
bus.reconnect();   // Reconnect

// Auto-reconnect with backoff
const bus = Bus.session({ autoReconnect: true, reconnectDelay: 1000 });
bus.on('disconnected', () => console.log('Lost connection'));
bus.on('reconnecting', ({ attempt }) => console.log(`Reconnecting #${attempt}`));
bus.on('connected', () => console.log('Connected'));

Method Calls

// Via InterfaceProxy
const result = await iface.call<string>('MethodName', 'si', ['arg1', 42]);

// Via Bus directly
const result = await bus.call<string>(dest, path, iface, method, 'si', ['arg1', 42]);

// With timeout and abort
const result = await bus.call<string>(dest, path, iface, method, 's', ['arg'],
  { timeout: 5000, signal: abortController.signal });

Properties

const val = await bus.getProperty<string>(dest, path, iface, 'PropName');
await bus.setProperty(dest, path, iface, 'PropName', 's', 'value');
const all = await bus.getAllProperties(dest, path, iface);

Signals

iface.on('SignalName', (...args) => { /* handle signal */ });
iface.off('SignalName', handler);
iface.removeAllListeners('SignalName');

Introspection

const data = await obj.introspect();  // Cached
data.interfaces;                     // IntrospectionInterface[]
data.nodes;                          // string[] (child paths)

Code Generation

Generate typed TypeScript proxies from DBus introspection:

# CLI: Introspect a live service
npx dbus-codegen --service org.mpris.MediaPlayer2.vlc -p /org/mpris/MediaPlayer2 -o mpris.ts

# CLI: From XML file
npx dbus-codegen --xml introspection.xml -o types.ts
// Programmatic API
import { parseIntrospectionXml, generateTypescript, signatureToTs } from '@timschrader/node-dbus';

signatureToTs('a{sv}');  // 'Record<string, Variant>'

const data = parseIntrospectionXml(xml);
const code = generateTypescript(data);

// Use generated proxy
import { MediaPlayer2Player } from './generated/mpris';
const proxy = new MediaPlayer2Player(iface);
await proxy.Play();  // Fully typed!

See docs/guide/codegen.md for full documentation.

Name Management

import { NameFlags, NameResult } from '@timschrader/node-dbus';

const result = bus.requestName('com.example.MyService', NameFlags.REPLACE_EXISTING);
if (result === NameResult.PRIMARY_OWNER) { /* success */ }

bus.releaseName('com.example.MyService');

Service Export

// Fixed object path
const builder = new ServiceBuilder('com.example.Iface')
  .method('Method', 'ii', 'i', (a, b) => a + b)
  .property('Prop', 's', getter, setter)
  .signal('Signal', 'si');

bus.exportObject('/path', builder);
bus.unexportObject('/path');

// Dynamic paths (fallback)
const fb = new FallbackBuilder('com.example.Users')
  .method('GetName', '', 's', (path) => path.split('/').pop()!);

bus.addFallback('/com/example/users', fb);

// ObjectManager (GetManagedObjects)
bus.addObjectManager('/com/example');

Type System

All DBus types are supported:

| Signature | Type | JavaScript | |-----------|------|------------| | y | byte | number | | b | boolean | boolean | | n, q, i, u | int16/uint16/int32/uint32 | number | | x, t | int64/uint64 | BigInt | | d | double | number | | s | string | string | | o | object path | string | | g | signature | string | | v | variant | Variant | | a... | array | array | | (...) | struct | array | | a{...} | dict | object |

import { Variant, VariantTypes, validateSignature } from '@timschrader/node-dbus';

// Create variants
const v = new Variant('s', 'hello');
const v2 = VariantTypes.int32(42);

// Validate
validateSignature('a{sv}');        // true
validateValue('i', 42);            // true
validateObjectPath('/org/test');    // true

Retry & Timeouts

import { withRetry } from '@timschrader/node-dbus';

// Per-call timeout
bus.setDefaultTimeout(10000);  // 10s default

// Retry with backoff
const result = await withRetry(
  () => bus.call(dest, path, iface, method),
  { retries: 3, delayMs: 100 }
);

Examples

See examples/ for runnable TypeScript examples:

npx tsx examples/client-basics.ts      # Connect, call methods, properties
npx tsx examples/signals.ts            # Signal subscription
npx tsx examples/service.ts            # Create a DBus service
npx tsx examples/introspection.ts      # Discover interfaces
npx tsx examples/types-and-variants.ts # Type system showcase
npx tsx examples/advanced.ts           # All features combined
npx tsx examples/codegen.ts            # Type code generation

Architecture

TypeScript (High-level API, Events, Timeouts)
    ↓ N-API
C++ (ALL DBus communication, Type serialization)
    ↓ sd-bus API
sd-bus Library (Wire protocol, Authentication)

All DBus communication happens in C++ via sd-bus. TypeScript provides the high-level API, event management, and object lifecycle. Type validation happens in C++ before any data reaches the wire.


Development

npm run build              # Build TypeScript
npm run build:native       # Build C++ addon
npm run build:all          # Both
npm test                   # Run tests (Vitest)
npm run dev                # Watch mode

Project Structure

src/           TypeScript source (Bus, InterfaceProxy, ServiceBuilder, ...)
native/src/    C++ N-API addon (bus, types, signals, methods, service)
test/          Vitest tests (unit + integration)
examples/      Runnable TypeScript examples
docs/          Documentation (user guide + dev reference)

See docs/ for full documentation including the API reference and architecture guide.


Requirements

  • OS: Linux (systemd-based distributions)
  • Node.js: ≥18.0.0
  • System: libsystemd-dev, pkg-config, build-essential

License

MIT © Tim Schrader