keeperboard 2.1.1 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -3
- package/dist/index.d.mts +87 -1
- package/dist/index.d.ts +87 -1
- package/dist/index.js +1 -937
- package/dist/index.mjs +1 -903
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -233,6 +233,81 @@ try {
|
|
|
233
233
|
|
|
234
234
|
---
|
|
235
235
|
|
|
236
|
+
## Anti-Cheat Protection
|
|
237
|
+
|
|
238
|
+
KeeperBoard provides optional anti-cheat measures to prevent casual leaderboard hacking:
|
|
239
|
+
|
|
240
|
+
### 1. HMAC Signing
|
|
241
|
+
|
|
242
|
+
When enabled, all requests are cryptographically signed to prevent tampering.
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const session = new KeeperBoardSession({
|
|
246
|
+
apiKey: 'kb_prod_xxx',
|
|
247
|
+
leaderboard: 'main',
|
|
248
|
+
signingSecret: process.env.KEEPERBOARD_SIGNING_SECRET, // From dashboard
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Setup:**
|
|
253
|
+
1. Enable "HMAC Signing" in KeeperBoard dashboard
|
|
254
|
+
2. Copy the signing secret
|
|
255
|
+
3. Add to your game's environment variables
|
|
256
|
+
4. Pass to SDK constructor
|
|
257
|
+
|
|
258
|
+
### 2. Run Tokens
|
|
259
|
+
|
|
260
|
+
For stronger protection, use run tokens to bind scores to game sessions:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// When game starts
|
|
264
|
+
await session.startRun();
|
|
265
|
+
|
|
266
|
+
// ... player plays the game ...
|
|
267
|
+
|
|
268
|
+
// When game ends (instead of submitScore)
|
|
269
|
+
const result = await session.finishRun(score);
|
|
270
|
+
if (result.isNewHighScore) {
|
|
271
|
+
console.log('New high score!');
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Server validates:**
|
|
276
|
+
- Run token exists and hasn't been used
|
|
277
|
+
- Minimum elapsed time passed (e.g., 5+ seconds)
|
|
278
|
+
- Score is within cap (if configured)
|
|
279
|
+
- Signature is valid (if signing enabled)
|
|
280
|
+
|
|
281
|
+
### 3. Build Obfuscation
|
|
282
|
+
|
|
283
|
+
For browser games, obfuscate your production build to make reverse-engineering harder:
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
// vite.config.js
|
|
287
|
+
import obfuscatorPlugin from 'vite-plugin-javascript-obfuscator';
|
|
288
|
+
|
|
289
|
+
export default {
|
|
290
|
+
plugins: [
|
|
291
|
+
obfuscatorPlugin({
|
|
292
|
+
include: ['src/**/*.ts'],
|
|
293
|
+
apply: 'build',
|
|
294
|
+
options: {
|
|
295
|
+
compact: true,
|
|
296
|
+
controlFlowFlattening: true,
|
|
297
|
+
stringArray: true,
|
|
298
|
+
stringArrayEncoding: ['base64'],
|
|
299
|
+
},
|
|
300
|
+
}),
|
|
301
|
+
],
|
|
302
|
+
};
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Security Model
|
|
306
|
+
|
|
307
|
+
These measures stop **casual cheaters** (DevTools interception, simple replay attacks). Determined reverse-engineers with time and skill may still find ways around them. This is an acceptable tradeoff for most indie games.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
236
311
|
## Phaser.js Integration
|
|
237
312
|
|
|
238
313
|
```typescript
|
|
@@ -242,6 +317,7 @@ import { KeeperBoardSession } from 'keeperboard';
|
|
|
242
317
|
const leaderboard = new KeeperBoardSession({
|
|
243
318
|
apiKey: import.meta.env.VITE_KEEPERBOARD_API_KEY,
|
|
244
319
|
leaderboard: 'main',
|
|
320
|
+
signingSecret: import.meta.env.VITE_KEEPERBOARD_SIGNING_SECRET, // Optional
|
|
245
321
|
cache: { ttlMs: 30000 },
|
|
246
322
|
retry: { maxAgeMs: 86400000 },
|
|
247
323
|
});
|
|
@@ -255,11 +331,20 @@ class BootScene extends Phaser.Scene {
|
|
|
255
331
|
}
|
|
256
332
|
}
|
|
257
333
|
|
|
258
|
-
// In
|
|
334
|
+
// In GameScene - start run for anti-cheat
|
|
335
|
+
class GameScene extends Phaser.Scene {
|
|
336
|
+
async create() {
|
|
337
|
+
await leaderboard.startRun(); // Optional: enables run token validation
|
|
338
|
+
// ... game logic ...
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// In GameOverScene - use finishRun if run was started
|
|
259
343
|
class GameOverScene extends Phaser.Scene {
|
|
260
344
|
async create() {
|
|
261
|
-
|
|
262
|
-
|
|
345
|
+
// finishRun() uses run token if active, falls back to submitScore()
|
|
346
|
+
const result = await leaderboard.finishRun(this.score);
|
|
347
|
+
if (result.isNewHighScore) {
|
|
263
348
|
this.showRank(result.rank, result.isNewHighScore);
|
|
264
349
|
}
|
|
265
350
|
|
package/dist/index.d.mts
CHANGED
|
@@ -10,6 +10,8 @@ interface KeeperBoardConfig {
|
|
|
10
10
|
apiKey: string;
|
|
11
11
|
/** Default leaderboard name — used when no leaderboard is specified in method calls */
|
|
12
12
|
defaultLeaderboard?: string;
|
|
13
|
+
/** Signing secret for HMAC request signing (get from dashboard when signing is enabled) */
|
|
14
|
+
signingSecret?: string;
|
|
13
15
|
/** @internal Base URL override for testing. Do not use in production. */
|
|
14
16
|
apiUrl?: string;
|
|
15
17
|
}
|
|
@@ -48,6 +50,20 @@ interface ClaimScoreOptions {
|
|
|
48
50
|
/** Leaderboard name. Falls back to `defaultLeaderboard` from config. */
|
|
49
51
|
leaderboard?: string;
|
|
50
52
|
}
|
|
53
|
+
interface StartRunOptions {
|
|
54
|
+
playerGuid: string;
|
|
55
|
+
/** Leaderboard name. Falls back to `defaultLeaderboard` from config. */
|
|
56
|
+
leaderboard?: string;
|
|
57
|
+
}
|
|
58
|
+
interface FinishRunOptions {
|
|
59
|
+
runId: string;
|
|
60
|
+
playerGuid: string;
|
|
61
|
+
playerName: string;
|
|
62
|
+
score: number;
|
|
63
|
+
/** Leaderboard name. Falls back to `defaultLeaderboard` from config. */
|
|
64
|
+
leaderboard?: string;
|
|
65
|
+
metadata?: Record<string, unknown>;
|
|
66
|
+
}
|
|
51
67
|
interface ScoreResult {
|
|
52
68
|
id: string;
|
|
53
69
|
playerGuid: string;
|
|
@@ -93,6 +109,16 @@ interface HealthResult {
|
|
|
93
109
|
version: string;
|
|
94
110
|
timestamp: string;
|
|
95
111
|
}
|
|
112
|
+
interface StartRunResult {
|
|
113
|
+
runId: string;
|
|
114
|
+
startedAt: string;
|
|
115
|
+
expiresAt: string;
|
|
116
|
+
}
|
|
117
|
+
interface FinishRunResult {
|
|
118
|
+
scoreId: string;
|
|
119
|
+
rank: number;
|
|
120
|
+
isNewHighScore: boolean;
|
|
121
|
+
}
|
|
96
122
|
type ErrorCode = 'PROFANITY_DETECTED' | 'RATE_LIMITED' | 'INVALID_REQUEST' | 'NOT_FOUND' | 'INTERNAL_ERROR';
|
|
97
123
|
interface SessionConfig {
|
|
98
124
|
/** API key from the KeeperBoard dashboard */
|
|
@@ -111,6 +137,8 @@ interface SessionConfig {
|
|
|
111
137
|
retry?: {
|
|
112
138
|
maxAgeMs?: number;
|
|
113
139
|
};
|
|
140
|
+
/** Signing secret for HMAC request signing (get from dashboard when signing is enabled) */
|
|
141
|
+
signingSecret?: string;
|
|
114
142
|
/** @internal Base URL override for testing. */
|
|
115
143
|
apiUrl?: string;
|
|
116
144
|
}
|
|
@@ -233,6 +261,7 @@ declare class KeeperBoardClient {
|
|
|
233
261
|
private readonly apiUrl;
|
|
234
262
|
private readonly apiKey;
|
|
235
263
|
private readonly defaultLeaderboard?;
|
|
264
|
+
private readonly signingSecret?;
|
|
236
265
|
constructor(config: KeeperBoardConfig);
|
|
237
266
|
/**
|
|
238
267
|
* Submit a score. Only updates if the new score is higher than the existing one.
|
|
@@ -288,10 +317,41 @@ declare class KeeperBoardClient {
|
|
|
288
317
|
* Check if the API is healthy. Does not require an API key.
|
|
289
318
|
*/
|
|
290
319
|
healthCheck(): Promise<HealthResult>;
|
|
320
|
+
/**
|
|
321
|
+
* Start a game run. Use this when the leaderboard requires run tokens.
|
|
322
|
+
* Returns a run ID that must be passed to finishRun() when submitting the score.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* const run = await client.startRun({ playerGuid: 'abc-123' });
|
|
326
|
+
* // ... play game ...
|
|
327
|
+
* const result = await client.finishRun({
|
|
328
|
+
* runId: run.runId,
|
|
329
|
+
* playerGuid: 'abc-123',
|
|
330
|
+
* playerName: 'ACE',
|
|
331
|
+
* score: 1500,
|
|
332
|
+
* });
|
|
333
|
+
*/
|
|
334
|
+
startRun(options: StartRunOptions): Promise<StartRunResult>;
|
|
335
|
+
/**
|
|
336
|
+
* Finish a game run and submit the score.
|
|
337
|
+
* The run must have been started with startRun() first.
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* const result = await client.finishRun({
|
|
341
|
+
* runId: run.runId,
|
|
342
|
+
* playerGuid: 'abc-123',
|
|
343
|
+
* playerName: 'ACE',
|
|
344
|
+
* score: 1500,
|
|
345
|
+
* });
|
|
346
|
+
* console.log(result.rank, result.isNewHighScore);
|
|
347
|
+
*/
|
|
348
|
+
finishRun(options: FinishRunOptions): Promise<FinishRunResult>;
|
|
291
349
|
private mapScoreResponse;
|
|
292
350
|
private mapLeaderboardResponse;
|
|
293
351
|
private mapPlayerResponse;
|
|
294
352
|
private mapClaimResponse;
|
|
353
|
+
private mapStartRunResponse;
|
|
354
|
+
private mapFinishRunResponse;
|
|
295
355
|
private request;
|
|
296
356
|
}
|
|
297
357
|
|
|
@@ -312,6 +372,7 @@ declare class KeeperBoardSession {
|
|
|
312
372
|
private readonly retryQueue;
|
|
313
373
|
private cachedLimit;
|
|
314
374
|
private isSubmitting;
|
|
375
|
+
private currentRunId;
|
|
315
376
|
constructor(config: SessionConfig);
|
|
316
377
|
/** Get or create a persistent player GUID. */
|
|
317
378
|
getPlayerGuid(): string;
|
|
@@ -331,6 +392,31 @@ declare class KeeperBoardSession {
|
|
|
331
392
|
* Prevents concurrent double-submissions.
|
|
332
393
|
*/
|
|
333
394
|
submitScore(score: number, metadata?: Record<string, unknown>): Promise<SessionScoreResult>;
|
|
395
|
+
/**
|
|
396
|
+
* Start a game run. Call this when a game session begins.
|
|
397
|
+
* For leaderboards with `require_run_token` enabled, scores must be submitted via finishRun().
|
|
398
|
+
*
|
|
399
|
+
* The run ID is stored internally and used automatically by finishRun().
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* await session.startRun();
|
|
403
|
+
* // ... play game ...
|
|
404
|
+
* const result = await session.finishRun(1500);
|
|
405
|
+
*/
|
|
406
|
+
startRun(): Promise<StartRunResult>;
|
|
407
|
+
/**
|
|
408
|
+
* Finish a game run and submit the score.
|
|
409
|
+
* Must be called after startRun(). Uses the stored run ID automatically.
|
|
410
|
+
*
|
|
411
|
+
* @example
|
|
412
|
+
* const result = await session.finishRun(1500);
|
|
413
|
+
* if (result.isNewHighScore) console.log('New high score!');
|
|
414
|
+
*/
|
|
415
|
+
finishRun(score: number, metadata?: Record<string, unknown>): Promise<FinishRunResult>;
|
|
416
|
+
/** Check if there's an active run in progress. */
|
|
417
|
+
hasActiveRun(): boolean;
|
|
418
|
+
/** Get the current run ID, or null if no run is active. */
|
|
419
|
+
getCurrentRunId(): string | null;
|
|
334
420
|
/**
|
|
335
421
|
* Get a combined snapshot: leaderboard entries (with `isCurrentPlayer` flag)
|
|
336
422
|
* plus the current player's rank if they're outside the top N.
|
|
@@ -519,4 +605,4 @@ declare class RetryQueue {
|
|
|
519
605
|
clear(): void;
|
|
520
606
|
}
|
|
521
607
|
|
|
522
|
-
export { Cache, type ClaimResponse, type ClaimResult, type ClaimScoreOptions, type ErrorCode, type GetLeaderboardOptions, type GetPlayerRankOptions, type HealthResponse, type HealthResult, KeeperBoardClient, type KeeperBoardConfig, KeeperBoardError, KeeperBoardSession, type LeaderboardEntry, type LeaderboardResponse, type LeaderboardResult, type NameValidationOptions, PlayerIdentity, type PlayerIdentityConfig, type PlayerResponse, type PlayerResult, type ResetSchedule, RetryQueue, type ScoreResponse, type ScoreResult, type ScoreSubmission, type SessionConfig, type SessionScoreResult, type SnapshotEntry, type SnapshotResult, type SubmitScoreOptions, type UpdateNameResult, type UpdatePlayerNameOptions, generatePlayerName, validateName };
|
|
608
|
+
export { Cache, type ClaimResponse, type ClaimResult, type ClaimScoreOptions, type ErrorCode, type FinishRunOptions, type FinishRunResult, type GetLeaderboardOptions, type GetPlayerRankOptions, type HealthResponse, type HealthResult, KeeperBoardClient, type KeeperBoardConfig, KeeperBoardError, KeeperBoardSession, type LeaderboardEntry, type LeaderboardResponse, type LeaderboardResult, type NameValidationOptions, PlayerIdentity, type PlayerIdentityConfig, type PlayerResponse, type PlayerResult, type ResetSchedule, RetryQueue, type ScoreResponse, type ScoreResult, type ScoreSubmission, type SessionConfig, type SessionScoreResult, type SnapshotEntry, type SnapshotResult, type StartRunOptions, type StartRunResult, type SubmitScoreOptions, type UpdateNameResult, type UpdatePlayerNameOptions, generatePlayerName, validateName };
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ interface KeeperBoardConfig {
|
|
|
10
10
|
apiKey: string;
|
|
11
11
|
/** Default leaderboard name — used when no leaderboard is specified in method calls */
|
|
12
12
|
defaultLeaderboard?: string;
|
|
13
|
+
/** Signing secret for HMAC request signing (get from dashboard when signing is enabled) */
|
|
14
|
+
signingSecret?: string;
|
|
13
15
|
/** @internal Base URL override for testing. Do not use in production. */
|
|
14
16
|
apiUrl?: string;
|
|
15
17
|
}
|
|
@@ -48,6 +50,20 @@ interface ClaimScoreOptions {
|
|
|
48
50
|
/** Leaderboard name. Falls back to `defaultLeaderboard` from config. */
|
|
49
51
|
leaderboard?: string;
|
|
50
52
|
}
|
|
53
|
+
interface StartRunOptions {
|
|
54
|
+
playerGuid: string;
|
|
55
|
+
/** Leaderboard name. Falls back to `defaultLeaderboard` from config. */
|
|
56
|
+
leaderboard?: string;
|
|
57
|
+
}
|
|
58
|
+
interface FinishRunOptions {
|
|
59
|
+
runId: string;
|
|
60
|
+
playerGuid: string;
|
|
61
|
+
playerName: string;
|
|
62
|
+
score: number;
|
|
63
|
+
/** Leaderboard name. Falls back to `defaultLeaderboard` from config. */
|
|
64
|
+
leaderboard?: string;
|
|
65
|
+
metadata?: Record<string, unknown>;
|
|
66
|
+
}
|
|
51
67
|
interface ScoreResult {
|
|
52
68
|
id: string;
|
|
53
69
|
playerGuid: string;
|
|
@@ -93,6 +109,16 @@ interface HealthResult {
|
|
|
93
109
|
version: string;
|
|
94
110
|
timestamp: string;
|
|
95
111
|
}
|
|
112
|
+
interface StartRunResult {
|
|
113
|
+
runId: string;
|
|
114
|
+
startedAt: string;
|
|
115
|
+
expiresAt: string;
|
|
116
|
+
}
|
|
117
|
+
interface FinishRunResult {
|
|
118
|
+
scoreId: string;
|
|
119
|
+
rank: number;
|
|
120
|
+
isNewHighScore: boolean;
|
|
121
|
+
}
|
|
96
122
|
type ErrorCode = 'PROFANITY_DETECTED' | 'RATE_LIMITED' | 'INVALID_REQUEST' | 'NOT_FOUND' | 'INTERNAL_ERROR';
|
|
97
123
|
interface SessionConfig {
|
|
98
124
|
/** API key from the KeeperBoard dashboard */
|
|
@@ -111,6 +137,8 @@ interface SessionConfig {
|
|
|
111
137
|
retry?: {
|
|
112
138
|
maxAgeMs?: number;
|
|
113
139
|
};
|
|
140
|
+
/** Signing secret for HMAC request signing (get from dashboard when signing is enabled) */
|
|
141
|
+
signingSecret?: string;
|
|
114
142
|
/** @internal Base URL override for testing. */
|
|
115
143
|
apiUrl?: string;
|
|
116
144
|
}
|
|
@@ -233,6 +261,7 @@ declare class KeeperBoardClient {
|
|
|
233
261
|
private readonly apiUrl;
|
|
234
262
|
private readonly apiKey;
|
|
235
263
|
private readonly defaultLeaderboard?;
|
|
264
|
+
private readonly signingSecret?;
|
|
236
265
|
constructor(config: KeeperBoardConfig);
|
|
237
266
|
/**
|
|
238
267
|
* Submit a score. Only updates if the new score is higher than the existing one.
|
|
@@ -288,10 +317,41 @@ declare class KeeperBoardClient {
|
|
|
288
317
|
* Check if the API is healthy. Does not require an API key.
|
|
289
318
|
*/
|
|
290
319
|
healthCheck(): Promise<HealthResult>;
|
|
320
|
+
/**
|
|
321
|
+
* Start a game run. Use this when the leaderboard requires run tokens.
|
|
322
|
+
* Returns a run ID that must be passed to finishRun() when submitting the score.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* const run = await client.startRun({ playerGuid: 'abc-123' });
|
|
326
|
+
* // ... play game ...
|
|
327
|
+
* const result = await client.finishRun({
|
|
328
|
+
* runId: run.runId,
|
|
329
|
+
* playerGuid: 'abc-123',
|
|
330
|
+
* playerName: 'ACE',
|
|
331
|
+
* score: 1500,
|
|
332
|
+
* });
|
|
333
|
+
*/
|
|
334
|
+
startRun(options: StartRunOptions): Promise<StartRunResult>;
|
|
335
|
+
/**
|
|
336
|
+
* Finish a game run and submit the score.
|
|
337
|
+
* The run must have been started with startRun() first.
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* const result = await client.finishRun({
|
|
341
|
+
* runId: run.runId,
|
|
342
|
+
* playerGuid: 'abc-123',
|
|
343
|
+
* playerName: 'ACE',
|
|
344
|
+
* score: 1500,
|
|
345
|
+
* });
|
|
346
|
+
* console.log(result.rank, result.isNewHighScore);
|
|
347
|
+
*/
|
|
348
|
+
finishRun(options: FinishRunOptions): Promise<FinishRunResult>;
|
|
291
349
|
private mapScoreResponse;
|
|
292
350
|
private mapLeaderboardResponse;
|
|
293
351
|
private mapPlayerResponse;
|
|
294
352
|
private mapClaimResponse;
|
|
353
|
+
private mapStartRunResponse;
|
|
354
|
+
private mapFinishRunResponse;
|
|
295
355
|
private request;
|
|
296
356
|
}
|
|
297
357
|
|
|
@@ -312,6 +372,7 @@ declare class KeeperBoardSession {
|
|
|
312
372
|
private readonly retryQueue;
|
|
313
373
|
private cachedLimit;
|
|
314
374
|
private isSubmitting;
|
|
375
|
+
private currentRunId;
|
|
315
376
|
constructor(config: SessionConfig);
|
|
316
377
|
/** Get or create a persistent player GUID. */
|
|
317
378
|
getPlayerGuid(): string;
|
|
@@ -331,6 +392,31 @@ declare class KeeperBoardSession {
|
|
|
331
392
|
* Prevents concurrent double-submissions.
|
|
332
393
|
*/
|
|
333
394
|
submitScore(score: number, metadata?: Record<string, unknown>): Promise<SessionScoreResult>;
|
|
395
|
+
/**
|
|
396
|
+
* Start a game run. Call this when a game session begins.
|
|
397
|
+
* For leaderboards with `require_run_token` enabled, scores must be submitted via finishRun().
|
|
398
|
+
*
|
|
399
|
+
* The run ID is stored internally and used automatically by finishRun().
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* await session.startRun();
|
|
403
|
+
* // ... play game ...
|
|
404
|
+
* const result = await session.finishRun(1500);
|
|
405
|
+
*/
|
|
406
|
+
startRun(): Promise<StartRunResult>;
|
|
407
|
+
/**
|
|
408
|
+
* Finish a game run and submit the score.
|
|
409
|
+
* Must be called after startRun(). Uses the stored run ID automatically.
|
|
410
|
+
*
|
|
411
|
+
* @example
|
|
412
|
+
* const result = await session.finishRun(1500);
|
|
413
|
+
* if (result.isNewHighScore) console.log('New high score!');
|
|
414
|
+
*/
|
|
415
|
+
finishRun(score: number, metadata?: Record<string, unknown>): Promise<FinishRunResult>;
|
|
416
|
+
/** Check if there's an active run in progress. */
|
|
417
|
+
hasActiveRun(): boolean;
|
|
418
|
+
/** Get the current run ID, or null if no run is active. */
|
|
419
|
+
getCurrentRunId(): string | null;
|
|
334
420
|
/**
|
|
335
421
|
* Get a combined snapshot: leaderboard entries (with `isCurrentPlayer` flag)
|
|
336
422
|
* plus the current player's rank if they're outside the top N.
|
|
@@ -519,4 +605,4 @@ declare class RetryQueue {
|
|
|
519
605
|
clear(): void;
|
|
520
606
|
}
|
|
521
607
|
|
|
522
|
-
export { Cache, type ClaimResponse, type ClaimResult, type ClaimScoreOptions, type ErrorCode, type GetLeaderboardOptions, type GetPlayerRankOptions, type HealthResponse, type HealthResult, KeeperBoardClient, type KeeperBoardConfig, KeeperBoardError, KeeperBoardSession, type LeaderboardEntry, type LeaderboardResponse, type LeaderboardResult, type NameValidationOptions, PlayerIdentity, type PlayerIdentityConfig, type PlayerResponse, type PlayerResult, type ResetSchedule, RetryQueue, type ScoreResponse, type ScoreResult, type ScoreSubmission, type SessionConfig, type SessionScoreResult, type SnapshotEntry, type SnapshotResult, type SubmitScoreOptions, type UpdateNameResult, type UpdatePlayerNameOptions, generatePlayerName, validateName };
|
|
608
|
+
export { Cache, type ClaimResponse, type ClaimResult, type ClaimScoreOptions, type ErrorCode, type FinishRunOptions, type FinishRunResult, type GetLeaderboardOptions, type GetPlayerRankOptions, type HealthResponse, type HealthResult, KeeperBoardClient, type KeeperBoardConfig, KeeperBoardError, KeeperBoardSession, type LeaderboardEntry, type LeaderboardResponse, type LeaderboardResult, type NameValidationOptions, PlayerIdentity, type PlayerIdentityConfig, type PlayerResponse, type PlayerResult, type ResetSchedule, RetryQueue, type ScoreResponse, type ScoreResult, type ScoreSubmission, type SessionConfig, type SessionScoreResult, type SnapshotEntry, type SnapshotResult, type StartRunOptions, type StartRunResult, type SubmitScoreOptions, type UpdateNameResult, type UpdatePlayerNameOptions, generatePlayerName, validateName };
|