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

velora-node-sdk

v1.1.0

Published

Node.js SDK for Velora local API with registration, HTTP endpoints, and WebSocket support

Readme

Velora SDK

Node.js SDK for the Velora local API, providing easy access to the Velora Electron app's playback controls, state queries, and real-time event streaming.

Features

  • HTTP & WebSocket Support — Read current track, playback state, and playback queue; control playback (play, pause, skip, seek)
  • App Registration — Secure request-based authorization with user consent
  • Token Management — Automatic token polling and permission checking
  • Real-time Events — Connect to WebSocket for track changes and playback state updates
  • Auto-reconnection — Exponential backoff reconnection on WebSocket disconnect
  • TypeScript Ready — Full type definitions for all APIs
  • Error Classification — Specific error types for easier error handling

Installation

npm install velora-node-sdk

Quick Start

1. Register Your App

import { VeloraClient } from 'velora-node-sdk';

const client = new VeloraClient();

const registrationConfig = {
  app: {
    name: 'My awesome app',
    description: 'An application that is awesome!',
    developer: 'ItsMeDev',
    website: 'https://example.com',
    icon: 'https://example.com/icon.png',
  },
  permissions: ['read', 'write'],
};

const requestId = await client.registerApp(registrationConfig);
console.log('Registration request ID:', requestId);

2. Poll for User Approval

const maxWaitMs = 5 * 60 * 1000;
await client.requestAccessToken(requestId, maxWaitMs);
console.log('User approved! Token acquired.');

3. Use HTTP Endpoints

const health = await client.getHealth();
console.log('Velora is running on port:', health.port);

const track = await client.getCurrentTrack();
console.log(`Now playing: ${track.track.title} by ${track.track.artist}`);

const playbackState = await client.getPlaybackState();
console.log('Is playing:', playbackState.is_playing);

const queue = await client.getPlaybackQueue();
console.log('Queue size:', queue.queue.length);

const user = await client.getUserPublic();
console.log('User:', user.user.name);

4. Control Playback

await client.play('OrZoMJcXje2');
await client.pause();
await client.next();
await client.seek(60000);
await client.toggle();

5. Listen to Real-time Events

await client.connectWebSocket();

client.on('track_changed', (data) => {
  console.log(`Track changed: ${data.title} by ${data.artist}`);
});

client.on('playback_state_changed', (data) => {
  console.log('Playing:', data.is_playing);
});

client.on('ws:connected', () => {
  console.log('WebSocket connected');
});

client.on('ws:disconnected', () => {
  console.log('WebSocket disconnected');
});

client.on('ws:error', (error) => {
  console.error('WebSocket error:', error);
});

API Reference

VeloraClient

Constructor

new VeloraClient(config?: ClientConfig)

Options:

  • host (string, default: 127.0.0.1) — Velora server host
  • port (number, default: 39031) — Velora server port
  • token (string, optional) — Pre-existing access token
  • requestedPermissions (array, optional) — Permissions for pre-existing token
  • httpOptions (object, optional) — HTTP client options (timeout, maxRetries)
  • wsOptions (object, optional) — WebSocket options

Authentication Methods

registerApp(appConfig: RegisterAppRequest): Promise<string>

Register your app and request permissions. Returns a request_id to poll.

const requestId = await client.registerApp({
  app: {
    name: 'My App',
    description: 'Optional description',
    developer: 'Developer name',
    website: 'https://example.com',
    icon: 'https://example.com/icon.png',
  },
  permissions: ['read', 'write'],
});
requestAccessToken(requestId: string, maxWaitMs?: number): Promise<void>

Poll for user approval. Waits up to maxWaitMs (default 5 minutes).

await client.requestAccessToken(requestId);
isAuthenticated(): boolean

Check if client has a valid token.

if (client.isAuthenticated()) {
  console.log('Ready to use API');
}
getToken(): string | null

Get the current access token.

setToken(token: string, permissions?: PermissionType[]): void

Manually set a token (e.g., from storage).

client.setToken('velora_...', ['read', 'write']);
clearCredentials(): void

Clear token and permissions.

client.clearCredentials();

Read Endpoints

All read endpoints require read permission.

getHealth(): Promise<HealthResponse>

Check Velora server status.

const health = await client.getHealth();
getCurrentTrack(): Promise<CurrentTrackResponse>

Get the current playing track.

const response = await client.getCurrentTrack();
console.log(response.track.title);
getPlaybackState(): Promise<PlaybackStateResponse>

Get playback flags (is_playing, shuffle, repeat).

const state = await client.getPlaybackState();
getPlaybackQueue(): Promise<PlaybackQueueResponse>

Get the current playback queue and metadata.

const queue = await client.getPlaybackQueue();
getUserPublic(): Promise<UserPublicResponse>

Get the signed-in user's public profile snapshot.

const user = await client.getUserPublic();

Write Endpoints

All write endpoints require write permission.

play(trackId?: string): Promise<PlayResponse>

Start playback or resume. Optionally specify a track ID.

await client.play();
await client.play('OrZoMJcXje2');
pause(): Promise<PauseResponse>

Pause playback.

await client.pause();
next(): Promise<NextResponse>

Skip to next track.

await client.next();
seek(position: number): Promise<SeekResponse>

Seek to a position in milliseconds.

await client.seek(60000);
toggle(): Promise<ToggleResponse>

Toggle between play and pause.

await client.toggle();

WebSocket Methods

connectWebSocket(): Promise<void>

Establish WebSocket connection to receive real-time events.

await client.connectWebSocket();
disconnectWebSocket(): Promise<void>

Close WebSocket connection.

await client.disconnectWebSocket();
isWSConnected(): boolean

Check if WebSocket is connected.

if (client.isWSConnected()) {
  console.log('Receiving real-time updates');
}

WebSocket Events

track_changed

Emitted when the track changes.

client.on('track_changed', (data: TrackChangedData) => {
  console.log(data.id, data.title, data.artist);
});
playback_state_changed

Emitted when playback state changes.

client.on('playback_state_changed', (data: PlaybackStateChangedData) => {
  console.log('is_playing:', data.is_playing);
  console.log('shuffle:', data.shuffle);
  console.log('repeat:', data.repeat);
});
ws:connected

Emitted when WebSocket connects.

client.on('ws:connected', () => {
  console.log('WebSocket connected');
});
ws:disconnected

Emitted when WebSocket disconnects.

client.on('ws:disconnected', () => {
  console.log('WebSocket disconnected');
});
ws:connecting

Emitted before each connection attempt.

client.on('ws:connecting', () => {
  console.log('Attempting to connect...');
});
ws:error

Emitted on WebSocket errors.

client.on('ws:error', (error: Error) => {
  console.error('WebSocket error:', error.message);
});

Error Handling

The SDK provides specific error classes to help identify issues:

import { 
  VeloraError,
  AuthError,
  NetworkError,
  ValidationError,
  TimeoutError,
} from 'velora-node-sdk';

try {
  await client.getCurrentTrack();
} catch (error) {
  if (error instanceof AuthError) {
    console.error('Permission denied or invalid token');
  } else if (error instanceof NetworkError) {
    console.error('Network issue:', error.message);
  } else if (error instanceof ValidationError) {
    console.error('Invalid input:', error.message);
  } else if (error instanceof TimeoutError) {
    console.error('Request timed out');
  } else if (error instanceof VeloraError) {
    console.error('Velora error:', error.message, error.code);
  }
}

Error Classes

  • VeloraError — Base error class; all Velora errors extend this
  • AuthError — Authentication or authorization failure (401/403)
  • NetworkError — Network or connection issue
  • ValidationError — Invalid input or request body
  • TimeoutError — Request timeout
  • RateLimitError — Rate limit exceeded (429)
  • RequestError — HTTP error (4xx or 5xx)

Configuration

HTTP Options

const client = new VeloraClient({
  httpOptions: {
    timeout: 30000,
    maxRetries: 3,
  },
});
  • timeout — Request timeout in milliseconds (default: 30000)
  • maxRetries — Max retry attempts for 5xx errors (default: 3)

WebSocket Options

const client = new VeloraClient({
  wsOptions: {
    initialBackoffMs: 1000,
    maxBackoffMs: 60000,
  },
});
  • initialBackoffMs — Initial reconnect backoff (default: 1000ms)
  • maxBackoffMs — Max reconnect backoff (default: 60000ms)

Connection Lifecycle

Basic Flow

  1. Create client
  2. Register app (or use pre-existing token)
  3. Poll for user approval (if registering)
  4. Call connect() to verify health and optionally start WebSocket
  5. Use HTTP or WebSocket APIs
  6. Call disconnect() when done

With Pre-existing Token

const client = new VeloraClient({
  token: 'velora_...',
  requestedPermissions: ['read', 'write'],
});

const track = await client.getCurrentTrack();

Error Recovery

HTTP client automatically retries on 5xx errors with exponential backoff. WebSocket client auto-reconnects on disconnect with backoff.

client.on('ws:error', (error) => {
  console.log('Disconnected, will attempt to reconnect...');
});

TypeScript Support

The SDK is written in TypeScript and includes full type definitions. All APIs are strictly typed:

import { VeloraClient, CurrentTrackResponse, TrackChangedData } from 'velora-node-sdk';

const client = new VeloraClient();

const response: CurrentTrackResponse = await client.getCurrentTrack();

client.on('track_changed', (data: TrackChangedData) => {
  console.log(data.title);
});

Permissions

  • read — Access to all GET endpoints and WebSocket
  • write — Access to all POST endpoints (play, pause, seek, etc.)

Check permissions at runtime:

if (client.getPermissions().includes('write')) {
  await client.play();
}

Localhost only

The Velora local API only accepts connections from 127.0.0.1 or ::1. The SDK enforces this at the client level.