Add agent skill (SKILL.md + per-domain reference)
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
---
|
||||
name: rudder-web-sdk
|
||||
description: Use when working with the Rudder TypeScript/JavaScript SDK (@rudder/js-sdk) — the browser/player-facing SDK for the Rudder LiveOps platform. Covers client setup, device/custom auth, observable domains (player, inventory, catalog, stores, remote config, storage), leaderboards, quests, battle pass, scenario effects, and error handling. Load this whenever code imports from @rudder/js-sdk or RudderClient appears.
|
||||
---
|
||||
|
||||
# Rudder Web SDK (@rudder/js-sdk)
|
||||
|
||||
Browser-facing player SDK for the Rudder LiveOps platform. Source of truth:
|
||||
`liveops-web-sdk/src` (generated wire types in `src/generated` come from the
|
||||
gateway's apigen — never edit them by hand).
|
||||
|
||||
## Install
|
||||
|
||||
Published to a private registry, not npmjs. Point the `@rudder` scope at it in
|
||||
`.npmrc` (anonymous read, no token):
|
||||
|
||||
```
|
||||
@rudder:registry=https://hub.rudder.build/api/packages/rudder/npm/
|
||||
```
|
||||
|
||||
```bash
|
||||
npm install @rudder/js-sdk
|
||||
```
|
||||
|
||||
ESM + CJS + `.d.ts`; `type: module`; zero runtime dependencies.
|
||||
|
||||
## Init
|
||||
|
||||
```ts
|
||||
import { RudderClient } from '@rudder/js-sdk';
|
||||
|
||||
const client = new RudderClient({
|
||||
baseUrl: 'https://api.rudder.build', // required
|
||||
projectKey: 'your-project-key', // required
|
||||
// tokenStore?: TokenStore — default: localStorage, in-memory fallback
|
||||
// requestTimeoutMs?: number — default 10000
|
||||
// syncIntervalMs?: number — revision poll, default 30000 (±20% jitter)
|
||||
// onEffectError?: (error) => void — default console.error
|
||||
// runtime?: { planStateStore?, loginEvent? } — advanced, see reference/scenarios.md
|
||||
});
|
||||
```
|
||||
|
||||
`client` is generic: `RudderClient<TConfig extends Record<string, unknown>>`
|
||||
types `client.remoteConfig.get()`. Missing `baseUrl`/`projectKey` throws
|
||||
`RudderError` with `code: 'sdk/invalid-options'` from the constructor.
|
||||
|
||||
Call `client.dispose()` on unmount/HMR to stop the sync poll, wait timers, and
|
||||
drop cached state.
|
||||
|
||||
## Auth essentials
|
||||
|
||||
```ts
|
||||
await client.auth.loginWithDevice({ region, language, nickname }); // device id auto-generated/persisted
|
||||
await client.auth.loginWithCustom({ customData, region, language, nickname });
|
||||
client.auth.logout();
|
||||
client.auth.isAuthenticated; // boolean
|
||||
client.auth.onAuthStateChange(cb); // fires immediately, returns unsubscribe
|
||||
```
|
||||
|
||||
Tokens are saved to the `TokenStore` automatically. The transport injects
|
||||
`Authorization: Bearer <token>`, retries GETs, and single-flight refreshes on
|
||||
401; a failed refresh clears tokens and emits `signed-out`. Details:
|
||||
[reference/auth.md](reference/auth.md).
|
||||
|
||||
## Client surface (all domains that exist)
|
||||
|
||||
Every member below is a property on `RudderClient`. There is no UGC, wallet
|
||||
service, or standalone economy service in this SDK — wallets live on
|
||||
`client.player.data.wallets`, and purchases go through `client.stores`.
|
||||
|
||||
| Area | Access | Kind |
|
||||
|---|---|---|
|
||||
| Auth | `client.auth` | service |
|
||||
| Player profile + wallets | `client.player` | observable `SyncedState<PlayerProfile>` |
|
||||
| Inventory (catalog-merged) | `client.inventory` | observable `SyncedState<InventoryItem[]>` |
|
||||
| Catalog | `client.catalog` | observable `SyncedState<Map<string, CatalogItem>>` |
|
||||
| Stores / purchases | `client.stores` + `client.stores.purchase(slug, offerId, opts?)` | observable `SyncedState<ShopHandle[]>` |
|
||||
| Remote config | `client.remoteConfig` + `.get(key, default?)` | observable, typed |
|
||||
| Player storage | `client.storage` + `.save(items)` / `.delete(type)` | observable + mutations |
|
||||
| Project storage | `client.projectStorage` + `.save(items)` | observable + mutation |
|
||||
| Leaderboards | `client.leaderboards.findBySlug(slug)` | service → cached handle |
|
||||
| Battle pass | `client.battlePass` | plain service (no live sync) |
|
||||
| Quests | `client.quests` | plain service (no live sync) |
|
||||
| Scenario effects | `client.effects.on*` | event subscriptions |
|
||||
|
||||
## Observable domains — the shared pattern
|
||||
|
||||
`player`, `catalog`, `inventory`, `remoteConfig`, `storage`,
|
||||
`projectStorage`, and `stores` all extend `SyncedState<T>`:
|
||||
|
||||
- `.data: T | undefined`, `.status: 'idle' | 'loading' | 'ready' | 'error'`,
|
||||
`.error?: Error`
|
||||
- `onChange(cb: (snapshot: SyncedSnapshot<T>) => void): () => void` — fires
|
||||
immediately with the current snapshot; maps onto React `useSyncExternalStore`
|
||||
- `load(): Promise<T>` — deduplicated, no-op when ready
|
||||
- `reload(): Promise<T>` — forced refetch
|
||||
|
||||
`remoteConfig`, `player`, `stores`, and `catalog` are warmed once at login;
|
||||
`inventory`, `storage`, and `projectStorage` load on first use. All observable
|
||||
domains are then kept fresh by a revision poll every 30 s (±20% jitter);
|
||||
polling pauses while the tab is hidden. Mutations (purchases, storage writes,
|
||||
scenario callbacks) invalidate affected domains immediately. Call `reload()`
|
||||
when you need a freshness guarantee.
|
||||
|
||||
`leaderboards`, `battlePass`, and `quests` are NOT observable — refetch
|
||||
explicitly after mutations.
|
||||
|
||||
## Errors
|
||||
|
||||
All SDK errors extend `RudderError` (optional machine-readable `code`):
|
||||
|
||||
- `RudderNetworkError` — fetch failed / timeout (`error.cause` holds the original)
|
||||
- `RudderHttpError` — non-2xx, carries `status`, `statusText`, `body`, `code`
|
||||
- `RudderAuthError extends RudderHttpError` — 401 after failed refresh; tokens
|
||||
already cleared, `signed-out` already emitted
|
||||
- `RudderError` with `code: 'sdk/invalid-options'` (`SDK_ERROR_INVALID_OPTIONS`)
|
||||
— constructor validation
|
||||
|
||||
Server error codes (`RudderErrorCodes`, from `src/generated/errors.ts`):
|
||||
`early_completion`, `forbidden`, `level_not_reached`, `node_not_active`,
|
||||
`objectives_incomplete`, `run_expired`, `run_not_active`,
|
||||
`scenario_not_active`, `unknown_run`. Compare with
|
||||
`error.code === RudderErrorCodes.runExpired`.
|
||||
|
||||
## Reference files
|
||||
|
||||
- [reference/auth.md](reference/auth.md) — login flows, options, token store, session lifecycle
|
||||
- [reference/player.md](reference/player.md) — profile + wallets (`PlayerProfile`, `Wallet`)
|
||||
- [reference/inventory.md](reference/inventory.md) — inventory domain, merged `InventoryItem`, catalog
|
||||
- [reference/stores.md](reference/stores.md) — `ShopHandle`/`OfferHandle`, purchases, idempotency
|
||||
- [reference/remote-config.md](reference/remote-config.md) — typed `get()`, value types, overrides
|
||||
- [reference/storage.md](reference/storage.md) — player + project storage, limits
|
||||
- [reference/leaderboards.md](reference/leaderboards.md) — handles, submit, list
|
||||
- [reference/quests.md](reference/quests.md) — list/claim/reportProgress, `QuestMetrics`
|
||||
- [reference/battlepass.md](reference/battlepass.md) — progress, XP, claims, premium
|
||||
- [reference/scenarios.md](reference/scenarios.md) — effects, scenario runtime, wait/quest/battlepass nodes
|
||||
Reference in New Issue
Block a user