@fluxomni/api-client
v0.12.0
Published
TypeScript GraphQL client for Fluxomni API
Downloads
226
Maintainers
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-clientMinimal 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-subscriptionIdempotent route convergence example:
FLUXOMNI_BASE_URL=http://127.0.0.1:8001 \
FLUXOMNI_USERNAME=admin \
FLUXOMNI_PASSWORD=... \
pnpm --filter @fluxomni/api-examples run ensure-routeRoute 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-controlsPlaylist, 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-fleetThe examples compile through the API client package:
pnpm --filter @fluxomni/api-client run examples:checkThe 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 testLicense
PolyForm Noncommercial License 1.0.0
