OPENHOOPSTeam build 2026.10.20-team1 · Windows
Team package status: see docs/VERIFICATION.md at the bundle root for current acceptance. Earlier source-version/pending/release statements in this API example reference retain their original capture scope.

OpenHoops TypeScript client

Private source package @openhoops/client0.1.0-dev.1 targets HTTPv1/private broker55. It has no runtime npm dependencies. Generated source follows the maintained OpenAPI contract; use the developer guide for preflight and game-free scenarios. This package has not been published to npm or included in a public hook release.

Build the local package with the pinned compiler:

npm ci --ignore-scripts
npm run build
npm run check
npm test

python generate.py --check detects schema/type drift; python generate.py regenerates the checked-in source. The compiler uses strict null checking, exact optional properties and checked index access. Finite command discriminators preserve conditional required fields. JSON Schema's ranges, patterns and other cross-field constraints still require server validation; TypeScript types do not validate untrusted JSON at runtime. Protocol/schema versions and declared capabilities remain separate from live verification.

import {OpenHoopsClient} from './dist/index.js';
import type {Schemas} from './dist/index.js';

const client = new OpenHoopsClient({token: privateToken, baseUrl: 'http://127.0.0.1:27614'});
const session = await client.session();
const snapshot = await client.snapshot();
const match = await client.request('GET /v1/matches/{id}', {path: {id: 'season:game-1'}});
const report = await client.compatibility({request: myCompleteMatchRequest});

Every JSON/binary operation has a generated input and response type. Path parameters are encoded, unknown operations/query keys refuse, and the token stays in a private field and Authorization header. The endpoint must be loopback HTTP, including a local SSH tunnel port; redirects are refused. Browser origin/CORS protections are unchanged. Node/desktop/backend applications can use the client directly; hosted web applications need their own trusted bridge. Node22+ is the declared core target; actual runtime evidence is recorded in the acceptance ledger. No browser or Mac/Linux game certification is implied.

Use uploadRoster, uploadMetadata and uploadAssets with independently owned Uint8Array data. The client copies before hashing/submitting and verifies the returned content ID. Raw metadata bytes retain their exact JSON encoding. Upload helpers buffer the supplied data; use the existing Python streaming uploader for larger asset packages where that memory cost is unsuitable. Roster and package admission never mean that the game loaded them.

ApiError preserves HTTP status, code and details. TransportError.outcomeUnknown identifies a mutation whose response could not be obtained. The SDK never retries a mutation automatically, invents a new command ID or interprets an uncertain Start as false. Keep durable command/request identities and inspect their existing receipts after ambiguous responses. Treat failed mutation responses, including HTTP5xx, as potentially applied until the matching receipt establishes their outcome. Pass signal/timeoutMs for cancellation and deadlines. Response reads are bounded; JSON must be finite and acyclic.

for await (const event of client.events({after: lastCommittedCursor, signal})) {
  await myDatabase.commitEvent(event);
  lastCommittedCursor = event.event_id;
}

SSE is a dedicated cancellable iterator. The caller persists a cursor only after its own transaction commits. HTTP refusals and in-stream gaps raise structured errors; there is no silent reconnect, cursor advance or invented basketball event. Unknown legal-state fields remain nullable and must be checked before use.

const result = await client.receiveResult({
  matchId, consumerId: 'my-dynasty', store: myDurableResultStore, signal
});

ResultStore.load/save is an application-owned durable boundary. save must enforce immutable (consumer,match,revision) content and resolve only after committing. The SDK stores each delivered revision before ACK, recovers lost ACK responses from the durable copy and returns the newest known revision without downgrading to an older outstanding delivery. A save failure, abandonment, review-required state or deadline does not generate a fabricated result or stop a game.

The optional SQLite inbox example uses Node's built-in SQLite module with WAL/FULL synchronization. It has no game token and no first-party league schema. It is an example of a storage implementation; a real dynasty application may commit into its own league transaction. SQLite runtime support is specific to the tested Node version and separate from the portable client core.

Primary platform references: TypeScript strict mode, Node Fetch/AbortController, Node SQLite. Tests and source identities are in the work64 ledger.