Files
rudder-js-sdk/skills/rudder-web-sdk/SKILL.md
T
edmand46 4ab406c5cd
CI / check (push) Successful in 16s
CI / publish (push) Has been skipped
docs: module call response, error codes, remove scenarios
2026-09-17 12:27:52 +03:00

140 lines
6.2 KiB
Markdown

---
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/google/apple/custom auth, identity linking, observable kernel domains (player, catalog, storage), modules.call, resources(slug), 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).
2.0 kernel surface: auth, player (wallets), catalog currencies, storage,
project storage, revision sync, `client.modules.call(module, fn, args)`,
and `client.resources(slug)`. Module-specific methods (battle pass, quests,
leaderboards, stores, inventory, remote config, scenarios) are gone.
## 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
});
```
Missing `baseUrl`/`projectKey` throws `RudderError` with
`code: 'sdk/invalid-options'` from the constructor.
Call `client.dispose()` on unmount/HMR to stop the sync poll and drop cached
state.
## Auth essentials
```ts
await client.auth.loginWithDevice({ region, language, nickname }); // device id auto-generated/persisted
await client.auth.loginWithGoogle({ idToken, region, language, nickname });
await client.auth.loginWithApple({ idToken, region, language, nickname });
await client.auth.loginWithCustom({ customData, provider?, region, language, nickname });
await client.auth.linkWithGoogle(idToken);
await client.auth.linkWithApple(idToken);
await client.auth.linkWithCustom({ customData, provider? });
await client.auth.unlinkIdentity(provider); // 'device' | 'google' | 'apple' | 'custom' | 'custom:<name>'
client.auth.logout();
client.auth.isAuthenticated;
client.auth.onAuthStateChange(cb);
```
Linked identities are listed on the profile: `client.player.data.identities`
(`PlayerProfileIdentity { provider, subject, createdAt }`).
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
| Area | Access | Kind |
|---|---|---|
| Auth | `client.auth` | service |
| Player profile + wallets | `client.player` | observable `SyncedState<PlayerProfile>` |
| Catalog currencies | `client.catalog` | observable `SyncedState<Map<string, CatalogCurrency>>` |
| Player storage | `client.storage` + `.save(items)` / `.delete(type)` | observable + mutations |
| Project storage | `client.projectStorage` + `.save(items)` | observable + mutation |
| Modules | `client.modules.call(module, fn, args?)` | `CallModuleFunctionClientResponse` (`{ result }`) |
| Resources | `client.resources(slug)` | `list` / `get` / `create` / `update` / `delete` |
There is no UGC, wallet service, or standalone economy service — wallets live
on `client.player.data.wallets`. Quests, stores, inventory, leaderboards,
battle pass, and remote config are installed modules: call
`client.modules.call('quests', 'list')` (etc.) and read rows with
`client.resources('items')`.
## Observable domains — the shared pattern
`player`, `catalog`, `storage`, and `projectStorage` 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
`player` and `catalog` are warmed once at login; `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. Storage mutations invalidate their domain immediately. Call `reload()`
when you need a freshness guarantee.
## 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
The platform error codes are `forbidden` and `row_referenced`
(`src/generated/errors.ts`, not exported from the package entry); compare
`error.code === 'forbidden'`.
`client.modules.call` resolves to `{ result }` only; console output and the
kernel call log never reach players. A module business error rejects with
`RudderHttpError` whose `status` is 422 and whose `code` is the module's own
code (the body is `{ error, code, requestId }`). Module codes are open strings
with no generated constants, so compare against the codes the module
documents. A module trap is a 500 and a timeout a 504, both without details.
## 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/storage.md](reference/storage.md) — player + project storage, limits