@wvdsh/sdk-js 1.3.3 → 1.3.5
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 +38 -29
- package/dist/index.js +103 -71
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -245,14 +245,28 @@ interface P2PConfig {
|
|
|
245
245
|
maxIncomingMessages?: number;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Base class for SDK managers. Provides the shared `sdk` reference and a
|
|
250
|
+
* default no-op `destroy()` so the SDK can safely iterate every manager
|
|
251
|
+
* during teardown without each one having to define an empty stub.
|
|
252
|
+
*
|
|
253
|
+
* Override `destroy()` in any manager that owns ongoing state — Convex
|
|
254
|
+
* subscriptions, intervals, peer connections, monkey-patched globals, etc.
|
|
255
|
+
* — to make sure that state is released when the SDK is torn down.
|
|
256
|
+
*/
|
|
257
|
+
declare abstract class WavedashManager {
|
|
258
|
+
protected sdk: WavedashSDK;
|
|
259
|
+
constructor(sdk: WavedashSDK);
|
|
260
|
+
destroy(): void;
|
|
261
|
+
}
|
|
262
|
+
|
|
248
263
|
/**
|
|
249
264
|
* Lobby service
|
|
250
265
|
*
|
|
251
266
|
* Implements each of the lobby methods of the Wavedash SDK
|
|
252
267
|
*/
|
|
253
268
|
|
|
254
|
-
declare class LobbyManager {
|
|
255
|
-
private sdk;
|
|
269
|
+
declare class LobbyManager extends WavedashManager {
|
|
256
270
|
private unsubscribeLobbyMessages;
|
|
257
271
|
private unsubscribeLobbyUsers;
|
|
258
272
|
private unsubscribeLobbyData;
|
|
@@ -342,8 +356,7 @@ declare class LobbyManager {
|
|
|
342
356
|
* TODO: Extend this to game-level assets as well.
|
|
343
357
|
*/
|
|
344
358
|
|
|
345
|
-
declare class FileSystemManager {
|
|
346
|
-
private sdk;
|
|
359
|
+
declare class FileSystemManager extends WavedashManager {
|
|
347
360
|
private remoteStorageOrigin;
|
|
348
361
|
constructor(sdk: WavedashSDK);
|
|
349
362
|
/**
|
|
@@ -399,11 +412,11 @@ declare class FileSystemManager {
|
|
|
399
412
|
* Implements each of the user generated content methods of the Wavedash SDK
|
|
400
413
|
*/
|
|
401
414
|
|
|
402
|
-
declare class UGCManager {
|
|
403
|
-
private sdk;
|
|
415
|
+
declare class UGCManager extends WavedashManager {
|
|
404
416
|
constructor(sdk: WavedashSDK);
|
|
405
417
|
createUGCItem(ugcType: UGCType, title?: string, description?: string, visibility?: UGCVisibility, filePath?: string): Promise<GenericId<"userGeneratedContent">>;
|
|
406
418
|
updateUGCItem(ugcId: GenericId<"userGeneratedContent">, title?: string, description?: string, visibility?: UGCVisibility, filePath?: string): Promise<GenericId<"userGeneratedContent">>;
|
|
419
|
+
deleteUGCItem(ugcId: GenericId<"userGeneratedContent">): Promise<GenericId<"userGeneratedContent">>;
|
|
407
420
|
downloadUGCItem(ugcId: GenericId<"userGeneratedContent">, filePath: string): Promise<GenericId<"userGeneratedContent">>;
|
|
408
421
|
}
|
|
409
422
|
|
|
@@ -413,8 +426,7 @@ declare class UGCManager {
|
|
|
413
426
|
* Implements each of the leaderboard methods of the Wavedash SDK
|
|
414
427
|
*/
|
|
415
428
|
|
|
416
|
-
declare class LeaderboardManager {
|
|
417
|
-
private sdk;
|
|
429
|
+
declare class LeaderboardManager extends WavedashManager {
|
|
418
430
|
private leaderboardCache;
|
|
419
431
|
constructor(sdk: WavedashSDK);
|
|
420
432
|
getLeaderboard(name: string): Promise<Leaderboard>;
|
|
@@ -433,8 +445,7 @@ declare class LeaderboardManager {
|
|
|
433
445
|
* Handles WebRTC peer-to-peer connections for lobbies
|
|
434
446
|
*/
|
|
435
447
|
|
|
436
|
-
declare class P2PManager {
|
|
437
|
-
private sdk;
|
|
448
|
+
declare class P2PManager extends WavedashManager {
|
|
438
449
|
private config;
|
|
439
450
|
private currentConnection;
|
|
440
451
|
private peerConnections;
|
|
@@ -479,6 +490,7 @@ declare class P2PManager {
|
|
|
479
490
|
private textDecoder;
|
|
480
491
|
private initialized;
|
|
481
492
|
constructor(sdk: WavedashSDK);
|
|
493
|
+
destroy(): void;
|
|
482
494
|
private ensureInitialized;
|
|
483
495
|
init(config?: Partial<P2PConfig>): void;
|
|
484
496
|
initializeP2PForCurrentLobby(lobbyId: GenericId<"lobbies">, members: SDKUser[]): Promise<P2PConnection>;
|
|
@@ -548,8 +560,7 @@ type StatEntry = {
|
|
|
548
560
|
identifier: string;
|
|
549
561
|
value: number;
|
|
550
562
|
};
|
|
551
|
-
declare class StatsManager {
|
|
552
|
-
private sdk;
|
|
563
|
+
declare class StatsManager extends WavedashManager {
|
|
553
564
|
private stats;
|
|
554
565
|
private unlockedAchievements;
|
|
555
566
|
private dirtyStats;
|
|
@@ -558,6 +569,7 @@ declare class StatsManager {
|
|
|
558
569
|
private knownAchievementIds;
|
|
559
570
|
private loaded;
|
|
560
571
|
private subscriptions;
|
|
572
|
+
private periodicPersistInterval;
|
|
561
573
|
constructor(sdk: WavedashSDK);
|
|
562
574
|
destroy(): void;
|
|
563
575
|
private isReady;
|
|
@@ -585,8 +597,7 @@ declare class StatsManager {
|
|
|
585
597
|
* Lets the game update userPresence in the backend
|
|
586
598
|
*/
|
|
587
599
|
|
|
588
|
-
declare class HeartbeatManager {
|
|
589
|
-
private sdk;
|
|
600
|
+
declare class HeartbeatManager extends WavedashManager {
|
|
590
601
|
private deviceFingerprint;
|
|
591
602
|
private deviceFingerprintReady;
|
|
592
603
|
private testConnectionInterval;
|
|
@@ -622,8 +633,7 @@ declare class HeartbeatManager {
|
|
|
622
633
|
isCurrentlyConnected(): boolean;
|
|
623
634
|
}
|
|
624
635
|
|
|
625
|
-
declare class GameEventManager {
|
|
626
|
-
private sdk;
|
|
636
|
+
declare class GameEventManager extends WavedashManager {
|
|
627
637
|
private eventQueue;
|
|
628
638
|
constructor(sdk: WavedashSDK);
|
|
629
639
|
notifyGame(event: WavedashEvent, payload: string | number | object): void;
|
|
@@ -650,10 +660,9 @@ declare class GameEventManager {
|
|
|
650
660
|
* calls route through us. The iframe isn't granted the fullscreen feature
|
|
651
661
|
* policy anymore, so without these shims those calls would silently reject.
|
|
652
662
|
*/
|
|
653
|
-
declare class FullscreenManager {
|
|
663
|
+
declare class FullscreenManager extends WavedashManager {
|
|
654
664
|
private _isFullscreen;
|
|
655
665
|
private listeners;
|
|
656
|
-
private sdk;
|
|
657
666
|
constructor(sdk: WavedashSDK);
|
|
658
667
|
isFullscreen(): boolean;
|
|
659
668
|
/**
|
|
@@ -680,8 +689,7 @@ declare class FullscreenManager {
|
|
|
680
689
|
* - `takeFocus()` is also called after load completes so the game starts
|
|
681
690
|
* with keyboard focus without the player clicking first.
|
|
682
691
|
*/
|
|
683
|
-
declare class OverlayManager {
|
|
684
|
-
private sdk;
|
|
692
|
+
declare class OverlayManager extends WavedashManager {
|
|
685
693
|
constructor(sdk: WavedashSDK);
|
|
686
694
|
toggleOverlay(): void;
|
|
687
695
|
takeFocus(): void;
|
|
@@ -694,8 +702,7 @@ declare class OverlayManager {
|
|
|
694
702
|
* Implements friend-related methods for the Wavedash SDK
|
|
695
703
|
*/
|
|
696
704
|
|
|
697
|
-
declare class FriendsManager {
|
|
698
|
-
private sdk;
|
|
705
|
+
declare class FriendsManager extends WavedashManager {
|
|
699
706
|
private userCache;
|
|
700
707
|
constructor(sdk: WavedashSDK);
|
|
701
708
|
/**
|
|
@@ -780,8 +787,7 @@ declare class WavedashSDK extends EventTarget {
|
|
|
780
787
|
private _eventsReady;
|
|
781
788
|
get eventsReady(): boolean;
|
|
782
789
|
private launchParams;
|
|
783
|
-
private
|
|
784
|
-
private convexHttpUrl;
|
|
790
|
+
private destroyed;
|
|
785
791
|
private gameFinishedLoading;
|
|
786
792
|
Events: {
|
|
787
793
|
readonly LOBBY_MESSAGE: "LobbyMessage";
|
|
@@ -869,6 +875,7 @@ declare class WavedashSDK extends EventTarget {
|
|
|
869
875
|
p2pManager: P2PManager;
|
|
870
876
|
fullscreenManager: FullscreenManager;
|
|
871
877
|
overlayManager: OverlayManager;
|
|
878
|
+
private managers;
|
|
872
879
|
private gameplayJwt;
|
|
873
880
|
private gameplayJwtPromise;
|
|
874
881
|
private setupWarningTimeout;
|
|
@@ -984,6 +991,11 @@ declare class WavedashSDK extends EventTarget {
|
|
|
984
991
|
* @returns ugcId
|
|
985
992
|
*/
|
|
986
993
|
updateUGCItem(ugcId: GenericId<"userGeneratedContent">, title?: string, description?: string, visibility?: UGCVisibility, filePath?: string): Promise<WavedashResponse<GenericId<"userGeneratedContent">>>;
|
|
994
|
+
/**
|
|
995
|
+
* Delete a UGC item: removes the row, the R2 object, and frees up the
|
|
996
|
+
* user's storage quota by the size of the deleted upload.
|
|
997
|
+
*/
|
|
998
|
+
deleteUGCItem(ugcId: GenericId<"userGeneratedContent">): Promise<WavedashResponse<GenericId<"userGeneratedContent">>>;
|
|
987
999
|
downloadUGCItem(ugcId: GenericId<"userGeneratedContent">, filePath: string): Promise<WavedashResponse<GenericId<"userGeneratedContent">>>;
|
|
988
1000
|
/**
|
|
989
1001
|
* Deletes a remote file from storage
|
|
@@ -1154,12 +1166,9 @@ declare class WavedashSDK extends EventTarget {
|
|
|
1154
1166
|
*/
|
|
1155
1167
|
ensureGameplayJwt(): Promise<string>;
|
|
1156
1168
|
/**
|
|
1157
|
-
*
|
|
1158
|
-
* is going away. We listen for three signals:
|
|
1159
|
-
* - `beforeunload` / `pagehide` on our own window: covers tab close, hard
|
|
1160
|
-
* reload, and top-level navigation of the parent.
|
|
1161
|
-
* - `END_SESSION` postMessage from the parent: covers parent SPA navigation
|
|
1169
|
+
* Tear down every manager. Called on the parent's `END_SESSION` signal
|
|
1162
1170
|
*/
|
|
1171
|
+
private destroy;
|
|
1163
1172
|
private setupSessionEndListeners;
|
|
1164
1173
|
}
|
|
1165
1174
|
declare global {
|
package/dist/index.js
CHANGED
|
@@ -83,8 +83,20 @@ var WavedashEvents = {
|
|
|
83
83
|
|
|
84
84
|
// src/services/lobby.ts
|
|
85
85
|
import { api, IFRAME_MESSAGE_TYPE } from "@wvdsh/api";
|
|
86
|
-
|
|
86
|
+
|
|
87
|
+
// src/services/manager.ts
|
|
88
|
+
var WavedashManager = class {
|
|
89
|
+
constructor(sdk) {
|
|
90
|
+
this.sdk = sdk;
|
|
91
|
+
}
|
|
92
|
+
destroy() {
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// src/services/lobby.ts
|
|
97
|
+
var LobbyManager = class extends WavedashManager {
|
|
87
98
|
constructor(sdk) {
|
|
99
|
+
super(sdk);
|
|
88
100
|
// Track current lobby state
|
|
89
101
|
this.unsubscribeLobbyMessages = null;
|
|
90
102
|
this.unsubscribeLobbyUsers = null;
|
|
@@ -182,7 +194,6 @@ var LobbyManager = class {
|
|
|
182
194
|
invites.map((invite) => invite.notificationId)
|
|
183
195
|
);
|
|
184
196
|
};
|
|
185
|
-
this.sdk = sdk;
|
|
186
197
|
this.unsubscribeLobbyInvites = this.sdk.convexClient.onUpdate(
|
|
187
198
|
api.sdk.gameLobby.getLobbyInvites,
|
|
188
199
|
{},
|
|
@@ -611,9 +622,9 @@ function toBlobFromIndexedDBValue(value) {
|
|
|
611
622
|
import { api as api2 } from "@wvdsh/api";
|
|
612
623
|
var REMOTE_STORAGE_FOLDER = "userfs";
|
|
613
624
|
var WAVEDASH_PERSISTENT_DATA_PATH = "/idbfs/wavedash";
|
|
614
|
-
var FileSystemManager = class {
|
|
625
|
+
var FileSystemManager = class extends WavedashManager {
|
|
615
626
|
constructor(sdk) {
|
|
616
|
-
|
|
627
|
+
super(sdk);
|
|
617
628
|
}
|
|
618
629
|
/**
|
|
619
630
|
* Converts a local filesystem path into a full R2 object key.
|
|
@@ -663,9 +674,19 @@ var FileSystemManager = class {
|
|
|
663
674
|
* @returns The path of the remote file that was deleted
|
|
664
675
|
*/
|
|
665
676
|
async deleteRemoteFile(filePath) {
|
|
666
|
-
|
|
667
|
-
|
|
677
|
+
const url = this.getRemoteStorageUrl(filePath);
|
|
678
|
+
const jwt = await this.sdk.ensureGameplayJwt();
|
|
679
|
+
const response = await fetch(url, {
|
|
680
|
+
method: "DELETE",
|
|
681
|
+
headers: {
|
|
682
|
+
Authorization: `Bearer ${jwt}`
|
|
683
|
+
}
|
|
668
684
|
});
|
|
685
|
+
if (!response.ok) {
|
|
686
|
+
const msg = `Failed to delete remote file ${filePath}: ${response.status} (${response.statusText})`;
|
|
687
|
+
this.sdk.logger.error(msg);
|
|
688
|
+
throw new Error(msg);
|
|
689
|
+
}
|
|
669
690
|
return filePath;
|
|
670
691
|
}
|
|
671
692
|
/**
|
|
@@ -907,9 +928,9 @@ var FileSystemManager = class {
|
|
|
907
928
|
|
|
908
929
|
// src/services/ugc.ts
|
|
909
930
|
import { api as api3 } from "@wvdsh/api";
|
|
910
|
-
var UGCManager = class {
|
|
931
|
+
var UGCManager = class extends WavedashManager {
|
|
911
932
|
constructor(sdk) {
|
|
912
|
-
|
|
933
|
+
super(sdk);
|
|
913
934
|
}
|
|
914
935
|
async createUGCItem(ugcType, title, description, visibility, filePath) {
|
|
915
936
|
const { ugcId, uploadUrl } = await this.sdk.convexClient.mutation(
|
|
@@ -931,10 +952,6 @@ var UGCManager = class {
|
|
|
931
952
|
uploadUrl,
|
|
932
953
|
filePath
|
|
933
954
|
);
|
|
934
|
-
await this.sdk.convexClient.mutation(
|
|
935
|
-
api3.sdk.userGeneratedContent.finishUGCUpload,
|
|
936
|
-
{ success, ugcId }
|
|
937
|
-
);
|
|
938
955
|
if (!success) {
|
|
939
956
|
throw new Error(`Failed to upload UGC item: ${filePath}`);
|
|
940
957
|
}
|
|
@@ -961,16 +978,19 @@ var UGCManager = class {
|
|
|
961
978
|
uploadUrl,
|
|
962
979
|
filePath
|
|
963
980
|
);
|
|
964
|
-
await this.sdk.convexClient.mutation(
|
|
965
|
-
api3.sdk.userGeneratedContent.finishUGCUpload,
|
|
966
|
-
{ success, ugcId }
|
|
967
|
-
);
|
|
968
981
|
if (!success) {
|
|
969
982
|
throw new Error(`Failed to upload UGC item: ${filePath}`);
|
|
970
983
|
}
|
|
971
984
|
}
|
|
972
985
|
return ugcId;
|
|
973
986
|
}
|
|
987
|
+
async deleteUGCItem(ugcId) {
|
|
988
|
+
await this.sdk.convexClient.mutation(
|
|
989
|
+
api3.sdk.userGeneratedContent.deleteUGCItem,
|
|
990
|
+
{ ugcId }
|
|
991
|
+
);
|
|
992
|
+
return ugcId;
|
|
993
|
+
}
|
|
974
994
|
async downloadUGCItem(ugcId, filePath) {
|
|
975
995
|
const downloadUrl = await this.sdk.convexClient.query(
|
|
976
996
|
api3.sdk.userGeneratedContent.getUGCItemDownloadUrl,
|
|
@@ -989,11 +1009,11 @@ var UGCManager = class {
|
|
|
989
1009
|
|
|
990
1010
|
// src/services/leaderboards.ts
|
|
991
1011
|
import { api as api4 } from "@wvdsh/api";
|
|
992
|
-
var LeaderboardManager = class {
|
|
1012
|
+
var LeaderboardManager = class extends WavedashManager {
|
|
993
1013
|
constructor(sdk) {
|
|
1014
|
+
super(sdk);
|
|
994
1015
|
// Cache leaderboards to return totalEntries synchronously without a network call
|
|
995
1016
|
this.leaderboardCache = /* @__PURE__ */ new Map();
|
|
996
|
-
this.sdk = sdk;
|
|
997
1017
|
}
|
|
998
1018
|
async getLeaderboard(name) {
|
|
999
1019
|
const leaderboard = await this.sdk.convexClient.query(
|
|
@@ -1086,8 +1106,9 @@ var DEFAULT_P2P_CONFIG = {
|
|
|
1086
1106
|
messageSize: 2048,
|
|
1087
1107
|
maxIncomingMessages: 1024
|
|
1088
1108
|
};
|
|
1089
|
-
var _P2PManager = class _P2PManager {
|
|
1109
|
+
var _P2PManager = class _P2PManager extends WavedashManager {
|
|
1090
1110
|
constructor(sdk) {
|
|
1111
|
+
super(sdk);
|
|
1091
1112
|
this.currentConnection = null;
|
|
1092
1113
|
// WebRTC connection state
|
|
1093
1114
|
this.peerConnections = /* @__PURE__ */ new Map();
|
|
@@ -1171,9 +1192,11 @@ var _P2PManager = class _P2PManager {
|
|
|
1171
1192
|
this.textEncoder = new TextEncoder();
|
|
1172
1193
|
this.textDecoder = new TextDecoder();
|
|
1173
1194
|
this.initialized = false;
|
|
1174
|
-
this.sdk = sdk;
|
|
1175
1195
|
this.config = { ...DEFAULT_P2P_CONFIG };
|
|
1176
1196
|
}
|
|
1197
|
+
destroy() {
|
|
1198
|
+
this.disconnectP2P();
|
|
1199
|
+
}
|
|
1177
1200
|
ensureInitialized() {
|
|
1178
1201
|
if (!this.initialized) {
|
|
1179
1202
|
this.init();
|
|
@@ -2403,8 +2426,10 @@ var P2PManager = _P2PManager;
|
|
|
2403
2426
|
import { api as api6 } from "@wvdsh/api";
|
|
2404
2427
|
import debounce2 from "lodash.debounce";
|
|
2405
2428
|
var STORE_DEBOUNCE_MS = 1e3;
|
|
2406
|
-
var
|
|
2429
|
+
var PERIODIC_PERSIST_MS = 1e4;
|
|
2430
|
+
var StatsManager = class extends WavedashManager {
|
|
2407
2431
|
constructor(sdk) {
|
|
2432
|
+
super(sdk);
|
|
2408
2433
|
// Current user values
|
|
2409
2434
|
this.stats = /* @__PURE__ */ new Map();
|
|
2410
2435
|
this.unlockedAchievements = /* @__PURE__ */ new Set();
|
|
@@ -2419,6 +2444,8 @@ var StatsManager = class {
|
|
|
2419
2444
|
this.loaded = { stats: false, achievements: false };
|
|
2420
2445
|
// Subscription cleanup
|
|
2421
2446
|
this.subscriptions = [];
|
|
2447
|
+
// Background flush timer — see PERIODIC_PERSIST_MS
|
|
2448
|
+
this.periodicPersistInterval = null;
|
|
2422
2449
|
// ================
|
|
2423
2450
|
// Store / Persist
|
|
2424
2451
|
// ================
|
|
@@ -2429,14 +2456,20 @@ var StatsManager = class {
|
|
|
2429
2456
|
leading: true,
|
|
2430
2457
|
trailing: true
|
|
2431
2458
|
});
|
|
2432
|
-
this.sdk = sdk;
|
|
2433
2459
|
this.subscribe();
|
|
2434
2460
|
this.requestStats().catch((error) => {
|
|
2435
2461
|
this.sdk.logger.error("Initial stats fetch failed:", error);
|
|
2436
2462
|
});
|
|
2463
|
+
this.periodicPersistInterval = setInterval(() => {
|
|
2464
|
+
void this.persist();
|
|
2465
|
+
}, PERIODIC_PERSIST_MS);
|
|
2437
2466
|
}
|
|
2438
2467
|
destroy() {
|
|
2439
2468
|
this.debouncedPersist.cancel();
|
|
2469
|
+
if (this.periodicPersistInterval !== null) {
|
|
2470
|
+
clearInterval(this.periodicPersistInterval);
|
|
2471
|
+
this.periodicPersistInterval = null;
|
|
2472
|
+
}
|
|
2440
2473
|
for (const unsub of this.subscriptions) unsub();
|
|
2441
2474
|
this.subscriptions = [];
|
|
2442
2475
|
}
|
|
@@ -2590,8 +2623,9 @@ import {
|
|
|
2590
2623
|
HEARTBEAT,
|
|
2591
2624
|
IFRAME_MESSAGE_TYPE as IFRAME_MESSAGE_TYPE2
|
|
2592
2625
|
} from "@wvdsh/api";
|
|
2593
|
-
var HeartbeatManager = class {
|
|
2626
|
+
var HeartbeatManager = class extends WavedashManager {
|
|
2594
2627
|
constructor(sdk) {
|
|
2628
|
+
super(sdk);
|
|
2595
2629
|
this.deviceFingerprint = void 0;
|
|
2596
2630
|
this.testConnectionInterval = null;
|
|
2597
2631
|
this.heartbeatInterval = null;
|
|
@@ -2610,7 +2644,6 @@ var HeartbeatManager = class {
|
|
|
2610
2644
|
this.stop();
|
|
2611
2645
|
}
|
|
2612
2646
|
};
|
|
2613
|
-
this.sdk = sdk;
|
|
2614
2647
|
this.isConnected = this.sdk.convexClient.client.connectionState().isWebSocketConnected;
|
|
2615
2648
|
document.addEventListener("visibilitychange", this.handleVisibilityChange);
|
|
2616
2649
|
this.deviceFingerprintReady = this.sdk.iframeMessenger.requestFromParent(IFRAME_MESSAGE_TYPE2.GET_DEVICE_FINGERPRINT).then((fingerprint) => {
|
|
@@ -2754,10 +2787,10 @@ var HeartbeatManager = class {
|
|
|
2754
2787
|
};
|
|
2755
2788
|
|
|
2756
2789
|
// src/services/gameEvents.ts
|
|
2757
|
-
var GameEventManager = class {
|
|
2790
|
+
var GameEventManager = class extends WavedashManager {
|
|
2758
2791
|
constructor(sdk) {
|
|
2792
|
+
super(sdk);
|
|
2759
2793
|
this.eventQueue = [];
|
|
2760
|
-
this.sdk = sdk;
|
|
2761
2794
|
}
|
|
2762
2795
|
// ==============================
|
|
2763
2796
|
// JS -> Game Event Broadcasting
|
|
@@ -2797,11 +2830,11 @@ var GameEventManager = class {
|
|
|
2797
2830
|
|
|
2798
2831
|
// src/services/fullscreen.ts
|
|
2799
2832
|
import { IFRAME_MESSAGE_TYPE as IFRAME_MESSAGE_TYPE3 } from "@wvdsh/api";
|
|
2800
|
-
var FullscreenManager = class {
|
|
2833
|
+
var FullscreenManager = class extends WavedashManager {
|
|
2801
2834
|
constructor(sdk) {
|
|
2835
|
+
super(sdk);
|
|
2802
2836
|
this._isFullscreen = false;
|
|
2803
2837
|
this.listeners = /* @__PURE__ */ new Set();
|
|
2804
|
-
this.sdk = sdk;
|
|
2805
2838
|
this.sdk.iframeMessenger.addEventListener(
|
|
2806
2839
|
IFRAME_MESSAGE_TYPE3.FULLSCREEN_CHANGED,
|
|
2807
2840
|
(data) => {
|
|
@@ -2886,15 +2919,15 @@ var FullscreenManager = class {
|
|
|
2886
2919
|
|
|
2887
2920
|
// src/services/overlay.ts
|
|
2888
2921
|
import { IFRAME_MESSAGE_TYPE as IFRAME_MESSAGE_TYPE4 } from "@wvdsh/api";
|
|
2889
|
-
var OverlayManager = class {
|
|
2922
|
+
var OverlayManager = class extends WavedashManager {
|
|
2890
2923
|
constructor(sdk) {
|
|
2924
|
+
super(sdk);
|
|
2891
2925
|
this.handleKeyDown = (event) => {
|
|
2892
2926
|
if (event.key === "Tab" && event.shiftKey) {
|
|
2893
2927
|
event.preventDefault();
|
|
2894
2928
|
this.toggleOverlay();
|
|
2895
2929
|
}
|
|
2896
2930
|
};
|
|
2897
|
-
this.sdk = sdk;
|
|
2898
2931
|
this.sdk.iframeMessenger.addEventListener(
|
|
2899
2932
|
IFRAME_MESSAGE_TYPE4.TAKE_FOCUS,
|
|
2900
2933
|
() => this.takeFocus()
|
|
@@ -2938,10 +2971,10 @@ function getCdnImageUrl(r2Key, host, options) {
|
|
|
2938
2971
|
}
|
|
2939
2972
|
|
|
2940
2973
|
// src/services/friends.ts
|
|
2941
|
-
var FriendsManager = class {
|
|
2974
|
+
var FriendsManager = class extends WavedashManager {
|
|
2942
2975
|
constructor(sdk) {
|
|
2976
|
+
super(sdk);
|
|
2943
2977
|
this.userCache = /* @__PURE__ */ new Map();
|
|
2944
|
-
this.sdk = sdk;
|
|
2945
2978
|
}
|
|
2946
2979
|
/**
|
|
2947
2980
|
* Cache users from any source (friends, lobby users)
|
|
@@ -3240,7 +3273,7 @@ var WavedashSDK = class extends EventTarget {
|
|
|
3240
3273
|
super();
|
|
3241
3274
|
this._initialized = false;
|
|
3242
3275
|
this._eventsReady = false;
|
|
3243
|
-
this.
|
|
3276
|
+
this.destroyed = false;
|
|
3244
3277
|
this.gameFinishedLoading = false;
|
|
3245
3278
|
// Expose constants for easy access `Wavedash.LobbyVisibility.PUBLIC` etc.
|
|
3246
3279
|
this.Events = WavedashEvents;
|
|
@@ -3272,7 +3305,6 @@ var WavedashSDK = class extends EventTarget {
|
|
|
3272
3305
|
this.convexClient.setAuth(
|
|
3273
3306
|
({ forceRefreshToken }) => this.getAuthToken(forceRefreshToken)
|
|
3274
3307
|
);
|
|
3275
|
-
this.convexHttpUrl = sdkConfig.convexHttpUrl;
|
|
3276
3308
|
this.wavedashUser = sdkConfig.wavedashUser;
|
|
3277
3309
|
this.iframeMessenger = iframeMessenger;
|
|
3278
3310
|
this.ugcHost = sdkConfig.ugcHost;
|
|
@@ -3289,6 +3321,19 @@ var WavedashSDK = class extends EventTarget {
|
|
|
3289
3321
|
this.gameEventManager = new GameEventManager(this);
|
|
3290
3322
|
this.fullscreenManager = new FullscreenManager(this);
|
|
3291
3323
|
this.overlayManager = new OverlayManager(this);
|
|
3324
|
+
this.managers = [
|
|
3325
|
+
this.p2pManager,
|
|
3326
|
+
this.lobbyManager,
|
|
3327
|
+
this.statsManager,
|
|
3328
|
+
this.heartbeatManager,
|
|
3329
|
+
this.fileSystemManager,
|
|
3330
|
+
this.ugcManager,
|
|
3331
|
+
this.leaderboardManager,
|
|
3332
|
+
this.friendsManager,
|
|
3333
|
+
this.gameEventManager,
|
|
3334
|
+
this.fullscreenManager,
|
|
3335
|
+
this.overlayManager
|
|
3336
|
+
];
|
|
3292
3337
|
this.friendsManager.cacheUsers([
|
|
3293
3338
|
{
|
|
3294
3339
|
userId: this.wavedashUser.id,
|
|
@@ -3683,6 +3728,18 @@ var WavedashSDK = class extends EventTarget {
|
|
|
3683
3728
|
filePath
|
|
3684
3729
|
);
|
|
3685
3730
|
}
|
|
3731
|
+
/**
|
|
3732
|
+
* Delete a UGC item: removes the row, the R2 object, and frees up the
|
|
3733
|
+
* user's storage quota by the size of the deleted upload.
|
|
3734
|
+
*/
|
|
3735
|
+
async deleteUGCItem(ugcId) {
|
|
3736
|
+
return this.apiCall(
|
|
3737
|
+
this.ugcManager,
|
|
3738
|
+
"deleteUGCItem",
|
|
3739
|
+
[["ugcId", vId("userGeneratedContent")]],
|
|
3740
|
+
ugcId
|
|
3741
|
+
);
|
|
3742
|
+
}
|
|
3686
3743
|
async downloadUGCItem(ugcId, filePath) {
|
|
3687
3744
|
return this.apiCall(
|
|
3688
3745
|
this.ugcManager,
|
|
@@ -4195,6 +4252,9 @@ var WavedashSDK = class extends EventTarget {
|
|
|
4195
4252
|
throw new Error(`Failed to refresh gameplay token: ${response.status}`);
|
|
4196
4253
|
}
|
|
4197
4254
|
this.gameplayJwt = await response.text();
|
|
4255
|
+
iframeMessenger.postToParent(IFRAME_MESSAGE_TYPE5.GAMEPLAY_JWT_READY, {
|
|
4256
|
+
gameplayJwt: this.gameplayJwt
|
|
4257
|
+
});
|
|
4198
4258
|
return this.gameplayJwt;
|
|
4199
4259
|
})().finally(() => {
|
|
4200
4260
|
if (this.gameplayJwtPromise === promise) {
|
|
@@ -4213,47 +4273,19 @@ var WavedashSDK = class extends EventTarget {
|
|
|
4213
4273
|
return this.getAuthToken();
|
|
4214
4274
|
}
|
|
4215
4275
|
/**
|
|
4216
|
-
*
|
|
4217
|
-
* is going away. We listen for three signals:
|
|
4218
|
-
* - `beforeunload` / `pagehide` on our own window: covers tab close, hard
|
|
4219
|
-
* reload, and top-level navigation of the parent.
|
|
4220
|
-
* - `END_SESSION` postMessage from the parent: covers parent SPA navigation
|
|
4276
|
+
* Tear down every manager. Called on the parent's `END_SESSION` signal
|
|
4221
4277
|
*/
|
|
4278
|
+
destroy() {
|
|
4279
|
+
if (this.destroyed) return;
|
|
4280
|
+
this.destroyed = true;
|
|
4281
|
+
for (const manager of this.managers) {
|
|
4282
|
+
manager.destroy();
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4222
4285
|
setupSessionEndListeners() {
|
|
4223
|
-
const endSessionEndpoint = `${this.convexHttpUrl}/gameplay/end-session`;
|
|
4224
|
-
const endGameplaySession = () => {
|
|
4225
|
-
if (this.sessionEndSent) return;
|
|
4226
|
-
if (!this.gameplayJwt) return;
|
|
4227
|
-
this.sessionEndSent = true;
|
|
4228
|
-
const pendingData = this.statsManager.getPendingData();
|
|
4229
|
-
this.lobbyManager.destroy();
|
|
4230
|
-
this.heartbeatManager.destroy();
|
|
4231
|
-
this.statsManager.destroy();
|
|
4232
|
-
const body = {
|
|
4233
|
-
gameplayJwt: this.gameplayJwt
|
|
4234
|
-
};
|
|
4235
|
-
if (pendingData?.stats?.length) {
|
|
4236
|
-
body.stats = pendingData.stats;
|
|
4237
|
-
}
|
|
4238
|
-
if (pendingData?.achievements?.length) {
|
|
4239
|
-
body.achievements = pendingData.achievements;
|
|
4240
|
-
}
|
|
4241
|
-
const payload = JSON.stringify(body);
|
|
4242
|
-
const beaconSent = navigator?.sendBeacon?.(endSessionEndpoint, payload);
|
|
4243
|
-
if (!beaconSent) {
|
|
4244
|
-
fetch(endSessionEndpoint, {
|
|
4245
|
-
method: "POST",
|
|
4246
|
-
body: payload,
|
|
4247
|
-
keepalive: true
|
|
4248
|
-
}).catch(() => {
|
|
4249
|
-
});
|
|
4250
|
-
}
|
|
4251
|
-
};
|
|
4252
|
-
window.addEventListener("beforeunload", endGameplaySession);
|
|
4253
|
-
window.addEventListener("pagehide", endGameplaySession);
|
|
4254
4286
|
iframeMessenger.addEventListener(
|
|
4255
4287
|
IFRAME_MESSAGE_TYPE5.END_SESSION,
|
|
4256
|
-
|
|
4288
|
+
() => this.destroy()
|
|
4257
4289
|
);
|
|
4258
4290
|
}
|
|
4259
4291
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wvdsh/sdk-js",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Wavedash JavaScript SDK",
|
|
6
6
|
"main": "./dist/client.js",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"typescript-eslint": "^8.52.0"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@wvdsh/api": "^0.1.
|
|
52
|
+
"@wvdsh/api": "^0.1.14",
|
|
53
53
|
"convex": "^1.34.0",
|
|
54
54
|
"lodash.debounce": "^4.0.8"
|
|
55
55
|
}
|