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

@emby-utils/client

v0.2.0

Published

Typed Emby HTTP client driven by the official Emby OpenAPI spec (447 operations).

Readme

@emby-utils/client

Typed HTTP client for the Emby REST API, driven by the official Emby OpenAPI spec. Every one of the 447 operations in the spec is reachable by its operationId, with path-param substitution, required-param validation, automatic retries on transient failures, async pagination, and streaming for binary endpoints.

Install

npm install @emby-utils/client

Requires Node.js >= 22.13. ESM-only.

Usage

import { EmbyClient } from "@emby-utils/client";

const client = new EmbyClient("http://emby.local:8096", "API_KEY");

// Typed calls — the return type is inferred from a curated ResponseTypeMap.
const info = await client.callOperation("getSystemInfo");
//    ^? SystemInfo

// Any operation in the spec is dispatchable:
const episodes = await client.callOperation("getItems", {
  queryParams: { IncludeItemTypes: "Episode", SearchTerm: "severance" },
});

Authentication

By default the client sends both X-Emby-Token and the legacy api_key query param, so it works with every endpoint.

To log in with a username/password and swap the token into the client:

const client = new EmbyClient("http://emby.local:8096", ""); // no key yet
const { AccessToken } = await client.loginWithPassword({
  username: "alice",
  password: "secret",
});

First-run (startup wizard)

The Emby startup-wizard endpoints are not in the OpenAPI spec. They are exposed as dedicated methods and work against an un-initialized server (no auth required). isStartupComplete() deliberately strips auth so it can reliably detect completion on a server that would otherwise accept an admin token.

const client = new EmbyClient("http://emby.local:8096", ""); // no key yet
if (!(await client.isStartupComplete())) {
  await client.postStartupConfiguration({
    UICulture: "en-US",
    MetadataCountryCode: "US",
    PreferredMetadataLanguage: "en",
  });
  await client.postStartupUser({ Name: "alice", Password: "secret" });
  await client.postStartupComplete();
}

Idempotent library creation

POST /Library/VirtualFolders is not idempotent — calling it twice creates a duplicate. addLibrary() checks the existing virtual folders first:

const result = await client.addLibrary({
  name: "Movies",
  path: "/data/movies",
  collectionType: "movies",
});
// { created: true } on first run, { created: false, existing: {...} } thereafter.

Pagination & streaming

for await (const item of client.paginate("getItems", { pageSize: 100 })) {
  console.log(item.Name);
}

const stream = await client.stream("getItemsByIdImagesByType", {
  pathParams: { Id: "abc", Type: "Primary" },
});
stream.pipe(process.stdout);

Retry policy

GET/HEAD/OPTIONS are retried up to 2 times on network errors or 5xx/408/425/429 responses, with exponential backoff (default base 250 ms). Override:

new EmbyClient(host, key, {
  timeoutMs: 10_000,
  retries: 5,
  retryBaseDelayMs: 500,
});

Or per-request:

await client.callOperation("getItems", { timeoutMs: 2_000, retries: 0 });

Discovering operations

import { operations } from "@emby-utils/client";
console.log(Object.keys(operations).length); // 447
console.log(operations.getSystemInfo);
// { operationId: "getSystemInfo", method: "GET", path: "/System/Info", ... }

The operation registry is also available at a zero-side-effect subpath, so tools that only need the spec metadata don't have to load axios:

import { operations } from "@emby-utils/client/operations";

Detecting errors

axios's type guard is re-exported so consumers don't need a direct dependency on axios:

import { isAxiosError } from "@emby-utils/client";

try {
  await client.callOperation("getSystemInfo");
} catch (err) {
  if (isAxiosError(err) && err.response?.status === 401) {
    // handle unauthenticated
  }
}

Notes

  • GET /Items/{Id} does not exist on Emby. Use getUsersByUseridItemsById (GET /Users/{UserId}/Items/{Id}) for a user-scoped item detail.
  • A handful of upstream path placeholders lack parameter metadata in the spec. Required-param validation tolerates this — failures surface only when the missing value is genuinely required.
  • The spec is vendored at spec/openapi.json. Regenerate the operation registry with npm run generate.

Relationship to the official Emby JS SDK

Emby publishes a Swagger-generated JavaScript client at MediaBrowser/Emby.ApiClients (embyclient-js). It is not published to npm, uses callback-style APIs, and its upstream README explicitly recommends vendoring rather than installing as a dep.

@emby-utils/client is a TypeScript-first alternative generated from the same Emby OpenAPI spec. It adds retries, pagination, streaming, typed responses, and coverage for workflows the official SDK skips (startup wizard, idempotent init, drift-safe library creation). If you need the official generated DTOs by name, they are a useful read-only reference in Clients/JavaScript/src/model/.

License

MIT