@wvdsh/sdk-js 1.3.8 → 1.3.10
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 -23
- package/dist/index.js +257 -164
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -730,28 +730,6 @@ declare class FriendsManager extends WavedashManager {
|
|
|
730
730
|
listFriends(): Promise<Friend[]>;
|
|
731
731
|
}
|
|
732
732
|
|
|
733
|
-
/**
|
|
734
|
-
* Logger interface and implementation
|
|
735
|
-
* Simply logs to the console with customizable log level
|
|
736
|
-
*
|
|
737
|
-
* In the future we could extend this to write .log files to IndexedDB or cache storage
|
|
738
|
-
*/
|
|
739
|
-
interface Logger {
|
|
740
|
-
debug(message: string, ...args: unknown[]): void;
|
|
741
|
-
info(message: string, ...args: unknown[]): void;
|
|
742
|
-
warn(message: string, ...args: unknown[]): void;
|
|
743
|
-
error(message: string, ...args: unknown[]): void;
|
|
744
|
-
}
|
|
745
|
-
declare class WavedashLogger implements Logger {
|
|
746
|
-
private logLevel;
|
|
747
|
-
constructor(logLevel?: number);
|
|
748
|
-
setLogLevel(level: number): void;
|
|
749
|
-
debug(message: string, ...args: unknown[]): void;
|
|
750
|
-
info(message: string, ...args: unknown[]): void;
|
|
751
|
-
warn(message: string, ...args: unknown[]): void;
|
|
752
|
-
error(message: string, ...args: unknown[]): void;
|
|
753
|
-
}
|
|
754
|
-
|
|
755
733
|
/**
|
|
756
734
|
* Utilities for handling iframe messaging between the iframe'd Wavedash SDK and the parent window.
|
|
757
735
|
* Assumes window is defined and this is only ever running inside an iframe.
|
|
@@ -778,6 +756,36 @@ declare class IFrameMessenger {
|
|
|
778
756
|
requestFromParent<T extends keyof IFrameEventPayloadMap>(requestType: T, data?: Record<string, unknown>): Promise<IFrameEventPayloadMap[T]>;
|
|
779
757
|
}
|
|
780
758
|
|
|
759
|
+
/**
|
|
760
|
+
* Utilities for messaging between the SDK and the service worker
|
|
761
|
+
* that proxies API requests on its behalf.
|
|
762
|
+
*/
|
|
763
|
+
type SwMessage<T = unknown> = {
|
|
764
|
+
type: string;
|
|
765
|
+
payload?: T;
|
|
766
|
+
};
|
|
767
|
+
type SwReply = (message: SwMessage) => void;
|
|
768
|
+
type SwListener = (payload: unknown, reply: SwReply) => void;
|
|
769
|
+
declare class SwMessenger {
|
|
770
|
+
private listeners;
|
|
771
|
+
constructor();
|
|
772
|
+
/**
|
|
773
|
+
* Register a handler for an incoming message type from the SW. The handler
|
|
774
|
+
* receives the message payload and a `reply` function that routes the
|
|
775
|
+
* response back via the transferred MessagePort when present, falling back
|
|
776
|
+
* to a controller postMessage otherwise.
|
|
777
|
+
*/
|
|
778
|
+
addEventListener(type: string, listener: SwListener): void;
|
|
779
|
+
removeEventListener(type: string, listener: SwListener): void;
|
|
780
|
+
/**
|
|
781
|
+
* Fire-and-forget message to the active service worker controller. No-op
|
|
782
|
+
* when no SW is controlling the page (first load before activation, or
|
|
783
|
+
* environments without SW support).
|
|
784
|
+
*/
|
|
785
|
+
postToServiceWorker(message: SwMessage): boolean;
|
|
786
|
+
private handleMessage;
|
|
787
|
+
}
|
|
788
|
+
|
|
781
789
|
declare class WavedashSDK extends EventTarget {
|
|
782
790
|
private _initialized;
|
|
783
791
|
get initialized(): boolean;
|
|
@@ -867,8 +875,8 @@ declare class WavedashSDK extends EventTarget {
|
|
|
867
875
|
convexClient: ConvexClient;
|
|
868
876
|
engineCallbackReceiver: string;
|
|
869
877
|
engineInstance: EngineInstance | null;
|
|
870
|
-
logger: WavedashLogger;
|
|
871
878
|
iframeMessenger: IFrameMessenger;
|
|
879
|
+
swMessenger: SwMessenger;
|
|
872
880
|
p2pManager: P2PManager;
|
|
873
881
|
fullscreenManager: FullscreenManager;
|
|
874
882
|
overlayManager: OverlayManager;
|
|
@@ -1167,6 +1175,13 @@ declare class WavedashSDK extends EventTarget {
|
|
|
1167
1175
|
*/
|
|
1168
1176
|
private destroy;
|
|
1169
1177
|
private setupSessionEndListeners;
|
|
1178
|
+
/**
|
|
1179
|
+
* Respond to the service worker's `embed.creds-request` with the SDK's
|
|
1180
|
+
* current gameplay JWT. The SW asks when it wakes from termination with no
|
|
1181
|
+
* in-memory or IDB credentials (e.g. Safari ITP storage decay) — we're the
|
|
1182
|
+
* fastest live source. JWT only; sessionToken is owned by the SW + cookies.
|
|
1183
|
+
*/
|
|
1184
|
+
private setupSwCredsListener;
|
|
1170
1185
|
}
|
|
1171
1186
|
declare global {
|
|
1172
1187
|
interface Window {
|
package/dist/index.js
CHANGED
|
@@ -93,6 +93,44 @@ var WavedashManager = class {
|
|
|
93
93
|
}
|
|
94
94
|
};
|
|
95
95
|
|
|
96
|
+
// src/utils/logger.ts
|
|
97
|
+
var LOG_LEVEL = {
|
|
98
|
+
DEBUG: 0,
|
|
99
|
+
// Most verbose
|
|
100
|
+
INFO: 1,
|
|
101
|
+
WARN: 2,
|
|
102
|
+
ERROR: 3
|
|
103
|
+
};
|
|
104
|
+
var WavedashLogger = class {
|
|
105
|
+
constructor(logLevel = LOG_LEVEL.WARN) {
|
|
106
|
+
this.logLevel = logLevel;
|
|
107
|
+
}
|
|
108
|
+
setLogLevel(level) {
|
|
109
|
+
this.logLevel = level;
|
|
110
|
+
}
|
|
111
|
+
debug(message, ...args) {
|
|
112
|
+
if (this.logLevel <= LOG_LEVEL.DEBUG) {
|
|
113
|
+
console.log(`[WavedashJS] ${message}`, ...args);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
info(message, ...args) {
|
|
117
|
+
if (this.logLevel <= LOG_LEVEL.INFO) {
|
|
118
|
+
console.log(`[WavedashJS] ${message}`, ...args);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
warn(message, ...args) {
|
|
122
|
+
if (this.logLevel <= LOG_LEVEL.WARN) {
|
|
123
|
+
console.warn(`[WavedashJS] ${message}`, ...args);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
error(message, ...args) {
|
|
127
|
+
if (this.logLevel <= LOG_LEVEL.ERROR) {
|
|
128
|
+
console.error(`[WavedashJS] ${message}`, ...args);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
var logger = new WavedashLogger();
|
|
133
|
+
|
|
96
134
|
// src/services/lobby.ts
|
|
97
135
|
var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
98
136
|
constructor(sdk) {
|
|
@@ -153,7 +191,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
153
191
|
for (const user of previousUsers) {
|
|
154
192
|
if (!newUserIds.has(user.userId)) {
|
|
155
193
|
if (user.userId === this.sdk.getUserId()) {
|
|
156
|
-
|
|
194
|
+
logger.warn(
|
|
157
195
|
"USER WAS KICKED FROM LOBBY! Received notification for myself leaving."
|
|
158
196
|
);
|
|
159
197
|
}
|
|
@@ -169,7 +207,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
169
207
|
}
|
|
170
208
|
if (this.lobbyId) {
|
|
171
209
|
this.p2pUpdateQueue = this.p2pUpdateQueue.then(() => this.updateP2PConnections(newUsers)).catch((error) => {
|
|
172
|
-
|
|
210
|
+
logger.error("Error in queued P2P update:", error);
|
|
173
211
|
});
|
|
174
212
|
}
|
|
175
213
|
};
|
|
@@ -204,7 +242,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
204
242
|
{},
|
|
205
243
|
this.processInviteUpdates,
|
|
206
244
|
(error) => {
|
|
207
|
-
|
|
245
|
+
logger.error(`Lobby invites subscription error: ${error}`);
|
|
208
246
|
}
|
|
209
247
|
);
|
|
210
248
|
}
|
|
@@ -232,7 +270,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
232
270
|
}
|
|
233
271
|
getLobbyUsers(lobbyId) {
|
|
234
272
|
if (this.lobbyId !== lobbyId) {
|
|
235
|
-
|
|
273
|
+
logger.error(
|
|
236
274
|
"Must be a member of the lobby to access user list"
|
|
237
275
|
);
|
|
238
276
|
return [];
|
|
@@ -241,7 +279,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
241
279
|
}
|
|
242
280
|
getHostId(lobbyId) {
|
|
243
281
|
if (this.lobbyId !== lobbyId) {
|
|
244
|
-
|
|
282
|
+
logger.error(
|
|
245
283
|
"Must be a member of the lobby to access the host ID"
|
|
246
284
|
);
|
|
247
285
|
return null;
|
|
@@ -317,11 +355,11 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
317
355
|
sendLobbyMessage(lobbyId, message) {
|
|
318
356
|
const args = { lobbyId, message };
|
|
319
357
|
if (message.length === 0) {
|
|
320
|
-
|
|
358
|
+
logger.error("Message cannot be empty");
|
|
321
359
|
return false;
|
|
322
360
|
}
|
|
323
361
|
if (message.length > LOBBY_MESSAGE_MAX_LENGTH) {
|
|
324
|
-
|
|
362
|
+
logger.error(
|
|
325
363
|
`Message cannot be longer than ${LOBBY_MESSAGE_MAX_LENGTH} characters`
|
|
326
364
|
);
|
|
327
365
|
return false;
|
|
@@ -329,7 +367,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
329
367
|
try {
|
|
330
368
|
this.sdk.convexClient.mutation(api.sdk.gameLobby.sendMessage, args);
|
|
331
369
|
} catch (error) {
|
|
332
|
-
|
|
370
|
+
logger.error(`Error sending lobby message: ${error}`);
|
|
333
371
|
return false;
|
|
334
372
|
}
|
|
335
373
|
return true;
|
|
@@ -372,7 +410,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
372
410
|
this.lobbyMetadata = response.metadata;
|
|
373
411
|
this.sdk.friendsManager.cacheUsers(response.users);
|
|
374
412
|
const onLobbySubscriptionError = (error) => {
|
|
375
|
-
|
|
413
|
+
logger.error(`Lobby subscription error: ${error.message}`);
|
|
376
414
|
if (error.message.includes("not a member")) {
|
|
377
415
|
this.handleLobbyKicked(LobbyKickedReason.KICKED);
|
|
378
416
|
} else {
|
|
@@ -406,7 +444,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
406
444
|
if (response.users.length > 1) {
|
|
407
445
|
this.p2pUpdateQueue = this.updateP2PConnections(response.users).catch(
|
|
408
446
|
(error) => {
|
|
409
|
-
|
|
447
|
+
logger.error("Error initializing P2P on join:", error);
|
|
410
448
|
}
|
|
411
449
|
);
|
|
412
450
|
}
|
|
@@ -419,7 +457,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
419
457
|
users: response.users,
|
|
420
458
|
metadata: response.metadata
|
|
421
459
|
});
|
|
422
|
-
|
|
460
|
+
logger.debug("Subscribed to lobby:", response.lobbyId);
|
|
423
461
|
}
|
|
424
462
|
/**
|
|
425
463
|
* Handle being kicked or removed from a lobby (subscription error)
|
|
@@ -429,7 +467,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
429
467
|
handleLobbyKicked(reason = LobbyKickedReason.KICKED) {
|
|
430
468
|
const lobbyId = this.lobbyId;
|
|
431
469
|
if (!lobbyId) return;
|
|
432
|
-
|
|
470
|
+
logger.warn(
|
|
433
471
|
`User was removed from lobby: ${lobbyId} (reason: ${reason})`
|
|
434
472
|
);
|
|
435
473
|
this.cleanupLobbyState();
|
|
@@ -516,7 +554,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
516
554
|
lobbyId: this.lobbyId,
|
|
517
555
|
updates
|
|
518
556
|
}).catch((error) => {
|
|
519
|
-
|
|
557
|
+
logger.error("Error updating lobby metadata:", error);
|
|
520
558
|
}).finally(() => {
|
|
521
559
|
this.inFlightMetadataUpdate = null;
|
|
522
560
|
if (Object.keys(this.pendingMetadataUpdates).length > 0) {
|
|
@@ -538,7 +576,7 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
538
576
|
try {
|
|
539
577
|
if (newUsers.length <= 1) {
|
|
540
578
|
this.sdk.p2pManager.disconnectP2P();
|
|
541
|
-
|
|
579
|
+
logger.debug(
|
|
542
580
|
"Only one user in lobby, P2P connections disconnected"
|
|
543
581
|
);
|
|
544
582
|
return;
|
|
@@ -552,11 +590,11 @@ var _LobbyManager = class _LobbyManager extends WavedashManager {
|
|
|
552
590
|
this.lobbyId,
|
|
553
591
|
wavedashUsers
|
|
554
592
|
);
|
|
555
|
-
|
|
593
|
+
logger.debug(
|
|
556
594
|
`P2P connections updated for lobby ${this.lobbyId} with ${wavedashUsers.length} users`
|
|
557
595
|
);
|
|
558
596
|
} catch (error) {
|
|
559
|
-
|
|
597
|
+
logger.error("Error updating P2P connections:", error);
|
|
560
598
|
}
|
|
561
599
|
}
|
|
562
600
|
};
|
|
@@ -701,7 +739,7 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
701
739
|
});
|
|
702
740
|
if (!response.ok) {
|
|
703
741
|
const msg = `Failed to delete remote file ${filePath}: ${response.status} (${response.statusText})`;
|
|
704
|
-
|
|
742
|
+
logger.error(msg);
|
|
705
743
|
throw new Error(msg);
|
|
706
744
|
}
|
|
707
745
|
return filePath;
|
|
@@ -760,9 +798,9 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
760
798
|
return path;
|
|
761
799
|
}
|
|
762
800
|
async writeLocalFile(filePath, data) {
|
|
763
|
-
|
|
801
|
+
logger.debug(`Writing local file: ${filePath}`);
|
|
764
802
|
if (this.sdk.engineInstance?.FS) {
|
|
765
|
-
|
|
803
|
+
logger.error(
|
|
766
804
|
`${this.sdk.engineInstance.type} engine detected, use engine's builtin file access to save files.`
|
|
767
805
|
);
|
|
768
806
|
return false;
|
|
@@ -771,14 +809,14 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
771
809
|
await writeToIndexedDB(filePath, data);
|
|
772
810
|
return true;
|
|
773
811
|
} catch (error) {
|
|
774
|
-
|
|
812
|
+
logger.error(`Failed to write local file: ${error}`);
|
|
775
813
|
return false;
|
|
776
814
|
}
|
|
777
815
|
}
|
|
778
816
|
async readLocalFile(filePath) {
|
|
779
|
-
|
|
817
|
+
logger.debug(`Reading local file: ${filePath}`);
|
|
780
818
|
if (this.sdk.engineInstance?.FS) {
|
|
781
|
-
|
|
819
|
+
logger.error(
|
|
782
820
|
`${this.sdk.engineInstance.type} engine detected, use engine's builtin file access to read files.`
|
|
783
821
|
);
|
|
784
822
|
return null;
|
|
@@ -789,7 +827,7 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
789
827
|
const arrayBuffer = await blob.arrayBuffer();
|
|
790
828
|
return new Uint8Array(arrayBuffer);
|
|
791
829
|
} catch (error) {
|
|
792
|
-
|
|
830
|
+
logger.error(`Failed to read local file: ${error}`);
|
|
793
831
|
return null;
|
|
794
832
|
}
|
|
795
833
|
}
|
|
@@ -798,9 +836,9 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
798
836
|
// ================
|
|
799
837
|
// Helper to upload a local file to a presigned URL
|
|
800
838
|
async upload(presignedUploadUrl, filePath) {
|
|
801
|
-
|
|
839
|
+
logger.debug(`Uploading ${filePath} to: ${presignedUploadUrl}`);
|
|
802
840
|
if (this.sdk.engineInstance && !this.sdk.engineInstance.FS) {
|
|
803
|
-
|
|
841
|
+
logger.error("Engine instance is missing the Emscripten FS API");
|
|
804
842
|
return false;
|
|
805
843
|
}
|
|
806
844
|
let success = false;
|
|
@@ -813,9 +851,9 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
813
851
|
}
|
|
814
852
|
// Helper to download a file from a URL and save locally
|
|
815
853
|
async download(url, filePath) {
|
|
816
|
-
|
|
854
|
+
logger.debug(`Downloading ${filePath} from: ${url}`);
|
|
817
855
|
if (this.sdk.engineInstance && !this.sdk.engineInstance.FS) {
|
|
818
|
-
|
|
856
|
+
logger.error("Engine instance is missing the Emscripten FS API");
|
|
819
857
|
return false;
|
|
820
858
|
}
|
|
821
859
|
const jwt = await this.sdk.ensureGameplayJwt();
|
|
@@ -826,7 +864,7 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
826
864
|
}
|
|
827
865
|
});
|
|
828
866
|
if (!response.ok) {
|
|
829
|
-
|
|
867
|
+
logger.error(
|
|
830
868
|
`Failed to download remote file: ${response.status} (${response.statusText})`
|
|
831
869
|
);
|
|
832
870
|
return false;
|
|
@@ -848,10 +886,10 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
848
886
|
const success = await this.writeLocalFile(filePath, dataArray);
|
|
849
887
|
if (!success) return false;
|
|
850
888
|
}
|
|
851
|
-
|
|
889
|
+
logger.debug(`Successfully saved to: ${filePath}`);
|
|
852
890
|
return true;
|
|
853
891
|
} catch (error) {
|
|
854
|
-
|
|
892
|
+
logger.error(
|
|
855
893
|
`Failed to save file ${filePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
856
894
|
);
|
|
857
895
|
return false;
|
|
@@ -888,7 +926,7 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
888
926
|
try {
|
|
889
927
|
const blob = await this.readLocalFileBlob(indexedDBKey);
|
|
890
928
|
if (!blob) {
|
|
891
|
-
|
|
929
|
+
logger.error(`File not found in IndexedDB: ${indexedDBKey}`);
|
|
892
930
|
return false;
|
|
893
931
|
}
|
|
894
932
|
const response = await fetch(presignedUploadUrl, {
|
|
@@ -898,7 +936,7 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
898
936
|
});
|
|
899
937
|
return response.ok;
|
|
900
938
|
} catch (error) {
|
|
901
|
-
|
|
939
|
+
logger.error(`Error uploading from IndexedDB: ${error}`);
|
|
902
940
|
return false;
|
|
903
941
|
}
|
|
904
942
|
}
|
|
@@ -920,14 +958,14 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
920
958
|
return response.ok;
|
|
921
959
|
} catch (error) {
|
|
922
960
|
const msg = error instanceof Error ? error.message : String(error);
|
|
923
|
-
|
|
961
|
+
logger.error(`Error uploading from FS: ${msg}`);
|
|
924
962
|
return false;
|
|
925
963
|
}
|
|
926
964
|
}
|
|
927
965
|
async readLocalFileBlob(filePath) {
|
|
928
|
-
|
|
966
|
+
logger.debug(`Reading local file (blob): ${filePath}`);
|
|
929
967
|
if (this.sdk.engineInstance?.FS) {
|
|
930
|
-
|
|
968
|
+
logger.error(
|
|
931
969
|
`${this.sdk.engineInstance.type} engine detected, use engine's builtin file access to read files.`
|
|
932
970
|
);
|
|
933
971
|
return null;
|
|
@@ -937,7 +975,7 @@ var FileSystemManager = class extends WavedashManager {
|
|
|
937
975
|
if (!record) return null;
|
|
938
976
|
return toBlobFromIndexedDBValue(record);
|
|
939
977
|
} catch (error) {
|
|
940
|
-
|
|
978
|
+
logger.error(`Failed to read local file blob: ${error}`);
|
|
941
979
|
return null;
|
|
942
980
|
}
|
|
943
981
|
}
|
|
@@ -1265,7 +1303,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1265
1303
|
return this.updateP2PConnection(members);
|
|
1266
1304
|
}
|
|
1267
1305
|
if (this.initializationInProgress && this.initializationLobbyId === lobbyId) {
|
|
1268
|
-
|
|
1306
|
+
logger.debug(
|
|
1269
1307
|
"P2P initialization already in progress, waiting..."
|
|
1270
1308
|
);
|
|
1271
1309
|
await this.initializationInProgress;
|
|
@@ -1333,7 +1371,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1333
1371
|
if (!this.currentConnection) {
|
|
1334
1372
|
throw new Error("No existing P2P connection to update");
|
|
1335
1373
|
}
|
|
1336
|
-
|
|
1374
|
+
logger.debug("Updating P2P connection with new member list");
|
|
1337
1375
|
const currentPeerUserIds = new Set(
|
|
1338
1376
|
Object.keys(this.currentConnection.peers)
|
|
1339
1377
|
);
|
|
@@ -1348,7 +1386,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1348
1386
|
existingPeer.username = member.username;
|
|
1349
1387
|
}
|
|
1350
1388
|
} else {
|
|
1351
|
-
|
|
1389
|
+
logger.debug(
|
|
1352
1390
|
`Adding new peer: ${member.username} (${member.id})`
|
|
1353
1391
|
);
|
|
1354
1392
|
this.currentConnection.peers[member.id] = {
|
|
@@ -1362,7 +1400,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1362
1400
|
const currentUserId = this.sdk.getUserId();
|
|
1363
1401
|
const connectionPromises = connectionsToCreate.map((userId) => {
|
|
1364
1402
|
const shouldCreateChannels = currentUserId < userId;
|
|
1365
|
-
|
|
1403
|
+
logger.debug(
|
|
1366
1404
|
`Creating connection to new peer ${userId}, shouldCreateChannels: ${shouldCreateChannels}`
|
|
1367
1405
|
);
|
|
1368
1406
|
return this.createPeerConnection(
|
|
@@ -1377,13 +1415,13 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1377
1415
|
);
|
|
1378
1416
|
if (peersToInitiate.length > 0) {
|
|
1379
1417
|
const offerPromises = peersToInitiate.map((userId) => {
|
|
1380
|
-
|
|
1418
|
+
logger.debug(
|
|
1381
1419
|
`Initiating offer to new peer ${userId} (lower userId rule)`
|
|
1382
1420
|
);
|
|
1383
1421
|
return this.createOfferToPeer(userId);
|
|
1384
1422
|
});
|
|
1385
1423
|
await Promise.all(offerPromises);
|
|
1386
|
-
|
|
1424
|
+
logger.debug(
|
|
1387
1425
|
`Initiated ${offerPromises.length} offers to new peers`
|
|
1388
1426
|
);
|
|
1389
1427
|
}
|
|
@@ -1393,7 +1431,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1393
1431
|
)) {
|
|
1394
1432
|
if (!newPeerUserIds.has(userId)) {
|
|
1395
1433
|
const peer = this.currentConnection.peers[userId];
|
|
1396
|
-
|
|
1434
|
+
logger.debug(`Peer left: ${peer.username} (${userId})`);
|
|
1397
1435
|
const pc = this.peerConnections.get(userId);
|
|
1398
1436
|
if (pc) {
|
|
1399
1437
|
pc.close();
|
|
@@ -1415,7 +1453,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1415
1453
|
this.subscribeToSignalingMessages(connection);
|
|
1416
1454
|
if (this.signalingSubscriptionReady) {
|
|
1417
1455
|
await this.signalingSubscriptionReady;
|
|
1418
|
-
|
|
1456
|
+
logger.debug("Signaling subscription confirmed ready");
|
|
1419
1457
|
}
|
|
1420
1458
|
await this.establishPeerConnections(connection);
|
|
1421
1459
|
}
|
|
@@ -1461,7 +1499,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1461
1499
|
await this.handleSignalingMessage(message, connection);
|
|
1462
1500
|
this.processedSignalingMessages.add(message._id);
|
|
1463
1501
|
} catch (error) {
|
|
1464
|
-
|
|
1502
|
+
logger.error("Error handling signaling message:", error);
|
|
1465
1503
|
}
|
|
1466
1504
|
}
|
|
1467
1505
|
if (newMessageIds.length > 0) {
|
|
@@ -1474,7 +1512,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1474
1512
|
this.pendingProcessedMessageIds.delete(messageId);
|
|
1475
1513
|
}
|
|
1476
1514
|
} catch (error) {
|
|
1477
|
-
|
|
1515
|
+
logger.error(
|
|
1478
1516
|
"Failed to mark signaling messages as processed:",
|
|
1479
1517
|
error
|
|
1480
1518
|
);
|
|
@@ -1491,7 +1529,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1491
1529
|
const remoteUserId = message.fromUserId;
|
|
1492
1530
|
if (!this.peerConnections.has(remoteUserId)) {
|
|
1493
1531
|
if (message.messageType === P2P_SIGNALING_MESSAGE_TYPE.OFFER) {
|
|
1494
|
-
|
|
1532
|
+
logger.debug(
|
|
1495
1533
|
`Received offer from ${remoteUserId} before peer connection exists, creating on-demand`
|
|
1496
1534
|
);
|
|
1497
1535
|
if (!connection.peers[remoteUserId]) {
|
|
@@ -1508,13 +1546,13 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1508
1546
|
// shouldCreateChannels = false, we'll receive them via ondatachannel
|
|
1509
1547
|
);
|
|
1510
1548
|
if (!success) {
|
|
1511
|
-
|
|
1549
|
+
logger.error(
|
|
1512
1550
|
`Failed to create on-demand peer connection for ${remoteUserId}`
|
|
1513
1551
|
);
|
|
1514
1552
|
return;
|
|
1515
1553
|
}
|
|
1516
1554
|
} else {
|
|
1517
|
-
|
|
1555
|
+
logger.warn(
|
|
1518
1556
|
`No peer connection for user ${remoteUserId}, dropping ${message.messageType} message`
|
|
1519
1557
|
);
|
|
1520
1558
|
return;
|
|
@@ -1524,14 +1562,14 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1524
1562
|
switch (message.messageType) {
|
|
1525
1563
|
case P2P_SIGNALING_MESSAGE_TYPE.OFFER: {
|
|
1526
1564
|
this.iceRestartInProgress.delete(remoteUserId);
|
|
1527
|
-
|
|
1565
|
+
logger.debug(`Processing offer from peer ${remoteUserId}:`);
|
|
1528
1566
|
await pc.setRemoteDescription(
|
|
1529
1567
|
new RTCSessionDescription(message.data)
|
|
1530
1568
|
);
|
|
1531
1569
|
await this.flushPendingIceCandidates(remoteUserId, pc);
|
|
1532
1570
|
const answer = await pc.createAnswer();
|
|
1533
1571
|
await pc.setLocalDescription(answer);
|
|
1534
|
-
|
|
1572
|
+
logger.debug(
|
|
1535
1573
|
` Answer created, waiting for ondatachannel events...`
|
|
1536
1574
|
);
|
|
1537
1575
|
const answerData = {
|
|
@@ -1556,7 +1594,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1556
1594
|
const pending = this.pendingIceCandidates.get(remoteUserId) || [];
|
|
1557
1595
|
pending.push(iceData);
|
|
1558
1596
|
this.pendingIceCandidates.set(remoteUserId, pending);
|
|
1559
|
-
|
|
1597
|
+
logger.debug(
|
|
1560
1598
|
`Buffered ICE candidate for ${remoteUserId} (remote description not yet set, ${pending.length} buffered)`
|
|
1561
1599
|
);
|
|
1562
1600
|
} else {
|
|
@@ -1565,7 +1603,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1565
1603
|
break;
|
|
1566
1604
|
}
|
|
1567
1605
|
default:
|
|
1568
|
-
|
|
1606
|
+
logger.warn(
|
|
1569
1607
|
"Unknown signaling message type:",
|
|
1570
1608
|
message.messageType
|
|
1571
1609
|
);
|
|
@@ -1582,7 +1620,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1582
1620
|
try {
|
|
1583
1621
|
await pc.addIceCandidate(new RTCIceCandidate(candidate));
|
|
1584
1622
|
} catch (error) {
|
|
1585
|
-
|
|
1623
|
+
logger.warn(
|
|
1586
1624
|
`Failed to add buffered ICE candidate for ${remoteUserId}:`,
|
|
1587
1625
|
error
|
|
1588
1626
|
);
|
|
@@ -1592,13 +1630,13 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1592
1630
|
}
|
|
1593
1631
|
}
|
|
1594
1632
|
async establishPeerConnections(connection) {
|
|
1595
|
-
|
|
1633
|
+
logger.debug("Establishing WebRTC connections to peers...");
|
|
1596
1634
|
const currentUserId = this.sdk.getUserId();
|
|
1597
1635
|
const connectionPromises = [];
|
|
1598
1636
|
Object.entries(connection.peers).forEach(
|
|
1599
1637
|
([userId, peer]) => {
|
|
1600
1638
|
const shouldCreateChannels = currentUserId < userId;
|
|
1601
|
-
|
|
1639
|
+
logger.debug(
|
|
1602
1640
|
`Creating connection to peer ${userId} (${peer.username}), shouldCreateChannels: ${shouldCreateChannels}`
|
|
1603
1641
|
);
|
|
1604
1642
|
connectionPromises.push(
|
|
@@ -1610,17 +1648,17 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1610
1648
|
const peersToInitiate = Object.keys(connection.peers).filter((userId) => currentUserId < userId);
|
|
1611
1649
|
if (peersToInitiate.length > 0) {
|
|
1612
1650
|
const offerPromises = peersToInitiate.map((userId) => {
|
|
1613
|
-
|
|
1651
|
+
logger.debug(
|
|
1614
1652
|
`Initiating offer to peer ${userId} (lower userId rule)`
|
|
1615
1653
|
);
|
|
1616
1654
|
return this.createOfferToPeer(userId);
|
|
1617
1655
|
});
|
|
1618
1656
|
await Promise.all(offerPromises);
|
|
1619
|
-
|
|
1657
|
+
logger.debug(
|
|
1620
1658
|
`Created ${connectionPromises.length} peer connections and initiated ${offerPromises.length} offers`
|
|
1621
1659
|
);
|
|
1622
1660
|
} else {
|
|
1623
|
-
|
|
1661
|
+
logger.debug(
|
|
1624
1662
|
`Created ${connectionPromises.length} peer connections, no offers to initiate`
|
|
1625
1663
|
);
|
|
1626
1664
|
}
|
|
@@ -1632,11 +1670,11 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1632
1670
|
}
|
|
1633
1671
|
const reliableChannel = this.reliableChannels.get(remoteUserId);
|
|
1634
1672
|
const unreliableChannel = this.unreliableChannels.get(remoteUserId);
|
|
1635
|
-
|
|
1636
|
-
|
|
1673
|
+
logger.debug(`Creating offer to peer ${remoteUserId}:`);
|
|
1674
|
+
logger.debug(
|
|
1637
1675
|
` Reliable channel state: ${reliableChannel?.readyState || "none"}`
|
|
1638
1676
|
);
|
|
1639
|
-
|
|
1677
|
+
logger.debug(
|
|
1640
1678
|
` Unreliable channel state: ${unreliableChannel?.readyState || "none"}`
|
|
1641
1679
|
);
|
|
1642
1680
|
const offer = await pc.createOffer();
|
|
@@ -1653,7 +1691,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1653
1691
|
async createPeerConnection(remoteUserId, connection, shouldCreateChannels = false) {
|
|
1654
1692
|
const iceServers = await this.getIceServers();
|
|
1655
1693
|
if (!iceServers) {
|
|
1656
|
-
|
|
1694
|
+
logger.error(
|
|
1657
1695
|
`No ICE servers available for peer ${remoteUserId}`
|
|
1658
1696
|
);
|
|
1659
1697
|
this.sdk.gameEventManager.notifyGame(
|
|
@@ -1677,7 +1715,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1677
1715
|
rtcpMuxPolicy: "require"
|
|
1678
1716
|
});
|
|
1679
1717
|
if (shouldCreateChannels) {
|
|
1680
|
-
|
|
1718
|
+
logger.debug(`Creating data channels for peer ${remoteUserId}`);
|
|
1681
1719
|
if (this.config.enableReliableChannel) {
|
|
1682
1720
|
const reliableChannel = pc.createDataChannel("reliable", {
|
|
1683
1721
|
ordered: true,
|
|
@@ -1705,17 +1743,17 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1705
1743
|
);
|
|
1706
1744
|
}
|
|
1707
1745
|
} else {
|
|
1708
|
-
|
|
1746
|
+
logger.debug(
|
|
1709
1747
|
`Will receive data channels from peer ${remoteUserId} via ondatachannel`
|
|
1710
1748
|
);
|
|
1711
1749
|
}
|
|
1712
1750
|
pc.onicecandidate = (event) => {
|
|
1713
1751
|
if (event.candidate) {
|
|
1714
1752
|
const candidateType = event.candidate.candidate.includes("typ host") ? "host" : event.candidate.candidate.includes("typ srflx") ? "srflx (STUN)" : event.candidate.candidate.includes("typ relay") ? "relay (TURN)" : "unknown";
|
|
1715
|
-
|
|
1753
|
+
logger.debug(
|
|
1716
1754
|
`Peer ${remoteUserId} gathered ICE candidate: ${candidateType}`
|
|
1717
1755
|
);
|
|
1718
|
-
|
|
1756
|
+
logger.debug(` Candidate: ${event.candidate.candidate}`);
|
|
1719
1757
|
const candidateData = {
|
|
1720
1758
|
candidate: event.candidate.candidate,
|
|
1721
1759
|
sdpMid: event.candidate.sdpMid,
|
|
@@ -1730,7 +1768,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1730
1768
|
};
|
|
1731
1769
|
pc.ondatachannel = (event) => {
|
|
1732
1770
|
const channel = event.channel;
|
|
1733
|
-
|
|
1771
|
+
logger.debug(
|
|
1734
1772
|
`Received ${channel.label} data channel from peer ${remoteUserId}`
|
|
1735
1773
|
);
|
|
1736
1774
|
if (channel.label === "reliable") {
|
|
@@ -1745,21 +1783,21 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1745
1783
|
);
|
|
1746
1784
|
};
|
|
1747
1785
|
pc.onconnectionstatechange = () => {
|
|
1748
|
-
|
|
1786
|
+
logger.debug(
|
|
1749
1787
|
`Peer ${remoteUserId} connection state: ${pc.connectionState}`
|
|
1750
1788
|
);
|
|
1751
1789
|
if (pc.connectionState === "connected") {
|
|
1752
|
-
|
|
1790
|
+
logger.debug(
|
|
1753
1791
|
` Peer ${remoteUserId} fully connected, expecting ondatachannel events now...`
|
|
1754
1792
|
);
|
|
1755
1793
|
}
|
|
1756
1794
|
};
|
|
1757
1795
|
pc.oniceconnectionstatechange = () => {
|
|
1758
|
-
|
|
1796
|
+
logger.debug(
|
|
1759
1797
|
`Peer ${remoteUserId} ICE connection state: ${pc.iceConnectionState}`
|
|
1760
1798
|
);
|
|
1761
1799
|
if (pc.iceConnectionState === "connected") {
|
|
1762
|
-
|
|
1800
|
+
logger.debug(
|
|
1763
1801
|
` ICE connected to peer ${remoteUserId}, data channels should be available...`
|
|
1764
1802
|
);
|
|
1765
1803
|
this.iceRestartAttempts.delete(remoteUserId);
|
|
@@ -1777,7 +1815,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1777
1815
|
}
|
|
1778
1816
|
}
|
|
1779
1817
|
} else if (pc.iceConnectionState === "failed") {
|
|
1780
|
-
|
|
1818
|
+
logger.debug(
|
|
1781
1819
|
`ICE connection to peer ${remoteUserId} failed, will retry in 500ms...`
|
|
1782
1820
|
);
|
|
1783
1821
|
if (!this.reconnectingPeers.has(remoteUserId)) {
|
|
@@ -1795,20 +1833,20 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1795
1833
|
}
|
|
1796
1834
|
setTimeout(() => {
|
|
1797
1835
|
if (pc.iceConnectionState === "failed") {
|
|
1798
|
-
|
|
1836
|
+
logger.warn(
|
|
1799
1837
|
`ICE connection to peer ${remoteUserId} still failed after delay, attempting ICE restart...`
|
|
1800
1838
|
);
|
|
1801
1839
|
this.attemptIceRestart(remoteUserId, pc);
|
|
1802
1840
|
}
|
|
1803
1841
|
}, 500);
|
|
1804
1842
|
} else if (pc.iceConnectionState === "disconnected") {
|
|
1805
|
-
|
|
1843
|
+
logger.debug(
|
|
1806
1844
|
`ICE connection to peer ${remoteUserId} disconnected, may recover...`
|
|
1807
1845
|
);
|
|
1808
1846
|
}
|
|
1809
1847
|
};
|
|
1810
1848
|
pc.onicegatheringstatechange = () => {
|
|
1811
|
-
|
|
1849
|
+
logger.debug(
|
|
1812
1850
|
`Peer ${remoteUserId} ICE gathering state: ${pc.iceGatheringState}`
|
|
1813
1851
|
);
|
|
1814
1852
|
};
|
|
@@ -1822,20 +1860,20 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1822
1860
|
async attemptIceRestart(remoteUserId, pc) {
|
|
1823
1861
|
const currentUserId = this.sdk.getUserId();
|
|
1824
1862
|
if (currentUserId > remoteUserId) {
|
|
1825
|
-
|
|
1863
|
+
logger.debug(
|
|
1826
1864
|
`Waiting for peer ${remoteUserId} to initiate ICE restart (they have lower userId)`
|
|
1827
1865
|
);
|
|
1828
1866
|
return;
|
|
1829
1867
|
}
|
|
1830
1868
|
if (this.iceRestartInProgress.has(remoteUserId)) {
|
|
1831
|
-
|
|
1869
|
+
logger.debug(
|
|
1832
1870
|
`ICE restart already in progress for peer ${remoteUserId}, skipping`
|
|
1833
1871
|
);
|
|
1834
1872
|
return;
|
|
1835
1873
|
}
|
|
1836
1874
|
const attempts = this.iceRestartAttempts.get(remoteUserId) || 0;
|
|
1837
1875
|
if (attempts >= this.MAX_ICE_RESTART_ATTEMPTS) {
|
|
1838
|
-
|
|
1876
|
+
logger.error(
|
|
1839
1877
|
`Max ICE restart attempts (${this.MAX_ICE_RESTART_ATTEMPTS}) reached for peer ${remoteUserId}, giving up`
|
|
1840
1878
|
);
|
|
1841
1879
|
this.reconnectingPeers.delete(remoteUserId);
|
|
@@ -1856,7 +1894,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1856
1894
|
}
|
|
1857
1895
|
this.iceRestartAttempts.set(remoteUserId, attempts + 1);
|
|
1858
1896
|
this.iceRestartInProgress.add(remoteUserId);
|
|
1859
|
-
|
|
1897
|
+
logger.debug(
|
|
1860
1898
|
`ICE restart attempt ${attempts + 1}/${this.MAX_ICE_RESTART_ATTEMPTS} for peer ${remoteUserId}`
|
|
1861
1899
|
);
|
|
1862
1900
|
try {
|
|
@@ -1871,9 +1909,9 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1871
1909
|
type: P2P_SIGNALING_MESSAGE_TYPE.OFFER,
|
|
1872
1910
|
data: offerData
|
|
1873
1911
|
});
|
|
1874
|
-
|
|
1912
|
+
logger.debug(`ICE restart offer sent to peer ${remoteUserId}`);
|
|
1875
1913
|
} catch (error) {
|
|
1876
|
-
|
|
1914
|
+
logger.error(
|
|
1877
1915
|
`Failed to initiate ICE restart for peer ${remoteUserId}:`,
|
|
1878
1916
|
error
|
|
1879
1917
|
);
|
|
@@ -1881,7 +1919,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1881
1919
|
}
|
|
1882
1920
|
setupDataChannelHandlers(channel, remoteUserId, type) {
|
|
1883
1921
|
channel.onopen = () => {
|
|
1884
|
-
|
|
1922
|
+
logger.debug(
|
|
1885
1923
|
`${type} data channel opened with peer ${remoteUserId}`
|
|
1886
1924
|
);
|
|
1887
1925
|
if (this.isPeerReady(remoteUserId) && !this.establishedPeers.has(remoteUserId)) {
|
|
@@ -1902,7 +1940,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1902
1940
|
this.enqueueMessage(event.data, remoteUserId);
|
|
1903
1941
|
};
|
|
1904
1942
|
channel.onerror = (error) => {
|
|
1905
|
-
|
|
1943
|
+
logger.error(
|
|
1906
1944
|
`Data channel error with peer ${remoteUserId}:`,
|
|
1907
1945
|
error
|
|
1908
1946
|
);
|
|
@@ -1919,7 +1957,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1919
1957
|
}
|
|
1920
1958
|
};
|
|
1921
1959
|
channel.onclose = () => {
|
|
1922
|
-
|
|
1960
|
+
logger.debug(
|
|
1923
1961
|
`${type} data channel closed with peer ${remoteUserId}`
|
|
1924
1962
|
);
|
|
1925
1963
|
this.establishedPeers.delete(remoteUserId);
|
|
@@ -1943,42 +1981,42 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1943
1981
|
this.ensureInitialized();
|
|
1944
1982
|
try {
|
|
1945
1983
|
if (!this.currentConnection) {
|
|
1946
|
-
|
|
1984
|
+
logger.error(
|
|
1947
1985
|
`P2P send called before P2P is initialized, dropping message.`
|
|
1948
1986
|
);
|
|
1949
1987
|
this.reportPacketDrop(appChannel, "SEND", "PEER_NOT_READY");
|
|
1950
1988
|
return false;
|
|
1951
1989
|
}
|
|
1952
1990
|
if (!payload) {
|
|
1953
|
-
|
|
1991
|
+
logger.error(
|
|
1954
1992
|
`P2P send called with missing payload, dropping message.`
|
|
1955
1993
|
);
|
|
1956
1994
|
this.reportPacketDrop(appChannel, "SEND", "INVALID_PAYLOAD_SIZE");
|
|
1957
1995
|
return false;
|
|
1958
1996
|
}
|
|
1959
1997
|
if (!Number.isInteger(appChannel) || appChannel < 0 || appChannel >= this.MAX_CHANNELS) {
|
|
1960
|
-
|
|
1998
|
+
logger.error(
|
|
1961
1999
|
`P2P appChannel must be an integer in [0, ${this.MAX_CHANNELS}), received ${appChannel}, dropping message.`
|
|
1962
2000
|
);
|
|
1963
2001
|
this.reportPacketDrop(-1, "SEND", "INVALID_CHANNEL");
|
|
1964
2002
|
return false;
|
|
1965
2003
|
}
|
|
1966
2004
|
if (payloadSize <= 0) {
|
|
1967
|
-
|
|
2005
|
+
logger.error(
|
|
1968
2006
|
`P2P payloadSize must be greater than 0, received ${payloadSize}, dropping message.`
|
|
1969
2007
|
);
|
|
1970
2008
|
this.reportPacketDrop(appChannel, "SEND", "INVALID_PAYLOAD_SIZE");
|
|
1971
2009
|
return false;
|
|
1972
2010
|
}
|
|
1973
2011
|
if (payloadSize > this.MAX_PAYLOAD_SIZE) {
|
|
1974
|
-
|
|
2012
|
+
logger.error(
|
|
1975
2013
|
`P2P payload too large: ${payloadSize} bytes exceeds max ${this.MAX_PAYLOAD_SIZE} bytes, dropping message.`
|
|
1976
2014
|
);
|
|
1977
2015
|
this.reportPacketDrop(appChannel, "SEND", "PAYLOAD_TOO_LARGE");
|
|
1978
2016
|
return false;
|
|
1979
2017
|
}
|
|
1980
2018
|
if (payloadSize > payload.length) {
|
|
1981
|
-
|
|
2019
|
+
logger.error(
|
|
1982
2020
|
`payloadSize is greater than payload buffer length: ${payloadSize} > ${payload.length}, dropping message.`
|
|
1983
2021
|
);
|
|
1984
2022
|
this.reportPacketDrop(appChannel, "SEND", "INVALID_PAYLOAD_SIZE");
|
|
@@ -1993,7 +2031,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
1993
2031
|
try {
|
|
1994
2032
|
channel.send(messageData);
|
|
1995
2033
|
} catch (error) {
|
|
1996
|
-
|
|
2034
|
+
logger.error(
|
|
1997
2035
|
`P2P broadcast to peer ${peerUserId} failed:`,
|
|
1998
2036
|
error
|
|
1999
2037
|
);
|
|
@@ -2002,7 +2040,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
2002
2040
|
} else {
|
|
2003
2041
|
const channel = channelMap.get(toUserId);
|
|
2004
2042
|
if (!channel || channel.readyState !== "open") {
|
|
2005
|
-
|
|
2043
|
+
logger.error(
|
|
2006
2044
|
`P2P no open channel to peer ${toUserId}, dropping message.`
|
|
2007
2045
|
);
|
|
2008
2046
|
this.reportPacketDrop(appChannel, "SEND", "PEER_NOT_READY");
|
|
@@ -2011,7 +2049,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
2011
2049
|
try {
|
|
2012
2050
|
channel.send(messageData);
|
|
2013
2051
|
} catch (error) {
|
|
2014
|
-
|
|
2052
|
+
logger.error(
|
|
2015
2053
|
`P2P send to peer ${toUserId} failed, dropping message:`,
|
|
2016
2054
|
error
|
|
2017
2055
|
);
|
|
@@ -2021,7 +2059,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
2021
2059
|
}
|
|
2022
2060
|
return true;
|
|
2023
2061
|
} catch (error) {
|
|
2024
|
-
|
|
2062
|
+
logger.error(`Error sending P2P message:`, error);
|
|
2025
2063
|
return false;
|
|
2026
2064
|
}
|
|
2027
2065
|
}
|
|
@@ -2042,9 +2080,9 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
2042
2080
|
data: message.data
|
|
2043
2081
|
}
|
|
2044
2082
|
);
|
|
2045
|
-
|
|
2083
|
+
logger.debug("Sent signaling message:", message.type);
|
|
2046
2084
|
} catch (error) {
|
|
2047
|
-
|
|
2085
|
+
logger.error("Failed to send signaling message:", error);
|
|
2048
2086
|
throw error;
|
|
2049
2087
|
}
|
|
2050
2088
|
}
|
|
@@ -2130,7 +2168,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
2130
2168
|
messageCount: 0,
|
|
2131
2169
|
incomingDataView
|
|
2132
2170
|
});
|
|
2133
|
-
|
|
2171
|
+
logger.debug(
|
|
2134
2172
|
`Allocated P2P ring buffer for channel ${channel} (${(queueDataSize / 1024 / 1024).toFixed(1)}MB)`
|
|
2135
2173
|
);
|
|
2136
2174
|
}
|
|
@@ -2200,7 +2238,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
2200
2238
|
enqueueMessage(wireData, fromUserId) {
|
|
2201
2239
|
try {
|
|
2202
2240
|
if (wireData.byteLength < this.WIRE_PAYLOAD_OFFSET) {
|
|
2203
|
-
|
|
2241
|
+
logger.warn("Binary message too short to extract channel");
|
|
2204
2242
|
this.reportPacketDrop(-1, "RECEIVE", "MALFORMED");
|
|
2205
2243
|
return;
|
|
2206
2244
|
}
|
|
@@ -2208,7 +2246,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
2208
2246
|
const channel = wireBytes[this.WIRE_CHANNEL_OFFSET];
|
|
2209
2247
|
if (!this.channelQueues.has(channel)) {
|
|
2210
2248
|
if (channel >= this.MAX_CHANNELS) {
|
|
2211
|
-
|
|
2249
|
+
logger.warn(
|
|
2212
2250
|
`Channel ${channel} exceeds max channels (${this.MAX_CHANNELS}), dropping message`
|
|
2213
2251
|
);
|
|
2214
2252
|
this.reportPacketDrop(channel, "RECEIVE", "INVALID_CHANNEL");
|
|
@@ -2218,7 +2256,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
2218
2256
|
}
|
|
2219
2257
|
const queue = this.channelQueues.get(channel);
|
|
2220
2258
|
if (queue.messageCount >= this.QUEUE_SIZE) {
|
|
2221
|
-
|
|
2259
|
+
logger.warn(
|
|
2222
2260
|
`P2P message queue full for channel ${channel}, dropping message`
|
|
2223
2261
|
);
|
|
2224
2262
|
this.reportPacketDrop(channel, "RECEIVE", "QUEUE_FULL");
|
|
@@ -2228,7 +2266,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
2228
2266
|
const storedSize = this.PAYLOAD_OFFSET + payloadLength;
|
|
2229
2267
|
const maxMessageSize = this.MESSAGE_SIZE - this.MESSAGE_SLOT_HEADER_SIZE;
|
|
2230
2268
|
if (storedSize > maxMessageSize) {
|
|
2231
|
-
|
|
2269
|
+
logger.warn(
|
|
2232
2270
|
`Message too large for queue: ${storedSize} > ${maxMessageSize}, dropping message.`
|
|
2233
2271
|
);
|
|
2234
2272
|
this.reportPacketDrop(channel, "RECEIVE", "PAYLOAD_TOO_LARGE");
|
|
@@ -2268,7 +2306,7 @@ var _P2PManager = class _P2PManager extends WavedashManager {
|
|
|
2268
2306
|
queue.writeIndex = (queue.writeIndex + 1) % this.QUEUE_SIZE;
|
|
2269
2307
|
queue.messageCount++;
|
|
2270
2308
|
} catch (error) {
|
|
2271
|
-
|
|
2309
|
+
logger.error(`Error enqueuing binary P2P message:`, error);
|
|
2272
2310
|
}
|
|
2273
2311
|
}
|
|
2274
2312
|
// Returns the max payload size (what game engines should report as max packet size)
|
|
@@ -2486,7 +2524,7 @@ var StatsManager = class extends WavedashManager {
|
|
|
2486
2524
|
);
|
|
2487
2525
|
this.subscribe();
|
|
2488
2526
|
this.requestStats().catch((error) => {
|
|
2489
|
-
|
|
2527
|
+
logger.error("Initial stats fetch failed:", error);
|
|
2490
2528
|
});
|
|
2491
2529
|
}
|
|
2492
2530
|
destroy() {
|
|
@@ -2509,7 +2547,7 @@ var StatsManager = class extends WavedashManager {
|
|
|
2509
2547
|
this.knownStatIds = new Set(ids);
|
|
2510
2548
|
},
|
|
2511
2549
|
(error) => {
|
|
2512
|
-
|
|
2550
|
+
logger.error("Stat identifiers subscription error:", error);
|
|
2513
2551
|
}
|
|
2514
2552
|
),
|
|
2515
2553
|
this.sdk.convexClient.onUpdate(
|
|
@@ -2519,7 +2557,7 @@ var StatsManager = class extends WavedashManager {
|
|
|
2519
2557
|
this.knownAchievementIds = new Set(ids);
|
|
2520
2558
|
},
|
|
2521
2559
|
(error) => {
|
|
2522
|
-
|
|
2560
|
+
logger.error(
|
|
2523
2561
|
"Achievement identifiers subscription error:",
|
|
2524
2562
|
error
|
|
2525
2563
|
);
|
|
@@ -2535,7 +2573,7 @@ var StatsManager = class extends WavedashManager {
|
|
|
2535
2573
|
}
|
|
2536
2574
|
},
|
|
2537
2575
|
(error) => {
|
|
2538
|
-
|
|
2576
|
+
logger.error("Achievement subscription error:", error);
|
|
2539
2577
|
}
|
|
2540
2578
|
)
|
|
2541
2579
|
);
|
|
@@ -2586,7 +2624,7 @@ var StatsManager = class extends WavedashManager {
|
|
|
2586
2624
|
});
|
|
2587
2625
|
}).catch((error) => {
|
|
2588
2626
|
const message = error instanceof Error ? error.message : `Error storing stats: ${error}`;
|
|
2589
|
-
|
|
2627
|
+
logger.error(message);
|
|
2590
2628
|
this.sdk.gameEventManager.notifyGame(WavedashEvents.STATS_STORED, {
|
|
2591
2629
|
success: false,
|
|
2592
2630
|
message
|
|
@@ -2750,7 +2788,7 @@ var HeartbeatManager = class extends WavedashManager {
|
|
|
2750
2788
|
this.lastHeartbeatTime = Date.now();
|
|
2751
2789
|
}
|
|
2752
2790
|
}).catch((error) => {
|
|
2753
|
-
|
|
2791
|
+
logger.error(`Heartbeat failed: ${error}`);
|
|
2754
2792
|
}).finally(() => {
|
|
2755
2793
|
this.heartbeatInFlight = false;
|
|
2756
2794
|
});
|
|
@@ -2769,7 +2807,7 @@ var HeartbeatManager = class extends WavedashManager {
|
|
|
2769
2807
|
});
|
|
2770
2808
|
return true;
|
|
2771
2809
|
} catch (error) {
|
|
2772
|
-
|
|
2810
|
+
logger.error(`Error updating presence: ${error}`);
|
|
2773
2811
|
return false;
|
|
2774
2812
|
}
|
|
2775
2813
|
}
|
|
@@ -2796,7 +2834,7 @@ var HeartbeatManager = class extends WavedashManager {
|
|
|
2796
2834
|
);
|
|
2797
2835
|
} else if (!this.isConnected && wasConnected) {
|
|
2798
2836
|
this.disconnectedAt = Date.now();
|
|
2799
|
-
|
|
2837
|
+
logger.warn(
|
|
2800
2838
|
"Backend disconnected - attempting to reconnect..."
|
|
2801
2839
|
);
|
|
2802
2840
|
this.sdk.gameEventManager.notifyGame(
|
|
@@ -2816,7 +2854,7 @@ var HeartbeatManager = class extends WavedashManager {
|
|
|
2816
2854
|
this.sentDisconnectedEvent = false;
|
|
2817
2855
|
}
|
|
2818
2856
|
} catch (error) {
|
|
2819
|
-
|
|
2857
|
+
logger.error("Error testing connection:", error);
|
|
2820
2858
|
}
|
|
2821
2859
|
}
|
|
2822
2860
|
isCurrentlyConnected() {
|
|
@@ -2836,7 +2874,7 @@ var GameEventManager = class extends WavedashManager {
|
|
|
2836
2874
|
notifyGame(event, payload) {
|
|
2837
2875
|
if (!this.sdk.eventsReady) {
|
|
2838
2876
|
this.eventQueue.push({ event, payload });
|
|
2839
|
-
|
|
2877
|
+
logger.debug(`Queued event: ${event}`);
|
|
2840
2878
|
return;
|
|
2841
2879
|
}
|
|
2842
2880
|
if (!this.sdk.engineInstance) {
|
|
@@ -2854,7 +2892,7 @@ var GameEventManager = class extends WavedashManager {
|
|
|
2854
2892
|
data
|
|
2855
2893
|
);
|
|
2856
2894
|
} else {
|
|
2857
|
-
|
|
2895
|
+
logger.error("Engine instance not set. Dropping event:", event);
|
|
2858
2896
|
}
|
|
2859
2897
|
}
|
|
2860
2898
|
flushEventQueue() {
|
|
@@ -3097,43 +3135,6 @@ var FriendsManager = class extends WavedashManager {
|
|
|
3097
3135
|
}
|
|
3098
3136
|
};
|
|
3099
3137
|
|
|
3100
|
-
// src/utils/logger.ts
|
|
3101
|
-
var LOG_LEVEL = {
|
|
3102
|
-
DEBUG: 0,
|
|
3103
|
-
// Most verbose
|
|
3104
|
-
INFO: 1,
|
|
3105
|
-
WARN: 2,
|
|
3106
|
-
ERROR: 3
|
|
3107
|
-
};
|
|
3108
|
-
var WavedashLogger = class {
|
|
3109
|
-
constructor(logLevel = LOG_LEVEL.WARN) {
|
|
3110
|
-
this.logLevel = logLevel;
|
|
3111
|
-
}
|
|
3112
|
-
setLogLevel(level) {
|
|
3113
|
-
this.logLevel = level;
|
|
3114
|
-
}
|
|
3115
|
-
debug(message, ...args) {
|
|
3116
|
-
if (this.logLevel <= LOG_LEVEL.DEBUG) {
|
|
3117
|
-
console.log(`[WavedashJS] ${message}`, ...args);
|
|
3118
|
-
}
|
|
3119
|
-
}
|
|
3120
|
-
info(message, ...args) {
|
|
3121
|
-
if (this.logLevel <= LOG_LEVEL.INFO) {
|
|
3122
|
-
console.log(`[WavedashJS] ${message}`, ...args);
|
|
3123
|
-
}
|
|
3124
|
-
}
|
|
3125
|
-
warn(message, ...args) {
|
|
3126
|
-
if (this.logLevel <= LOG_LEVEL.WARN) {
|
|
3127
|
-
console.warn(`[WavedashJS] ${message}`, ...args);
|
|
3128
|
-
}
|
|
3129
|
-
}
|
|
3130
|
-
error(message, ...args) {
|
|
3131
|
-
if (this.logLevel <= LOG_LEVEL.ERROR) {
|
|
3132
|
-
console.error(`[WavedashJS] ${message}`, ...args);
|
|
3133
|
-
}
|
|
3134
|
-
}
|
|
3135
|
-
};
|
|
3136
|
-
|
|
3137
3138
|
// src/utils/parentOrigin.ts
|
|
3138
3139
|
var _parentOrigin = "";
|
|
3139
3140
|
function setParentOrigin(origin) {
|
|
@@ -3228,6 +3229,69 @@ var IFrameMessenger = class {
|
|
|
3228
3229
|
}
|
|
3229
3230
|
};
|
|
3230
3231
|
|
|
3232
|
+
// src/utils/swMessenger.ts
|
|
3233
|
+
var SwMessenger = class {
|
|
3234
|
+
constructor() {
|
|
3235
|
+
this.handleMessage = (event) => {
|
|
3236
|
+
const data = event.data;
|
|
3237
|
+
const type = data?.type;
|
|
3238
|
+
if (!type) return;
|
|
3239
|
+
const set = this.listeners.get(type);
|
|
3240
|
+
if (!set || set.size === 0) return;
|
|
3241
|
+
const port = event.ports?.[0];
|
|
3242
|
+
const reply = (message) => {
|
|
3243
|
+
if (port) {
|
|
3244
|
+
try {
|
|
3245
|
+
port.postMessage(message);
|
|
3246
|
+
} catch (err) {
|
|
3247
|
+
logger.warn("Failed to reply to SW via port", err);
|
|
3248
|
+
}
|
|
3249
|
+
}
|
|
3250
|
+
this.postToServiceWorker(message);
|
|
3251
|
+
};
|
|
3252
|
+
for (const listener of set) listener(data?.payload, reply);
|
|
3253
|
+
};
|
|
3254
|
+
this.listeners = /* @__PURE__ */ new Map();
|
|
3255
|
+
if (typeof navigator !== "undefined" && navigator.serviceWorker) {
|
|
3256
|
+
navigator.serviceWorker.addEventListener("message", this.handleMessage);
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
/**
|
|
3260
|
+
* Register a handler for an incoming message type from the SW. The handler
|
|
3261
|
+
* receives the message payload and a `reply` function that routes the
|
|
3262
|
+
* response back via the transferred MessagePort when present, falling back
|
|
3263
|
+
* to a controller postMessage otherwise.
|
|
3264
|
+
*/
|
|
3265
|
+
addEventListener(type, listener) {
|
|
3266
|
+
let set = this.listeners.get(type);
|
|
3267
|
+
if (!set) {
|
|
3268
|
+
set = /* @__PURE__ */ new Set();
|
|
3269
|
+
this.listeners.set(type, set);
|
|
3270
|
+
}
|
|
3271
|
+
set.add(listener);
|
|
3272
|
+
}
|
|
3273
|
+
removeEventListener(type, listener) {
|
|
3274
|
+
this.listeners.get(type)?.delete(listener);
|
|
3275
|
+
}
|
|
3276
|
+
/**
|
|
3277
|
+
* Fire-and-forget message to the active service worker controller. No-op
|
|
3278
|
+
* when no SW is controlling the page (first load before activation, or
|
|
3279
|
+
* environments without SW support).
|
|
3280
|
+
*/
|
|
3281
|
+
postToServiceWorker(message) {
|
|
3282
|
+
if (typeof navigator === "undefined" || !navigator.serviceWorker) {
|
|
3283
|
+
return false;
|
|
3284
|
+
}
|
|
3285
|
+
try {
|
|
3286
|
+
navigator.serviceWorker.controller?.postMessage(message);
|
|
3287
|
+
return true;
|
|
3288
|
+
} catch (err) {
|
|
3289
|
+
logger.warn("Failed to post message to service worker", err);
|
|
3290
|
+
return false;
|
|
3291
|
+
}
|
|
3292
|
+
}
|
|
3293
|
+
};
|
|
3294
|
+
|
|
3231
3295
|
// src/index.ts
|
|
3232
3296
|
import { IFRAME_MESSAGE_TYPE as IFRAME_MESSAGE_TYPE5, UrlParams } from "@wvdsh/api";
|
|
3233
3297
|
|
|
@@ -3378,7 +3442,7 @@ var WavedashSDK = class extends EventTarget {
|
|
|
3378
3442
|
this.iframeMessenger = iframeMessenger;
|
|
3379
3443
|
this.ugcHost = sdkConfig.ugcHost;
|
|
3380
3444
|
this.uploadsHost = sdkConfig.uploadsHost;
|
|
3381
|
-
this.
|
|
3445
|
+
this.swMessenger = new SwMessenger();
|
|
3382
3446
|
this.p2pManager = new P2PManager(this);
|
|
3383
3447
|
this.lobbyManager = new LobbyManager(this);
|
|
3384
3448
|
this.statsManager = new StatsManager(this);
|
|
@@ -3411,10 +3475,11 @@ var WavedashSDK = class extends EventTarget {
|
|
|
3411
3475
|
}
|
|
3412
3476
|
]);
|
|
3413
3477
|
this.setupSessionEndListeners();
|
|
3478
|
+
this.setupSwCredsListener();
|
|
3414
3479
|
this.launchParams = sdkConfig.launchParams ?? {};
|
|
3415
3480
|
this.setupWarningTimeout = setTimeout(() => {
|
|
3416
3481
|
this.setupWarningTimeout = null;
|
|
3417
|
-
|
|
3482
|
+
logger.warn(
|
|
3418
3483
|
"Wavedash.init(), Wavedash.loadComplete(), or Wavedash.updateLoadProgressZeroToOne() not called yet"
|
|
3419
3484
|
);
|
|
3420
3485
|
}, 1e4);
|
|
@@ -3437,24 +3502,24 @@ var WavedashSDK = class extends EventTarget {
|
|
|
3437
3502
|
init(config) {
|
|
3438
3503
|
this.loadComplete();
|
|
3439
3504
|
if (this._initialized) {
|
|
3440
|
-
|
|
3505
|
+
logger.warn("init called twice! Already initialized, skipping init");
|
|
3441
3506
|
return false;
|
|
3442
3507
|
}
|
|
3443
3508
|
if (typeof config === "string") {
|
|
3444
3509
|
try {
|
|
3445
3510
|
config = JSON.parse(config);
|
|
3446
3511
|
} catch (error) {
|
|
3447
|
-
|
|
3512
|
+
logger.error("Initialized with invalid config:", error);
|
|
3448
3513
|
return false;
|
|
3449
3514
|
}
|
|
3450
3515
|
}
|
|
3451
3516
|
this.config = config ?? {};
|
|
3452
3517
|
this._initialized = true;
|
|
3453
|
-
|
|
3518
|
+
logger.setLogLevel(
|
|
3454
3519
|
this.config.debug ? LOG_LEVEL.DEBUG : LOG_LEVEL.WARN
|
|
3455
3520
|
);
|
|
3456
3521
|
this.p2pManager.init(this.config.p2p);
|
|
3457
|
-
|
|
3522
|
+
logger.debug("Initialized with config:", this.config);
|
|
3458
3523
|
if (!this.config.deferEvents) {
|
|
3459
3524
|
this.readyForEvents();
|
|
3460
3525
|
}
|
|
@@ -3601,13 +3666,13 @@ var WavedashSDK = class extends EventTarget {
|
|
|
3601
3666
|
* @returns The user's JWT signed by the Wavedash backend
|
|
3602
3667
|
*/
|
|
3603
3668
|
async getUserJwt() {
|
|
3604
|
-
|
|
3669
|
+
logger.debug("getUserJwt");
|
|
3605
3670
|
try {
|
|
3606
3671
|
const data = await this.ensureGameplayJwt();
|
|
3607
3672
|
return this.formatResponse({ success: true, data });
|
|
3608
3673
|
} catch (error) {
|
|
3609
3674
|
const message = error instanceof Error ? error.message : String(error);
|
|
3610
|
-
|
|
3675
|
+
logger.error("getUserJwt", message);
|
|
3611
3676
|
return this.formatResponse({ success: false, data: null, message });
|
|
3612
3677
|
}
|
|
3613
3678
|
}
|
|
@@ -4251,29 +4316,29 @@ var WavedashSDK = class extends EventTarget {
|
|
|
4251
4316
|
// require config or produce events (lobby join/create, P2P).
|
|
4252
4317
|
ensureInit() {
|
|
4253
4318
|
if (!this._initialized) {
|
|
4254
|
-
|
|
4319
|
+
logger.error("SDK not initialized. Call WavedashJS.init first.");
|
|
4255
4320
|
throw new Error("SDK not initialized");
|
|
4256
4321
|
}
|
|
4257
4322
|
}
|
|
4258
4323
|
async apiCall(manager, method, argSpecs, ...args) {
|
|
4259
|
-
|
|
4324
|
+
logger.debug(method, ...args);
|
|
4260
4325
|
try {
|
|
4261
4326
|
validateArgs(method, argSpecs, args);
|
|
4262
4327
|
const data = await manager[method](...args);
|
|
4263
4328
|
return this.formatResponse({ success: true, data });
|
|
4264
4329
|
} catch (error) {
|
|
4265
4330
|
const message = error instanceof Error ? error.message : String(error);
|
|
4266
|
-
|
|
4331
|
+
logger.error(method, message);
|
|
4267
4332
|
return this.formatResponse({ success: false, data: null, message });
|
|
4268
4333
|
}
|
|
4269
4334
|
}
|
|
4270
4335
|
apiCallSync(target, method, argSpecs, ...args) {
|
|
4271
|
-
|
|
4336
|
+
logger.debug(method, ...args);
|
|
4272
4337
|
try {
|
|
4273
4338
|
validateArgs(method, argSpecs, args);
|
|
4274
4339
|
} catch (error) {
|
|
4275
4340
|
const message = error instanceof Error ? error.message : String(error);
|
|
4276
|
-
|
|
4341
|
+
logger.error(method, message);
|
|
4277
4342
|
throw error;
|
|
4278
4343
|
}
|
|
4279
4344
|
return this.formatResponse(target[method](...args));
|
|
@@ -4324,6 +4389,10 @@ var WavedashSDK = class extends EventTarget {
|
|
|
4324
4389
|
iframeMessenger.postToParent(IFRAME_MESSAGE_TYPE5.GAMEPLAY_JWT_READY, {
|
|
4325
4390
|
gameplayJwt: this.gameplayJwt
|
|
4326
4391
|
});
|
|
4392
|
+
this.swMessenger.postToServiceWorker({
|
|
4393
|
+
type: "embed.jwt-update",
|
|
4394
|
+
payload: { gameplayJwt: this.gameplayJwt }
|
|
4395
|
+
});
|
|
4327
4396
|
return this.gameplayJwt;
|
|
4328
4397
|
})().finally(() => {
|
|
4329
4398
|
if (this.gameplayJwtPromise === promise) {
|
|
@@ -4357,6 +4426,30 @@ var WavedashSDK = class extends EventTarget {
|
|
|
4357
4426
|
() => this.destroy()
|
|
4358
4427
|
);
|
|
4359
4428
|
}
|
|
4429
|
+
/**
|
|
4430
|
+
* Respond to the service worker's `embed.creds-request` with the SDK's
|
|
4431
|
+
* current gameplay JWT. The SW asks when it wakes from termination with no
|
|
4432
|
+
* in-memory or IDB credentials (e.g. Safari ITP storage decay) — we're the
|
|
4433
|
+
* fastest live source. JWT only; sessionToken is owned by the SW + cookies.
|
|
4434
|
+
*/
|
|
4435
|
+
setupSwCredsListener() {
|
|
4436
|
+
this.swMessenger.addEventListener(
|
|
4437
|
+
"embed.creds-request",
|
|
4438
|
+
async (_payload, reply) => {
|
|
4439
|
+
let jwt;
|
|
4440
|
+
try {
|
|
4441
|
+
jwt = await this.ensureGameplayJwt();
|
|
4442
|
+
} catch (err) {
|
|
4443
|
+
logger.warn("Failed to resolve JWT for creds-request", err);
|
|
4444
|
+
return;
|
|
4445
|
+
}
|
|
4446
|
+
reply({
|
|
4447
|
+
type: "embed.creds-response",
|
|
4448
|
+
payload: { gameplayJwt: jwt }
|
|
4449
|
+
});
|
|
4450
|
+
}
|
|
4451
|
+
);
|
|
4452
|
+
}
|
|
4360
4453
|
};
|
|
4361
4454
|
function setupWavedashSDK() {
|
|
4362
4455
|
const existing = window.Wavedash;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wvdsh/sdk-js",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Wavedash JavaScript SDK",
|
|
6
6
|
"main": "./dist/client.js",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@wvdsh/api": "^0.1.16",
|
|
53
|
-
"convex": "^1.
|
|
53
|
+
"convex": "^1.38.0",
|
|
54
54
|
"lodash.throttle": "^4.1.1"
|
|
55
55
|
}
|
|
56
56
|
}
|