@wvdsh/sdk-js 1.3.15 → 1.3.17
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/dist/index.d.ts +386 -324
- package/dist/index.js +3013 -2864
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,76 @@ import { FunctionReturnType, FunctionArgs } from 'convex/server';
|
|
|
5
5
|
import { LOBBY_VISIBILITY, api, UGC_TYPE, UGC_VISIBILITY, LEADERBOARD_SORT_ORDER, LEADERBOARD_DISPLAY_TYPE, GAME_ENGINE, SDKUser, IFrameEventPayloadMap, IFRAME_MESSAGE_TYPE, SDKConfig, GameLaunchParams } from '@wvdsh/api';
|
|
6
6
|
export { GameLaunchParams } from '@wvdsh/api';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Base class for SDK managers. Provides the shared `sdk` reference and a
|
|
10
|
+
* default no-op `destroy()` so the SDK can safely iterate every manager
|
|
11
|
+
* during teardown without each one having to define an empty stub.
|
|
12
|
+
*
|
|
13
|
+
* Override `destroy()` in any manager that owns ongoing state — Convex
|
|
14
|
+
* subscriptions, intervals, peer connections, monkey-patched globals, etc.
|
|
15
|
+
* — to make sure that state is released when the SDK is torn down.
|
|
16
|
+
*/
|
|
17
|
+
declare abstract class WavedashManager {
|
|
18
|
+
protected sdk: WavedashSDK;
|
|
19
|
+
constructor(sdk: WavedashSDK);
|
|
20
|
+
destroy(): void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* AudioManager
|
|
25
|
+
*
|
|
26
|
+
* Mutes & unmutes the game in response to MUTE_CHANGED iframe messages, without
|
|
27
|
+
* the game needing to know anything about it.
|
|
28
|
+
*
|
|
29
|
+
* Web Audio: subclass `AudioContext` so `ctx.destination` resolves to a master
|
|
30
|
+
* GainNode that we control. The master gain wires to the real native destination,
|
|
31
|
+
* so `node.connect(ctx.destination)` and any other game code is unaffected.
|
|
32
|
+
*
|
|
33
|
+
* HTML Media (`<audio>`/`<video>`): override `HTMLMediaElement.prototype.muted`
|
|
34
|
+
* to record the game's intended state, but write `true` to the underlying element
|
|
35
|
+
* whenever the SDK is muted. Tracked elements come from three sources:
|
|
36
|
+
* 1. Pre-existing DOM media (`querySelectorAll`)
|
|
37
|
+
* 2. `new Audio()` constructor shim (covers detached SFX)
|
|
38
|
+
* 3. MutationObserver for any media added to the DOM later (covers innerHTML,
|
|
39
|
+
* framework rendering, createElement + append, etc.)
|
|
40
|
+
*/
|
|
41
|
+
declare class AudioManager extends WavedashManager {
|
|
42
|
+
private _isMuted;
|
|
43
|
+
private contexts;
|
|
44
|
+
private elements;
|
|
45
|
+
private intendedMuted;
|
|
46
|
+
private originalAudioContext;
|
|
47
|
+
private originalWebKitAudioContext;
|
|
48
|
+
private originalAudio;
|
|
49
|
+
private originalMutedDescriptor;
|
|
50
|
+
private mutationObserver;
|
|
51
|
+
constructor(sdk: WavedashSDK);
|
|
52
|
+
isMuted(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Ask the host to mute (true) or unmute (false). Resolves to `true` if the
|
|
55
|
+
* host applied the change, `false` otherwise — notably, the host rejects an
|
|
56
|
+
* unmute when the user muted the game from the Wavedash UI, so games can't
|
|
57
|
+
* override an explicit user mute. The resulting state arrives via the usual
|
|
58
|
+
* MUTE_CHANGED broadcast, so `isMuted()` updates independently of this result.
|
|
59
|
+
*/
|
|
60
|
+
requestMute(muted: boolean): Promise<boolean>;
|
|
61
|
+
/**
|
|
62
|
+
* Toggle mute. Like `requestMute`, the host may reject the unmute half of a
|
|
63
|
+
* toggle if the user muted from the Wavedash UI. Resolves to `true` if the
|
|
64
|
+
* host applied the change.
|
|
65
|
+
*/
|
|
66
|
+
toggleMute(): Promise<boolean>;
|
|
67
|
+
private handleMute;
|
|
68
|
+
/**
|
|
69
|
+
* Track a media element and (if SDK is currently muted) silence it.
|
|
70
|
+
* Idempotent — safe to call multiple times for the same element.
|
|
71
|
+
*/
|
|
72
|
+
private trackElement;
|
|
73
|
+
private installShims;
|
|
74
|
+
private shimAudioContextClass;
|
|
75
|
+
destroy(): void;
|
|
76
|
+
}
|
|
77
|
+
|
|
8
78
|
/**
|
|
9
79
|
* SDK-to-Engine Events
|
|
10
80
|
*
|
|
@@ -91,6 +161,8 @@ type UpsertedLeaderboardEntry = FunctionReturnType<typeof api.sdk.leaderboards.u
|
|
|
91
161
|
userId: GenericId<"users">;
|
|
92
162
|
username: string;
|
|
93
163
|
userAvatarUrl?: string;
|
|
164
|
+
submittedScore: number;
|
|
165
|
+
submittedRank: number;
|
|
94
166
|
};
|
|
95
167
|
type WavedashEvent = (typeof WavedashEvents)[keyof typeof WavedashEvents];
|
|
96
168
|
interface WavedashConfig {
|
|
@@ -260,18 +332,234 @@ interface P2PConfig {
|
|
|
260
332
|
}
|
|
261
333
|
|
|
262
334
|
/**
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
* during teardown without each one having to define an empty stub.
|
|
335
|
+
* File system service
|
|
336
|
+
* Utilities for syncing local IndexedDB files with remote storage.
|
|
266
337
|
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
* — to make sure that state is released when the SDK is torn down.
|
|
338
|
+
* Exposes a specific remote folder for the game to save user-specific files to.
|
|
339
|
+
* TODO: Extend this to game-level assets as well.
|
|
270
340
|
*/
|
|
271
|
-
|
|
272
|
-
|
|
341
|
+
|
|
342
|
+
declare class FileSystemManager extends WavedashManager {
|
|
343
|
+
private remoteStorageOrigin;
|
|
344
|
+
constructor(sdk: WavedashSDK);
|
|
345
|
+
/**
|
|
346
|
+
* Converts a local filesystem path into a full R2 object key.
|
|
347
|
+
* Normalizes the Unity persistentDataPath and prepends the R2 prefix.
|
|
348
|
+
*/
|
|
349
|
+
private toRemoteKey;
|
|
350
|
+
/**
|
|
351
|
+
* Converts a full R2 object key back into the local filesystem path
|
|
352
|
+
* the engine expects. Inverse of toRemoteKey.
|
|
353
|
+
*/
|
|
354
|
+
private toLocalPath;
|
|
355
|
+
/**
|
|
356
|
+
* Uploads a local file to remote storage
|
|
357
|
+
* @param filePath - The path of the local file to upload
|
|
358
|
+
* @returns The path of the remote file that the local file was uploaded to
|
|
359
|
+
*/
|
|
360
|
+
uploadRemoteFile(filePath: string): Promise<string>;
|
|
361
|
+
/**
|
|
362
|
+
* Deletes a remote file from storage
|
|
363
|
+
* @param filePath - The path of the remote file to delete
|
|
364
|
+
* @returns The path of the remote file that was deleted
|
|
365
|
+
*/
|
|
366
|
+
deleteRemoteFile(filePath: string): Promise<string>;
|
|
367
|
+
/**
|
|
368
|
+
* Downloads a remote file to a local location.
|
|
369
|
+
* Throws on failure; the error message is the server's HTTP status (e.g. "404 (Not Found)")
|
|
370
|
+
* or a network-level description if the server didn't respond. See also: {@link remoteFileExists}
|
|
371
|
+
* @param filePath - The path of the remote file to download
|
|
372
|
+
* @returns The path of the local file that the remote file was downloaded to
|
|
373
|
+
*/
|
|
374
|
+
downloadRemoteFile(filePath: string): Promise<string>;
|
|
375
|
+
/**
|
|
376
|
+
* Checks whether a remote file exists by issuing a HEAD request.
|
|
377
|
+
* Does NOT throw for the "file does not exist" case — returns false.
|
|
378
|
+
* Throws only for real errors (network failure, auth failure, server error).
|
|
379
|
+
* @param filePath - The path of the remote file to check
|
|
380
|
+
* @returns true if the remote file exists, false otherwise
|
|
381
|
+
*/
|
|
382
|
+
remoteFileExists(filePath: string): Promise<boolean>;
|
|
383
|
+
/**
|
|
384
|
+
* Lists each file in a remote directory, including its subdirectories.
|
|
385
|
+
* Returns only file paths, no directory paths.
|
|
386
|
+
* An empty or non-existent directory returns an empty array — not an error.
|
|
387
|
+
* @param path - The path of the remote directory to list
|
|
388
|
+
* @returns A list of metadata for each file in the remote directory
|
|
389
|
+
*/
|
|
390
|
+
listRemoteDirectory(path: string): Promise<RemoteFileMetadata[]>;
|
|
391
|
+
downloadRemoteDirectory(path: string): Promise<string>;
|
|
392
|
+
writeLocalFile(filePath: string, data: Uint8Array): Promise<boolean>;
|
|
393
|
+
readLocalFile(filePath: string): Promise<Uint8Array | null>;
|
|
394
|
+
upload(presignedUploadUrl: string, filePath: string): Promise<boolean>;
|
|
395
|
+
download(url: string, filePath: string): Promise<void>;
|
|
396
|
+
private getRemoteStorageOrigin;
|
|
397
|
+
private getRemoteStorageUrl;
|
|
398
|
+
private uploadFromIndexedDb;
|
|
399
|
+
private uploadFromFS;
|
|
400
|
+
private readLocalFileBlob;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Friends service
|
|
405
|
+
*
|
|
406
|
+
* Implements friend-related methods for the Wavedash SDK
|
|
407
|
+
*/
|
|
408
|
+
|
|
409
|
+
declare class FriendsManager extends WavedashManager {
|
|
410
|
+
private userCache;
|
|
411
|
+
private leaderboardPageUserCache;
|
|
412
|
+
constructor(sdk: WavedashSDK);
|
|
413
|
+
/**
|
|
414
|
+
* Returns CDN URL with size transformation for a cached user's avatar.
|
|
415
|
+
* @param userId - The user ID to get the avatar URL for
|
|
416
|
+
* @param size - Pixel size for width and height. Use a value from
|
|
417
|
+
* `AvatarSize` (SMALL=64, MEDIUM=128, LARGE=256) or any custom pixel size.
|
|
418
|
+
* @returns CDN URL with size transformation, or null if user not cached or has no avatar
|
|
419
|
+
*/
|
|
420
|
+
getUserAvatarUrl(userId: GenericId<"users">, size?: number): string | null;
|
|
421
|
+
/**
|
|
422
|
+
* Returns the cached username for a given user ID
|
|
423
|
+
* @param userId - The user ID to get the username for
|
|
424
|
+
* @returns The username, or null if user not cached
|
|
425
|
+
*/
|
|
426
|
+
getUsername(userId: GenericId<"users">): string | null;
|
|
427
|
+
/**
|
|
428
|
+
* List all friends for the logged in user
|
|
429
|
+
* @returns Array<{
|
|
430
|
+
* avatarUrl?: string;
|
|
431
|
+
* isOnline: boolean;
|
|
432
|
+
* userId: Id<"users">;
|
|
433
|
+
* username: string;
|
|
434
|
+
* }>
|
|
435
|
+
*/
|
|
436
|
+
listFriends(): Promise<Friend[]>;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* FullscreenManager
|
|
441
|
+
*
|
|
442
|
+
* Wavedash owns the fullscreen target (a wrapper DIV on the host page that
|
|
443
|
+
* contains both the game iframe and our overlay UI). The SDK inside the iframe
|
|
444
|
+
* therefore can't call `requestFullscreen` directly — it asks the parent to
|
|
445
|
+
* do it via postMessage, and the parent broadcasts state changes back through
|
|
446
|
+
* FULLSCREEN_CHANGED so we can keep a local mirror of `isFullscreen`.
|
|
447
|
+
*
|
|
448
|
+
* User activation: browsers require a fresh user gesture to enter fullscreen.
|
|
449
|
+
* The click happens in the iframe, User Activation v2 propagates transient
|
|
450
|
+
* activation to ancestor frames, and the parent's message handler runs within
|
|
451
|
+
* the ~5s window — so the parent's requestFullscreen call stays activated.
|
|
452
|
+
*
|
|
453
|
+
* Legacy compat: games that call `element.requestFullscreen()` or listen for
|
|
454
|
+
* `fullscreenchange` directly are monkey-patched in the constructor so those
|
|
455
|
+
* calls route through us. The iframe isn't granted the fullscreen feature
|
|
456
|
+
* policy anymore, so without these shims those calls would silently reject.
|
|
457
|
+
*/
|
|
458
|
+
declare class FullscreenManager extends WavedashManager {
|
|
459
|
+
private _isFullscreen;
|
|
460
|
+
private listeners;
|
|
461
|
+
constructor(sdk: WavedashSDK);
|
|
462
|
+
isFullscreen(): boolean;
|
|
463
|
+
/**
|
|
464
|
+
* Ask the host to enter (true) or exit (false) fullscreen. Resolves to
|
|
465
|
+
* `true` if the host reports the operation succeeded, `false` otherwise
|
|
466
|
+
* (e.g. browser rejected for lack of user activation).
|
|
467
|
+
*/
|
|
468
|
+
requestFullscreen(fullscreen: boolean): Promise<boolean>;
|
|
469
|
+
toggleFullscreen(): Promise<boolean>;
|
|
470
|
+
/** Subscribe to state flips. Returns an unsubscribe fn. */
|
|
471
|
+
subscribe(listener: (isFullscreen: boolean) => void): () => void;
|
|
472
|
+
private setState;
|
|
473
|
+
private installCompatShims;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
declare class GameEventManager extends WavedashManager {
|
|
477
|
+
private eventQueue;
|
|
273
478
|
constructor(sdk: WavedashSDK);
|
|
479
|
+
notifyGame(event: WavedashEvent, payload: string | number | object): void;
|
|
480
|
+
private sendGameEvent;
|
|
481
|
+
flushEventQueue(): void;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Heartbeat service
|
|
486
|
+
*
|
|
487
|
+
* Polls connection state and allows the game to update rich user presence
|
|
488
|
+
* Lets the game know if backend connection ever changes.
|
|
489
|
+
* Lets the game update userPresence in the backend
|
|
490
|
+
*/
|
|
491
|
+
|
|
492
|
+
declare class HeartbeatManager extends WavedashManager {
|
|
493
|
+
private deviceFingerprint;
|
|
494
|
+
private deviceFingerprintReady;
|
|
495
|
+
private testConnectionInterval;
|
|
496
|
+
private heartbeatInterval;
|
|
497
|
+
private gamepadPollInterval;
|
|
498
|
+
private inactivityTimeout;
|
|
499
|
+
private isConnected;
|
|
500
|
+
private sentDisconnectedEvent;
|
|
501
|
+
private disconnectedAt;
|
|
502
|
+
private lastHeartbeatTime;
|
|
503
|
+
private lastInputResetAt;
|
|
504
|
+
private heartbeatInFlight;
|
|
505
|
+
private isFirstTick;
|
|
506
|
+
private readonly TEST_CONNECTION_INTERVAL_MS;
|
|
507
|
+
private readonly DISCONNECTED_TIMEOUT_MS;
|
|
508
|
+
private readonly INACTIVITY_TIMEOUT_MS;
|
|
509
|
+
private readonly INPUT_THROTTLE_MS;
|
|
510
|
+
private readonly GAMEPAD_POLL_INTERVAL_MS;
|
|
511
|
+
private readonly GAMEPAD_AXIS_DEADZONE;
|
|
512
|
+
private cachedPresenceData;
|
|
513
|
+
constructor(sdk: WavedashSDK);
|
|
514
|
+
/**
|
|
515
|
+
* Start (or refresh) the heartbeat. Idempotent: if intervals are already
|
|
516
|
+
* running this just reschedules the inactivity timer. No-op if the game
|
|
517
|
+
* hasn't loaded yet or the tab is hidden.
|
|
518
|
+
*/
|
|
519
|
+
start(): void;
|
|
520
|
+
/** Stop the heartbeat and clear the inactivity timer. Idempotent. */
|
|
521
|
+
stop(): void;
|
|
522
|
+
/**
|
|
523
|
+
* Updates user presence in the backend.
|
|
524
|
+
* @param data - Data to send to the backend
|
|
525
|
+
* @returns true if the presence was updated successfully
|
|
526
|
+
*/
|
|
527
|
+
updateUserPresence(data: Record<string, string | number | boolean | null>): Promise<boolean>;
|
|
528
|
+
isCurrentlyConnected(): boolean;
|
|
529
|
+
/** Full teardown — stops intervals and removes all listeners */
|
|
274
530
|
destroy(): void;
|
|
531
|
+
private tickHeartbeat;
|
|
532
|
+
private sendHeartbeat;
|
|
533
|
+
private handleVisibilityChange;
|
|
534
|
+
private handleUserInput;
|
|
535
|
+
/**
|
|
536
|
+
* Polls connected gamepads; any pressed button or out-of-deadzone axis
|
|
537
|
+
* counts as user activity and (re)starts the heartbeat.
|
|
538
|
+
*/
|
|
539
|
+
private pollGamepads;
|
|
540
|
+
/**
|
|
541
|
+
* Tests the connection to the backend
|
|
542
|
+
*/
|
|
543
|
+
private testConnection;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Leaderboard service
|
|
548
|
+
*
|
|
549
|
+
* Implements each of the leaderboard methods of the Wavedash SDK
|
|
550
|
+
*/
|
|
551
|
+
|
|
552
|
+
declare class LeaderboardManager extends WavedashManager {
|
|
553
|
+
private leaderboardCache;
|
|
554
|
+
constructor(sdk: WavedashSDK);
|
|
555
|
+
getLeaderboard(name: string): Promise<Leaderboard>;
|
|
556
|
+
getOrCreateLeaderboard(name: string, sortOrder: LeaderboardSortOrder, displayType: LeaderboardDisplayType): Promise<Leaderboard>;
|
|
557
|
+
getLeaderboardEntryCount(leaderboardId: GenericId<"leaderboards">): number;
|
|
558
|
+
getMyLeaderboardEntries(leaderboardId: GenericId<"leaderboards">): Promise<LeaderboardEntries>;
|
|
559
|
+
listLeaderboardEntriesAroundUser(leaderboardId: GenericId<"leaderboards">, countAhead: number, countBehind: number, friendsOnly?: boolean): Promise<LeaderboardEntries>;
|
|
560
|
+
listLeaderboardEntries(leaderboardId: GenericId<"leaderboards">, offset: number, limit: number, friendsOnly?: boolean): Promise<LeaderboardEntries>;
|
|
561
|
+
uploadLeaderboardScore(leaderboardId: GenericId<"leaderboards">, score: number, keepBest: boolean, ugcId?: GenericId<"userGeneratedContent">): Promise<UpsertedLeaderboardEntry>;
|
|
562
|
+
private updateCachedTotalEntries;
|
|
275
563
|
}
|
|
276
564
|
|
|
277
565
|
/**
|
|
@@ -350,121 +638,36 @@ declare class LobbyManager extends WavedashManager {
|
|
|
350
638
|
destroy(): void;
|
|
351
639
|
private throttledSetMetadata;
|
|
352
640
|
private setMetadata;
|
|
353
|
-
/**
|
|
354
|
-
* Process user updates and emit individual user events
|
|
355
|
-
* @param newUsers - The updated list of lobby users
|
|
356
|
-
*/
|
|
357
|
-
private processUserUpdates;
|
|
358
|
-
private processMessageUpdates;
|
|
359
|
-
private processInviteUpdates;
|
|
360
|
-
/**
|
|
361
|
-
* Update P2P connections when lobby membership changes
|
|
362
|
-
* @param newUsers - The updated list of lobby users
|
|
363
|
-
*/
|
|
364
|
-
private updateP2PConnections;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
/**
|
|
368
|
-
* File system service
|
|
369
|
-
* Utilities for syncing local IndexedDB files with remote storage.
|
|
370
|
-
*
|
|
371
|
-
* Exposes a specific remote folder for the game to save user-specific files to.
|
|
372
|
-
* TODO: Extend this to game-level assets as well.
|
|
373
|
-
*/
|
|
374
|
-
|
|
375
|
-
declare class FileSystemManager extends WavedashManager {
|
|
376
|
-
private remoteStorageOrigin;
|
|
377
|
-
constructor(sdk: WavedashSDK);
|
|
378
|
-
/**
|
|
379
|
-
* Converts a local filesystem path into a full R2 object key.
|
|
380
|
-
* Normalizes the Unity persistentDataPath and prepends the R2 prefix.
|
|
381
|
-
*/
|
|
382
|
-
private toRemoteKey;
|
|
383
|
-
/**
|
|
384
|
-
* Converts a full R2 object key back into the local filesystem path
|
|
385
|
-
* the engine expects. Inverse of toRemoteKey.
|
|
386
|
-
*/
|
|
387
|
-
private toLocalPath;
|
|
388
|
-
/**
|
|
389
|
-
* Uploads a local file to remote storage
|
|
390
|
-
* @param filePath - The path of the local file to upload
|
|
391
|
-
* @returns The path of the remote file that the local file was uploaded to
|
|
392
|
-
*/
|
|
393
|
-
uploadRemoteFile(filePath: string): Promise<string>;
|
|
394
|
-
/**
|
|
395
|
-
* Deletes a remote file from storage
|
|
396
|
-
* @param filePath - The path of the remote file to delete
|
|
397
|
-
* @returns The path of the remote file that was deleted
|
|
398
|
-
*/
|
|
399
|
-
deleteRemoteFile(filePath: string): Promise<string>;
|
|
400
|
-
/**
|
|
401
|
-
* Downloads a remote file to a local location.
|
|
402
|
-
* Throws on failure; the error message is the server's HTTP status (e.g. "404 (Not Found)")
|
|
403
|
-
* or a network-level description if the server didn't respond. See also: {@link remoteFileExists}
|
|
404
|
-
* @param filePath - The path of the remote file to download
|
|
405
|
-
* @returns The path of the local file that the remote file was downloaded to
|
|
406
|
-
*/
|
|
407
|
-
downloadRemoteFile(filePath: string): Promise<string>;
|
|
408
|
-
/**
|
|
409
|
-
* Checks whether a remote file exists by issuing a HEAD request.
|
|
410
|
-
* Does NOT throw for the "file does not exist" case — returns false.
|
|
411
|
-
* Throws only for real errors (network failure, auth failure, server error).
|
|
412
|
-
* @param filePath - The path of the remote file to check
|
|
413
|
-
* @returns true if the remote file exists, false otherwise
|
|
414
|
-
*/
|
|
415
|
-
remoteFileExists(filePath: string): Promise<boolean>;
|
|
416
|
-
/**
|
|
417
|
-
* Lists each file in a remote directory, including its subdirectories.
|
|
418
|
-
* Returns only file paths, no directory paths.
|
|
419
|
-
* An empty or non-existent directory returns an empty array — not an error.
|
|
420
|
-
* @param path - The path of the remote directory to list
|
|
421
|
-
* @returns A list of metadata for each file in the remote directory
|
|
422
|
-
*/
|
|
423
|
-
listRemoteDirectory(path: string): Promise<RemoteFileMetadata[]>;
|
|
424
|
-
downloadRemoteDirectory(path: string): Promise<string>;
|
|
425
|
-
writeLocalFile(filePath: string, data: Uint8Array): Promise<boolean>;
|
|
426
|
-
readLocalFile(filePath: string): Promise<Uint8Array | null>;
|
|
427
|
-
upload(presignedUploadUrl: string, filePath: string): Promise<boolean>;
|
|
428
|
-
download(url: string, filePath: string): Promise<void>;
|
|
429
|
-
private getRemoteStorageOrigin;
|
|
430
|
-
private getRemoteStorageUrl;
|
|
431
|
-
private uploadFromIndexedDb;
|
|
432
|
-
private uploadFromFS;
|
|
433
|
-
private readLocalFileBlob;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* UGC service
|
|
438
|
-
*
|
|
439
|
-
* Implements each of the user generated content methods of the Wavedash SDK
|
|
440
|
-
*/
|
|
441
|
-
|
|
442
|
-
declare class UGCManager extends WavedashManager {
|
|
443
|
-
constructor(sdk: WavedashSDK);
|
|
444
|
-
createUGCItem(ugcType: UGCType, title?: string, description?: string, visibility?: UGCVisibility, filePath?: string): Promise<GenericId<"userGeneratedContent">>;
|
|
445
|
-
updateUGCItem(ugcId: GenericId<"userGeneratedContent">, updates?: UpdateUGCItemArgs): Promise<GenericId<"userGeneratedContent">>;
|
|
446
|
-
deleteUGCItem(ugcId: GenericId<"userGeneratedContent">): Promise<GenericId<"userGeneratedContent">>;
|
|
447
|
-
downloadUGCItem(ugcId: GenericId<"userGeneratedContent">, filePath: string): Promise<GenericId<"userGeneratedContent">>;
|
|
448
|
-
listUGCItems(args?: ListUGCItemsArgs): Promise<PaginatedUGCItems>;
|
|
641
|
+
/**
|
|
642
|
+
* Process user updates and emit individual user events
|
|
643
|
+
* @param newUsers - The updated list of lobby users
|
|
644
|
+
*/
|
|
645
|
+
private processUserUpdates;
|
|
646
|
+
private processMessageUpdates;
|
|
647
|
+
private processInviteUpdates;
|
|
648
|
+
/**
|
|
649
|
+
* Update P2P connections when lobby membership changes
|
|
650
|
+
* @param newUsers - The updated list of lobby users
|
|
651
|
+
*/
|
|
652
|
+
private updateP2PConnections;
|
|
449
653
|
}
|
|
450
654
|
|
|
451
655
|
/**
|
|
452
|
-
*
|
|
656
|
+
* OverlayManager
|
|
453
657
|
*
|
|
454
|
-
*
|
|
658
|
+
* Owns the iframe ↔ parent interactions for the Wavedash overlay UI:
|
|
659
|
+
* - Shift+Tab inside the iframe toggles the overlay on the host page
|
|
660
|
+
* (the host owns the overlay, so we postMessage up).
|
|
661
|
+
* - When the parent closes the overlay it sends TAKE_FOCUS so keyboard
|
|
662
|
+
* input goes back to the game; we walk the DOM for a focusable target.
|
|
663
|
+
* - `takeFocus()` is also called after load completes so the game starts
|
|
664
|
+
* with keyboard focus without the player clicking first.
|
|
455
665
|
*/
|
|
456
|
-
|
|
457
|
-
declare class LeaderboardManager extends WavedashManager {
|
|
458
|
-
private leaderboardCache;
|
|
666
|
+
declare class OverlayManager extends WavedashManager {
|
|
459
667
|
constructor(sdk: WavedashSDK);
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
getMyLeaderboardEntries(leaderboardId: GenericId<"leaderboards">): Promise<LeaderboardEntries>;
|
|
464
|
-
listLeaderboardEntriesAroundUser(leaderboardId: GenericId<"leaderboards">, countAhead: number, countBehind: number, friendsOnly?: boolean): Promise<LeaderboardEntries>;
|
|
465
|
-
listLeaderboardEntries(leaderboardId: GenericId<"leaderboards">, offset: number, limit: number, friendsOnly?: boolean): Promise<LeaderboardEntries>;
|
|
466
|
-
uploadLeaderboardScore(leaderboardId: GenericId<"leaderboards">, score: number, keepBest: boolean, ugcId?: GenericId<"userGeneratedContent">): Promise<UpsertedLeaderboardEntry>;
|
|
467
|
-
private updateCachedTotalEntries;
|
|
668
|
+
toggleOverlay(): void;
|
|
669
|
+
takeFocus(): void;
|
|
670
|
+
private handleKeyDown;
|
|
468
671
|
}
|
|
469
672
|
|
|
470
673
|
/**
|
|
@@ -584,6 +787,12 @@ declare class P2PManager extends WavedashManager {
|
|
|
584
787
|
private decodeBinaryMessage;
|
|
585
788
|
}
|
|
586
789
|
|
|
790
|
+
declare class PaidContentManager extends WavedashManager {
|
|
791
|
+
isEntitled(contentId: string): Promise<boolean>;
|
|
792
|
+
getEntitlements(): Promise<string[]>;
|
|
793
|
+
triggerPaywall(contentIdentifier: string): Promise<boolean>;
|
|
794
|
+
}
|
|
795
|
+
|
|
587
796
|
declare class StatsManager extends WavedashManager {
|
|
588
797
|
private stats;
|
|
589
798
|
private unlockedAchievements;
|
|
@@ -613,205 +822,18 @@ declare class StatsManager extends WavedashManager {
|
|
|
613
822
|
}
|
|
614
823
|
|
|
615
824
|
/**
|
|
616
|
-
*
|
|
617
|
-
*
|
|
618
|
-
* Polls connection state and allows the game to update rich user presence
|
|
619
|
-
* Lets the game know if backend connection ever changes.
|
|
620
|
-
* Lets the game update userPresence in the backend
|
|
621
|
-
*/
|
|
622
|
-
|
|
623
|
-
declare class HeartbeatManager extends WavedashManager {
|
|
624
|
-
private deviceFingerprint;
|
|
625
|
-
private deviceFingerprintReady;
|
|
626
|
-
private testConnectionInterval;
|
|
627
|
-
private heartbeatInterval;
|
|
628
|
-
private gamepadPollInterval;
|
|
629
|
-
private inactivityTimeout;
|
|
630
|
-
private isConnected;
|
|
631
|
-
private sentDisconnectedEvent;
|
|
632
|
-
private disconnectedAt;
|
|
633
|
-
private lastHeartbeatTime;
|
|
634
|
-
private lastInputResetAt;
|
|
635
|
-
private heartbeatInFlight;
|
|
636
|
-
private isFirstTick;
|
|
637
|
-
private readonly TEST_CONNECTION_INTERVAL_MS;
|
|
638
|
-
private readonly DISCONNECTED_TIMEOUT_MS;
|
|
639
|
-
private readonly INACTIVITY_TIMEOUT_MS;
|
|
640
|
-
private readonly INPUT_THROTTLE_MS;
|
|
641
|
-
private readonly GAMEPAD_POLL_INTERVAL_MS;
|
|
642
|
-
private readonly GAMEPAD_AXIS_DEADZONE;
|
|
643
|
-
private cachedPresenceData;
|
|
644
|
-
constructor(sdk: WavedashSDK);
|
|
645
|
-
/**
|
|
646
|
-
* Start (or refresh) the heartbeat. Idempotent: if intervals are already
|
|
647
|
-
* running this just reschedules the inactivity timer. No-op if the game
|
|
648
|
-
* hasn't loaded yet or the tab is hidden.
|
|
649
|
-
*/
|
|
650
|
-
start(): void;
|
|
651
|
-
/** Stop the heartbeat and clear the inactivity timer. Idempotent. */
|
|
652
|
-
stop(): void;
|
|
653
|
-
/**
|
|
654
|
-
* Updates user presence in the backend.
|
|
655
|
-
* @param data - Data to send to the backend
|
|
656
|
-
* @returns true if the presence was updated successfully
|
|
657
|
-
*/
|
|
658
|
-
updateUserPresence(data: Record<string, string | number | boolean | null>): Promise<boolean>;
|
|
659
|
-
isCurrentlyConnected(): boolean;
|
|
660
|
-
/** Full teardown — stops intervals and removes all listeners */
|
|
661
|
-
destroy(): void;
|
|
662
|
-
private tickHeartbeat;
|
|
663
|
-
private sendHeartbeat;
|
|
664
|
-
private handleVisibilityChange;
|
|
665
|
-
private handleUserInput;
|
|
666
|
-
/**
|
|
667
|
-
* Polls connected gamepads; any pressed button or out-of-deadzone axis
|
|
668
|
-
* counts as user activity and (re)starts the heartbeat.
|
|
669
|
-
*/
|
|
670
|
-
private pollGamepads;
|
|
671
|
-
/**
|
|
672
|
-
* Tests the connection to the backend
|
|
673
|
-
*/
|
|
674
|
-
private testConnection;
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
declare class GameEventManager extends WavedashManager {
|
|
678
|
-
private eventQueue;
|
|
679
|
-
constructor(sdk: WavedashSDK);
|
|
680
|
-
notifyGame(event: WavedashEvent, payload: string | number | object): void;
|
|
681
|
-
private sendGameEvent;
|
|
682
|
-
flushEventQueue(): void;
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
/**
|
|
686
|
-
* FullscreenManager
|
|
687
|
-
*
|
|
688
|
-
* Wavedash owns the fullscreen target (a wrapper DIV on the host page that
|
|
689
|
-
* contains both the game iframe and our overlay UI). The SDK inside the iframe
|
|
690
|
-
* therefore can't call `requestFullscreen` directly — it asks the parent to
|
|
691
|
-
* do it via postMessage, and the parent broadcasts state changes back through
|
|
692
|
-
* FULLSCREEN_CHANGED so we can keep a local mirror of `isFullscreen`.
|
|
693
|
-
*
|
|
694
|
-
* User activation: browsers require a fresh user gesture to enter fullscreen.
|
|
695
|
-
* The click happens in the iframe, User Activation v2 propagates transient
|
|
696
|
-
* activation to ancestor frames, and the parent's message handler runs within
|
|
697
|
-
* the ~5s window — so the parent's requestFullscreen call stays activated.
|
|
698
|
-
*
|
|
699
|
-
* Legacy compat: games that call `element.requestFullscreen()` or listen for
|
|
700
|
-
* `fullscreenchange` directly are monkey-patched in the constructor so those
|
|
701
|
-
* calls route through us. The iframe isn't granted the fullscreen feature
|
|
702
|
-
* policy anymore, so without these shims those calls would silently reject.
|
|
703
|
-
*/
|
|
704
|
-
declare class FullscreenManager extends WavedashManager {
|
|
705
|
-
private _isFullscreen;
|
|
706
|
-
private listeners;
|
|
707
|
-
constructor(sdk: WavedashSDK);
|
|
708
|
-
isFullscreen(): boolean;
|
|
709
|
-
/**
|
|
710
|
-
* Ask the host to enter (true) or exit (false) fullscreen. Resolves to
|
|
711
|
-
* `true` if the host reports the operation succeeded, `false` otherwise
|
|
712
|
-
* (e.g. browser rejected for lack of user activation).
|
|
713
|
-
*/
|
|
714
|
-
requestFullscreen(fullscreen: boolean): Promise<boolean>;
|
|
715
|
-
toggleFullscreen(): Promise<boolean>;
|
|
716
|
-
/** Subscribe to state flips. Returns an unsubscribe fn. */
|
|
717
|
-
subscribe(listener: (isFullscreen: boolean) => void): () => void;
|
|
718
|
-
private setState;
|
|
719
|
-
private installCompatShims;
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
/**
|
|
723
|
-
* OverlayManager
|
|
724
|
-
*
|
|
725
|
-
* Owns the iframe ↔ parent interactions for the Wavedash overlay UI:
|
|
726
|
-
* - Shift+Tab inside the iframe toggles the overlay on the host page
|
|
727
|
-
* (the host owns the overlay, so we postMessage up).
|
|
728
|
-
* - When the parent closes the overlay it sends TAKE_FOCUS so keyboard
|
|
729
|
-
* input goes back to the game; we walk the DOM for a focusable target.
|
|
730
|
-
* - `takeFocus()` is also called after load completes so the game starts
|
|
731
|
-
* with keyboard focus without the player clicking first.
|
|
732
|
-
*/
|
|
733
|
-
declare class OverlayManager extends WavedashManager {
|
|
734
|
-
constructor(sdk: WavedashSDK);
|
|
735
|
-
toggleOverlay(): void;
|
|
736
|
-
takeFocus(): void;
|
|
737
|
-
private handleKeyDown;
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
/**
|
|
741
|
-
* AudioManager
|
|
742
|
-
*
|
|
743
|
-
* Mutes & unmutes the game in response to MUTE_CHANGED iframe messages, without
|
|
744
|
-
* the game needing to know anything about it.
|
|
745
|
-
*
|
|
746
|
-
* Web Audio: subclass `AudioContext` so `ctx.destination` resolves to a master
|
|
747
|
-
* GainNode that we control. The master gain wires to the real native destination,
|
|
748
|
-
* so `node.connect(ctx.destination)` and any other game code is unaffected.
|
|
749
|
-
*
|
|
750
|
-
* HTML Media (`<audio>`/`<video>`): override `HTMLMediaElement.prototype.muted`
|
|
751
|
-
* to record the game's intended state, but write `true` to the underlying element
|
|
752
|
-
* whenever the SDK is muted. Tracked elements come from three sources:
|
|
753
|
-
* 1. Pre-existing DOM media (`querySelectorAll`)
|
|
754
|
-
* 2. `new Audio()` constructor shim (covers detached SFX)
|
|
755
|
-
* 3. MutationObserver for any media added to the DOM later (covers innerHTML,
|
|
756
|
-
* framework rendering, createElement + append, etc.)
|
|
757
|
-
*/
|
|
758
|
-
declare class AudioManager extends WavedashManager {
|
|
759
|
-
private _isMuted;
|
|
760
|
-
private contexts;
|
|
761
|
-
private elements;
|
|
762
|
-
private intendedMuted;
|
|
763
|
-
private originalAudioContext;
|
|
764
|
-
private originalWebKitAudioContext;
|
|
765
|
-
private originalAudio;
|
|
766
|
-
private originalMutedDescriptor;
|
|
767
|
-
private mutationObserver;
|
|
768
|
-
constructor(sdk: WavedashSDK);
|
|
769
|
-
isMuted(): boolean;
|
|
770
|
-
private handleMute;
|
|
771
|
-
/**
|
|
772
|
-
* Track a media element and (if SDK is currently muted) silence it.
|
|
773
|
-
* Idempotent — safe to call multiple times for the same element.
|
|
774
|
-
*/
|
|
775
|
-
private trackElement;
|
|
776
|
-
private installShims;
|
|
777
|
-
private shimAudioContextClass;
|
|
778
|
-
destroy(): void;
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
/**
|
|
782
|
-
* Friends service
|
|
825
|
+
* UGC service
|
|
783
826
|
*
|
|
784
|
-
* Implements
|
|
827
|
+
* Implements each of the user generated content methods of the Wavedash SDK
|
|
785
828
|
*/
|
|
786
829
|
|
|
787
|
-
declare class
|
|
788
|
-
private userCache;
|
|
789
|
-
private leaderboardPageUserCache;
|
|
830
|
+
declare class UGCManager extends WavedashManager {
|
|
790
831
|
constructor(sdk: WavedashSDK);
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
* @returns CDN URL with size transformation, or null if user not cached or has no avatar
|
|
797
|
-
*/
|
|
798
|
-
getUserAvatarUrl(userId: GenericId<"users">, size?: number): string | null;
|
|
799
|
-
/**
|
|
800
|
-
* Returns the cached username for a given user ID
|
|
801
|
-
* @param userId - The user ID to get the username for
|
|
802
|
-
* @returns The username, or null if user not cached
|
|
803
|
-
*/
|
|
804
|
-
getUsername(userId: GenericId<"users">): string | null;
|
|
805
|
-
/**
|
|
806
|
-
* List all friends for the logged in user
|
|
807
|
-
* @returns Array<{
|
|
808
|
-
* avatarUrl?: string;
|
|
809
|
-
* isOnline: boolean;
|
|
810
|
-
* userId: Id<"users">;
|
|
811
|
-
* username: string;
|
|
812
|
-
* }>
|
|
813
|
-
*/
|
|
814
|
-
listFriends(): Promise<Friend[]>;
|
|
832
|
+
createUGCItem(ugcType: UGCType, title?: string, description?: string, visibility?: UGCVisibility, filePath?: string): Promise<GenericId<"userGeneratedContent">>;
|
|
833
|
+
updateUGCItem(ugcId: GenericId<"userGeneratedContent">, updates?: UpdateUGCItemArgs): Promise<GenericId<"userGeneratedContent">>;
|
|
834
|
+
deleteUGCItem(ugcId: GenericId<"userGeneratedContent">): Promise<GenericId<"userGeneratedContent">>;
|
|
835
|
+
downloadUGCItem(ugcId: GenericId<"userGeneratedContent">, filePath: string): Promise<GenericId<"userGeneratedContent">>;
|
|
836
|
+
listUGCItems(args?: ListUGCItemsArgs): Promise<PaginatedUGCItems>;
|
|
815
837
|
}
|
|
816
838
|
|
|
817
839
|
/**
|
|
@@ -837,7 +859,7 @@ declare class IFrameMessenger {
|
|
|
837
859
|
removeEventListener<T extends PushType>(type: T, listener: PushListener<T>): void;
|
|
838
860
|
private handleMessage;
|
|
839
861
|
postToParent(requestType: (typeof IFRAME_MESSAGE_TYPE)[keyof typeof IFRAME_MESSAGE_TYPE], data: Record<string, string | number | boolean>): boolean;
|
|
840
|
-
requestFromParent<T extends keyof IFrameEventPayloadMap>(requestType: T, data?: Record<string, unknown
|
|
862
|
+
requestFromParent<T extends keyof IFrameEventPayloadMap>(requestType: T, data?: Record<string, unknown>, timeoutMs?: number): Promise<IFrameEventPayloadMap[T]>;
|
|
841
863
|
}
|
|
842
864
|
|
|
843
865
|
/**
|
|
@@ -965,6 +987,7 @@ declare class WavedashSDK extends EventTarget {
|
|
|
965
987
|
fullscreenManager: FullscreenManager;
|
|
966
988
|
overlayManager: OverlayManager;
|
|
967
989
|
audioManager: AudioManager;
|
|
990
|
+
paidContentManager: PaidContentManager;
|
|
968
991
|
private managers;
|
|
969
992
|
private gameplayJwt;
|
|
970
993
|
private gameplayJwtPromise;
|
|
@@ -1021,6 +1044,22 @@ declare class WavedashSDK extends EventTarget {
|
|
|
1021
1044
|
* a user gesture handler when entering fullscreen.
|
|
1022
1045
|
*/
|
|
1023
1046
|
toggleFullscreen(): Promise<boolean>;
|
|
1047
|
+
/**
|
|
1048
|
+
* Whether the game is currently muted. Mirrored from the Wavedash host page,
|
|
1049
|
+
* which owns the mute control so its UI button and the game stay in sync.
|
|
1050
|
+
*/
|
|
1051
|
+
isMuted(): boolean;
|
|
1052
|
+
/**
|
|
1053
|
+
* Ask the host to mute (true) or unmute (false). Resolves to `true` if the
|
|
1054
|
+
* change was applied, `false` if it was rejected — the host won't let the
|
|
1055
|
+
* game unmute when the user has muted from the Wavedash UI.
|
|
1056
|
+
*/
|
|
1057
|
+
requestMute(muted: boolean): Promise<boolean>;
|
|
1058
|
+
/**
|
|
1059
|
+
* Toggle mute. Resolves to `true` if the change was applied, `false` if it
|
|
1060
|
+
* was rejected (e.g. trying to unmute over an explicit user mute).
|
|
1061
|
+
*/
|
|
1062
|
+
toggleMute(): Promise<boolean>;
|
|
1024
1063
|
getUser(): SDKUser;
|
|
1025
1064
|
/**
|
|
1026
1065
|
* Get a username. Returns the logged in user's username if no ID is passed.
|
|
@@ -1228,6 +1267,31 @@ declare class WavedashSDK extends EventTarget {
|
|
|
1228
1267
|
sendLobbyMessage(lobbyId: GenericId<"lobbies">, message: string): boolean;
|
|
1229
1268
|
inviteUserToLobby(lobbyId: GenericId<"lobbies">, userId: GenericId<"users">): Promise<WavedashResponse<boolean>>;
|
|
1230
1269
|
getLobbyInviteLink(copyToClipboard?: boolean): Promise<WavedashResponse<string>>;
|
|
1270
|
+
/**
|
|
1271
|
+
* Returns true if the player owns the given paid content for this game.
|
|
1272
|
+
* Reads the `entitlements` claim from the gameplay JWT — this is a UX hint, not a
|
|
1273
|
+
* security check. The builds server re-verifies the JWT signature and gates
|
|
1274
|
+
* paid asset bytes on every request, so a tampered client return value
|
|
1275
|
+
* doesn't actually unlock anything. Pair with triggerPaywall() to drive
|
|
1276
|
+
* in-game UI.
|
|
1277
|
+
*/
|
|
1278
|
+
isEntitled_EXPERIMENTAL(contentId: string): Promise<WavedashResponse<boolean>>;
|
|
1279
|
+
/**
|
|
1280
|
+
* Returns the full list of paid-content IDs the player owns for this game.
|
|
1281
|
+
* Reads the `entitlements` claim from the gameplay JWT — this is a UX hint,
|
|
1282
|
+
* not a security check (see {@link isEntitled_EXPERIMENTAL}). Useful
|
|
1283
|
+
* for access gating multiple items at once without a call per content ID.
|
|
1284
|
+
*/
|
|
1285
|
+
getEntitlements_EXPERIMENTAL(): Promise<WavedashResponse<string[]>>;
|
|
1286
|
+
/**
|
|
1287
|
+
* Trigger the Wavedash-rendered paywall flow for the given content. Resolves
|
|
1288
|
+
* immediately with data `true` if the player already owns it; otherwise
|
|
1289
|
+
* opens the modal and resolves with whether the user completed the purchase.
|
|
1290
|
+
* After a successful purchase the JWT is refreshed automatically so a
|
|
1291
|
+
* subsequent resource fetch is authenticated with the new purchase, and isEntitled
|
|
1292
|
+
* will return true if the purchase was successful.
|
|
1293
|
+
*/
|
|
1294
|
+
triggerPaywall_EXPERIMENTAL(contentIdentifier: string): Promise<WavedashResponse<boolean>>;
|
|
1231
1295
|
/**
|
|
1232
1296
|
* Updates rich user presence so friends can see what the player is doing in game.
|
|
1233
1297
|
* Supported keys:
|
|
@@ -1245,17 +1309,15 @@ declare class WavedashSDK extends EventTarget {
|
|
|
1245
1309
|
private apiCall;
|
|
1246
1310
|
private apiCallSync;
|
|
1247
1311
|
/**
|
|
1248
|
-
*
|
|
1249
|
-
*
|
|
1250
|
-
*
|
|
1251
|
-
* server can invalidate a stale token.
|
|
1252
|
-
*
|
|
1253
|
-
* Same-origin POST to /auth/refresh on the play domain — the
|
|
1254
|
-
* gameplaySession cookie set by the play server during playKey exchange
|
|
1255
|
-
* authenticates the request, so no cross-origin credentials handling needed.
|
|
1312
|
+
* Fetcher wired into `ConvexClient.setAuth`; other callers use
|
|
1313
|
+
* {@link ensureGameplayJwt}. Same-origin POST to /auth/refresh, authenticated
|
|
1314
|
+
* by the gameplaySession cookie.
|
|
1256
1315
|
*
|
|
1257
|
-
* Concurrent callers share
|
|
1258
|
-
*
|
|
1316
|
+
* Concurrent callers share one in-flight fetch. A forced refresh instead
|
|
1317
|
+
* serializes behind any in-flight fetch (it may predate the event that
|
|
1318
|
+
* required it, e.g. a purchase) and becomes the current promise; only the
|
|
1319
|
+
* current promise notifies the parent, so a superseded refresh can't
|
|
1320
|
+
* broadcast a stale token
|
|
1259
1321
|
*/
|
|
1260
1322
|
private getAuthToken;
|
|
1261
1323
|
/**
|
|
@@ -1263,7 +1325,7 @@ declare class WavedashSDK extends EventTarget {
|
|
|
1263
1325
|
* already running (e.g. from Convex's initial setAuth). Use this anywhere
|
|
1264
1326
|
* you need to authenticate a request outside of the Convex client.
|
|
1265
1327
|
*/
|
|
1266
|
-
ensureGameplayJwt(): Promise<string>;
|
|
1328
|
+
ensureGameplayJwt(forceRefresh?: boolean): Promise<string>;
|
|
1267
1329
|
/**
|
|
1268
1330
|
* Tear down every manager. Called on the parent's `END_SESSION` signal
|
|
1269
1331
|
*/
|