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

@fluxomni/api-client

v0.12.0

Published

TypeScript GraphQL client for Fluxomni API

Downloads

226

Readme

@fluxomni/api-client

Thin TypeScript transport for the Fluxomni GraphQL API. The public automation surface is intentionally small: authenticate with the session API, send direct GraphQL documents, and opt into generated documents/types when compile-time operation typing is useful.

The current package surface is a public API preview. The stable contract is the GraphQL schema, the transport client, and the generated documents/types.

Installation

pnpm add @fluxomni/api-client
# or
npm install @fluxomni/api-client

Minimal Automation Client

Use executeRaw() for scripts and examples. It sends the GraphQL text exactly as written and returns the data payload.

import { GraphQLClient } from '@fluxomni/api-client';

const { client } = await GraphQLClient.login({
  baseUrl: 'http://localhost:8001',
  username: process.env.FLUXOMNI_USERNAME!,
  password: process.env.FLUXOMNI_PASSWORD!,
});

const data = await client.executeRaw<{
  routes: { allRoutes: Array<{ id: string; label?: string | null }> };
}>(`
  query Routes {
    routes {
      allRoutes {
        id
        label
      }
    }
  }
`);

console.log(data.routes.allRoutes);

Session Login

The first public automation path is user session login through /api/auth/login. GraphQLClient.login() posts the username and password, then builds a GraphQL client that reuses the returned fluxomni_session cookie for /api requests and /api/subscriptions WebSocket connection params when the runtime exposes Set-Cookie.

Browser and same-origin callers can omit endpoints:

const { client } = await GraphQLClient.login({
  username,
  password,
});

Server-side callers usually pass a server base URL:

const { client, cookieHeader } = await GraphQLClient.login({
  baseUrl: 'http://localhost:8001',
  username,
  password,
});

Session lifetime is controlled by the server's sessionTtlSeconds setting. 0 or null disables expiry; otherwise the in-memory session expires after that many seconds from login. Scripts should treat HTTP 401 or GraphQL extensions.code: "UNAUTHORIZED" as a signal to log in again.

For same-origin browser code, keep browser wiring in the webapp boundary. @fluxomni/api-client stays transport-only; the webapp should construct same-origin clients through its local createWebappGraphQLClient() helper.

Typed Generated Operations

Generated GraphQL documents and result types are exported from the package. Use them when compile-time operation typing matters.

import { GraphQLClient, ServerInfoDocument } from '@fluxomni/api-client';

const { client } = await GraphQLClient.login({
  username: process.env.FLUXOMNI_USERNAME!,
  password: process.env.FLUXOMNI_PASSWORD!,
});
const data = await client.query({ query: ServerInfoDocument });

Subscriptions

The client owns Apollo and graphql-ws setup so callers do not need to wire the transport manually.

import { GraphQLClient, StateDocument } from '@fluxomni/api-client';

const client = new GraphQLClient(
  {
    httpEndpoint: 'http://localhost:8001/api',
    wsEndpoint: 'ws://localhost:8001/api/subscriptions',
    credentials: 'same-origin',
  },
  {
    onConnect: () => console.log('connected'),
    onDisconnect: () => console.log('disconnected'),
  },
);

const subscription = client.subscribe({
  query: StateDocument,
}).subscribe({
  next: (result) => console.log(result.data),
  error: (error) => console.error(error),
});

subscription.unsubscribe();
client.stop();

Server-side subscription callers can pass a session cookie through login:

const { client } = await GraphQLClient.login({
  baseUrl: 'http://localhost:8001',
  username: process.env.FLUXOMNI_USERNAME!,
  password: process.env.FLUXOMNI_PASSWORD!,
  wsEndpoint: 'ws://localhost:8001/api/subscriptions',
});

The login helper forwards the session cookie through connection_init.cookie for server-side graphql-ws callers. Browser callers normally rely on the browser's same-origin cookie handling instead.

Examples

Executable examples live under api/examples/typescript.

FLUXOMNI_BASE_URL=http://127.0.0.1:8001 \
FLUXOMNI_USERNAME=admin \
FLUXOMNI_PASSWORD=... \
pnpm --filter @fluxomni/api-examples run session:raw-subscription

Idempotent route convergence example:

FLUXOMNI_BASE_URL=http://127.0.0.1:8001 \
FLUXOMNI_USERNAME=admin \
FLUXOMNI_PASSWORD=... \
pnpm --filter @fluxomni/api-examples run ensure-route

Route controls example:

FLUXOMNI_BASE_URL=http://127.0.0.1:8001 \
FLUXOMNI_USERNAME=admin \
FLUXOMNI_PASSWORD=... \
FLUXOMNI_ROUTE_ID=... \
FLUXOMNI_SOURCE_ID=... \
FLUXOMNI_OUTPUT_ID=... \
pnpm --filter @fluxomni/api-examples run manage-route-controls

Playlist, artifact tags, settings export/import, and Fleet read/command example:

FLUXOMNI_BASE_URL=http://127.0.0.1:8001 \
FLUXOMNI_USERNAME=admin \
FLUXOMNI_PASSWORD=... \
pnpm --filter @fluxomni/api-examples run manage-playlist-artifacts-settings-fleet

The examples compile through the API client package:

pnpm --filter @fluxomni/api-client run examples:check

The examples print the public error category from classifyGraphQLError() next to each server extensions.code, so scripts can use the same taxonomy as the README error-handling snippet.

Error Handling

import {
  ClientError,
  GraphQLError,
  NetworkError,
  classifyGraphQLError,
} from '@fluxomni/api-client';

try {
  await client.executeRaw('query Routes { routes { allRoutes { id } } }');
} catch (error) {
  if (error instanceof GraphQLError) {
    for (const serverError of error.errors) {
      switch (classifyGraphQLError(serverError)) {
        case 'unauthenticated':
          throw new Error('Session expired; log in again.');
        case 'forbidden':
          throw new Error('The current role cannot run this operation.');
        case 'not_found':
          console.warn('Target was already absent:', serverError.code);
          break;
        case 'conflict':
        case 'operation_rejected':
          throw new Error(`State changed before the operation: ${serverError.code}`);
        case 'runtime_unavailable':
          throw new Error(`Runtime state is unavailable: ${serverError.code}`);
        default:
          throw error;
      }
    }
  } else if (error instanceof NetworkError) {
    console.error('Network error:', error.message);
  } else if (error instanceof ClientError) {
    console.error('Client error:', error.message);
  }
}

Mutation result payloads are not exceptions. Treat statuses such as UPDATED, UNCHANGED, and NOT_FOUND as normal convergence outcomes when the schema returns them.

Development

pnpm install --frozen-lockfile
pnpm --filter @fluxomni/api-client run graphql:codegen
pnpm --filter @fluxomni/api-client run build
pnpm --filter @fluxomni/api-client run lint
pnpm --filter @fluxomni/api-client run test

License

PolyForm Noncommercial License 1.0.0