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

@cinadmin/game-sdk

v0.1.0-alpha.0

Published

Official runtime SDK for CinAdmin AR games (TypeScript/JS). Token-exchange auth, discover/join, and the v2 runtime WebSocket.

Readme

@cinadmin/game-sdk

The official runtime SDK for CinAdmin AR games (TypeScript / JavaScript). The TS twin of the Unity SDK (CinAdmin.GameSdk) — same surface, same contract.

It handles the three things a runtime title needs at showtime:

  1. Auth — exchanges your short-lived runtime token and re-mints it transparently.
  2. Discover / join — finds and joins the session running in a venue.
  3. The v2 WebSocket — live scores, game messages, player join/leave, with an offline queue that flushes on reconnect.

This package is the runtime client. For registering plays / managing your catalogue use the admin SDK (@cinadmin/sdk).

Install

npm install @cinadmin/game-sdk

Auth model (read this first)

There are two tokens. Keep them straight:

| Token | What it is | Where it lives | | ---------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | Build token (cinadm_sdk_*, ~90-day) | Your GP identity. Issued once in the portal (Settings → SDK access, one-shot reveal). | Your backend only. Never in an APK, never in the browser, never in this SDK. | | Runtime session token (ES256 JWT, ~20-min) | The Bearer on every runtime call. | Minted by exchanging the build token at POST /api/v1/sdk/session-token. This SDK uses it. |

The SDK takes a tokenProvider callback: a function that returns a fresh runtime token. You implement the exchange in your own broker (so the build token never reaches the client), and the SDK calls your callback whenever it needs a token — first use, near expiry, or when the server reports the token expired.

const client = new CinAdminGameClient({
  baseUrl: 'https://api.cinadmin.com',
  webSocketUrl: 'wss://ws-v2.cinadmin.com',
  tokenProvider: async () => {
    // Call YOUR backend, which holds the cinadm_sdk_* build token and exchanges
    // it at POST /api/v1/sdk/session-token. Return the minted runtime token.
    const res = await fetch('https://your-broker.example/runtime-token', { method: 'POST' })
    const { token, expiresAt } = await res.json()
    return { token, expiresAt } // expiresAt = ISO-8601
  },
})

The SDK refuses a cinadm_sdk_* token from tokenProvider (HC-01 guardrail) — if you see TOKEN_UNAVAILABLE complaining about a build token, your broker is returning the wrong one.

Quickstart

import { CinAdminGameClient } from '@cinadmin/game-sdk'

const client = new CinAdminGameClient({ baseUrl, webSocketUrl, tokenProvider })

// 1. Find the session running on this screen.
const [session] = await client.discoverSessions({ venueId: 'venue-123' })

// 2. Join it.
await client.joinSession(session.sessionId!)

// 3. Go live.
client.on('scoreUpdate', e => console.log(`${e.playerId} → ${e.score}`))
client.on('playerJoined', e => console.log(`${e.playerId} joined seat ${e.seat}`))
client.on('connectionState', s => console.log('ws:', s))
client.on('error', e => console.warn(e.error.code, e.error.message))

await client.openSessionWebSocket(session.sessionId!)
await client.sendScoreUpdate('player-1', 4200, 'the-human-reality')

// 4. Tear down.
await client.closeWebSocket()
client.dispose()

Node usage

In Node there is no global WebSocket (< Node 22) — pass a factory backed by the ws package, and (on Node < 18) a fetch:

import WebSocket from 'ws'

new CinAdminGameClient({
  baseUrl,
  webSocketUrl,
  tokenProvider,
  webSocketFactory: url => new WebSocket(url) as never,
})

Offline-first

Outbound frames (sendScoreUpdate, sendGameMessage, …) sent while the socket is down are queued in an in-memory store and flushed FIFO on the next connect — a transient drop never loses data and never throws into your game loop. For cross-restart durability supply your own offlineStore (an IOfflineStore over IndexedDB / the filesystem).

For scores accumulated entirely offline, upload them when you reconnect with the idempotent batch — a re-flush of the same clientResultId is a server no-op, so the leaderboard never double-counts:

await client.submitResultsBatch(sessionId, [
  { sessionPlayerId: 'sp-1', score: 1200, gameName: 'g', clientResultId: 'cr-7f3a' },
])
// → { accepted, duplicates, total }

Errors

Every call throws a typed CinAdminError with a stable .code (see ErrorCodes): FORBIDDEN (cross-tenant), CONFLICT (session closed/not open), RUNTIME_TOKEN_EXPIRED (auto-re-minted once for you), UPGRADE_REQUIRED (your SDK is below the supported floor — upgrade), NOT_IMPLEMENTED (a contract path not yet shipped). Background/WS failures arrive on the error event, not as throws.

Contract

Every REST path and WS frame this client uses is defined in @cinadmin/game-sdk-contract (openapi.yaml + ws-v2.schema.json). The contract test pins the client to it.

License

UNLICENSED — © SSEL. Distributed for use by CinAdmin platform partners.