@playcademy/sdk 0.1.14 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -1
- package/dist/index.d.ts +885 -339
- package/dist/index.js +400 -112
- package/dist/types.d.ts +184 -16
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -281,6 +281,333 @@ function isInIframe() {
|
|
|
281
281
|
}
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
+
// src/core/connection/monitor.ts
|
|
285
|
+
class ConnectionMonitor {
|
|
286
|
+
state = "online";
|
|
287
|
+
callbacks = new Set;
|
|
288
|
+
heartbeatInterval;
|
|
289
|
+
consecutiveFailures = 0;
|
|
290
|
+
isMonitoring = false;
|
|
291
|
+
config;
|
|
292
|
+
constructor(config) {
|
|
293
|
+
this.config = {
|
|
294
|
+
baseUrl: config.baseUrl,
|
|
295
|
+
heartbeatInterval: config.heartbeatInterval ?? 1e4,
|
|
296
|
+
heartbeatTimeout: config.heartbeatTimeout ?? 5000,
|
|
297
|
+
failureThreshold: config.failureThreshold ?? 2,
|
|
298
|
+
enableHeartbeat: config.enableHeartbeat ?? true,
|
|
299
|
+
enableOfflineEvents: config.enableOfflineEvents ?? true
|
|
300
|
+
};
|
|
301
|
+
this._detectInitialState();
|
|
302
|
+
}
|
|
303
|
+
start() {
|
|
304
|
+
if (this.isMonitoring)
|
|
305
|
+
return;
|
|
306
|
+
this.isMonitoring = true;
|
|
307
|
+
if (this.config.enableOfflineEvents && typeof window !== "undefined") {
|
|
308
|
+
window.addEventListener("online", this._handleOnline);
|
|
309
|
+
window.addEventListener("offline", this._handleOffline);
|
|
310
|
+
}
|
|
311
|
+
if (this.config.enableHeartbeat) {
|
|
312
|
+
this._startHeartbeat();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
stop() {
|
|
316
|
+
if (!this.isMonitoring)
|
|
317
|
+
return;
|
|
318
|
+
this.isMonitoring = false;
|
|
319
|
+
if (typeof window !== "undefined") {
|
|
320
|
+
window.removeEventListener("online", this._handleOnline);
|
|
321
|
+
window.removeEventListener("offline", this._handleOffline);
|
|
322
|
+
}
|
|
323
|
+
if (this.heartbeatInterval) {
|
|
324
|
+
clearInterval(this.heartbeatInterval);
|
|
325
|
+
this.heartbeatInterval = undefined;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
onChange(callback) {
|
|
329
|
+
this.callbacks.add(callback);
|
|
330
|
+
return () => this.callbacks.delete(callback);
|
|
331
|
+
}
|
|
332
|
+
getState() {
|
|
333
|
+
return this.state;
|
|
334
|
+
}
|
|
335
|
+
async checkNow() {
|
|
336
|
+
await this._performHeartbeat();
|
|
337
|
+
return this.state;
|
|
338
|
+
}
|
|
339
|
+
reportRequestFailure(error) {
|
|
340
|
+
const isNetworkError = error instanceof TypeError || error instanceof Error && error.message.includes("fetch");
|
|
341
|
+
if (!isNetworkError)
|
|
342
|
+
return;
|
|
343
|
+
this.consecutiveFailures++;
|
|
344
|
+
if (this.consecutiveFailures >= this.config.failureThreshold) {
|
|
345
|
+
this._setState("degraded", "Multiple consecutive request failures");
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
reportRequestSuccess() {
|
|
349
|
+
if (this.consecutiveFailures > 0) {
|
|
350
|
+
this.consecutiveFailures = 0;
|
|
351
|
+
if (this.state === "degraded") {
|
|
352
|
+
this._setState("online", "Requests succeeding again");
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
_detectInitialState() {
|
|
357
|
+
if (typeof navigator !== "undefined" && !navigator.onLine) {
|
|
358
|
+
this.state = "offline";
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
_handleOnline = () => {
|
|
362
|
+
this.consecutiveFailures = 0;
|
|
363
|
+
this._setState("online", "Browser online event");
|
|
364
|
+
};
|
|
365
|
+
_handleOffline = () => {
|
|
366
|
+
this._setState("offline", "Browser offline event");
|
|
367
|
+
};
|
|
368
|
+
_startHeartbeat() {
|
|
369
|
+
this._performHeartbeat();
|
|
370
|
+
this.heartbeatInterval = setInterval(() => {
|
|
371
|
+
this._performHeartbeat();
|
|
372
|
+
}, this.config.heartbeatInterval);
|
|
373
|
+
}
|
|
374
|
+
async _performHeartbeat() {
|
|
375
|
+
if (typeof navigator !== "undefined" && !navigator.onLine) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
try {
|
|
379
|
+
const controller = new AbortController;
|
|
380
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.heartbeatTimeout);
|
|
381
|
+
const response = await fetch(`${this.config.baseUrl}/ping`, {
|
|
382
|
+
method: "GET",
|
|
383
|
+
signal: controller.signal,
|
|
384
|
+
cache: "no-store"
|
|
385
|
+
});
|
|
386
|
+
clearTimeout(timeoutId);
|
|
387
|
+
if (response.ok) {
|
|
388
|
+
this.consecutiveFailures = 0;
|
|
389
|
+
if (this.state !== "online") {
|
|
390
|
+
this._setState("online", "Heartbeat successful");
|
|
391
|
+
}
|
|
392
|
+
} else {
|
|
393
|
+
this._handleHeartbeatFailure("Heartbeat returned non-OK status");
|
|
394
|
+
}
|
|
395
|
+
} catch (error) {
|
|
396
|
+
this._handleHeartbeatFailure(error instanceof Error ? error.message : "Heartbeat failed");
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
_handleHeartbeatFailure(reason) {
|
|
400
|
+
this.consecutiveFailures++;
|
|
401
|
+
if (this.consecutiveFailures >= this.config.failureThreshold) {
|
|
402
|
+
if (typeof navigator !== "undefined" && !navigator.onLine) {
|
|
403
|
+
this._setState("offline", reason);
|
|
404
|
+
} else {
|
|
405
|
+
this._setState("degraded", reason);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
_setState(newState, reason) {
|
|
410
|
+
if (this.state === newState)
|
|
411
|
+
return;
|
|
412
|
+
const oldState = this.state;
|
|
413
|
+
this.state = newState;
|
|
414
|
+
console.debug(`[ConnectionMonitor] ${oldState} → ${newState}: ${reason}`);
|
|
415
|
+
this.callbacks.forEach((callback) => {
|
|
416
|
+
try {
|
|
417
|
+
callback(newState, reason);
|
|
418
|
+
} catch (error) {
|
|
419
|
+
console.error("[ConnectionMonitor] Error in callback:", error);
|
|
420
|
+
}
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// src/messaging.ts
|
|
426
|
+
class PlaycademyMessaging {
|
|
427
|
+
listeners = new Map;
|
|
428
|
+
send(type, payload, options) {
|
|
429
|
+
if (options?.target) {
|
|
430
|
+
this.sendViaPostMessage(type, payload, options.target, options.origin || "*");
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const context = this.getMessagingContext(type);
|
|
434
|
+
if (context.shouldUsePostMessage) {
|
|
435
|
+
this.sendViaPostMessage(type, payload, context.target, context.origin);
|
|
436
|
+
} else {
|
|
437
|
+
this.sendViaCustomEvent(type, payload);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
listen(type, handler) {
|
|
441
|
+
const postMessageListener = (event) => {
|
|
442
|
+
const messageEvent = event;
|
|
443
|
+
if (messageEvent.data?.type === type) {
|
|
444
|
+
handler(messageEvent.data.payload || messageEvent.data);
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
const customEventListener = (event) => {
|
|
448
|
+
handler(event.detail);
|
|
449
|
+
};
|
|
450
|
+
if (!this.listeners.has(type)) {
|
|
451
|
+
this.listeners.set(type, new Map);
|
|
452
|
+
}
|
|
453
|
+
const listenerMap = this.listeners.get(type);
|
|
454
|
+
listenerMap.set(handler, {
|
|
455
|
+
postMessage: postMessageListener,
|
|
456
|
+
customEvent: customEventListener
|
|
457
|
+
});
|
|
458
|
+
window.addEventListener("message", postMessageListener);
|
|
459
|
+
window.addEventListener(type, customEventListener);
|
|
460
|
+
}
|
|
461
|
+
unlisten(type, handler) {
|
|
462
|
+
const typeListeners = this.listeners.get(type);
|
|
463
|
+
if (!typeListeners || !typeListeners.has(handler)) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
const listeners = typeListeners.get(handler);
|
|
467
|
+
window.removeEventListener("message", listeners.postMessage);
|
|
468
|
+
window.removeEventListener(type, listeners.customEvent);
|
|
469
|
+
typeListeners.delete(handler);
|
|
470
|
+
if (typeListeners.size === 0) {
|
|
471
|
+
this.listeners.delete(type);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
getMessagingContext(eventType) {
|
|
475
|
+
const isIframe = typeof window !== "undefined" && window.self !== window.top;
|
|
476
|
+
const iframeToParentEvents = [
|
|
477
|
+
"PLAYCADEMY_READY" /* READY */,
|
|
478
|
+
"PLAYCADEMY_EXIT" /* EXIT */,
|
|
479
|
+
"PLAYCADEMY_TELEMETRY" /* TELEMETRY */,
|
|
480
|
+
"PLAYCADEMY_KEY_EVENT" /* KEY_EVENT */,
|
|
481
|
+
"PLAYCADEMY_DISPLAY_ALERT" /* DISPLAY_ALERT */
|
|
482
|
+
];
|
|
483
|
+
const shouldUsePostMessage = isIframe && iframeToParentEvents.includes(eventType);
|
|
484
|
+
return {
|
|
485
|
+
shouldUsePostMessage,
|
|
486
|
+
target: shouldUsePostMessage ? window.parent : undefined,
|
|
487
|
+
origin: "*"
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
sendViaPostMessage(type, payload, target = window.parent, origin = "*") {
|
|
491
|
+
const messageData = { type };
|
|
492
|
+
if (payload !== undefined) {
|
|
493
|
+
messageData.payload = payload;
|
|
494
|
+
}
|
|
495
|
+
target.postMessage(messageData, origin);
|
|
496
|
+
}
|
|
497
|
+
sendViaCustomEvent(type, payload) {
|
|
498
|
+
window.dispatchEvent(new CustomEvent(type, { detail: payload }));
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
var MessageEvents, messaging;
|
|
502
|
+
var init_messaging = __esm(() => {
|
|
503
|
+
((MessageEvents2) => {
|
|
504
|
+
MessageEvents2["INIT"] = "PLAYCADEMY_INIT";
|
|
505
|
+
MessageEvents2["TOKEN_REFRESH"] = "PLAYCADEMY_TOKEN_REFRESH";
|
|
506
|
+
MessageEvents2["PAUSE"] = "PLAYCADEMY_PAUSE";
|
|
507
|
+
MessageEvents2["RESUME"] = "PLAYCADEMY_RESUME";
|
|
508
|
+
MessageEvents2["FORCE_EXIT"] = "PLAYCADEMY_FORCE_EXIT";
|
|
509
|
+
MessageEvents2["OVERLAY"] = "PLAYCADEMY_OVERLAY";
|
|
510
|
+
MessageEvents2["CONNECTION_STATE"] = "PLAYCADEMY_CONNECTION_STATE";
|
|
511
|
+
MessageEvents2["READY"] = "PLAYCADEMY_READY";
|
|
512
|
+
MessageEvents2["EXIT"] = "PLAYCADEMY_EXIT";
|
|
513
|
+
MessageEvents2["TELEMETRY"] = "PLAYCADEMY_TELEMETRY";
|
|
514
|
+
MessageEvents2["KEY_EVENT"] = "PLAYCADEMY_KEY_EVENT";
|
|
515
|
+
MessageEvents2["DISPLAY_ALERT"] = "PLAYCADEMY_DISPLAY_ALERT";
|
|
516
|
+
MessageEvents2["AUTH_STATE_CHANGE"] = "PLAYCADEMY_AUTH_STATE_CHANGE";
|
|
517
|
+
MessageEvents2["AUTH_CALLBACK"] = "PLAYCADEMY_AUTH_CALLBACK";
|
|
518
|
+
})(MessageEvents ||= {});
|
|
519
|
+
messaging = new PlaycademyMessaging;
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
// src/core/connection/utils.ts
|
|
523
|
+
function createDisplayAlert(authContext) {
|
|
524
|
+
return (message, options) => {
|
|
525
|
+
if (authContext?.isInIframe && typeof window !== "undefined" && window.parent !== window) {
|
|
526
|
+
window.parent.postMessage({
|
|
527
|
+
type: "PLAYCADEMY_DISPLAY_ALERT",
|
|
528
|
+
message,
|
|
529
|
+
options
|
|
530
|
+
}, "*");
|
|
531
|
+
} else {
|
|
532
|
+
const prefix = options?.type === "error" ? "❌" : options?.type === "warning" ? "⚠️" : "ℹ️";
|
|
533
|
+
console.log(`${prefix} ${message}`);
|
|
534
|
+
}
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// src/core/connection/manager.ts
|
|
539
|
+
class ConnectionManager {
|
|
540
|
+
monitor;
|
|
541
|
+
authContext;
|
|
542
|
+
disconnectHandler;
|
|
543
|
+
connectionChangeCallback;
|
|
544
|
+
currentState = "online";
|
|
545
|
+
additionalDisconnectHandlers = new Set;
|
|
546
|
+
constructor(config) {
|
|
547
|
+
this.authContext = config.authContext;
|
|
548
|
+
this.disconnectHandler = config.onDisconnect;
|
|
549
|
+
this.connectionChangeCallback = config.onConnectionChange;
|
|
550
|
+
if (config.authContext?.isInIframe) {
|
|
551
|
+
this._setupPlatformListener();
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
getState() {
|
|
555
|
+
return this.monitor?.getState() ?? this.currentState;
|
|
556
|
+
}
|
|
557
|
+
async checkNow() {
|
|
558
|
+
if (!this.monitor) {
|
|
559
|
+
return this.currentState;
|
|
560
|
+
}
|
|
561
|
+
return await this.monitor.checkNow();
|
|
562
|
+
}
|
|
563
|
+
reportRequestSuccess() {
|
|
564
|
+
this.monitor?.reportRequestSuccess();
|
|
565
|
+
}
|
|
566
|
+
reportRequestFailure(error) {
|
|
567
|
+
this.monitor?.reportRequestFailure(error);
|
|
568
|
+
}
|
|
569
|
+
onDisconnect(callback) {
|
|
570
|
+
this.additionalDisconnectHandlers.add(callback);
|
|
571
|
+
return () => {
|
|
572
|
+
this.additionalDisconnectHandlers.delete(callback);
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
stop() {
|
|
576
|
+
this.monitor?.stop();
|
|
577
|
+
}
|
|
578
|
+
_setupPlatformListener() {
|
|
579
|
+
messaging.listen("PLAYCADEMY_CONNECTION_STATE" /* CONNECTION_STATE */, ({ state, reason }) => {
|
|
580
|
+
this.currentState = state;
|
|
581
|
+
this._handleConnectionChange(state, reason);
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
_handleConnectionChange(state, reason) {
|
|
585
|
+
this.connectionChangeCallback?.(state, reason);
|
|
586
|
+
if (state === "offline" || state === "degraded") {
|
|
587
|
+
const context = {
|
|
588
|
+
state,
|
|
589
|
+
reason,
|
|
590
|
+
timestamp: Date.now(),
|
|
591
|
+
displayAlert: createDisplayAlert(this.authContext)
|
|
592
|
+
};
|
|
593
|
+
if (this.disconnectHandler) {
|
|
594
|
+
this.disconnectHandler(context);
|
|
595
|
+
}
|
|
596
|
+
this.additionalDisconnectHandlers.forEach((handler) => {
|
|
597
|
+
handler(context);
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
var init_manager = __esm(() => {
|
|
603
|
+
init_messaging();
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
// src/core/connection/index.ts
|
|
607
|
+
var init_connection = __esm(() => {
|
|
608
|
+
init_manager();
|
|
609
|
+
});
|
|
610
|
+
|
|
284
611
|
// src/core/errors.ts
|
|
285
612
|
function extractApiErrorInfo(error) {
|
|
286
613
|
if (!(error instanceof ApiError)) {
|
|
@@ -664,100 +991,6 @@ var init_identity = __esm(() => {
|
|
|
664
991
|
init_login();
|
|
665
992
|
});
|
|
666
993
|
|
|
667
|
-
// src/messaging.ts
|
|
668
|
-
class PlaycademyMessaging {
|
|
669
|
-
listeners = new Map;
|
|
670
|
-
send(type, payload, options) {
|
|
671
|
-
if (options?.target) {
|
|
672
|
-
this.sendViaPostMessage(type, payload, options.target, options.origin || "*");
|
|
673
|
-
return;
|
|
674
|
-
}
|
|
675
|
-
const context = this.getMessagingContext(type);
|
|
676
|
-
if (context.shouldUsePostMessage) {
|
|
677
|
-
this.sendViaPostMessage(type, payload, context.target, context.origin);
|
|
678
|
-
} else {
|
|
679
|
-
this.sendViaCustomEvent(type, payload);
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
listen(type, handler) {
|
|
683
|
-
const postMessageListener = (event) => {
|
|
684
|
-
const messageEvent = event;
|
|
685
|
-
if (messageEvent.data?.type === type) {
|
|
686
|
-
handler(messageEvent.data.payload || messageEvent.data);
|
|
687
|
-
}
|
|
688
|
-
};
|
|
689
|
-
const customEventListener = (event) => {
|
|
690
|
-
handler(event.detail);
|
|
691
|
-
};
|
|
692
|
-
if (!this.listeners.has(type)) {
|
|
693
|
-
this.listeners.set(type, new Map);
|
|
694
|
-
}
|
|
695
|
-
const listenerMap = this.listeners.get(type);
|
|
696
|
-
listenerMap.set(handler, {
|
|
697
|
-
postMessage: postMessageListener,
|
|
698
|
-
customEvent: customEventListener
|
|
699
|
-
});
|
|
700
|
-
window.addEventListener("message", postMessageListener);
|
|
701
|
-
window.addEventListener(type, customEventListener);
|
|
702
|
-
}
|
|
703
|
-
unlisten(type, handler) {
|
|
704
|
-
const typeListeners = this.listeners.get(type);
|
|
705
|
-
if (!typeListeners || !typeListeners.has(handler)) {
|
|
706
|
-
return;
|
|
707
|
-
}
|
|
708
|
-
const listeners = typeListeners.get(handler);
|
|
709
|
-
window.removeEventListener("message", listeners.postMessage);
|
|
710
|
-
window.removeEventListener(type, listeners.customEvent);
|
|
711
|
-
typeListeners.delete(handler);
|
|
712
|
-
if (typeListeners.size === 0) {
|
|
713
|
-
this.listeners.delete(type);
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
getMessagingContext(eventType) {
|
|
717
|
-
const isIframe = typeof window !== "undefined" && window.self !== window.top;
|
|
718
|
-
const iframeToParentEvents = [
|
|
719
|
-
"PLAYCADEMY_READY" /* READY */,
|
|
720
|
-
"PLAYCADEMY_EXIT" /* EXIT */,
|
|
721
|
-
"PLAYCADEMY_TELEMETRY" /* TELEMETRY */,
|
|
722
|
-
"PLAYCADEMY_KEY_EVENT" /* KEY_EVENT */
|
|
723
|
-
];
|
|
724
|
-
const shouldUsePostMessage = isIframe && iframeToParentEvents.includes(eventType);
|
|
725
|
-
return {
|
|
726
|
-
shouldUsePostMessage,
|
|
727
|
-
target: shouldUsePostMessage ? window.parent : undefined,
|
|
728
|
-
origin: "*"
|
|
729
|
-
};
|
|
730
|
-
}
|
|
731
|
-
sendViaPostMessage(type, payload, target = window.parent, origin = "*") {
|
|
732
|
-
const messageData = { type };
|
|
733
|
-
if (payload !== undefined) {
|
|
734
|
-
messageData.payload = payload;
|
|
735
|
-
}
|
|
736
|
-
target.postMessage(messageData, origin);
|
|
737
|
-
}
|
|
738
|
-
sendViaCustomEvent(type, payload) {
|
|
739
|
-
window.dispatchEvent(new CustomEvent(type, { detail: payload }));
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
var MessageEvents, messaging;
|
|
743
|
-
var init_messaging = __esm(() => {
|
|
744
|
-
((MessageEvents2) => {
|
|
745
|
-
MessageEvents2["INIT"] = "PLAYCADEMY_INIT";
|
|
746
|
-
MessageEvents2["TOKEN_REFRESH"] = "PLAYCADEMY_TOKEN_REFRESH";
|
|
747
|
-
MessageEvents2["PAUSE"] = "PLAYCADEMY_PAUSE";
|
|
748
|
-
MessageEvents2["RESUME"] = "PLAYCADEMY_RESUME";
|
|
749
|
-
MessageEvents2["FORCE_EXIT"] = "PLAYCADEMY_FORCE_EXIT";
|
|
750
|
-
MessageEvents2["OVERLAY"] = "PLAYCADEMY_OVERLAY";
|
|
751
|
-
MessageEvents2["READY"] = "PLAYCADEMY_READY";
|
|
752
|
-
MessageEvents2["EXIT"] = "PLAYCADEMY_EXIT";
|
|
753
|
-
MessageEvents2["TELEMETRY"] = "PLAYCADEMY_TELEMETRY";
|
|
754
|
-
MessageEvents2["KEY_EVENT"] = "PLAYCADEMY_KEY_EVENT";
|
|
755
|
-
MessageEvents2["AUTH_STATE_CHANGE"] = "PLAYCADEMY_AUTH_STATE_CHANGE";
|
|
756
|
-
MessageEvents2["AUTH_CALLBACK"] = "PLAYCADEMY_AUTH_CALLBACK";
|
|
757
|
-
})(MessageEvents ||= {});
|
|
758
|
-
messaging = new PlaycademyMessaging;
|
|
759
|
-
});
|
|
760
|
-
|
|
761
994
|
// src/core/namespaces/runtime.ts
|
|
762
995
|
function createRuntimeNamespace(client) {
|
|
763
996
|
const eventListeners = new Map;
|
|
@@ -2593,7 +2826,7 @@ async function waitForPlaycademyInit(allowedParentOrigins) {
|
|
|
2593
2826
|
});
|
|
2594
2827
|
}
|
|
2595
2828
|
function createStandaloneConfig() {
|
|
2596
|
-
console.
|
|
2829
|
+
console.debug("[Playcademy SDK] Standalone mode detected, creating mock context for sandbox development");
|
|
2597
2830
|
const mockConfig = {
|
|
2598
2831
|
baseUrl: "http://localhost:4321",
|
|
2599
2832
|
gameUrl: window.location.origin,
|
|
@@ -2618,7 +2851,9 @@ async function init(options) {
|
|
|
2618
2851
|
gameUrl: config.gameUrl,
|
|
2619
2852
|
token: config.token,
|
|
2620
2853
|
gameId: config.gameId,
|
|
2621
|
-
autoStartSession: window.self !== window.top
|
|
2854
|
+
autoStartSession: window.self !== window.top,
|
|
2855
|
+
onDisconnect: options?.onDisconnect,
|
|
2856
|
+
enableConnectionMonitoring: options?.enableConnectionMonitoring
|
|
2622
2857
|
});
|
|
2623
2858
|
client["initPayload"] = config;
|
|
2624
2859
|
messaging.listen("PLAYCADEMY_TOKEN_REFRESH" /* TOKEN_REFRESH */, ({ token }) => client.setToken(token));
|
|
@@ -2687,6 +2922,7 @@ __export(exports_client, {
|
|
|
2687
2922
|
var PlaycademyClient;
|
|
2688
2923
|
var init_client = __esm(() => {
|
|
2689
2924
|
init_src();
|
|
2925
|
+
init_connection();
|
|
2690
2926
|
init_errors();
|
|
2691
2927
|
init_namespaces();
|
|
2692
2928
|
init_request();
|
|
@@ -2701,6 +2937,7 @@ var init_client = __esm(() => {
|
|
|
2701
2937
|
internalClientSessionId;
|
|
2702
2938
|
authContext;
|
|
2703
2939
|
initPayload;
|
|
2940
|
+
connectionManager;
|
|
2704
2941
|
constructor(config) {
|
|
2705
2942
|
this.baseUrl = config?.baseUrl?.endsWith("/api") ? config.baseUrl : `${config?.baseUrl}/api`;
|
|
2706
2943
|
this.gameUrl = config?.gameUrl;
|
|
@@ -2709,6 +2946,7 @@ var init_client = __esm(() => {
|
|
|
2709
2946
|
this.authStrategy = createAuthStrategy(config?.token ?? null, config?.tokenType);
|
|
2710
2947
|
this._detectAuthContext();
|
|
2711
2948
|
this._initializeInternalSession().catch(() => {});
|
|
2949
|
+
this._initializeConnectionMonitor();
|
|
2712
2950
|
}
|
|
2713
2951
|
getBaseUrl() {
|
|
2714
2952
|
const isRelative = this.baseUrl.startsWith("/");
|
|
@@ -2743,6 +2981,20 @@ var init_client = __esm(() => {
|
|
|
2743
2981
|
onAuthChange(callback) {
|
|
2744
2982
|
this.on("authChange", (payload) => callback(payload.token));
|
|
2745
2983
|
}
|
|
2984
|
+
onDisconnect(callback) {
|
|
2985
|
+
if (!this.connectionManager) {
|
|
2986
|
+
return () => {};
|
|
2987
|
+
}
|
|
2988
|
+
return this.connectionManager.onDisconnect(callback);
|
|
2989
|
+
}
|
|
2990
|
+
getConnectionState() {
|
|
2991
|
+
return this.connectionManager?.getState() ?? "unknown";
|
|
2992
|
+
}
|
|
2993
|
+
async checkConnection() {
|
|
2994
|
+
if (!this.connectionManager)
|
|
2995
|
+
return "unknown";
|
|
2996
|
+
return await this.connectionManager.checkNow();
|
|
2997
|
+
}
|
|
2746
2998
|
_setAuthContext(context) {
|
|
2747
2999
|
this.authContext = context;
|
|
2748
3000
|
}
|
|
@@ -2760,28 +3012,42 @@ var init_client = __esm(() => {
|
|
|
2760
3012
|
...options?.headers,
|
|
2761
3013
|
...this.authStrategy.getHeaders()
|
|
2762
3014
|
};
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
3015
|
+
try {
|
|
3016
|
+
const result = await request({
|
|
3017
|
+
path,
|
|
3018
|
+
method,
|
|
3019
|
+
body: options?.body,
|
|
3020
|
+
baseUrl: this.baseUrl,
|
|
3021
|
+
extraHeaders: effectiveHeaders,
|
|
3022
|
+
raw: options?.raw
|
|
3023
|
+
});
|
|
3024
|
+
this.connectionManager?.reportRequestSuccess();
|
|
3025
|
+
return result;
|
|
3026
|
+
} catch (error) {
|
|
3027
|
+
this.connectionManager?.reportRequestFailure(error);
|
|
3028
|
+
throw error;
|
|
3029
|
+
}
|
|
2771
3030
|
}
|
|
2772
3031
|
async requestGameBackend(path, method, body, headers, raw) {
|
|
2773
3032
|
const effectiveHeaders = {
|
|
2774
3033
|
...headers,
|
|
2775
3034
|
...this.authStrategy.getHeaders()
|
|
2776
3035
|
};
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
3036
|
+
try {
|
|
3037
|
+
const result = await request({
|
|
3038
|
+
path,
|
|
3039
|
+
method,
|
|
3040
|
+
body,
|
|
3041
|
+
baseUrl: this.getGameBackendUrl(),
|
|
3042
|
+
extraHeaders: effectiveHeaders,
|
|
3043
|
+
raw
|
|
3044
|
+
});
|
|
3045
|
+
this.connectionManager?.reportRequestSuccess();
|
|
3046
|
+
return result;
|
|
3047
|
+
} catch (error) {
|
|
3048
|
+
this.connectionManager?.reportRequestFailure(error);
|
|
3049
|
+
throw error;
|
|
3050
|
+
}
|
|
2785
3051
|
}
|
|
2786
3052
|
_ensureGameId() {
|
|
2787
3053
|
if (!this.gameId) {
|
|
@@ -2792,6 +3058,25 @@ var init_client = __esm(() => {
|
|
|
2792
3058
|
_detectAuthContext() {
|
|
2793
3059
|
this.authContext = { isInIframe: isInIframe() };
|
|
2794
3060
|
}
|
|
3061
|
+
_initializeConnectionMonitor() {
|
|
3062
|
+
if (typeof window === "undefined")
|
|
3063
|
+
return;
|
|
3064
|
+
const isEnabled = this.config.enableConnectionMonitoring ?? true;
|
|
3065
|
+
if (!isEnabled)
|
|
3066
|
+
return;
|
|
3067
|
+
try {
|
|
3068
|
+
this.connectionManager = new ConnectionManager({
|
|
3069
|
+
baseUrl: this.baseUrl,
|
|
3070
|
+
authContext: this.authContext,
|
|
3071
|
+
onDisconnect: this.config.onDisconnect,
|
|
3072
|
+
onConnectionChange: (state, reason) => {
|
|
3073
|
+
this.emit("connectionChange", { state, reason });
|
|
3074
|
+
}
|
|
3075
|
+
});
|
|
3076
|
+
} catch (error) {
|
|
3077
|
+
log.error("[Playcademy SDK] Failed to initialize connection manager:", { error });
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
2795
3080
|
async _initializeInternalSession() {
|
|
2796
3081
|
if (!this.gameId || this.internalClientSessionId)
|
|
2797
3082
|
return;
|
|
@@ -2842,6 +3127,7 @@ var init_client = __esm(() => {
|
|
|
2842
3127
|
// src/index.ts
|
|
2843
3128
|
init_client();
|
|
2844
3129
|
init_errors();
|
|
3130
|
+
init_connection();
|
|
2845
3131
|
init_messaging();
|
|
2846
3132
|
export {
|
|
2847
3133
|
messaging,
|
|
@@ -2849,5 +3135,7 @@ export {
|
|
|
2849
3135
|
PlaycademyError,
|
|
2850
3136
|
PlaycademyClient,
|
|
2851
3137
|
MessageEvents,
|
|
3138
|
+
ConnectionMonitor,
|
|
3139
|
+
ConnectionManager,
|
|
2852
3140
|
ApiError
|
|
2853
3141
|
};
|