@playcademy/sdk 0.4.1-beta.4 → 0.4.1-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/types.d.ts CHANGED
@@ -22,241 +22,6 @@ declare function parseOAuthState(state: string): {
22
22
  /** Permitted HTTP verbs */
23
23
  type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
24
24
 
25
- /**
26
- * User Types
27
- *
28
- * Enums, DTOs and API response types. Database row types are in @playcademy/data/types.
29
- *
30
- * @module types/user
31
- */
32
- type UserRoleEnumType = 'admin' | 'player' | 'developer' | 'teacher';
33
- type DeveloperStatusEnumType = 'none' | 'pending' | 'approved';
34
- type DeveloperStatusValue = DeveloperStatusEnumType;
35
- type TimebackUserRole = 'administrator' | 'aide' | 'guardian' | 'parent' | 'proctor' | 'relative' | 'student' | 'teacher';
36
- type TimebackOrgType = 'department' | 'school' | 'district' | 'local' | 'state' | 'national';
37
- interface UserEnrollment {
38
- gameId?: string;
39
- courseId: string;
40
- grade: number;
41
- subject: string;
42
- orgId?: string;
43
- }
44
- interface UserOrganization {
45
- id: string;
46
- name: string | null;
47
- type: TimebackOrgType | string;
48
- isPrimary: boolean;
49
- }
50
- interface TimebackStudentProfile {
51
- role: TimebackUserRole;
52
- organizations: UserOrganization[];
53
- }
54
- interface UserTimebackData extends TimebackStudentProfile {
55
- id: string;
56
- enrollments: UserEnrollment[];
57
- }
58
- /**
59
- * OpenID Connect UserInfo claims (NOT a database row).
60
- */
61
- interface UserInfo {
62
- sub: string;
63
- email: string;
64
- name: string | null;
65
- email_verified?: boolean;
66
- given_name?: string;
67
- family_name?: string;
68
- issuer?: string;
69
- lti_roles?: unknown;
70
- lti_context?: unknown;
71
- lti_resource_link?: unknown;
72
- timeback_id?: string;
73
- }
74
- interface DeveloperStatusResponse {
75
- status: DeveloperStatusEnumType;
76
- }
77
- /**
78
- * Authenticated user for API responses.
79
- * Differs from UserRow: omits timebackId, adds hasTimebackAccount and timeback.
80
- */
81
- interface AuthenticatedUser {
82
- id: string;
83
- email: string;
84
- emailVerified: boolean;
85
- name: string | null;
86
- image: string | null;
87
- username: string | null;
88
- role: UserRoleEnumType;
89
- developerStatus: DeveloperStatusEnumType;
90
- characterCreated: boolean;
91
- createdAt: Date;
92
- updatedAt: Date;
93
- hasTimebackAccount: boolean;
94
- timeback?: UserTimebackData;
95
- }
96
- interface GameUser {
97
- id: string;
98
- name: string | null;
99
- role: UserRoleEnumType;
100
- username: string | null;
101
- email: string | null;
102
- timeback?: UserTimebackData;
103
- }
104
-
105
- /**
106
- * Game Types
107
- *
108
- * Literal types and API DTOs. Database row types are in @playcademy/data/types.
109
- *
110
- * @module types/game
111
- */
112
- type GameType = 'hosted' | 'external';
113
- type GamePlatform = 'web' | 'godot' | 'unity' | (string & {});
114
- /**
115
- * Game manifest file format (manifest.json).
116
- * Note: createdAt is a string here because it's parsed from JSON file.
117
- */
118
- interface ManifestV1 {
119
- version: string;
120
- platform: string;
121
- createdAt: string;
122
- }
123
- interface DomainValidationRecords {
124
- ownership?: {
125
- name?: string;
126
- value?: string;
127
- type?: string;
128
- };
129
- ssl?: {
130
- txt_name?: string;
131
- txt_value?: string;
132
- }[];
133
- }
134
-
135
- /**
136
- * Leaderboard Types
137
- *
138
- * @module types/leaderboard
139
- */
140
- type LeaderboardTimeframe = 'all_time' | 'monthly' | 'weekly' | 'daily';
141
- interface LeaderboardOptions {
142
- timeframe?: LeaderboardTimeframe;
143
- limit?: number;
144
- offset?: number;
145
- gameId?: string;
146
- }
147
- interface LeaderboardEntry {
148
- rank: number;
149
- userId: string;
150
- username: string;
151
- userImage?: string | null;
152
- score: number;
153
- achievedAt: Date;
154
- metadata?: Record<string, unknown>;
155
- gameId?: string;
156
- gameTitle?: string;
157
- gameSlug?: string;
158
- }
159
- interface UserRank {
160
- rank: number;
161
- totalPlayers: number;
162
- score: number;
163
- percentile: number;
164
- }
165
- interface UserRankResponse {
166
- rank: number;
167
- score: number;
168
- userId: string;
169
- }
170
- interface UserScore {
171
- id: string;
172
- score: number;
173
- achievedAt: Date;
174
- metadata?: Record<string, unknown>;
175
- gameId: string;
176
- gameTitle: string;
177
- gameSlug: string;
178
- }
179
- /**
180
- * Leaderboard entry with required game context.
181
- * Used when fetching leaderboards for a specific game.
182
- */
183
- interface GameLeaderboardEntry {
184
- rank: number;
185
- userId: string;
186
- username: string;
187
- userImage?: string | null;
188
- score: number;
189
- achievedAt: Date;
190
- metadata?: Record<string, unknown>;
191
- gameId: string;
192
- gameTitle: string;
193
- gameSlug: string;
194
- }
195
-
196
- /**
197
- * Achievement Types
198
- *
199
- * @module types/achievement
200
- */
201
- type AchievementScopeType = 'daily' | 'weekly' | 'monthly' | 'yearly' | 'game' | 'global' | 'map' | 'level' | 'event';
202
- declare enum AchievementCompletionType {
203
- TIME_PLAYED_SESSION = "time_played_session",
204
- INTERACTION = "interaction",
205
- LEADERBOARD_RANK = "leaderboard_rank",
206
- FIRST_SCORE = "first_score",
207
- PERSONAL_BEST = "personal_best"
208
- }
209
- interface AchievementCurrent {
210
- id: string;
211
- title: string;
212
- description?: string | null;
213
- scope: AchievementScopeType;
214
- rewardCredits: number;
215
- limit: number;
216
- completionType: string;
217
- completionConfig: unknown;
218
- target: unknown;
219
- active: boolean;
220
- createdAt?: Date | null;
221
- updatedAt?: Date | null;
222
- status: 'available' | 'completed';
223
- scopeKey: string;
224
- windowStart: string;
225
- windowEnd: string;
226
- }
227
- interface AchievementWithStatus {
228
- id: string;
229
- title: string;
230
- description: string | null;
231
- scope: AchievementScopeType;
232
- rewardCredits: number;
233
- limit: number;
234
- completionType: string;
235
- completionConfig: unknown;
236
- target: unknown;
237
- active: boolean;
238
- createdAt: Date | null;
239
- updatedAt: Date | null;
240
- status: 'available' | 'completed';
241
- scopeKey: string;
242
- windowStart?: string;
243
- windowEnd?: string;
244
- }
245
- interface AchievementHistoryEntry {
246
- achievementId: string;
247
- title: string;
248
- rewardCredits: number;
249
- createdAt: Date;
250
- scopeKey: string;
251
- }
252
- interface AchievementProgressResponse {
253
- achievementId: string;
254
- status: 'completed' | 'already_completed';
255
- rewardCredits: number;
256
- scopeKey: string;
257
- createdAt: Date;
258
- }
259
-
260
25
  /**
261
26
  * TimeBack Enums & Literal Types
262
27
  *
@@ -575,120 +340,67 @@ interface EndActivityResponse {
575
340
  }
576
341
 
577
342
  /**
578
- * Inventory & Shop Types
579
- *
580
- * Literal types for inventory system. Database row types are in @playcademy/data/types.
581
- *
582
- * @module types/inventory
583
- */
584
- /**
585
- * Item categories available on the platform.
586
- */
587
- type ItemType = 'currency' | 'badge' | 'trophy' | 'collectible' | 'consumable' | 'unlock' | 'upgrade' | 'accessory' | 'other';
588
-
589
- /**
590
- * Map & Placement Types
591
- *
592
- * Literal types and JSON shapes for maps. Database row types are in @playcademy/data/types.
343
+ * Achievement Types
593
344
  *
594
- * @module types/map
595
- */
596
- /**
597
- * Allowed map interaction types.
345
+ * @module types/achievement
598
346
  */
599
- type InteractionType = 'game_entry' | 'game_registry' | 'info' | 'teleport' | 'door_in' | 'door_out' | 'npc_interaction' | 'quest_trigger';
600
- /**
601
- * Metadata for interactive map elements.
602
- */
603
- interface MapElementMetadata {
604
- description?: string;
605
- title?: string;
606
- targetMapIdentifier?: string;
607
- targetSpawnTileX?: number;
608
- targetSpawnTileY?: number;
609
- sourceTiledObjects?: Record<string, unknown>[];
610
- [key: string]: unknown;
611
- }
612
- /**
613
- * Metadata describing how an item should be placed on the map.
614
- */
615
- interface PlaceableItemMetadata {
616
- tilesWide?: number;
617
- tilesHigh?: number;
618
- flippable?: boolean;
619
- [key: string]: unknown;
347
+ type AchievementScopeType = 'daily' | 'weekly' | 'monthly' | 'yearly' | 'game' | 'global' | 'map' | 'level' | 'event';
348
+ declare enum AchievementCompletionType {
349
+ TIME_PLAYED_SESSION = "time_played_session",
350
+ INTERACTION = "interaction",
351
+ LEADERBOARD_RANK = "leaderboard_rank",
352
+ FIRST_SCORE = "first_score",
353
+ PERSONAL_BEST = "personal_best"
620
354
  }
621
- /**
622
- * Simplified map data for API responses.
623
- */
624
- interface MapData {
355
+ interface AchievementCurrent {
625
356
  id: string;
626
- identifier: string;
627
- displayName: string;
357
+ title: string;
628
358
  description?: string | null;
629
- metadata?: Record<string, unknown> | null;
630
- }
631
- /**
632
- * Input for creating a map object.
633
- */
634
- interface CreateMapObjectData {
635
- itemId: string;
636
- worldX: number;
637
- worldY: number;
638
- width?: number;
639
- height?: number;
640
- rotation?: number;
641
- scale?: number;
642
- metadata?: Record<string, unknown>;
359
+ scope: AchievementScopeType;
360
+ rewardCredits: number;
361
+ limit: number;
362
+ completionType: string;
363
+ completionConfig: unknown;
364
+ target: unknown;
365
+ active: boolean;
366
+ createdAt?: Date | null;
367
+ updatedAt?: Date | null;
368
+ status: 'available' | 'completed';
369
+ scopeKey: string;
370
+ windowStart: string;
371
+ windowEnd: string;
643
372
  }
644
-
645
- /**
646
- * Character & Avatar Types
647
- *
648
- * Literal types for character system. Database row types are in @playcademy/data/types.
649
- *
650
- * @module types/character
651
- */
652
- /**
653
- * Character component categories.
654
- */
655
- type CharacterComponentType = 'body' | 'outfit' | 'hairstyle' | 'eyes' | 'accessory';
656
-
657
- /**
658
- * Level & Progression Types
659
- *
660
- * API response DTOs for level system. Database row types are in @playcademy/data/types.
661
- *
662
- * @module types/level
663
- */
664
- /**
665
- * Result of adding XP to a user.
666
- */
667
- interface XPAddResult {
668
- totalXP: number;
669
- newLevel: number;
670
- leveledUp: boolean;
671
- creditsAwarded: number;
672
- xpToNextLevel: number;
373
+ interface AchievementWithStatus {
374
+ id: string;
375
+ title: string;
376
+ description: string | null;
377
+ scope: AchievementScopeType;
378
+ rewardCredits: number;
379
+ limit: number;
380
+ completionType: string;
381
+ completionConfig: unknown;
382
+ target: unknown;
383
+ active: boolean;
384
+ createdAt: Date | null;
385
+ updatedAt: Date | null;
386
+ status: 'available' | 'completed';
387
+ scopeKey: string;
388
+ windowStart?: string;
389
+ windowEnd?: string;
673
390
  }
674
- /**
675
- * Result of checking whether a level up occurred.
676
- */
677
- interface LevelUpCheckResult {
678
- newLevel: number;
679
- remainingXp: number;
680
- leveledUp: boolean;
681
- creditsAwarded: number;
682
- xpToNextLevel: number;
391
+ interface AchievementHistoryEntry {
392
+ achievementId: string;
393
+ title: string;
394
+ rewardCredits: number;
395
+ createdAt: Date;
396
+ scopeKey: string;
683
397
  }
684
- /**
685
- * Level progress API response.
686
- */
687
- interface LevelProgressResponse {
688
- level: number;
689
- currentXp: number;
690
- xpToNextLevel: number;
691
- totalXP: number;
398
+ interface AchievementProgressResponse {
399
+ achievementId: string;
400
+ status: 'completed' | 'already_completed';
401
+ rewardCredits: number;
402
+ scopeKey: string;
403
+ createdAt: Date;
692
404
  }
693
405
 
694
406
  /**
@@ -721,435 +433,389 @@ interface NotificationStats {
721
433
  }
722
434
 
723
435
  /**
724
- * Shop Types
436
+ * User Types
725
437
  *
726
- * @module types/shop
727
- */
728
- /**
729
- * Currency display info for shop UI.
438
+ * Enums, DTOs and API response types. Database row types are in @playcademy/data/types.
439
+ *
440
+ * @module types/user
730
441
  */
731
- interface ShopCurrency {
442
+ type UserRoleEnumType = 'admin' | 'player' | 'developer' | 'teacher';
443
+ type DeveloperStatusEnumType = 'none' | 'pending' | 'approved';
444
+ type DeveloperStatusValue = DeveloperStatusEnumType;
445
+ type TimebackUserRole = 'administrator' | 'aide' | 'guardian' | 'parent' | 'proctor' | 'relative' | 'student' | 'teacher';
446
+ type TimebackOrgType = 'department' | 'school' | 'district' | 'local' | 'state' | 'national';
447
+ interface UserEnrollment {
448
+ gameId?: string;
449
+ courseId: string;
450
+ grade: number;
451
+ subject: string;
452
+ orgId?: string;
453
+ }
454
+ interface UserOrganization {
732
455
  id: string;
733
- symbol: string | null;
456
+ name: string | null;
457
+ type: TimebackOrgType | string;
734
458
  isPrimary: boolean;
735
- displayName?: string | null;
736
- imageUrl?: string | null;
459
+ }
460
+ interface TimebackStudentProfile {
461
+ role: TimebackUserRole;
462
+ organizations: UserOrganization[];
463
+ }
464
+ interface UserTimebackData extends TimebackStudentProfile {
465
+ id: string;
466
+ enrollments: UserEnrollment[];
737
467
  }
738
468
  /**
739
- * Shop item for display.
740
- * Combines Item fields (excluding createdAt) with shop listing data.
469
+ * OpenID Connect UserInfo claims (NOT a database row).
741
470
  */
742
- interface ShopDisplayItem {
743
- id: string;
744
- slug: string;
745
- gameId?: string | null;
746
- displayName: string;
747
- description?: string | null;
748
- type: string;
749
- isPlaceable: boolean;
750
- imageUrl?: string | null;
751
- metadata?: unknown;
752
- listingId: string;
753
- shopPrice: number;
754
- currencyId: string;
755
- currencySymbol?: string | null;
756
- currencyDisplayName?: string | null;
757
- currencyImageUrl?: string | null;
758
- stock?: number | null;
759
- sellBackPercentage?: number | null;
471
+ interface UserInfo {
472
+ sub: string;
473
+ email: string;
474
+ name: string | null;
475
+ email_verified?: boolean;
476
+ given_name?: string;
477
+ family_name?: string;
478
+ issuer?: string;
479
+ lti_roles?: unknown;
480
+ lti_context?: unknown;
481
+ lti_resource_link?: unknown;
482
+ timeback_id?: string;
483
+ }
484
+ interface DeveloperStatusResponse {
485
+ status: DeveloperStatusEnumType;
760
486
  }
761
487
  /**
762
- * Complete shop view response.
488
+ * Authenticated user for API responses.
489
+ * Differs from UserRow: omits timebackId, adds hasTimebackAccount and timeback.
763
490
  */
764
- interface ShopViewResponse {
765
- shopItems: ShopDisplayItem[];
766
- currencies: ShopCurrency[];
491
+ interface AuthenticatedUser {
492
+ id: string;
493
+ email: string;
494
+ emailVerified: boolean;
495
+ name: string | null;
496
+ image: string | null;
497
+ username: string | null;
498
+ role: UserRoleEnumType;
499
+ developerStatus: DeveloperStatusEnumType;
500
+ characterCreated: boolean;
501
+ createdAt: Date;
502
+ updatedAt: Date;
503
+ hasTimebackAccount: boolean;
504
+ timeback?: UserTimebackData;
505
+ }
506
+ interface GameUser {
507
+ id: string;
508
+ name: string | null;
509
+ role: UserRoleEnumType;
510
+ username: string | null;
511
+ email: string | null;
512
+ timeback?: UserTimebackData;
767
513
  }
768
514
 
769
515
  /**
770
- * Sprite Types
516
+ * Game Types
771
517
  *
772
- * JSON shapes for sprite configuration. Database row types are in @playcademy/data/types.
518
+ * Literal types and API DTOs. Database row types are in @playcademy/data/types.
773
519
  *
774
- * @module types/sprite
520
+ * @module types/game
775
521
  */
522
+ type GameType = 'hosted' | 'external';
523
+ type GamePlatform = 'web' | 'godot' | 'unity' | (string & {});
776
524
  /**
777
- * Animation frame configuration.
525
+ * Game manifest file format (manifest.json).
526
+ * Note: createdAt is a string here because it's parsed from JSON file.
778
527
  */
779
- interface SpriteAnimationFrame {
780
- row: number;
781
- frameStart: number;
782
- numFrames: number;
783
- fps: number;
784
- }
785
- /**
786
- * Sprite template data structure (stored in JSONB).
787
- */
788
- interface SpriteTemplateData {
789
- tileSize: number;
790
- tileHeight: number;
791
- columns: number;
792
- rows: number;
793
- spacing: number;
794
- animations: {
795
- base_right: SpriteAnimationFrame;
796
- base_up: SpriteAnimationFrame;
797
- base_left: SpriteAnimationFrame;
798
- base_down: SpriteAnimationFrame;
799
- idle_right: SpriteAnimationFrame;
800
- walk_right: SpriteAnimationFrame;
801
- idle_up: SpriteAnimationFrame;
802
- walk_up: SpriteAnimationFrame;
803
- idle_left: SpriteAnimationFrame;
804
- walk_left: SpriteAnimationFrame;
805
- idle_down: SpriteAnimationFrame;
806
- walk_down: SpriteAnimationFrame;
528
+ interface ManifestV1 {
529
+ version: string;
530
+ platform: string;
531
+ createdAt: string;
532
+ }
533
+ interface DomainValidationRecords {
534
+ ownership?: {
535
+ name?: string;
536
+ value?: string;
537
+ type?: string;
807
538
  };
539
+ ssl?: {
540
+ txt_name?: string;
541
+ txt_value?: string;
542
+ }[];
808
543
  }
544
+
809
545
  /**
810
- * Sprite sheet configuration with precomputed dimensions.
546
+ * Leaderboard Types
547
+ *
548
+ * @module types/leaderboard
811
549
  */
812
- interface SpriteConfigWithDimensions {
813
- textureUrl: string;
814
- columns: number;
815
- rows: number;
816
- spriteWidth: number;
817
- spriteHeight: number;
818
- animations: Record<string, SpriteAnimationFrame>;
550
+ type LeaderboardTimeframe = 'all_time' | 'monthly' | 'weekly' | 'daily';
551
+ interface LeaderboardOptions {
552
+ timeframe?: LeaderboardTimeframe;
553
+ limit?: number;
554
+ offset?: number;
555
+ gameId?: string;
556
+ }
557
+ interface LeaderboardEntry {
558
+ rank: number;
559
+ userId: string;
560
+ username: string;
561
+ userImage?: string | null;
562
+ score: number;
563
+ achievedAt: Date;
564
+ metadata?: Record<string, unknown>;
565
+ gameId?: string;
566
+ gameTitle?: string;
567
+ gameSlug?: string;
568
+ }
569
+ interface UserRank {
570
+ rank: number;
571
+ totalPlayers: number;
572
+ score: number;
573
+ percentile: number;
574
+ }
575
+ interface UserRankResponse {
576
+ rank: number;
577
+ score: number;
578
+ userId: string;
579
+ }
580
+ interface UserScore {
581
+ id: string;
582
+ score: number;
583
+ achievedAt: Date;
584
+ metadata?: Record<string, unknown>;
585
+ gameId: string;
586
+ gameTitle: string;
587
+ gameSlug: string;
588
+ }
589
+ /**
590
+ * Leaderboard entry with required game context.
591
+ * Used when fetching leaderboards for a specific game.
592
+ */
593
+ interface GameLeaderboardEntry {
594
+ rank: number;
595
+ userId: string;
596
+ username: string;
597
+ userImage?: string | null;
598
+ score: number;
599
+ achievedAt: Date;
600
+ metadata?: Record<string, unknown>;
601
+ gameId: string;
602
+ gameTitle: string;
603
+ gameSlug: string;
819
604
  }
820
605
 
821
606
  /**
822
- * Connection monitoring types
607
+ * Inventory & Shop Types
823
608
  *
824
- * Type definitions for connection state, configuration, and callbacks.
609
+ * Literal types for inventory system. Database row types are in @playcademy/data/types.
610
+ *
611
+ * @module types/inventory
825
612
  */
826
613
  /**
827
- * Possible connection states.
828
- *
829
- * - **online**: Connection is stable and healthy
830
- * - **offline**: Complete loss of network connectivity
831
- * - **degraded**: Connection is slow or experiencing intermittent issues
614
+ * Item categories available on the platform.
832
615
  */
833
- type ConnectionState = 'online' | 'offline' | 'degraded';
616
+ type ItemType = 'currency' | 'badge' | 'trophy' | 'collectible' | 'consumable' | 'unlock' | 'upgrade' | 'accessory' | 'other';
834
617
 
835
618
  /**
836
- * Connection Manager
619
+ * Map & Placement Types
837
620
  *
838
- * Manages connection monitoring and integrates it with the Playcademy client.
839
- * Handles event wiring, state management, and disconnect callbacks.
621
+ * Literal types and JSON shapes for maps. Database row types are in @playcademy/data/types.
840
622
  *
841
- * In iframe mode, disables local monitoring and listens to platform connection
842
- * state broadcasts instead (avoids duplicate heartbeats).
623
+ * @module types/map
843
624
  */
844
-
845
625
  /**
846
- * Configuration for the ConnectionManager.
626
+ * Allowed map interaction types.
847
627
  */
848
- interface ConnectionManagerConfig {
849
- /** Base URL for API requests (used for heartbeat pings) */
850
- baseUrl: string;
851
- /** Authentication context (iframe vs standalone) for alert routing */
852
- authContext?: {
853
- isInIframe: boolean;
854
- };
855
- /** Handler to call when connection issues are detected */
856
- onDisconnect?: DisconnectHandler;
857
- /** Callback to emit connection change events to the client */
858
- onConnectionChange?: (state: ConnectionState, reason: string) => void;
628
+ type InteractionType = 'game_entry' | 'game_registry' | 'info' | 'teleport' | 'door_in' | 'door_out' | 'npc_interaction' | 'quest_trigger';
629
+ /**
630
+ * Metadata for interactive map elements.
631
+ */
632
+ interface MapElementMetadata {
633
+ description?: string;
634
+ title?: string;
635
+ targetMapIdentifier?: string;
636
+ targetSpawnTileX?: number;
637
+ targetSpawnTileY?: number;
638
+ sourceTiledObjects?: Record<string, unknown>[];
639
+ [key: string]: unknown;
859
640
  }
860
641
  /**
861
- * Manages connection monitoring for the Playcademy client.
862
- *
863
- * The ConnectionManager serves as an integration layer between the low-level
864
- * ConnectionMonitor and the PlaycademyClient. It handles:
865
- * - Event wiring and coordination
866
- * - Disconnect callbacks with context
867
- * - Platform-level alert integration
868
- * - Request success/failure tracking
869
- *
870
- * This class is used internally by PlaycademyClient and typically not
871
- * instantiated directly by game developers.
872
- *
873
- * @see {@link ConnectionMonitor} for the underlying monitoring implementation
874
- * @see {@link PlaycademyClient.onDisconnect} for the public API
642
+ * Metadata describing how an item should be placed on the map.
875
643
  */
876
- declare class ConnectionManager {
877
- private monitor?;
878
- private authContext?;
879
- private disconnectHandler?;
880
- private connectionChangeCallback?;
881
- private currentState;
882
- private additionalDisconnectHandlers;
883
- /**
884
- * Creates a new ConnectionManager instance.
885
- *
886
- * @param config - Configuration options for the manager
887
- *
888
- * @example
889
- * ```typescript
890
- * const manager = new ConnectionManager({
891
- * baseUrl: 'https://api.playcademy.com',
892
- * authContext: { isInIframe: false },
893
- * onDisconnect: (context) => {
894
- * console.log(`Disconnected: ${context.state}`)
895
- * },
896
- * onConnectionChange: (state, reason) => {
897
- * console.log(`Connection changed: ${state}`)
898
- * }
899
- * })
900
- * ```
901
- */
902
- constructor(config: ConnectionManagerConfig);
903
- /**
904
- * Gets the current connection state.
905
- *
906
- * @returns The current connection state ('online', 'offline', or 'degraded')
907
- *
908
- * @example
909
- * ```typescript
910
- * const state = manager.getState()
911
- * if (state === 'offline') {
912
- * console.log('No connection')
913
- * }
914
- * ```
915
- */
916
- getState(): ConnectionState;
917
- /**
918
- * Manually triggers a connection check immediately.
919
- *
920
- * Forces a heartbeat ping to verify the current connection status.
921
- * Useful when you need to check connectivity before a critical operation.
922
- *
923
- * In iframe mode, this returns the last known state from platform.
924
- *
925
- * @returns Promise resolving to the current connection state
926
- *
927
- * @example
928
- * ```typescript
929
- * const state = await manager.checkNow()
930
- * if (state === 'online') {
931
- * await performCriticalOperation()
932
- * }
933
- * ```
934
- */
935
- checkNow(): Promise<ConnectionState>;
936
- /**
937
- * Reports a successful API request to the connection monitor.
938
- *
939
- * This resets the consecutive failure counter and transitions from
940
- * 'degraded' to 'online' state if applicable.
941
- *
942
- * Typically called automatically by the SDK's request wrapper.
943
- * No-op in iframe mode (platform handles monitoring).
944
- */
945
- reportRequestSuccess(): void;
946
- /**
947
- * Reports a failed API request to the connection monitor.
948
- *
949
- * Only network errors are tracked (not 4xx/5xx HTTP responses).
950
- * After consecutive failures exceed the threshold, the state transitions
951
- * to 'degraded' or 'offline'.
952
- *
953
- * Typically called automatically by the SDK's request wrapper.
954
- * No-op in iframe mode (platform handles monitoring).
955
- *
956
- * @param error - The error from the failed request
957
- */
958
- reportRequestFailure(error: unknown): void;
959
- /**
960
- * Registers a callback to be called when connection issues are detected.
961
- *
962
- * The callback only fires for 'offline' and 'degraded' states, not when
963
- * recovering to 'online'. This provides a clean API for games to handle
964
- * disconnect scenarios without being notified of every state change.
965
- *
966
- * Works in both iframe and standalone modes transparently.
967
- *
968
- * @param callback - Function to call when connection degrades
969
- * @returns Cleanup function to unregister the callback
970
- *
971
- * @example
972
- * ```typescript
973
- * const cleanup = manager.onDisconnect(({ state, reason, displayAlert }) => {
974
- * if (state === 'offline') {
975
- * displayAlert?.('Connection lost. Saving your progress...', { type: 'error' })
976
- * saveGameState()
977
- * }
978
- * })
979
- *
980
- * // Later: cleanup() to unregister
981
- * ```
982
- */
983
- onDisconnect(callback: DisconnectHandler): () => void;
984
- /**
985
- * Stops connection monitoring and performs cleanup.
986
- *
987
- * Removes event listeners and clears heartbeat intervals.
988
- * Should be called when the client is being destroyed.
989
- */
990
- stop(): void;
991
- /**
992
- * Sets up listener for platform connection state broadcasts (iframe mode only).
993
- */
994
- private _setupPlatformListener;
995
- /**
996
- * Handles connection state changes from the monitor or platform.
997
- *
998
- * Coordinates between:
999
- * 1. Emitting events to the client (for client.on('connectionChange'))
1000
- * 2. Calling the disconnect handler if configured
1001
- * 3. Calling any additional handlers registered via onDisconnect()
1002
- *
1003
- * @param state - The new connection state
1004
- * @param reason - Human-readable reason for the state change
1005
- */
1006
- private _handleConnectionChange;
644
+ interface PlaceableItemMetadata {
645
+ tilesWide?: number;
646
+ tilesHigh?: number;
647
+ flippable?: boolean;
648
+ [key: string]: unknown;
649
+ }
650
+ /**
651
+ * Simplified map data for API responses.
652
+ */
653
+ interface MapData {
654
+ id: string;
655
+ identifier: string;
656
+ displayName: string;
657
+ description?: string | null;
658
+ metadata?: Record<string, unknown> | null;
659
+ }
660
+ /**
661
+ * Input for creating a map object.
662
+ */
663
+ interface CreateMapObjectData {
664
+ itemId: string;
665
+ worldX: number;
666
+ worldY: number;
667
+ width?: number;
668
+ height?: number;
669
+ rotation?: number;
670
+ scale?: number;
671
+ metadata?: Record<string, unknown>;
1007
672
  }
1008
673
 
1009
674
  /**
1010
- * @fileoverview Playcademy Messaging System
1011
- *
1012
- * This file implements a unified messaging system for the Playcademy platform that handles
1013
- * communication between different contexts:
1014
- *
1015
- * 1. **Iframe-to-Parent Communication**: When games run inside iframes (production/development),
1016
- * they need to communicate with the parent window using postMessage API
1017
- *
1018
- * 2. **Local Communication**: When games run in the same context (local development),
1019
- * they use CustomEvents for internal messaging
675
+ * Character & Avatar Types
1020
676
  *
1021
- * The system automatically detects the runtime environment and chooses the appropriate
1022
- * transport method, abstracting this complexity from the developer.
677
+ * Literal types for character system. Database row types are in @playcademy/data/types.
1023
678
  *
1024
- * **Architecture Overview**:
1025
- * - Games run in iframes for security and isolation
1026
- * - Parent window (Playcademy shell) manages game lifecycle
1027
- * - Messages flow bidirectionally between parent and iframe
1028
- * - Local development mode simulates this architecture without iframes
679
+ * @module types/character
680
+ */
681
+ /**
682
+ * Character component categories.
1029
683
  */
684
+ type CharacterComponentType = 'body' | 'outfit' | 'hairstyle' | 'eyes' | 'accessory';
1030
685
 
1031
686
  /**
1032
- * Enumeration of all message types used in the Playcademy messaging system.
1033
- *
1034
- * **Message Flow Patterns**:
687
+ * Level & Progression Types
1035
688
  *
1036
- * **Parent Game (Overworld Game)**:
1037
- * - INIT: Provides game with authentication token and configuration
1038
- * - TOKEN_REFRESH: Updates game's authentication token before expiry
1039
- * - PAUSE/RESUME: Controls game execution state
1040
- * - FORCE_EXIT: Immediately terminates the game
1041
- * - OVERLAY: Shows/hides UI overlays over the game
689
+ * API response DTOs for level system. Database row types are in @playcademy/data/types.
1042
690
  *
1043
- * **Game → Parent (Game → Overworld)**:
1044
- * - READY: Game has loaded and is ready to receive messages
1045
- * - EXIT: Game requests to be closed (user clicked exit, game ended, etc.)
1046
- * - TELEMETRY: Game reports performance metrics (FPS, memory usage, etc.)
691
+ * @module types/level
1047
692
  */
1048
- declare enum MessageEvents {
1049
- /**
1050
- * Initializes the game with authentication context and configuration.
1051
- * Sent immediately after game iframe loads.
1052
- * Payload:
1053
- * - `baseUrl`: string
1054
- * - `token`: string
1055
- * - `gameId`: string
1056
- */
1057
- INIT = "PLAYCADEMY_INIT",
1058
- /**
1059
- * Updates the game's authentication token before it expires.
1060
- * Sent periodically to maintain valid authentication.
1061
- * Payload:
1062
- * - `token`: string
1063
- * - `exp`: number
1064
- */
1065
- TOKEN_REFRESH = "PLAYCADEMY_TOKEN_REFRESH",
1066
- /**
1067
- * Pauses game execution (e.g., when user switches tabs).
1068
- * Game should pause timers, animations, and user input.
1069
- * Payload: void
1070
- */
1071
- PAUSE = "PLAYCADEMY_PAUSE",
1072
- /**
1073
- * Resumes game execution after being paused.
1074
- * Game should restore timers, animations, and user input.
1075
- * Payload: void
1076
- */
1077
- RESUME = "PLAYCADEMY_RESUME",
1078
- /**
1079
- * Forces immediate game termination (emergency exit).
1080
- * Game should clean up resources and exit immediately.
1081
- * Payload: void
1082
- */
1083
- FORCE_EXIT = "PLAYCADEMY_FORCE_EXIT",
1084
- /**
1085
- * Shows or hides UI overlays over the game.
1086
- * Game may need to pause or adjust rendering accordingly.
1087
- * Payload: boolean (true = show overlay, false = hide overlay)
1088
- */
1089
- OVERLAY = "PLAYCADEMY_OVERLAY",
1090
- /**
1091
- * Broadcasts connection state changes to games.
1092
- * Sent by platform when network connectivity changes.
1093
- * Payload:
1094
- * - `state`: 'online' | 'offline' | 'degraded'
1095
- * - `reason`: string
1096
- */
1097
- CONNECTION_STATE = "PLAYCADEMY_CONNECTION_STATE",
1098
- /**
1099
- * Game has finished loading and is ready to receive messages.
1100
- * Sent once after game initialization is complete.
1101
- * Payload: void
1102
- */
1103
- READY = "PLAYCADEMY_READY",
1104
- /**
1105
- * Game requests to be closed/exited.
1106
- * Sent when user clicks exit button or game naturally ends.
1107
- * Payload: void
1108
- */
1109
- EXIT = "PLAYCADEMY_EXIT",
1110
- /**
1111
- * Game reports performance telemetry data.
1112
- * Sent periodically for monitoring and analytics.
1113
- * Payload:
1114
- * - `fps`: number
1115
- * - `mem`: number
1116
- */
1117
- TELEMETRY = "PLAYCADEMY_TELEMETRY",
1118
- /**
1119
- * Game reports key events to parent.
1120
- * Sent when certain keys are pressed within the game iframe.
1121
- * Payload:
1122
- * - `key`: string
1123
- * - `code?`: string
1124
- * - `type`: 'keydown' | 'keyup'
1125
- */
1126
- KEY_EVENT = "PLAYCADEMY_KEY_EVENT",
1127
- /**
1128
- * Game requests platform to display an alert.
1129
- * Sent when connection issues are detected or other important events occur.
1130
- * Payload:
1131
- * - `message`: string
1132
- * - `options`: `{ type?: 'info' | 'warning' | 'error', duration?: number }`
1133
- */
1134
- DISPLAY_ALERT = "PLAYCADEMY_DISPLAY_ALERT",
1135
- /**
1136
- * Notifies about authentication state changes.
1137
- * Can be sent in both directions depending on auth flow.
1138
- * Payload:
1139
- * - `authenticated`: boolean
1140
- * - `user`: UserInfo | null
1141
- * - `error`: Error | null
1142
- */
1143
- AUTH_STATE_CHANGE = "PLAYCADEMY_AUTH_STATE_CHANGE",
1144
- /**
1145
- * OAuth callback data from popup/new-tab windows.
1146
- * Sent from popup window back to parent after OAuth completes.
1147
- * Payload:
1148
- * - `code`: string (OAuth authorization code)
1149
- * - `state`: string (OAuth state for CSRF protection)
1150
- * - `error`: string | null (OAuth error if any)
1151
- */
1152
- AUTH_CALLBACK = "PLAYCADEMY_AUTH_CALLBACK"
693
+ /**
694
+ * Result of adding XP to a user.
695
+ */
696
+ interface XPAddResult {
697
+ totalXP: number;
698
+ newLevel: number;
699
+ leveledUp: boolean;
700
+ creditsAwarded: number;
701
+ xpToNextLevel: number;
702
+ }
703
+ /**
704
+ * Result of checking whether a level up occurred.
705
+ */
706
+ interface LevelUpCheckResult {
707
+ newLevel: number;
708
+ remainingXp: number;
709
+ leveledUp: boolean;
710
+ creditsAwarded: number;
711
+ xpToNextLevel: number;
712
+ }
713
+ /**
714
+ * Level progress API response.
715
+ */
716
+ interface LevelProgressResponse {
717
+ level: number;
718
+ currentXp: number;
719
+ xpToNextLevel: number;
720
+ totalXP: number;
721
+ }
722
+
723
+ /**
724
+ * Shop Types
725
+ *
726
+ * @module types/shop
727
+ */
728
+ /**
729
+ * Currency display info for shop UI.
730
+ */
731
+ interface ShopCurrency {
732
+ id: string;
733
+ symbol: string | null;
734
+ isPrimary: boolean;
735
+ displayName?: string | null;
736
+ imageUrl?: string | null;
737
+ }
738
+ /**
739
+ * Shop item for display.
740
+ * Combines Item fields (excluding createdAt) with shop listing data.
741
+ */
742
+ interface ShopDisplayItem {
743
+ id: string;
744
+ slug: string;
745
+ gameId?: string | null;
746
+ displayName: string;
747
+ description?: string | null;
748
+ type: string;
749
+ isPlaceable: boolean;
750
+ imageUrl?: string | null;
751
+ metadata?: unknown;
752
+ listingId: string;
753
+ shopPrice: number;
754
+ currencyId: string;
755
+ currencySymbol?: string | null;
756
+ currencyDisplayName?: string | null;
757
+ currencyImageUrl?: string | null;
758
+ stock?: number | null;
759
+ sellBackPercentage?: number | null;
760
+ }
761
+ /**
762
+ * Complete shop view response.
763
+ */
764
+ interface ShopViewResponse {
765
+ shopItems: ShopDisplayItem[];
766
+ currencies: ShopCurrency[];
767
+ }
768
+
769
+ /**
770
+ * Sprite Types
771
+ *
772
+ * JSON shapes for sprite configuration. Database row types are in @playcademy/data/types.
773
+ *
774
+ * @module types/sprite
775
+ */
776
+ /**
777
+ * Animation frame configuration.
778
+ */
779
+ interface SpriteAnimationFrame {
780
+ row: number;
781
+ frameStart: number;
782
+ numFrames: number;
783
+ fps: number;
784
+ }
785
+ /**
786
+ * Sprite template data structure (stored in JSONB).
787
+ */
788
+ interface SpriteTemplateData {
789
+ tileSize: number;
790
+ tileHeight: number;
791
+ columns: number;
792
+ rows: number;
793
+ spacing: number;
794
+ animations: {
795
+ base_right: SpriteAnimationFrame;
796
+ base_up: SpriteAnimationFrame;
797
+ base_left: SpriteAnimationFrame;
798
+ base_down: SpriteAnimationFrame;
799
+ idle_right: SpriteAnimationFrame;
800
+ walk_right: SpriteAnimationFrame;
801
+ idle_up: SpriteAnimationFrame;
802
+ walk_up: SpriteAnimationFrame;
803
+ idle_left: SpriteAnimationFrame;
804
+ walk_left: SpriteAnimationFrame;
805
+ idle_down: SpriteAnimationFrame;
806
+ walk_down: SpriteAnimationFrame;
807
+ };
808
+ }
809
+ /**
810
+ * Sprite sheet configuration with precomputed dimensions.
811
+ */
812
+ interface SpriteConfigWithDimensions {
813
+ textureUrl: string;
814
+ columns: number;
815
+ rows: number;
816
+ spriteWidth: number;
817
+ spriteHeight: number;
818
+ animations: Record<string, SpriteAnimationFrame>;
1153
819
  }
1154
820
 
1155
821
  declare const users: drizzle_orm_pg_core.PgTableWithColumns<{
@@ -4668,44 +4334,232 @@ interface PlayerSessionPayload {
4668
4334
  characterCreated?: UserRow['characterCreated'];
4669
4335
  playerCharacter?: PlayerCharacterRow | null;
4670
4336
  }
4671
- /**
4672
- * Map-related Composite Types
4673
- * DB row + joined game/item data
4674
- */
4675
- type MapElementWithGame = MapElementRow & {
4676
- game: {
4677
- id: string;
4678
- displayName: string;
4679
- } | null;
4680
- };
4681
- type MapObjectWithItem = MapObjectRow & {
4682
- item: {
4683
- id: string;
4684
- slug: string;
4685
- displayName: string;
4686
- description?: string | null;
4687
- imageUrl?: string | null;
4688
- isPlaceable: boolean;
4689
- metadata?: PlaceableItemMetadata | null;
4690
- };
4691
- };
4692
- /**
4693
- * Game custom hostname with validation records
4694
- */
4695
- type GameCustomHostname = GameCustomHostnameRow & {
4696
- validationRecords?: DomainValidationRecords;
4697
- };
4698
-
4699
- type UserLevelRow = typeof userLevels.$inferSelect;
4700
- type LevelConfigRow = typeof levelConfigs.$inferSelect;
4701
- type UserLevelWithConfig = UserLevelRow & {
4702
- xpToNextLevel: number;
4703
- nextLevelConfig?: LevelConfigRow;
4704
- };
4705
-
4706
- type SpriteTemplateRow = typeof spriteTemplates.$inferSelect;
4707
-
4708
- type NotificationRow = InferSelectModel<typeof notifications>;
4337
+ /**
4338
+ * Map-related Composite Types
4339
+ * DB row + joined game/item data
4340
+ */
4341
+ type MapElementWithGame = MapElementRow & {
4342
+ game: {
4343
+ id: string;
4344
+ displayName: string;
4345
+ } | null;
4346
+ };
4347
+ type MapObjectWithItem = MapObjectRow & {
4348
+ item: {
4349
+ id: string;
4350
+ slug: string;
4351
+ displayName: string;
4352
+ description?: string | null;
4353
+ imageUrl?: string | null;
4354
+ isPlaceable: boolean;
4355
+ metadata?: PlaceableItemMetadata | null;
4356
+ };
4357
+ };
4358
+ /**
4359
+ * Game custom hostname with validation records
4360
+ */
4361
+ type GameCustomHostname = GameCustomHostnameRow & {
4362
+ validationRecords?: DomainValidationRecords;
4363
+ };
4364
+
4365
+ type UserLevelRow = typeof userLevels.$inferSelect;
4366
+ type LevelConfigRow = typeof levelConfigs.$inferSelect;
4367
+ type UserLevelWithConfig = UserLevelRow & {
4368
+ xpToNextLevel: number;
4369
+ nextLevelConfig?: LevelConfigRow;
4370
+ };
4371
+
4372
+ type SpriteTemplateRow = typeof spriteTemplates.$inferSelect;
4373
+
4374
+ type NotificationRow = InferSelectModel<typeof notifications>;
4375
+
4376
+ /**
4377
+ * Connection monitoring types
4378
+ *
4379
+ * Type definitions for connection state, configuration, and callbacks.
4380
+ */
4381
+ /**
4382
+ * Possible connection states.
4383
+ *
4384
+ * - **online**: Connection is stable and healthy
4385
+ * - **offline**: Complete loss of network connectivity
4386
+ * - **degraded**: Connection is slow or experiencing intermittent issues
4387
+ */
4388
+ type ConnectionState = 'online' | 'offline' | 'degraded';
4389
+
4390
+ /**
4391
+ * Connection Manager
4392
+ *
4393
+ * Manages connection monitoring and integrates it with the Playcademy client.
4394
+ * Handles event wiring, state management, and disconnect callbacks.
4395
+ *
4396
+ * In iframe mode, disables local monitoring and listens to platform connection
4397
+ * state broadcasts instead (avoids duplicate heartbeats).
4398
+ */
4399
+
4400
+ /**
4401
+ * Configuration for the ConnectionManager.
4402
+ */
4403
+ interface ConnectionManagerConfig {
4404
+ /** Base URL for API requests (used for heartbeat pings) */
4405
+ baseUrl: string;
4406
+ /** Authentication context (iframe vs standalone) for alert routing */
4407
+ authContext?: {
4408
+ isInIframe: boolean;
4409
+ };
4410
+ /** Handler to call when connection issues are detected */
4411
+ onDisconnect?: DisconnectHandler;
4412
+ /** Callback to emit connection change events to the client */
4413
+ onConnectionChange?: (state: ConnectionState, reason: string) => void;
4414
+ }
4415
+ /**
4416
+ * Manages connection monitoring for the Playcademy client.
4417
+ *
4418
+ * The ConnectionManager serves as an integration layer between the low-level
4419
+ * ConnectionMonitor and the PlaycademyClient. It handles:
4420
+ * - Event wiring and coordination
4421
+ * - Disconnect callbacks with context
4422
+ * - Platform-level alert integration
4423
+ * - Request success/failure tracking
4424
+ *
4425
+ * This class is used internally by PlaycademyClient and typically not
4426
+ * instantiated directly by game developers.
4427
+ *
4428
+ * @see {@link ConnectionMonitor} for the underlying monitoring implementation
4429
+ * @see {@link PlaycademyClient.onDisconnect} for the public API
4430
+ */
4431
+ declare class ConnectionManager {
4432
+ private monitor?;
4433
+ private authContext?;
4434
+ private disconnectHandler?;
4435
+ private connectionChangeCallback?;
4436
+ private currentState;
4437
+ private additionalDisconnectHandlers;
4438
+ /**
4439
+ * Creates a new ConnectionManager instance.
4440
+ *
4441
+ * @param config - Configuration options for the manager
4442
+ *
4443
+ * @example
4444
+ * ```typescript
4445
+ * const manager = new ConnectionManager({
4446
+ * baseUrl: 'https://api.playcademy.com',
4447
+ * authContext: { isInIframe: false },
4448
+ * onDisconnect: (context) => {
4449
+ * console.log(`Disconnected: ${context.state}`)
4450
+ * },
4451
+ * onConnectionChange: (state, reason) => {
4452
+ * console.log(`Connection changed: ${state}`)
4453
+ * }
4454
+ * })
4455
+ * ```
4456
+ */
4457
+ constructor(config: ConnectionManagerConfig);
4458
+ /**
4459
+ * Gets the current connection state.
4460
+ *
4461
+ * @returns The current connection state ('online', 'offline', or 'degraded')
4462
+ *
4463
+ * @example
4464
+ * ```typescript
4465
+ * const state = manager.getState()
4466
+ * if (state === 'offline') {
4467
+ * console.log('No connection')
4468
+ * }
4469
+ * ```
4470
+ */
4471
+ getState(): ConnectionState;
4472
+ /**
4473
+ * Manually triggers a connection check immediately.
4474
+ *
4475
+ * Forces a heartbeat ping to verify the current connection status.
4476
+ * Useful when you need to check connectivity before a critical operation.
4477
+ *
4478
+ * In iframe mode, this returns the last known state from platform.
4479
+ *
4480
+ * @returns Promise resolving to the current connection state
4481
+ *
4482
+ * @example
4483
+ * ```typescript
4484
+ * const state = await manager.checkNow()
4485
+ * if (state === 'online') {
4486
+ * await performCriticalOperation()
4487
+ * }
4488
+ * ```
4489
+ */
4490
+ checkNow(): Promise<ConnectionState>;
4491
+ /**
4492
+ * Reports a successful API request to the connection monitor.
4493
+ *
4494
+ * This resets the consecutive failure counter and transitions from
4495
+ * 'degraded' to 'online' state if applicable.
4496
+ *
4497
+ * Typically called automatically by the SDK's request wrapper.
4498
+ * No-op in iframe mode (platform handles monitoring).
4499
+ */
4500
+ reportRequestSuccess(): void;
4501
+ /**
4502
+ * Reports a failed API request to the connection monitor.
4503
+ *
4504
+ * Only network errors are tracked (not 4xx/5xx HTTP responses).
4505
+ * After consecutive failures exceed the threshold, the state transitions
4506
+ * to 'degraded' or 'offline'.
4507
+ *
4508
+ * Typically called automatically by the SDK's request wrapper.
4509
+ * No-op in iframe mode (platform handles monitoring).
4510
+ *
4511
+ * @param error - The error from the failed request
4512
+ */
4513
+ reportRequestFailure(error: unknown): void;
4514
+ /**
4515
+ * Registers a callback to be called when connection issues are detected.
4516
+ *
4517
+ * The callback only fires for 'offline' and 'degraded' states, not when
4518
+ * recovering to 'online'. This provides a clean API for games to handle
4519
+ * disconnect scenarios without being notified of every state change.
4520
+ *
4521
+ * Works in both iframe and standalone modes transparently.
4522
+ *
4523
+ * @param callback - Function to call when connection degrades
4524
+ * @returns Cleanup function to unregister the callback
4525
+ *
4526
+ * @example
4527
+ * ```typescript
4528
+ * const cleanup = manager.onDisconnect(({ state, reason, displayAlert }) => {
4529
+ * if (state === 'offline') {
4530
+ * displayAlert?.('Connection lost. Saving your progress...', { type: 'error' })
4531
+ * saveGameState()
4532
+ * }
4533
+ * })
4534
+ *
4535
+ * // Later: cleanup() to unregister
4536
+ * ```
4537
+ */
4538
+ onDisconnect(callback: DisconnectHandler): () => void;
4539
+ /**
4540
+ * Stops connection monitoring and performs cleanup.
4541
+ *
4542
+ * Removes event listeners and clears heartbeat intervals.
4543
+ * Should be called when the client is being destroyed.
4544
+ */
4545
+ stop(): void;
4546
+ /**
4547
+ * Sets up listener for platform connection state broadcasts (iframe mode only).
4548
+ */
4549
+ private _setupPlatformListener;
4550
+ /**
4551
+ * Handles connection state changes from the monitor or platform.
4552
+ *
4553
+ * Coordinates between:
4554
+ * 1. Emitting events to the client (for client.on('connectionChange'))
4555
+ * 2. Calling the disconnect handler if configured
4556
+ * 3. Calling any additional handlers registered via onDisconnect()
4557
+ *
4558
+ * @param state - The new connection state
4559
+ * @param reason - Human-readable reason for the state change
4560
+ */
4561
+ private _handleConnectionChange;
4562
+ }
4709
4563
 
4710
4564
  /**
4711
4565
  * @fileoverview Authentication Strategy Pattern
@@ -4862,6 +4716,169 @@ declare abstract class PlaycademyBaseClient {
4862
4716
  };
4863
4717
  }
4864
4718
 
4719
+ /**
4720
+ * Options for configuring activity tracking behavior.
4721
+ */
4722
+ interface StartActivityOptions {
4723
+ /**
4724
+ * How long the tab can stay hidden before the timing window resets on return.
4725
+ * Defaults to 10 minutes. Set to `Infinity` to disable.
4726
+ */
4727
+ hiddenTimeoutMs?: number;
4728
+ /**
4729
+ * How often to flush periodic heartbeats with accumulated time data.
4730
+ * Defaults to 15 seconds. Set to `Infinity` to disable the interval;
4731
+ * final unload/endActivity flushes still run.
4732
+ */
4733
+ heartbeatIntervalMs?: number;
4734
+ }
4735
+
4736
+ /**
4737
+ * @fileoverview Playcademy Messaging System
4738
+ *
4739
+ * This file implements a unified messaging system for the Playcademy platform that handles
4740
+ * communication between different contexts:
4741
+ *
4742
+ * 1. **Iframe-to-Parent Communication**: When games run inside iframes (production/development),
4743
+ * they need to communicate with the parent window using postMessage API
4744
+ *
4745
+ * 2. **Local Communication**: When games run in the same context (local development),
4746
+ * they use CustomEvents for internal messaging
4747
+ *
4748
+ * The system automatically detects the runtime environment and chooses the appropriate
4749
+ * transport method, abstracting this complexity from the developer.
4750
+ *
4751
+ * **Architecture Overview**:
4752
+ * - Games run in iframes for security and isolation
4753
+ * - Parent window (Playcademy shell) manages game lifecycle
4754
+ * - Messages flow bidirectionally between parent and iframe
4755
+ * - Local development mode simulates this architecture without iframes
4756
+ */
4757
+
4758
+ /**
4759
+ * Enumeration of all message types used in the Playcademy messaging system.
4760
+ *
4761
+ * **Message Flow Patterns**:
4762
+ *
4763
+ * **Parent → Game (Overworld → Game)**:
4764
+ * - INIT: Provides game with authentication token and configuration
4765
+ * - TOKEN_REFRESH: Updates game's authentication token before expiry
4766
+ * - PAUSE/RESUME: Controls game execution state
4767
+ * - FORCE_EXIT: Immediately terminates the game
4768
+ * - OVERLAY: Shows/hides UI overlays over the game
4769
+ *
4770
+ * **Game → Parent (Game → Overworld)**:
4771
+ * - READY: Game has loaded and is ready to receive messages
4772
+ * - EXIT: Game requests to be closed (user clicked exit, game ended, etc.)
4773
+ * - TELEMETRY: Game reports performance metrics (FPS, memory usage, etc.)
4774
+ */
4775
+ declare enum MessageEvents {
4776
+ /**
4777
+ * Initializes the game with authentication context and configuration.
4778
+ * Sent immediately after game iframe loads.
4779
+ * Payload:
4780
+ * - `baseUrl`: string
4781
+ * - `token`: string
4782
+ * - `gameId`: string
4783
+ */
4784
+ INIT = "PLAYCADEMY_INIT",
4785
+ /**
4786
+ * Updates the game's authentication token before it expires.
4787
+ * Sent periodically to maintain valid authentication.
4788
+ * Payload:
4789
+ * - `token`: string
4790
+ * - `exp`: number
4791
+ */
4792
+ TOKEN_REFRESH = "PLAYCADEMY_TOKEN_REFRESH",
4793
+ /**
4794
+ * Pauses game execution (e.g., when user switches tabs).
4795
+ * Game should pause timers, animations, and user input.
4796
+ * Payload: void
4797
+ */
4798
+ PAUSE = "PLAYCADEMY_PAUSE",
4799
+ /**
4800
+ * Resumes game execution after being paused.
4801
+ * Game should restore timers, animations, and user input.
4802
+ * Payload: void
4803
+ */
4804
+ RESUME = "PLAYCADEMY_RESUME",
4805
+ /**
4806
+ * Forces immediate game termination (emergency exit).
4807
+ * Game should clean up resources and exit immediately.
4808
+ * Payload: void
4809
+ */
4810
+ FORCE_EXIT = "PLAYCADEMY_FORCE_EXIT",
4811
+ /**
4812
+ * Shows or hides UI overlays over the game.
4813
+ * Game may need to pause or adjust rendering accordingly.
4814
+ * Payload: boolean (true = show overlay, false = hide overlay)
4815
+ */
4816
+ OVERLAY = "PLAYCADEMY_OVERLAY",
4817
+ /**
4818
+ * Broadcasts connection state changes to games.
4819
+ * Sent by platform when network connectivity changes.
4820
+ * Payload:
4821
+ * - `state`: 'online' | 'offline' | 'degraded'
4822
+ * - `reason`: string
4823
+ */
4824
+ CONNECTION_STATE = "PLAYCADEMY_CONNECTION_STATE",
4825
+ /**
4826
+ * Game has finished loading and is ready to receive messages.
4827
+ * Sent once after game initialization is complete.
4828
+ * Payload: void
4829
+ */
4830
+ READY = "PLAYCADEMY_READY",
4831
+ /**
4832
+ * Game requests to be closed/exited.
4833
+ * Sent when user clicks exit button or game naturally ends.
4834
+ * Payload: void
4835
+ */
4836
+ EXIT = "PLAYCADEMY_EXIT",
4837
+ /**
4838
+ * Game reports performance telemetry data.
4839
+ * Sent periodically for monitoring and analytics.
4840
+ * Payload:
4841
+ * - `fps`: number
4842
+ * - `mem`: number
4843
+ */
4844
+ TELEMETRY = "PLAYCADEMY_TELEMETRY",
4845
+ /**
4846
+ * Game reports key events to parent.
4847
+ * Sent when certain keys are pressed within the game iframe.
4848
+ * Payload:
4849
+ * - `key`: string
4850
+ * - `code?`: string
4851
+ * - `type`: 'keydown' | 'keyup'
4852
+ */
4853
+ KEY_EVENT = "PLAYCADEMY_KEY_EVENT",
4854
+ /**
4855
+ * Game requests platform to display an alert.
4856
+ * Sent when connection issues are detected or other important events occur.
4857
+ * Payload:
4858
+ * - `message`: string
4859
+ * - `options`: `{ type?: 'info' | 'warning' | 'error', duration?: number }`
4860
+ */
4861
+ DISPLAY_ALERT = "PLAYCADEMY_DISPLAY_ALERT",
4862
+ /**
4863
+ * Notifies about authentication state changes.
4864
+ * Can be sent in both directions depending on auth flow.
4865
+ * Payload:
4866
+ * - `authenticated`: boolean
4867
+ * - `user`: UserInfo | null
4868
+ * - `error`: Error | null
4869
+ */
4870
+ AUTH_STATE_CHANGE = "PLAYCADEMY_AUTH_STATE_CHANGE",
4871
+ /**
4872
+ * OAuth callback data from popup/new-tab windows.
4873
+ * Sent from popup window back to parent after OAuth completes.
4874
+ * Payload:
4875
+ * - `code`: string (OAuth authorization code)
4876
+ * - `state`: string (OAuth state for CSRF protection)
4877
+ * - `error`: string | null (OAuth error if any)
4878
+ */
4879
+ AUTH_CALLBACK = "PLAYCADEMY_AUTH_CALLBACK"
4880
+ }
4881
+
4865
4882
  /**
4866
4883
  * Auto-initializes a PlaycademyClient with context from the environment.
4867
4884
  * Works in both iframe mode (production/development) and standalone mode (local dev).
@@ -4999,7 +5016,7 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
4999
5016
  */
5000
5017
  timeback: {
5001
5018
  readonly user: TimebackUser;
5002
- startActivity: (metadata: ActivityData) => void;
5019
+ startActivity: (metadata: ActivityData, options?: StartActivityOptions | undefined) => void;
5003
5020
  pauseActivity: () => void;
5004
5021
  resumeActivity: () => void;
5005
5022
  endActivity: (data: EndActivityScoreData) => Promise<EndActivityResponse>;