@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/dist/index.d.ts CHANGED
@@ -1,12 +1,250 @@
1
- import * as _playcademy_realtime_server_types from '@playcademy/realtime/server/types';
1
+ import { AUTH_PROVIDER_IDS } from '@playcademy/constants';
2
2
  import { InferSelectModel } from 'drizzle-orm';
3
3
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
4
4
  import * as drizzle_zod from 'drizzle-zod';
5
5
  import { z } from 'zod';
6
+ import * as _playcademy_realtime_server_types from '@playcademy/realtime/server/types';
6
7
  import * as _playcademy_timeback_types from '@playcademy/timeback/types';
7
8
  import { OrganizationConfig, CourseConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig } from '@playcademy/timeback/types';
8
9
  import { SchemaInfo } from '@playcademy/cloudflare';
9
- import { AUTH_PROVIDER_IDS } from '@playcademy/constants';
10
+
11
+ /**
12
+ * Base error class for Cademy SDK specific errors.
13
+ */
14
+ declare class PlaycademyError extends Error {
15
+ constructor(message: string);
16
+ }
17
+ declare class ApiError extends Error {
18
+ status: number;
19
+ details: unknown;
20
+ constructor(status: number, message: string, details: unknown);
21
+ }
22
+ /**
23
+ * Extract useful error information from an API error
24
+ * Useful for displaying errors to users in a friendly way
25
+ */
26
+ interface ApiErrorInfo {
27
+ status: number;
28
+ statusText: string;
29
+ error?: string;
30
+ message?: string;
31
+ details?: unknown;
32
+ }
33
+ declare function extractApiErrorInfo(error: unknown): ApiErrorInfo | null;
34
+
35
+ /**
36
+ * Connection monitoring types
37
+ *
38
+ * Type definitions for connection state, configuration, and callbacks.
39
+ */
40
+ /**
41
+ * Possible connection states.
42
+ *
43
+ * - **online**: Connection is stable and healthy
44
+ * - **offline**: Complete loss of network connectivity
45
+ * - **degraded**: Connection is slow or experiencing intermittent issues
46
+ */
47
+ type ConnectionState = 'online' | 'offline' | 'degraded';
48
+ /**
49
+ * Configuration options for ConnectionMonitor.
50
+ *
51
+ * @see {@link ConnectionMonitor} for usage
52
+ */
53
+ interface ConnectionMonitorConfig {
54
+ /** Base URL for heartbeat pings (e.g., 'https://api.playcademy.com') */
55
+ baseUrl: string;
56
+ /** How often to send heartbeat pings in milliseconds (default: 10000) */
57
+ heartbeatInterval?: number;
58
+ /** How long to wait for heartbeat response in milliseconds (default: 5000) */
59
+ heartbeatTimeout?: number;
60
+ /** Number of consecutive failures before triggering disconnect (default: 2) */
61
+ failureThreshold?: number;
62
+ /** Enable periodic heartbeat monitoring (default: true) */
63
+ enableHeartbeat?: boolean;
64
+ /** Enable browser online/offline event listeners (default: true) */
65
+ enableOfflineEvents?: boolean;
66
+ }
67
+ /**
68
+ * Callback function signature for connection state changes.
69
+ *
70
+ * @param state - The new connection state
71
+ * @param reason - Human-readable reason for the state change
72
+ */
73
+ type ConnectionChangeCallback = (state: ConnectionState, reason: string) => void;
74
+
75
+ /**
76
+ * Connection Monitor
77
+ *
78
+ * Monitors network connectivity using multiple signals:
79
+ * 1. navigator.onLine - Instant offline detection
80
+ * 2. Periodic heartbeat - Detects slow/degraded connections
81
+ * 3. Request failure tracking - Piggybacks on actual API calls
82
+ *
83
+ * Designed for school WiFi environments where connections may be
84
+ * unstable or degraded without fully disconnecting.
85
+ */
86
+
87
+ /**
88
+ * Monitors network connectivity using multiple signals and notifies callbacks of state changes.
89
+ *
90
+ * The ConnectionMonitor uses a multi-signal approach to detect connection issues:
91
+ *
92
+ * 1. **navigator.onLine events** - Instant detection of hard disconnects
93
+ * 2. **Heartbeat pings** - Periodic checks to detect slow/degraded connections
94
+ * 3. **Request failure tracking** - Piggybacks on actual API calls
95
+ *
96
+ * This comprehensive approach ensures reliable detection across different network
97
+ * failure modes common in school WiFi environments (hard disconnect, slow connection,
98
+ * intermittent failures).
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * const monitor = new ConnectionMonitor({
103
+ * baseUrl: 'https://api.playcademy.com',
104
+ * heartbeatInterval: 10000, // Check every 10s
105
+ * failureThreshold: 2 // Trigger after 2 failures
106
+ * })
107
+ *
108
+ * monitor.onChange((state, reason) => {
109
+ * console.log(`Connection: ${state} - ${reason}`)
110
+ * })
111
+ *
112
+ * monitor.start()
113
+ * ```
114
+ *
115
+ * @see {@link ConnectionManagerConfig} for configuration options
116
+ */
117
+ declare class ConnectionMonitor {
118
+ private state;
119
+ private callbacks;
120
+ private heartbeatInterval?;
121
+ private consecutiveFailures;
122
+ private isMonitoring;
123
+ private config;
124
+ /**
125
+ * Creates a new ConnectionMonitor instance.
126
+ *
127
+ * The monitor starts in a stopped state. Call `start()` to begin monitoring.
128
+ *
129
+ * @param config - Configuration options
130
+ * @param config.baseUrl - Base URL for heartbeat pings
131
+ * @param config.heartbeatInterval - How often to check (default: 10000ms)
132
+ * @param config.heartbeatTimeout - Request timeout (default: 5000ms)
133
+ * @param config.failureThreshold - Failures before triggering disconnect (default: 2)
134
+ * @param config.enableHeartbeat - Enable periodic checks (default: true)
135
+ * @param config.enableOfflineEvents - Listen to browser events (default: true)
136
+ */
137
+ constructor(config: ConnectionMonitorConfig);
138
+ /**
139
+ * Starts monitoring the connection state.
140
+ *
141
+ * Sets up event listeners and begins heartbeat checks based on configuration.
142
+ * Idempotent - safe to call multiple times.
143
+ */
144
+ start(): void;
145
+ /**
146
+ * Stops monitoring the connection state and cleans up resources.
147
+ *
148
+ * Removes event listeners and clears heartbeat intervals.
149
+ * Idempotent - safe to call multiple times.
150
+ */
151
+ stop(): void;
152
+ /**
153
+ * Registers a callback to be notified of all connection state changes.
154
+ *
155
+ * The callback fires for all state transitions: online → offline,
156
+ * offline → degraded, degraded → online, etc.
157
+ *
158
+ * @param callback - Function called with (state, reason) when connection changes
159
+ * @returns Cleanup function to unregister the callback
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * const cleanup = monitor.onChange((state, reason) => {
164
+ * console.log(`Connection: ${state}`)
165
+ * if (state === 'offline') {
166
+ * showReconnectingUI()
167
+ * }
168
+ * })
169
+ *
170
+ * // Later: cleanup() to unregister
171
+ * ```
172
+ */
173
+ onChange(callback: ConnectionChangeCallback): () => void;
174
+ /**
175
+ * Gets the current connection state.
176
+ *
177
+ * @returns The current state ('online', 'offline', or 'degraded')
178
+ */
179
+ getState(): ConnectionState;
180
+ /**
181
+ * Manually triggers an immediate connection check.
182
+ *
183
+ * Forces a heartbeat ping to verify connectivity right now, bypassing
184
+ * the normal interval. Useful before critical operations.
185
+ *
186
+ * @returns Promise resolving to the current connection state after the check
187
+ *
188
+ * @example
189
+ * ```typescript
190
+ * const state = await monitor.checkNow()
191
+ * if (state !== 'online') {
192
+ * alert('Please check your internet connection')
193
+ * }
194
+ * ```
195
+ */
196
+ checkNow(): Promise<ConnectionState>;
197
+ /**
198
+ * Reports a request failure for tracking.
199
+ *
200
+ * This should be called from your request wrapper whenever an API call fails.
201
+ * Only network errors are tracked (TypeError, fetch failures) - HTTP error
202
+ * responses (4xx, 5xx) are ignored.
203
+ *
204
+ * After consecutive failures exceed the threshold, the monitor transitions
205
+ * to 'degraded' or 'offline' state.
206
+ *
207
+ * @param error - The error from the failed request
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * try {
212
+ * await fetch('/api/data')
213
+ * } catch (error) {
214
+ * monitor.reportRequestFailure(error)
215
+ * throw error
216
+ * }
217
+ * ```
218
+ */
219
+ reportRequestFailure(error: unknown): void;
220
+ /**
221
+ * Reports a successful request.
222
+ *
223
+ * This should be called from your request wrapper whenever an API call succeeds.
224
+ * Resets the consecutive failure counter and transitions from 'degraded' to
225
+ * 'online' if the connection has recovered.
226
+ *
227
+ * @example
228
+ * ```typescript
229
+ * try {
230
+ * const result = await fetch('/api/data')
231
+ * monitor.reportRequestSuccess()
232
+ * return result
233
+ * } catch (error) {
234
+ * monitor.reportRequestFailure(error)
235
+ * throw error
236
+ * }
237
+ * ```
238
+ */
239
+ reportRequestSuccess(): void;
240
+ private _detectInitialState;
241
+ private _handleOnline;
242
+ private _handleOffline;
243
+ private _startHeartbeat;
244
+ private _performHeartbeat;
245
+ private _handleHeartbeatFailure;
246
+ private _setState;
247
+ }
10
248
 
11
249
  declare const users: drizzle_orm_pg_core.PgTableWithColumns<{
12
250
  name: "user";
@@ -3289,6 +3527,91 @@ type EndActivityResponse = {
3289
3527
  xpAwarded: number;
3290
3528
  };
3291
3529
 
3530
+ /**
3531
+ * OAuth 2.0 implementation for the Playcademy SDK
3532
+ */
3533
+
3534
+ /**
3535
+ * Parses an OAuth state parameter to extract CSRF token and any encoded data.
3536
+ *
3537
+ * @param state - The OAuth state parameter to parse
3538
+ * @returns Object containing CSRF token and optional decoded data
3539
+ */
3540
+ declare function parseOAuthState(state: string): {
3541
+ csrfToken: string;
3542
+ data?: Record<string, string>;
3543
+ };
3544
+
3545
+ /**
3546
+ * Response type for the realtime token API
3547
+ */
3548
+ interface RealtimeTokenResponse {
3549
+ token: string;
3550
+ }
3551
+
3552
+ /**
3553
+ * Cache configuration types for runtime customization
3554
+ */
3555
+ /**
3556
+ * Runtime configuration for TTL cache behavior
3557
+ */
3558
+ interface TTLCacheConfig {
3559
+ /** Time-to-live in milliseconds. Set to 0 to disable caching for this call. */
3560
+ ttl?: number;
3561
+ /** Force refresh, bypassing cache */
3562
+ force?: boolean;
3563
+ /** Skip cache and fetch fresh data (alias for force) */
3564
+ skipCache?: boolean;
3565
+ }
3566
+ /**
3567
+ * Runtime configuration for cooldown cache behavior
3568
+ */
3569
+ interface CooldownCacheConfig {
3570
+ /** Cooldown period in milliseconds. Set to 0 to disable cooldown for this call. */
3571
+ cooldown?: number;
3572
+ /** Force refresh, bypassing cooldown */
3573
+ force?: boolean;
3574
+ }
3575
+
3576
+ interface CharacterComponentsOptions {
3577
+ /**
3578
+ * Optional level filter for components
3579
+ * When provided, only components available at this level or below are returned
3580
+ */
3581
+ level?: number;
3582
+ /**
3583
+ * Whether to bypass the cache and force a fresh API request
3584
+ * Default: false (use cache when available)
3585
+ */
3586
+ skipCache?: boolean;
3587
+ }
3588
+ interface CreateCharacterData {
3589
+ bodyComponentId: string;
3590
+ eyesComponentId: string;
3591
+ hairstyleComponentId: string;
3592
+ outfitComponentId: string;
3593
+ }
3594
+ interface UpdateCharacterData {
3595
+ bodyComponentId?: string;
3596
+ eyesComponentId?: string;
3597
+ hairstyleComponentId?: string;
3598
+ outfitComponentId?: string;
3599
+ }
3600
+
3601
+ interface ScoreSubmission {
3602
+ id: string;
3603
+ score: number;
3604
+ achievedAt: Date;
3605
+ }
3606
+
3607
+ /**
3608
+ * Combined response type for summary method
3609
+ */
3610
+ type XpSummaryResponse = {
3611
+ today: TodayXpResponse;
3612
+ total: TotalXpResponse;
3613
+ };
3614
+
3292
3615
  /**
3293
3616
  * @fileoverview Server SDK Type Definitions
3294
3617
  *
@@ -3396,303 +3719,14 @@ interface BackendDeploymentBundle {
3396
3719
  secrets?: Record<string, string>;
3397
3720
  }
3398
3721
 
3399
- type TokenType = 'session' | 'apiKey' | 'gameJwt';
3400
- interface ClientConfig {
3401
- baseUrl: string;
3402
- gameUrl?: string;
3403
- token?: string;
3404
- tokenType?: TokenType;
3405
- gameId?: string;
3406
- autoStartSession?: boolean;
3407
- }
3408
- type AuthProviderType = (typeof AUTH_PROVIDER_IDS)[keyof typeof AUTH_PROVIDER_IDS];
3409
- interface AuthOptions {
3410
- /** The identity provider to use for authentication */
3411
- provider: AuthProviderType;
3412
- /** The OAuth callback URL where your server handles the callback */
3413
- callbackUrl: string;
3414
- /** Authentication mode - auto detects best option based on context */
3415
- mode?: 'auto' | 'popup' | 'redirect';
3416
- /** Callback for authentication state changes */
3417
- onStateChange?: (state: AuthStateUpdate) => void;
3418
- /** Custom OAuth configuration (for users embedding the SDK outside of the Playcademy platform) */
3419
- oauth?: {
3420
- clientId: string;
3421
- authorizationEndpoint?: string;
3422
- tokenEndpoint?: string;
3423
- scope?: string;
3424
- };
3425
- /**
3426
- * Optional custom data to encode in OAuth state parameter.
3427
- * By default, the SDK automatically includes playcademy_user_id and game_id.
3428
- * Use this to add additional custom data if needed.
3429
- */
3430
- stateData?: Record<string, string>;
3431
- }
3432
- interface AuthStateUpdate {
3433
- /** Current status of the authentication flow */
3434
- status: 'opening_popup' | 'exchanging_token' | 'complete' | 'error';
3435
- /** Human-readable message about the current state */
3436
- message: string;
3437
- /** Error details if status is 'error' */
3438
- error?: Error;
3439
- }
3440
- interface AuthResult {
3441
- /** Whether authentication was successful */
3442
- success: boolean;
3443
- /** User information if authentication was successful */
3444
- user?: UserInfo;
3445
- /** Error if authentication failed */
3446
- error?: Error;
3447
- }
3448
- /**
3449
- * Authentication state change event payload.
3450
- * Used when authentication state changes in the application.
3451
- */
3452
- interface AuthStateChangePayload {
3453
- /** Whether the user is currently authenticated */
3454
- authenticated: boolean;
3455
- /** User information if authenticated, null otherwise */
3456
- user: UserInfo | null;
3457
- /** Error information if authentication failed */
3458
- error: Error | null;
3459
- }
3460
- /**
3461
- * OAuth callback event payload.
3462
- * Used when OAuth flow completes in popup/new-tab windows.
3463
- */
3464
- interface AuthCallbackPayload {
3465
- /** OAuth authorization code */
3466
- code: string;
3467
- /** OAuth state parameter for CSRF protection */
3468
- state: string;
3469
- /** Error message if OAuth flow failed */
3470
- error: string | null;
3471
- }
3472
- /**
3473
- * Token refresh event payload.
3474
- * Sent when authentication token is updated.
3475
- */
3476
- interface TokenRefreshPayload {
3477
- /** New authentication token */
3478
- token: string;
3479
- /** Token expiration timestamp */
3480
- exp: number;
3481
- }
3482
- /**
3483
- * Telemetry event payload.
3484
- * Performance metrics sent from the game.
3485
- */
3486
- interface TelemetryPayload {
3487
- /** Frames per second */
3488
- fps: number;
3489
- /** Memory usage in MB */
3490
- mem: number;
3491
- }
3492
- /**
3493
- * Keyboard event payload.
3494
- * Key events forwarded from the game.
3495
- */
3496
- interface KeyEventPayload {
3497
- /** Key value (e.g., 'Escape', 'F1') */
3498
- key: string;
3499
- /** Key code (optional) */
3500
- code?: string;
3501
- /** Event type */
3502
- type: 'keydown' | 'keyup';
3503
- }
3504
- interface ClientEvents {
3505
- authChange: {
3506
- token: string | null;
3507
- };
3508
- inventoryChange: {
3509
- itemId: string;
3510
- delta: number;
3511
- newTotal: number;
3512
- };
3513
- levelUp: {
3514
- oldLevel: number;
3515
- newLevel: number;
3516
- creditsAwarded: number;
3517
- };
3518
- xpGained: {
3519
- amount: number;
3520
- totalXP: number;
3521
- leveledUp: boolean;
3522
- };
3523
- }
3524
- type GameContextPayload = {
3525
- token: string;
3526
- baseUrl: string;
3527
- realtimeUrl: string;
3528
- gameId: string;
3529
- forwardKeys?: string[];
3530
- };
3531
- type LoginResponse = {
3532
- token: string;
3533
- };
3534
- type GameTokenResponse = {
3535
- token: string;
3536
- exp: number;
3537
- };
3538
- type StartSessionResponse = {
3539
- sessionId: string;
3540
- };
3541
- type InventoryMutationResponse = {
3542
- newTotal: number;
3543
- };
3544
- type DevUploadEvent = {
3545
- type: 'init';
3546
- } | {
3547
- type: 's3Progress';
3548
- loaded: number;
3549
- total: number;
3550
- percent: number;
3551
- } | {
3552
- type: 'finalizeStart';
3553
- } | {
3554
- type: 'finalizeProgress';
3555
- percent: number;
3556
- currentFileLabel?: string;
3557
- } | {
3558
- type: 'finalizeStatus';
3559
- message: string;
3560
- } | {
3561
- type: 'close';
3562
- };
3563
- type DevUploadHooks = {
3564
- onEvent?: (e: DevUploadEvent) => void;
3565
- onClose?: () => void;
3566
- };
3567
- /**
3568
- * Better-auth API key creation response
3569
- */
3570
- interface BetterAuthApiKeyResponse {
3571
- apiKey: string;
3572
- key: {
3573
- id: string;
3574
- name: string | null;
3575
- expiresAt: string | null;
3576
- createdAt: string;
3577
- };
3578
- }
3579
- /**
3580
- * Better-auth API key list item
3581
- */
3582
- interface BetterAuthApiKey {
3583
- id: string;
3584
- name: string | null;
3585
- start: string;
3586
- enabled: boolean;
3587
- expiresAt: string | null;
3588
- createdAt: string;
3589
- updatedAt: string;
3590
- lastRequest: string | null;
3591
- requestCount: number;
3592
- }
3593
- /**
3594
- * Bucket file metadata
3595
- */
3596
- interface BucketFile {
3597
- key: string;
3598
- size: number;
3599
- uploaded: string;
3600
- contentType?: string;
3601
- }
3602
-
3603
- /**
3604
- * OAuth 2.0 implementation for the Playcademy SDK
3605
- */
3606
-
3607
- /**
3608
- * Parses an OAuth state parameter to extract CSRF token and any encoded data.
3609
- *
3610
- * @param state - The OAuth state parameter to parse
3611
- * @returns Object containing CSRF token and optional decoded data
3612
- */
3613
- declare function parseOAuthState(state: string): {
3614
- csrfToken: string;
3615
- data?: Record<string, string>;
3616
- };
3617
-
3618
- /**
3619
- * Response type for the realtime token API
3620
- */
3621
- interface RealtimeTokenResponse {
3622
- token: string;
3623
- }
3624
-
3625
- /**
3626
- * Cache configuration types for runtime customization
3627
- */
3628
- /**
3629
- * Runtime configuration for TTL cache behavior
3630
- */
3631
- interface TTLCacheConfig {
3632
- /** Time-to-live in milliseconds. Set to 0 to disable caching for this call. */
3633
- ttl?: number;
3634
- /** Force refresh, bypassing cache */
3635
- force?: boolean;
3636
- /** Skip cache and fetch fresh data (alias for force) */
3637
- skipCache?: boolean;
3638
- }
3639
- /**
3640
- * Runtime configuration for cooldown cache behavior
3641
- */
3642
- interface CooldownCacheConfig {
3643
- /** Cooldown period in milliseconds. Set to 0 to disable cooldown for this call. */
3644
- cooldown?: number;
3645
- /** Force refresh, bypassing cooldown */
3646
- force?: boolean;
3647
- }
3648
-
3649
- interface CharacterComponentsOptions {
3650
- /**
3651
- * Optional level filter for components
3652
- * When provided, only components available at this level or below are returned
3653
- */
3654
- level?: number;
3655
- /**
3656
- * Whether to bypass the cache and force a fresh API request
3657
- * Default: false (use cache when available)
3658
- */
3659
- skipCache?: boolean;
3660
- }
3661
- interface CreateCharacterData {
3662
- bodyComponentId: string;
3663
- eyesComponentId: string;
3664
- hairstyleComponentId: string;
3665
- outfitComponentId: string;
3666
- }
3667
- interface UpdateCharacterData {
3668
- bodyComponentId?: string;
3669
- eyesComponentId?: string;
3670
- hairstyleComponentId?: string;
3671
- outfitComponentId?: string;
3672
- }
3673
-
3674
- interface ScoreSubmission {
3675
- id: string;
3676
- score: number;
3677
- achievedAt: Date;
3678
- }
3679
-
3680
- /**
3681
- * Combined response type for summary method
3682
- */
3683
- type XpSummaryResponse = {
3684
- today: TodayXpResponse;
3685
- total: TotalXpResponse;
3686
- };
3687
-
3688
- interface UserScore {
3689
- id: string;
3690
- score: number;
3691
- achievedAt: Date;
3692
- metadata?: Record<string, unknown>;
3693
- gameId: string;
3694
- gameTitle: string;
3695
- gameSlug: string;
3722
+ interface UserScore {
3723
+ id: string;
3724
+ score: number;
3725
+ achievedAt: Date;
3726
+ metadata?: Record<string, unknown>;
3727
+ gameId: string;
3728
+ gameTitle: string;
3729
+ gameSlug: string;
3696
3730
  }
3697
3731
 
3698
3732
  /**
@@ -3722,6 +3756,8 @@ interface UserScore {
3722
3756
  declare function init(options?: {
3723
3757
  baseUrl?: string;
3724
3758
  allowedParentOrigins?: string[];
3759
+ onDisconnect?: DisconnectHandler;
3760
+ enableConnectionMonitoring?: boolean;
3725
3761
  }): Promise<PlaycademyClient>;
3726
3762
 
3727
3763
  /**
@@ -3775,6 +3811,7 @@ declare class PlaycademyClient {
3775
3811
  private internalClientSessionId?;
3776
3812
  private authContext?;
3777
3813
  private initPayload?;
3814
+ private connectionManager?;
3778
3815
  /**
3779
3816
  * Creates a new PlaycademyClient instance.
3780
3817
  *
@@ -3867,13 +3904,92 @@ declare class PlaycademyClient {
3867
3904
  */
3868
3905
  onAuthChange(callback: (token: string | null) => void): void;
3869
3906
  /**
3870
- * Sets the authentication context for the client.
3871
- * This is called during initialization to store environment info.
3872
- * @internal
3873
- */
3874
- _setAuthContext(context: {
3875
- isInIframe: boolean;
3876
- }): void;
3907
+ * Registers a callback to be called when connection issues are detected.
3908
+ *
3909
+ * This is a convenience method that filters connection change events to only
3910
+ * fire when the connection degrades (offline or degraded states). Use this
3911
+ * when you want to handle disconnects without being notified of recoveries.
3912
+ *
3913
+ * For all connection state changes, use `client.on('connectionChange', ...)` instead.
3914
+ *
3915
+ * @param callback - Function to call when connection state changes to offline or degraded
3916
+ * @returns Cleanup function to unregister the callback
3917
+ *
3918
+ * @example
3919
+ * ```typescript
3920
+ * const cleanup = client.onDisconnect(({ state, reason, displayAlert }) => {
3921
+ * console.log(`Connection ${state}: ${reason}`)
3922
+ *
3923
+ * if (state === 'offline') {
3924
+ * // Save state and return to game lobby
3925
+ * displayAlert?.('Connection lost. Your progress has been saved.', { type: 'error' })
3926
+ * saveGameState()
3927
+ * returnToLobby()
3928
+ * } else if (state === 'degraded') {
3929
+ * displayAlert?.('Slow connection detected.', { type: 'warning' })
3930
+ * }
3931
+ * })
3932
+ *
3933
+ * // Later: cleanup() to unregister
3934
+ * ```
3935
+ *
3936
+ * @see {@link DISCONNECT_HANDLING.md} for detailed usage examples
3937
+ * @see {@link ConnectionManager.onDisconnect} for the underlying implementation
3938
+ */
3939
+ onDisconnect(callback: (context: DisconnectContext) => void | Promise<void>): () => void;
3940
+ /**
3941
+ * Gets the current connection state.
3942
+ *
3943
+ * Returns the last known connection state without triggering a new check.
3944
+ * Use `checkConnection()` to force an immediate verification.
3945
+ *
3946
+ * @returns Current connection state ('online', 'offline', 'degraded') or 'unknown' if monitoring is disabled
3947
+ *
3948
+ * @example
3949
+ * ```typescript
3950
+ * const state = client.getConnectionState()
3951
+ * if (state === 'offline') {
3952
+ * console.log('No connection available')
3953
+ * }
3954
+ * ```
3955
+ *
3956
+ * @see {@link checkConnection} to trigger an immediate connection check
3957
+ * @see {@link ConnectionManager.getState} for the underlying implementation
3958
+ */
3959
+ getConnectionState(): ConnectionState | 'unknown';
3960
+ /**
3961
+ * Manually triggers a connection check immediately.
3962
+ *
3963
+ * Forces a heartbeat ping to verify connectivity right now, bypassing the normal
3964
+ * interval. Useful when you need to verify connection status before a critical
3965
+ * operation (e.g., saving important game state).
3966
+ *
3967
+ * @returns Promise resolving to the current connection state after verification
3968
+ *
3969
+ * @example
3970
+ * ```typescript
3971
+ * // Check before critical operation
3972
+ * const state = await client.checkConnection()
3973
+ * if (state !== 'online') {
3974
+ * alert('Please check your internet connection before saving')
3975
+ * return
3976
+ * }
3977
+ *
3978
+ * await client.games.saveState(importantData)
3979
+ * ```
3980
+ *
3981
+ * @see {@link getConnectionState} to get the last known state without checking
3982
+ * @see {@link ConnectionManager.checkNow} for the underlying implementation
3983
+ */
3984
+ checkConnection(): Promise<ConnectionState | 'unknown'>;
3985
+ /**
3986
+ * Sets the authentication context for the client.
3987
+ * This is called during initialization to store environment info.
3988
+ * @internal
3989
+ */
3990
+ _setAuthContext(context: {
3991
+ isInIframe: boolean;
3992
+ }): void;
3877
3993
  /**
3878
3994
  * Registers an event listener for client events.
3879
3995
  *
@@ -3928,6 +4044,11 @@ declare class PlaycademyClient {
3928
4044
  * Safe to call in any environment - isInIframe handles browser detection.
3929
4045
  */
3930
4046
  private _detectAuthContext;
4047
+ /**
4048
+ * Initializes connection monitoring if enabled.
4049
+ * Safe to call in any environment - only runs in browser.
4050
+ */
4051
+ private _initializeConnectionMonitor;
3931
4052
  /**
3932
4053
  * Initializes an internal game session for automatic session management.
3933
4054
  * Only starts a session if:
@@ -4129,50 +4250,50 @@ declare class PlaycademyClient {
4129
4250
  };
4130
4251
  items: {
4131
4252
  create: (props: InsertItemInput) => Promise<{
4132
- type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4133
4253
  id: string;
4134
- metadata: unknown;
4135
- slug: string;
4136
4254
  createdAt: Date;
4137
4255
  gameId: string | null;
4256
+ slug: string;
4138
4257
  displayName: string;
4258
+ metadata: unknown;
4139
4259
  description: string | null;
4260
+ type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4140
4261
  isPlaceable: boolean;
4141
4262
  imageUrl: string | null;
4142
4263
  }>;
4143
4264
  get: (itemId: string) => Promise<{
4144
- type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4145
4265
  id: string;
4146
- metadata: unknown;
4147
- slug: string;
4148
4266
  createdAt: Date;
4149
4267
  gameId: string | null;
4268
+ slug: string;
4150
4269
  displayName: string;
4270
+ metadata: unknown;
4151
4271
  description: string | null;
4272
+ type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4152
4273
  isPlaceable: boolean;
4153
4274
  imageUrl: string | null;
4154
4275
  }>;
4155
4276
  list: () => Promise<{
4156
- type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4157
4277
  id: string;
4158
- metadata: unknown;
4159
- slug: string;
4160
4278
  createdAt: Date;
4161
4279
  gameId: string | null;
4280
+ slug: string;
4162
4281
  displayName: string;
4282
+ metadata: unknown;
4163
4283
  description: string | null;
4284
+ type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4164
4285
  isPlaceable: boolean;
4165
4286
  imageUrl: string | null;
4166
4287
  }[]>;
4167
4288
  update: (itemId: string, props: UpdateItemInput) => Promise<{
4168
- type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4169
4289
  id: string;
4170
- metadata: unknown;
4171
- slug: string;
4172
4290
  createdAt: Date;
4173
4291
  gameId: string | null;
4292
+ slug: string;
4174
4293
  displayName: string;
4294
+ metadata: unknown;
4175
4295
  description: string | null;
4296
+ type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4176
4297
  isPlaceable: boolean;
4177
4298
  imageUrl: string | null;
4178
4299
  }>;
@@ -4307,9 +4428,7 @@ declare class PlaycademyClient {
4307
4428
  }) => Promise<TodayXpResponse>;
4308
4429
  total: () => Promise<TotalXpResponse>;
4309
4430
  history: (options?: {
4310
- startDate
4311
- /** Auto-initializes a PlaycademyClient with context from the environment */
4312
- ?: string;
4431
+ startDate?: string;
4313
4432
  endDate?: string;
4314
4433
  }) => Promise<XpHistoryResponse>;
4315
4434
  summary: (options?: {
@@ -4422,29 +4541,436 @@ declare class PlaycademyClient {
4422
4541
  };
4423
4542
  }
4424
4543
 
4544
+ type TokenType = 'session' | 'apiKey' | 'gameJwt';
4545
+ interface ClientConfig {
4546
+ baseUrl: string;
4547
+ gameUrl?: string;
4548
+ token?: string;
4549
+ tokenType?: TokenType;
4550
+ gameId?: string;
4551
+ autoStartSession?: boolean;
4552
+ onDisconnect?: DisconnectHandler;
4553
+ enableConnectionMonitoring?: boolean;
4554
+ }
4425
4555
  /**
4426
- * Base error class for Cademy SDK specific errors.
4556
+ * Handler called when connection state changes to offline or degraded.
4557
+ * Games can implement this to handle disconnects gracefully.
4427
4558
  */
4428
- declare class PlaycademyError extends Error {
4429
- constructor(message: string);
4559
+ type DisconnectHandler = (context: DisconnectContext) => void | Promise<void>;
4560
+ /**
4561
+ * Context provided to disconnect handlers
4562
+ */
4563
+ interface DisconnectContext {
4564
+ /** Current connection state */
4565
+ state: 'offline' | 'degraded';
4566
+ /** Reason for the disconnect */
4567
+ reason: string;
4568
+ /** Timestamp when disconnect was detected */
4569
+ timestamp: number;
4570
+ /** Utility to display a platform-level alert */
4571
+ displayAlert: (message: string, options?: {
4572
+ type?: 'info' | 'warning' | 'error';
4573
+ duration?: number;
4574
+ }) => void;
4430
4575
  }
4431
- declare class ApiError extends Error {
4432
- status: number;
4433
- details: unknown;
4434
- constructor(status: number, message: string, details: unknown);
4576
+ type AuthProviderType = (typeof AUTH_PROVIDER_IDS)[keyof typeof AUTH_PROVIDER_IDS];
4577
+ interface AuthOptions {
4578
+ /** The identity provider to use for authentication */
4579
+ provider: AuthProviderType;
4580
+ /** The OAuth callback URL where your server handles the callback */
4581
+ callbackUrl: string;
4582
+ /** Authentication mode - auto detects best option based on context */
4583
+ mode?: 'auto' | 'popup' | 'redirect';
4584
+ /** Callback for authentication state changes */
4585
+ onStateChange?: (state: AuthStateUpdate) => void;
4586
+ /** Custom OAuth configuration (for users embedding the SDK outside of the Playcademy platform) */
4587
+ oauth?: {
4588
+ clientId: string;
4589
+ authorizationEndpoint?: string;
4590
+ tokenEndpoint?: string;
4591
+ scope?: string;
4592
+ };
4593
+ /**
4594
+ * Optional custom data to encode in OAuth state parameter.
4595
+ * By default, the SDK automatically includes playcademy_user_id and game_id.
4596
+ * Use this to add additional custom data if needed.
4597
+ */
4598
+ stateData?: Record<string, string>;
4599
+ }
4600
+ interface AuthStateUpdate {
4601
+ /** Current status of the authentication flow */
4602
+ status: 'opening_popup' | 'exchanging_token' | 'complete' | 'error';
4603
+ /** Human-readable message about the current state */
4604
+ message: string;
4605
+ /** Error details if status is 'error' */
4606
+ error?: Error;
4607
+ }
4608
+ interface AuthResult {
4609
+ /** Whether authentication was successful */
4610
+ success: boolean;
4611
+ /** User information if authentication was successful */
4612
+ user?: UserInfo;
4613
+ /** Error if authentication failed */
4614
+ error?: Error;
4435
4615
  }
4436
4616
  /**
4437
- * Extract useful error information from an API error
4438
- * Useful for displaying errors to users in a friendly way
4617
+ * Authentication state change event payload.
4618
+ * Used when authentication state changes in the application.
4439
4619
  */
4440
- interface ApiErrorInfo {
4441
- status: number;
4442
- statusText: string;
4443
- error?: string;
4444
- message?: string;
4445
- details?: unknown;
4620
+ interface AuthStateChangePayload {
4621
+ /** Whether the user is currently authenticated */
4622
+ authenticated: boolean;
4623
+ /** User information if authenticated, null otherwise */
4624
+ user: UserInfo | null;
4625
+ /** Error information if authentication failed */
4626
+ error: Error | null;
4627
+ }
4628
+ /**
4629
+ * OAuth callback event payload.
4630
+ * Used when OAuth flow completes in popup/new-tab windows.
4631
+ */
4632
+ interface AuthCallbackPayload {
4633
+ /** OAuth authorization code */
4634
+ code: string;
4635
+ /** OAuth state parameter for CSRF protection */
4636
+ state: string;
4637
+ /** Error message if OAuth flow failed */
4638
+ error: string | null;
4639
+ }
4640
+ /**
4641
+ * Token refresh event payload.
4642
+ * Sent when authentication token is updated.
4643
+ */
4644
+ interface TokenRefreshPayload {
4645
+ /** New authentication token */
4646
+ token: string;
4647
+ /** Token expiration timestamp */
4648
+ exp: number;
4649
+ }
4650
+ /**
4651
+ * Telemetry event payload.
4652
+ * Performance metrics sent from the game.
4653
+ */
4654
+ interface TelemetryPayload {
4655
+ /** Frames per second */
4656
+ fps: number;
4657
+ /** Memory usage in MB */
4658
+ mem: number;
4659
+ }
4660
+ /**
4661
+ * Keyboard event payload.
4662
+ * Key events forwarded from the game.
4663
+ */
4664
+ interface KeyEventPayload {
4665
+ /** Key value (e.g., 'Escape', 'F1') */
4666
+ key: string;
4667
+ /** Key code (optional) */
4668
+ code?: string;
4669
+ /** Event type */
4670
+ type: 'keydown' | 'keyup';
4671
+ }
4672
+ interface DisplayAlertPayload {
4673
+ message: string;
4674
+ options?: {
4675
+ type?: 'info' | 'warning' | 'error';
4676
+ duration?: number;
4677
+ };
4678
+ }
4679
+ /**
4680
+ * Display alert payload.
4681
+ * Request from game to show platform-level alert.
4682
+ */
4683
+ interface DisplayAlertPayload {
4684
+ message: string;
4685
+ options?: {
4686
+ type?: 'info' | 'warning' | 'error';
4687
+ duration?: number;
4688
+ };
4689
+ }
4690
+ /**
4691
+ * Connection state payload.
4692
+ * Broadcast from platform to games when connection changes.
4693
+ */
4694
+ interface ConnectionStatePayload {
4695
+ state: 'online' | 'offline' | 'degraded';
4696
+ reason: string;
4697
+ }
4698
+ interface ClientEvents {
4699
+ authChange: {
4700
+ token: string | null;
4701
+ };
4702
+ inventoryChange: {
4703
+ itemId: string;
4704
+ delta: number;
4705
+ newTotal: number;
4706
+ };
4707
+ levelUp: {
4708
+ oldLevel: number;
4709
+ newLevel: number;
4710
+ creditsAwarded: number;
4711
+ };
4712
+ xpGained: {
4713
+ amount: number;
4714
+ totalXP: number;
4715
+ leveledUp: boolean;
4716
+ };
4717
+ connectionChange: {
4718
+ state: 'online' | 'offline' | 'degraded';
4719
+ reason: string;
4720
+ };
4721
+ }
4722
+ type GameContextPayload = {
4723
+ token: string;
4724
+ baseUrl: string;
4725
+ realtimeUrl: string;
4726
+ gameId: string;
4727
+ forwardKeys?: string[];
4728
+ };
4729
+ type LoginResponse = {
4730
+ token: string;
4731
+ };
4732
+ type GameTokenResponse = {
4733
+ token: string;
4734
+ exp: number;
4735
+ };
4736
+ type StartSessionResponse = {
4737
+ sessionId: string;
4738
+ };
4739
+ type InventoryMutationResponse = {
4740
+ newTotal: number;
4741
+ };
4742
+ type DevUploadEvent = {
4743
+ type: 'init';
4744
+ } | {
4745
+ type: 's3Progress';
4746
+ loaded: number;
4747
+ total: number;
4748
+ percent: number;
4749
+ } | {
4750
+ type: 'finalizeStart';
4751
+ } | {
4752
+ type: 'finalizeProgress';
4753
+ percent: number;
4754
+ currentFileLabel?: string;
4755
+ } | {
4756
+ type: 'finalizeStatus';
4757
+ message: string;
4758
+ } | {
4759
+ type: 'close';
4760
+ };
4761
+ type DevUploadHooks = {
4762
+ onEvent?: (e: DevUploadEvent) => void;
4763
+ onClose?: () => void;
4764
+ };
4765
+ /**
4766
+ * Better-auth API key creation response
4767
+ */
4768
+ interface BetterAuthApiKeyResponse {
4769
+ apiKey: string;
4770
+ key: {
4771
+ id: string;
4772
+ name: string | null;
4773
+ expiresAt: string | null;
4774
+ createdAt: string;
4775
+ };
4776
+ }
4777
+ /**
4778
+ * Better-auth API key list item
4779
+ */
4780
+ interface BetterAuthApiKey {
4781
+ id: string;
4782
+ name: string | null;
4783
+ start: string;
4784
+ enabled: boolean;
4785
+ expiresAt: string | null;
4786
+ createdAt: string;
4787
+ updatedAt: string;
4788
+ lastRequest: string | null;
4789
+ requestCount: number;
4790
+ }
4791
+ /**
4792
+ * Bucket file metadata
4793
+ */
4794
+ interface BucketFile {
4795
+ key: string;
4796
+ size: number;
4797
+ uploaded: string;
4798
+ contentType?: string;
4799
+ }
4800
+
4801
+ /**
4802
+ * Connection Manager
4803
+ *
4804
+ * Manages connection monitoring and integrates it with the Playcademy client.
4805
+ * Handles event wiring, state management, and disconnect callbacks.
4806
+ *
4807
+ * In iframe mode, disables local monitoring and listens to platform connection
4808
+ * state broadcasts instead (avoids duplicate heartbeats).
4809
+ */
4810
+
4811
+ /**
4812
+ * Configuration for the ConnectionManager.
4813
+ */
4814
+ interface ConnectionManagerConfig {
4815
+ /** Base URL for API requests (used for heartbeat pings) */
4816
+ baseUrl: string;
4817
+ /** Authentication context (iframe vs standalone) for alert routing */
4818
+ authContext?: {
4819
+ isInIframe: boolean;
4820
+ };
4821
+ /** Handler to call when connection issues are detected */
4822
+ onDisconnect?: DisconnectHandler;
4823
+ /** Callback to emit connection change events to the client */
4824
+ onConnectionChange?: (state: ConnectionState, reason: string) => void;
4825
+ }
4826
+ /**
4827
+ * Manages connection monitoring for the Playcademy client.
4828
+ *
4829
+ * The ConnectionManager serves as an integration layer between the low-level
4830
+ * ConnectionMonitor and the PlaycademyClient. It handles:
4831
+ * - Event wiring and coordination
4832
+ * - Disconnect callbacks with context
4833
+ * - Platform-level alert integration
4834
+ * - Request success/failure tracking
4835
+ *
4836
+ * This class is used internally by PlaycademyClient and typically not
4837
+ * instantiated directly by game developers.
4838
+ *
4839
+ * @see {@link ConnectionMonitor} for the underlying monitoring implementation
4840
+ * @see {@link PlaycademyClient.onDisconnect} for the public API
4841
+ */
4842
+ declare class ConnectionManager {
4843
+ private monitor?;
4844
+ private authContext?;
4845
+ private disconnectHandler?;
4846
+ private connectionChangeCallback?;
4847
+ private currentState;
4848
+ private additionalDisconnectHandlers;
4849
+ /**
4850
+ * Creates a new ConnectionManager instance.
4851
+ *
4852
+ * @param config - Configuration options for the manager
4853
+ *
4854
+ * @example
4855
+ * ```typescript
4856
+ * const manager = new ConnectionManager({
4857
+ * baseUrl: 'https://api.playcademy.com',
4858
+ * authContext: { isInIframe: false },
4859
+ * onDisconnect: (context) => {
4860
+ * console.log(`Disconnected: ${context.state}`)
4861
+ * },
4862
+ * onConnectionChange: (state, reason) => {
4863
+ * console.log(`Connection changed: ${state}`)
4864
+ * }
4865
+ * })
4866
+ * ```
4867
+ */
4868
+ constructor(config: ConnectionManagerConfig);
4869
+ /**
4870
+ * Gets the current connection state.
4871
+ *
4872
+ * @returns The current connection state ('online', 'offline', or 'degraded')
4873
+ *
4874
+ * @example
4875
+ * ```typescript
4876
+ * const state = manager.getState()
4877
+ * if (state === 'offline') {
4878
+ * console.log('No connection')
4879
+ * }
4880
+ * ```
4881
+ */
4882
+ getState(): ConnectionState;
4883
+ /**
4884
+ * Manually triggers a connection check immediately.
4885
+ *
4886
+ * Forces a heartbeat ping to verify the current connection status.
4887
+ * Useful when you need to check connectivity before a critical operation.
4888
+ *
4889
+ * In iframe mode, this returns the last known state from platform.
4890
+ *
4891
+ * @returns Promise resolving to the current connection state
4892
+ *
4893
+ * @example
4894
+ * ```typescript
4895
+ * const state = await manager.checkNow()
4896
+ * if (state === 'online') {
4897
+ * await performCriticalOperation()
4898
+ * }
4899
+ * ```
4900
+ */
4901
+ checkNow(): Promise<ConnectionState>;
4902
+ /**
4903
+ * Reports a successful API request to the connection monitor.
4904
+ *
4905
+ * This resets the consecutive failure counter and transitions from
4906
+ * 'degraded' to 'online' state if applicable.
4907
+ *
4908
+ * Typically called automatically by the SDK's request wrapper.
4909
+ * No-op in iframe mode (platform handles monitoring).
4910
+ */
4911
+ reportRequestSuccess(): void;
4912
+ /**
4913
+ * Reports a failed API request to the connection monitor.
4914
+ *
4915
+ * Only network errors are tracked (not 4xx/5xx HTTP responses).
4916
+ * After consecutive failures exceed the threshold, the state transitions
4917
+ * to 'degraded' or 'offline'.
4918
+ *
4919
+ * Typically called automatically by the SDK's request wrapper.
4920
+ * No-op in iframe mode (platform handles monitoring).
4921
+ *
4922
+ * @param error - The error from the failed request
4923
+ */
4924
+ reportRequestFailure(error: unknown): void;
4925
+ /**
4926
+ * Registers a callback to be called when connection issues are detected.
4927
+ *
4928
+ * The callback only fires for 'offline' and 'degraded' states, not when
4929
+ * recovering to 'online'. This provides a clean API for games to handle
4930
+ * disconnect scenarios without being notified of every state change.
4931
+ *
4932
+ * Works in both iframe and standalone modes transparently.
4933
+ *
4934
+ * @param callback - Function to call when connection degrades
4935
+ * @returns Cleanup function to unregister the callback
4936
+ *
4937
+ * @example
4938
+ * ```typescript
4939
+ * const cleanup = manager.onDisconnect(({ state, reason, displayAlert }) => {
4940
+ * if (state === 'offline') {
4941
+ * displayAlert?.('Connection lost. Saving your progress...', { type: 'error' })
4942
+ * saveGameState()
4943
+ * }
4944
+ * })
4945
+ *
4946
+ * // Later: cleanup() to unregister
4947
+ * ```
4948
+ */
4949
+ onDisconnect(callback: DisconnectHandler): () => void;
4950
+ /**
4951
+ * Stops connection monitoring and performs cleanup.
4952
+ *
4953
+ * Removes event listeners and clears heartbeat intervals.
4954
+ * Should be called when the client is being destroyed.
4955
+ */
4956
+ stop(): void;
4957
+ /**
4958
+ * Sets up listener for platform connection state broadcasts (iframe mode only).
4959
+ */
4960
+ private _setupPlatformListener;
4961
+ /**
4962
+ * Handles connection state changes from the monitor or platform.
4963
+ *
4964
+ * Coordinates between:
4965
+ * 1. Emitting events to the client (for client.on('connectionChange'))
4966
+ * 2. Calling the disconnect handler if configured
4967
+ * 3. Calling any additional handlers registered via onDisconnect()
4968
+ *
4969
+ * @param state - The new connection state
4970
+ * @param reason - Human-readable reason for the state change
4971
+ */
4972
+ private _handleConnectionChange;
4446
4973
  }
4447
- declare function extractApiErrorInfo(error: unknown): ApiErrorInfo | null;
4448
4974
 
4449
4975
  /**
4450
4976
  * @fileoverview Playcademy Messaging System
@@ -4527,6 +5053,14 @@ declare enum MessageEvents {
4527
5053
  * Payload: boolean (true = show overlay, false = hide overlay)
4528
5054
  */
4529
5055
  OVERLAY = "PLAYCADEMY_OVERLAY",
5056
+ /**
5057
+ * Broadcasts connection state changes to games.
5058
+ * Sent by platform when network connectivity changes.
5059
+ * Payload:
5060
+ * - `state`: 'online' | 'offline' | 'degraded'
5061
+ * - `reason`: string
5062
+ */
5063
+ CONNECTION_STATE = "PLAYCADEMY_CONNECTION_STATE",
4530
5064
  /**
4531
5065
  * Game has finished loading and is ready to receive messages.
4532
5066
  * Sent once after game initialization is complete.
@@ -4556,6 +5090,14 @@ declare enum MessageEvents {
4556
5090
  * - `type`: 'keydown' | 'keyup'
4557
5091
  */
4558
5092
  KEY_EVENT = "PLAYCADEMY_KEY_EVENT",
5093
+ /**
5094
+ * Game requests platform to display an alert.
5095
+ * Sent when connection issues are detected or other important events occur.
5096
+ * Payload:
5097
+ * - `message`: string
5098
+ * - `options`: { type?: 'info' | 'warning' | 'error', duration?: number }
5099
+ */
5100
+ DISPLAY_ALERT = "PLAYCADEMY_DISPLAY_ALERT",
4559
5101
  /**
4560
5102
  * Notifies about authentication state changes.
4561
5103
  * Can be sent in both directions depending on auth flow.
@@ -4611,6 +5153,8 @@ type MessageEventMap = {
4611
5153
  [MessageEvents.FORCE_EXIT]: void;
4612
5154
  /** Overlay visibility state (true = show, false = hide) */
4613
5155
  [MessageEvents.OVERLAY]: boolean;
5156
+ /** Connection state change from platform */
5157
+ [MessageEvents.CONNECTION_STATE]: ConnectionStatePayload;
4614
5158
  /** Ready message has no payload data */
4615
5159
  [MessageEvents.READY]: void;
4616
5160
  /** Exit message has no payload data */
@@ -4619,6 +5163,8 @@ type MessageEventMap = {
4619
5163
  [MessageEvents.TELEMETRY]: TelemetryPayload;
4620
5164
  /** Key event data */
4621
5165
  [MessageEvents.KEY_EVENT]: KeyEventPayload;
5166
+ /** Display alert request from game */
5167
+ [MessageEvents.DISPLAY_ALERT]: DisplayAlertPayload;
4622
5168
  /** Authentication state change notification */
4623
5169
  [MessageEvents.AUTH_STATE_CHANGE]: AuthStateChangePayload;
4624
5170
  /** OAuth callback data from popup/new-tab windows */
@@ -4990,5 +5536,5 @@ declare class PlaycademyMessaging {
4990
5536
  */
4991
5537
  declare const messaging: PlaycademyMessaging;
4992
5538
 
4993
- export { ApiError, MessageEvents, PlaycademyClient, PlaycademyError, extractApiErrorInfo, messaging };
4994
- export type { ApiErrorInfo, DevUploadEvent, DevUploadHooks };
5539
+ export { ApiError, ConnectionManager, ConnectionMonitor, MessageEvents, PlaycademyClient, PlaycademyError, extractApiErrorInfo, messaging };
5540
+ export type { ApiErrorInfo, ConnectionMonitorConfig, ConnectionState, ConnectionStatePayload, DevUploadEvent, DevUploadHooks, DisconnectContext, DisconnectHandler, DisplayAlertPayload };