Skip to content

Latest commit

 

History

History
249 lines (178 loc) · 8.91 KB

File metadata and controls

249 lines (178 loc) · 8.91 KB

⤴️ Back to the Clients README

TypeScript/JavaScript Client

A comprehensive TypeScript client that provides full access to all NeuroInfoAPI endpoints with proper type definitions.

Note

The client defaults to https://neuro.appstun.net/api/v2 and unwraps API responses automatically.
Upgrading from v1? See the client migration guide.

The client is also available as an NPM package: neuroinfoapi-client

File: NeuroInfoAPI-Client.ts


Note

JavaScript is already prebuilt in this folder (NeuroInfoAPI-Client.js). You do not need to convert the TypeScript file yourself.

Features

  • 🔒 Authentication Support - Automatic Bearer token handling
  • 📝 Full TypeScript Support - Complete type definitions for all API responses
  • ⏱️ Timeout Protection - 10-second request timeout by default
  • Type-Safe Error Handling - Result pattern with { data, error } return type
  • 📦 Response Unwrapping - Automatically unwraps { data: ... } API responses
  • 📰 Blog Feed Support - Fetch parsed or raw blog feed data
  • 📡 Event System - NeuroInfoApiEventer for "real-time" updates (deprecated)
  • WebSocket Client - NeuroInfoApiWebsocketClient for true real-time updates with auto reconnect

Requirements

The client uses a bundled lightweight HttpClient built on the standard fetch, AbortController, URL, and WebSocket Web APIs. No external HTTP package is required.

Works in browser projects too (Vite/Webpack/Rollup/etc.). For direct browser ESM imports, import the prebuilt JavaScript file with its extension:

import { NeuroInfoApiClient } from "./NeuroInfoAPI-Client.js";

Node.js usage requires a runtime with global fetch and WebSocket support for the WebSocket client. If your Node.js version does not provide global WebSocket, use a browser/bundler runtime or provide a compatible global before connecting.

Quick Start

Use the file that matches your project setup:

  • TypeScript: NeuroInfoAPI-Client.ts
  • JavaScript: NeuroInfoAPI-Client.js
import { NeuroInfoApiClient } from "./NeuroInfoAPI-Client";

const client = new NeuroInfoApiClient();

// For endpoints requiring authentication
client.setApiToken("your-api-token-here");

Browser Usage

import { NeuroInfoApiClient, NeuroInfoApiWebsocketClient } from "./NeuroInfoAPI-Client";

const client = new NeuroInfoApiClient();
client.setApiToken("your-api-token-here");

// Browser-safe default uses ticket auth (no token in WS URL)
const wsClient = new NeuroInfoApiWebsocketClient("your-api-token-here");
await wsClient.connect();

Note

For browsers, keep authMethod as the default ("ticket"). "header" auth is runtime-dependent and mainly intended for Node.js environments.

Error Handling

All client methods return a result object with either data or error:

const { data, error } = await client.getCurrentStream();

if (error) {
  // NeuroApiError: code, message, status, timestamp, path
  console.log(`Error ${error.code}: ${error.message}`);
  if (error.path) console.log(`At ${error.path} (${error.timestamp})`);
  return;
}

// TypeScript knows data is TwitchStreamData here
console.log(data.title);

Blog Feed

getBlogFeed() requires an API token. Use getBlogFeed() for parsed sections or getBlogFeed(true) for raw HTML content.

client.setApiToken("your-api-token-here");

const parsedFeed = await client.getBlogFeed();
const rawFeed = await client.getBlogFeed(true);

if (parsedFeed.data) {
  console.log(parsedFeed.data.entries[0]?.content);
}

if (rawFeed.data) {
  console.log(rawFeed.data.entries[0]?.rawContent);
}

Schedule Status

Schedule responses include a status field:

  • confirmed — final, manually confirmed
  • auto_discord — auto-collected from the Discord schedule channel
  • auto_twitch — auto-collected or fetched from Twitch

Use the exported helper isScheduleFinal(status) when you need a boolean check.

import { isScheduleFinal } from "./NeuroInfoAPI-Client";

const { data } = await client.getLatestSchedule();
if (data && !isScheduleFinal(data.status)) {
  console.log("Schedule may still change");
}

Schedule Search Pagination

Use getScheduleSearch to search schedule entries and continue with nextCursor. Optional filter: type (normal, offline, canceled, TBD, unknown).

Important

/schedule/search uses two limits: 6 requests/minute and 2 requests/10 seconds per token. Pagination can continue immediately, but avoid tight loops.

const firstPage = await client.getScheduleSearch("karaoke", { limit: 5, sort: "desc", type: "normal" });
if (firstPage.error) {
  console.error(firstPage.error.code, firstPage.error.message);
} else {
  console.log("matches:", firstPage.data.results.length);

  if (firstPage.data.nextCursor) {
    const secondPage = await client.getScheduleSearch("karaoke", {
      limit: 5,
      sort: "desc",
      cursor: firstPage.data.nextCursor,
    });
    console.log("next page:", secondPage.data?.results.length ?? 0);
  }
}

Event System (deprecated)

Important

The NeuroInfoApiEventer is now deprecated in favor of the more robust NeuroInfoApiWebsocketClient.
The WebSocket client provides true real-time updates with lower latency and better reliability. However, the eventer is still available for use if you prefer a simpler polling-based approach.

Use NeuroInfoApiEventer to listen for "real-time" updates:

import { NeuroInfoApiEventer } from "./NeuroInfoAPI-Client";

const eventer = new NeuroInfoApiEventer();
eventer.setApiToken("your-api-token-here");

// Listen for stream going live
eventer.on("streamOnline", (stream) => {
  console.log(`${stream.title} is now live!`);
});

// With optional error handler
eventer.on(
  "scheduleUpdate",
  (schedule) => console.log(`New schedule for week ${schedule.week}`),
  (error) => console.log(`Failed to fetch schedule: ${error.code}`)
);

// Start polling (default: every 60 seconds, minimum: 10 seconds)
eventer.fetchInterval = 30000; // 30 seconds
eventer.startEventLoop();

Available Events:

Event Description
streamOnline Stream went live
streamOffline Stream went offline
streamUpdate Any stream data changed
scheduleUpdate Schedule was updated
subathonUpdate Subathon data changed
subathonGoalUpdate A subathon goal was reached/updated

WebSocket Client

Use NeuroInfoApiWebsocketClient for low-latency, push-based updates:

import { NeuroInfoApiWebsocketClient } from "./NeuroInfoAPI-Client";

const wsClient = new NeuroInfoApiWebsocketClient("your-api-token-here");

wsClient.on("_connected", (sessionId) => {
  console.log("Connected with session:", sessionId);
});

wsClient.on("_eventAdded", (eventType) => {
  console.log("Subscribed:", eventType);
});

wsClient.on("_eventRemoved", (eventType) => {
  console.log("Unsubscribed:", eventType);
});

wsClient.on("streamOnline", (stream) => {
  console.log("Stream online:", stream.title);
});

await wsClient.connect();

Available WebSocket Events:

Event Description
streamOnline Stream went live
streamOffline Stream went offline
streamUpdate Stream metadata changed
secretneuroaccountOnline Special alert: secretneuroaccount is live
streamRaidIncoming Incoming raid event
streamRaidOutgoing Outgoing raid event
blogFeedUpdate Blog feed changed; includes changed/new entries only
scheduleUpdate Weekly schedule changed
subathonUpdate Subathon state changed
subathonGoalUpdate Subathon goal changed

secretneuroaccountOnline sends the same payload shape as streamOnline, but it is emitted specifically when the Twitch account secretneuroaccount goes live. This is the only event for this account.

Note

By default, the WebSocket client uses ticket-based authentication (GET /api/v2/ws/ticket) before connecting. This avoids putting API tokens into URL query parameters.


Need help or found a bug? Feel free to open an issue or start a discussion!