@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/types.d.ts CHANGED
@@ -4244,6 +4244,20 @@ interface UserScore {
4244
4244
  gameSlug: string;
4245
4245
  }
4246
4246
 
4247
+ /**
4248
+ * Connection monitoring types
4249
+ *
4250
+ * Type definitions for connection state, configuration, and callbacks.
4251
+ */
4252
+ /**
4253
+ * Possible connection states.
4254
+ *
4255
+ * - **online**: Connection is stable and healthy
4256
+ * - **offline**: Complete loss of network connectivity
4257
+ * - **degraded**: Connection is slow or experiencing intermittent issues
4258
+ */
4259
+ type ConnectionState = 'online' | 'offline' | 'degraded';
4260
+
4247
4261
  /**
4248
4262
  * @fileoverview Playcademy Messaging System
4249
4263
  *
@@ -4325,6 +4339,14 @@ declare enum MessageEvents {
4325
4339
  * Payload: boolean (true = show overlay, false = hide overlay)
4326
4340
  */
4327
4341
  OVERLAY = "PLAYCADEMY_OVERLAY",
4342
+ /**
4343
+ * Broadcasts connection state changes to games.
4344
+ * Sent by platform when network connectivity changes.
4345
+ * Payload:
4346
+ * - `state`: 'online' | 'offline' | 'degraded'
4347
+ * - `reason`: string
4348
+ */
4349
+ CONNECTION_STATE = "PLAYCADEMY_CONNECTION_STATE",
4328
4350
  /**
4329
4351
  * Game has finished loading and is ready to receive messages.
4330
4352
  * Sent once after game initialization is complete.
@@ -4354,6 +4376,14 @@ declare enum MessageEvents {
4354
4376
  * - `type`: 'keydown' | 'keyup'
4355
4377
  */
4356
4378
  KEY_EVENT = "PLAYCADEMY_KEY_EVENT",
4379
+ /**
4380
+ * Game requests platform to display an alert.
4381
+ * Sent when connection issues are detected or other important events occur.
4382
+ * Payload:
4383
+ * - `message`: string
4384
+ * - `options`: { type?: 'info' | 'warning' | 'error', duration?: number }
4385
+ */
4386
+ DISPLAY_ALERT = "PLAYCADEMY_DISPLAY_ALERT",
4357
4387
  /**
4358
4388
  * Notifies about authentication state changes.
4359
4389
  * Can be sent in both directions depending on auth flow.
@@ -4401,6 +4431,8 @@ declare enum MessageEvents {
4401
4431
  declare function init(options?: {
4402
4432
  baseUrl?: string;
4403
4433
  allowedParentOrigins?: string[];
4434
+ onDisconnect?: DisconnectHandler;
4435
+ enableConnectionMonitoring?: boolean;
4404
4436
  }): Promise<PlaycademyClient>;
4405
4437
 
4406
4438
  /**
@@ -4454,6 +4486,7 @@ declare class PlaycademyClient {
4454
4486
  private internalClientSessionId?;
4455
4487
  private authContext?;
4456
4488
  private initPayload?;
4489
+ private connectionManager?;
4457
4490
  /**
4458
4491
  * Creates a new PlaycademyClient instance.
4459
4492
  *
@@ -4545,6 +4578,85 @@ declare class PlaycademyClient {
4545
4578
  * @param callback - Function to call when auth state changes
4546
4579
  */
4547
4580
  onAuthChange(callback: (token: string | null) => void): void;
4581
+ /**
4582
+ * Registers a callback to be called when connection issues are detected.
4583
+ *
4584
+ * This is a convenience method that filters connection change events to only
4585
+ * fire when the connection degrades (offline or degraded states). Use this
4586
+ * when you want to handle disconnects without being notified of recoveries.
4587
+ *
4588
+ * For all connection state changes, use `client.on('connectionChange', ...)` instead.
4589
+ *
4590
+ * @param callback - Function to call when connection state changes to offline or degraded
4591
+ * @returns Cleanup function to unregister the callback
4592
+ *
4593
+ * @example
4594
+ * ```typescript
4595
+ * const cleanup = client.onDisconnect(({ state, reason, displayAlert }) => {
4596
+ * console.log(`Connection ${state}: ${reason}`)
4597
+ *
4598
+ * if (state === 'offline') {
4599
+ * // Save state and return to game lobby
4600
+ * displayAlert?.('Connection lost. Your progress has been saved.', { type: 'error' })
4601
+ * saveGameState()
4602
+ * returnToLobby()
4603
+ * } else if (state === 'degraded') {
4604
+ * displayAlert?.('Slow connection detected.', { type: 'warning' })
4605
+ * }
4606
+ * })
4607
+ *
4608
+ * // Later: cleanup() to unregister
4609
+ * ```
4610
+ *
4611
+ * @see {@link DISCONNECT_HANDLING.md} for detailed usage examples
4612
+ * @see {@link ConnectionManager.onDisconnect} for the underlying implementation
4613
+ */
4614
+ onDisconnect(callback: (context: DisconnectContext) => void | Promise<void>): () => void;
4615
+ /**
4616
+ * Gets the current connection state.
4617
+ *
4618
+ * Returns the last known connection state without triggering a new check.
4619
+ * Use `checkConnection()` to force an immediate verification.
4620
+ *
4621
+ * @returns Current connection state ('online', 'offline', 'degraded') or 'unknown' if monitoring is disabled
4622
+ *
4623
+ * @example
4624
+ * ```typescript
4625
+ * const state = client.getConnectionState()
4626
+ * if (state === 'offline') {
4627
+ * console.log('No connection available')
4628
+ * }
4629
+ * ```
4630
+ *
4631
+ * @see {@link checkConnection} to trigger an immediate connection check
4632
+ * @see {@link ConnectionManager.getState} for the underlying implementation
4633
+ */
4634
+ getConnectionState(): ConnectionState | 'unknown';
4635
+ /**
4636
+ * Manually triggers a connection check immediately.
4637
+ *
4638
+ * Forces a heartbeat ping to verify connectivity right now, bypassing the normal
4639
+ * interval. Useful when you need to verify connection status before a critical
4640
+ * operation (e.g., saving important game state).
4641
+ *
4642
+ * @returns Promise resolving to the current connection state after verification
4643
+ *
4644
+ * @example
4645
+ * ```typescript
4646
+ * // Check before critical operation
4647
+ * const state = await client.checkConnection()
4648
+ * if (state !== 'online') {
4649
+ * alert('Please check your internet connection before saving')
4650
+ * return
4651
+ * }
4652
+ *
4653
+ * await client.games.saveState(importantData)
4654
+ * ```
4655
+ *
4656
+ * @see {@link getConnectionState} to get the last known state without checking
4657
+ * @see {@link ConnectionManager.checkNow} for the underlying implementation
4658
+ */
4659
+ checkConnection(): Promise<ConnectionState | 'unknown'>;
4548
4660
  /**
4549
4661
  * Sets the authentication context for the client.
4550
4662
  * This is called during initialization to store environment info.
@@ -4607,6 +4719,11 @@ declare class PlaycademyClient {
4607
4719
  * Safe to call in any environment - isInIframe handles browser detection.
4608
4720
  */
4609
4721
  private _detectAuthContext;
4722
+ /**
4723
+ * Initializes connection monitoring if enabled.
4724
+ * Safe to call in any environment - only runs in browser.
4725
+ */
4726
+ private _initializeConnectionMonitor;
4610
4727
  /**
4611
4728
  * Initializes an internal game session for automatic session management.
4612
4729
  * Only starts a session if:
@@ -4808,50 +4925,50 @@ declare class PlaycademyClient {
4808
4925
  };
4809
4926
  items: {
4810
4927
  create: (props: InsertItemInput) => Promise<{
4811
- type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4812
4928
  id: string;
4813
- metadata: unknown;
4814
- slug: string;
4815
4929
  createdAt: Date;
4816
4930
  gameId: string | null;
4931
+ slug: string;
4817
4932
  displayName: string;
4933
+ metadata: unknown;
4818
4934
  description: string | null;
4935
+ type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4819
4936
  isPlaceable: boolean;
4820
4937
  imageUrl: string | null;
4821
4938
  }>;
4822
4939
  get: (itemId: string) => Promise<{
4823
- type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4824
4940
  id: string;
4825
- metadata: unknown;
4826
- slug: string;
4827
4941
  createdAt: Date;
4828
4942
  gameId: string | null;
4943
+ slug: string;
4829
4944
  displayName: string;
4945
+ metadata: unknown;
4830
4946
  description: string | null;
4947
+ type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4831
4948
  isPlaceable: boolean;
4832
4949
  imageUrl: string | null;
4833
4950
  }>;
4834
4951
  list: () => Promise<{
4835
- type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4836
4952
  id: string;
4837
- metadata: unknown;
4838
- slug: string;
4839
4953
  createdAt: Date;
4840
4954
  gameId: string | null;
4955
+ slug: string;
4841
4956
  displayName: string;
4957
+ metadata: unknown;
4842
4958
  description: string | null;
4959
+ type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4843
4960
  isPlaceable: boolean;
4844
4961
  imageUrl: string | null;
4845
4962
  }[]>;
4846
4963
  update: (itemId: string, props: UpdateItemInput) => Promise<{
4847
- type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4848
4964
  id: string;
4849
- metadata: unknown;
4850
- slug: string;
4851
4965
  createdAt: Date;
4852
4966
  gameId: string | null;
4967
+ slug: string;
4853
4968
  displayName: string;
4969
+ metadata: unknown;
4854
4970
  description: string | null;
4971
+ type: "accessory" | "currency" | "badge" | "trophy" | "collectible" | "consumable" | "unlock" | "upgrade" | "other";
4855
4972
  isPlaceable: boolean;
4856
4973
  imageUrl: string | null;
4857
4974
  }>;
@@ -4986,9 +5103,7 @@ declare class PlaycademyClient {
4986
5103
  }) => Promise<TodayXpResponse>;
4987
5104
  total: () => Promise<TotalXpResponse>;
4988
5105
  history: (options?: {
4989
- startDate
4990
- /** Auto-initializes a PlaycademyClient with context from the environment */
4991
- ?: string;
5106
+ startDate?: string;
4992
5107
  endDate?: string;
4993
5108
  }) => Promise<XpHistoryResponse>;
4994
5109
  summary: (options?: {
@@ -5109,6 +5224,29 @@ interface ClientConfig {
5109
5224
  tokenType?: TokenType;
5110
5225
  gameId?: string;
5111
5226
  autoStartSession?: boolean;
5227
+ onDisconnect?: DisconnectHandler;
5228
+ enableConnectionMonitoring?: boolean;
5229
+ }
5230
+ /**
5231
+ * Handler called when connection state changes to offline or degraded.
5232
+ * Games can implement this to handle disconnects gracefully.
5233
+ */
5234
+ type DisconnectHandler = (context: DisconnectContext) => void | Promise<void>;
5235
+ /**
5236
+ * Context provided to disconnect handlers
5237
+ */
5238
+ interface DisconnectContext {
5239
+ /** Current connection state */
5240
+ state: 'offline' | 'degraded';
5241
+ /** Reason for the disconnect */
5242
+ reason: string;
5243
+ /** Timestamp when disconnect was detected */
5244
+ timestamp: number;
5245
+ /** Utility to display a platform-level alert */
5246
+ displayAlert: (message: string, options?: {
5247
+ type?: 'info' | 'warning' | 'error';
5248
+ duration?: number;
5249
+ }) => void;
5112
5250
  }
5113
5251
  interface InitPayload {
5114
5252
  /** Hub API base URL */
@@ -5254,6 +5392,32 @@ interface KeyEventPayload {
5254
5392
  /** Event type */
5255
5393
  type: 'keydown' | 'keyup';
5256
5394
  }
5395
+ interface DisplayAlertPayload {
5396
+ message: string;
5397
+ options?: {
5398
+ type?: 'info' | 'warning' | 'error';
5399
+ duration?: number;
5400
+ };
5401
+ }
5402
+ /**
5403
+ * Display alert payload.
5404
+ * Request from game to show platform-level alert.
5405
+ */
5406
+ interface DisplayAlertPayload {
5407
+ message: string;
5408
+ options?: {
5409
+ type?: 'info' | 'warning' | 'error';
5410
+ duration?: number;
5411
+ };
5412
+ }
5413
+ /**
5414
+ * Connection state payload.
5415
+ * Broadcast from platform to games when connection changes.
5416
+ */
5417
+ interface ConnectionStatePayload {
5418
+ state: 'online' | 'offline' | 'degraded';
5419
+ reason: string;
5420
+ }
5257
5421
  interface ClientEvents {
5258
5422
  authChange: {
5259
5423
  token: string | null;
@@ -5273,6 +5437,10 @@ interface ClientEvents {
5273
5437
  totalXP: number;
5274
5438
  leveledUp: boolean;
5275
5439
  };
5440
+ connectionChange: {
5441
+ state: 'online' | 'offline' | 'degraded';
5442
+ reason: string;
5443
+ };
5276
5444
  }
5277
5445
  type GameContextPayload = {
5278
5446
  token: string;
@@ -5368,4 +5536,4 @@ interface BucketFile {
5368
5536
  }
5369
5537
 
5370
5538
  export { PlaycademyClient };
5371
- export type { Achievement, AchievementCurrent, AchievementProgressResponse, AuthCallbackPayload, AuthOptions, AuthProviderType, AuthResult, AuthServerMessage, AuthStateChangePayload, AuthStateUpdate, AuthenticatedUser, BetterAuthApiKey, BetterAuthApiKeyResponse, BetterAuthSignInResponse, BucketFile, CharacterComponent, CharacterComponentWithSpriteUrl, ClientConfig, ClientEvents, Currency, DevUploadEvent, DevUploadHooks, DeveloperStatusResponse, EventListeners, ExternalGame, FetchedGame, Game, GameContextPayload, GameLeaderboardEntry, GameSession, GameStateData, GameTokenResponse, GameUser, HostedGame, InitPayload, InventoryItem, InventoryItemWithItem, InventoryMutationResponse, Item, KeyEventPayload, LeaderboardEntry, LevelConfig, LoginResponse, ManifestV1, Map, MapElement, MapElementWithGame, MapObject, MapObjectWithItem, PlaycademyServerClientConfig, PlaycademyServerClientState, PlayerCharacter, ShopCurrency, ShopDisplayItem, ShopViewResponse, SpriteTemplate, SpriteTemplateData, StartSessionResponse, TelemetryPayload, TodayXpResponse, TokenRefreshPayload, TokenType, TotalXpResponse, User, UserInfo, UserLevel, UserLevelWithConfig, UserRank, UserRankResponse, UserRoleEnumType, UserScore$1 as UserScore, XpHistoryResponse };
5539
+ export type { Achievement, AchievementCurrent, AchievementProgressResponse, AuthCallbackPayload, AuthOptions, AuthProviderType, AuthResult, AuthServerMessage, AuthStateChangePayload, AuthStateUpdate, AuthenticatedUser, BetterAuthApiKey, BetterAuthApiKeyResponse, BetterAuthSignInResponse, BucketFile, CharacterComponent, CharacterComponentWithSpriteUrl, ClientConfig, ClientEvents, ConnectionStatePayload, Currency, DevUploadEvent, DevUploadHooks, DeveloperStatusResponse, DisconnectContext, DisconnectHandler, DisplayAlertPayload, EventListeners, ExternalGame, FetchedGame, Game, GameContextPayload, GameLeaderboardEntry, GameSession, GameStateData, GameTokenResponse, GameUser, HostedGame, InitPayload, InventoryItem, InventoryItemWithItem, InventoryMutationResponse, Item, KeyEventPayload, LeaderboardEntry, LevelConfig, LoginResponse, ManifestV1, Map, MapElement, MapElementWithGame, MapObject, MapObjectWithItem, PlaycademyServerClientConfig, PlaycademyServerClientState, PlayerCharacter, ShopCurrency, ShopDisplayItem, ShopViewResponse, SpriteTemplate, SpriteTemplateData, StartSessionResponse, TelemetryPayload, TodayXpResponse, TokenRefreshPayload, TokenType, TotalXpResponse, User, UserInfo, UserLevel, UserLevelWithConfig, UserRank, UserRankResponse, UserRoleEnumType, UserScore$1 as UserScore, XpHistoryResponse };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/sdk",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -37,12 +37,12 @@
37
37
  "@playcademy/constants": "0.0.1",
38
38
  "@playcademy/data": "0.0.1",
39
39
  "@playcademy/logger": "0.0.1",
40
- "@playcademy/sandbox": "0.1.9",
40
+ "@playcademy/sandbox": "0.1.10",
41
41
  "@playcademy/test": "0.0.1",
42
42
  "@playcademy/timeback": "0.0.1",
43
43
  "@playcademy/utils": "0.0.1",
44
44
  "@types/bun": "latest",
45
- "playcademy": "0.14.4",
45
+ "playcademy": "0.14.5",
46
46
  "rollup": "^4.50.2",
47
47
  "rollup-plugin-dts": "^6.2.3",
48
48
  "typescript": "^5.7.2"