6.4 KiB
name, description
| name | description |
|---|---|
| rudder-web-sdk | 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
liveops-backend/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/
npm install @rudder/js-sdk
ESM + CJS + .d.ts; type: module; zero runtime dependencies.
Init
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)
});
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
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.
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 |
Wallets live on client.player.data.wallets. Game features are installed
modules, not SDK services (first-party modules: items, inventory, reward,
remote_config, leaderboards, quests, store, battlepass). Call them with
client.modules.call('my_module', 'hello', { ... }) and read their rows with
client.resources(slug). Details: reference/modules.md,
reference/resources.md.
Observable domains — the shared pattern
player, catalog, storage, and projectStorage all extend
SyncedState<T>:
.data: T | undefined,.status: 'idle' | 'loading' | 'ready' | 'error',.error?: ErroronChange(cb: (snapshot: SyncedSnapshot<T>) => void): () => void— fires immediately with the current snapshot; maps onto ReactuseSyncExternalStoreload(): Promise<T>— deduplicated, no-op when readyreload(): 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.causeholds the original)RudderHttpError— non-2xx, carriesstatus,statusText,body,codeRudderAuthError extends RudderHttpError— 401 after failed refresh; tokens already cleared,signed-outalready emittedRudderErrorwithcode: '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 — login flows, options, token store, session lifecycle
- reference/player.md — profile + wallets (
PlayerProfile,Wallet) - reference/storage.md — player + project storage, limits
- reference/modules.md —
modules.call, response, module errors - reference/resources.md —
resources(slug)row operations