@playcademy/sdk 0.9.1-beta.1 → 0.9.1-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -599
- package/dist/index.d.ts +346 -1390
- package/dist/index.js +122 -756
- package/dist/internal.d.ts +2104 -7121
- package/dist/internal.js +187 -1166
- package/dist/server/edge.d.ts +9 -359
- package/dist/server.d.ts +9 -359
- package/dist/types.d.ts +360 -4497
- package/package.json +2 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import * as _playcademy_types from '@playcademy/types';
|
|
2
|
+
import { TimebackGrade, TimebackSubject } from '@playcademy/types/timeback';
|
|
3
|
+
import { TimebackUserRole, UserEnrollment, UserOrganization, UserInfo } from '@playcademy/types/user';
|
|
4
|
+
import { AUTH_PROVIDER_IDS } from '@playcademy/constants';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Base error class for Cademy SDK specific errors.
|
|
@@ -138,11 +140,11 @@ interface ApiErrorInfo {
|
|
|
138
140
|
* @example
|
|
139
141
|
* ```typescript
|
|
140
142
|
* try {
|
|
141
|
-
* await client.
|
|
143
|
+
* await client.scores.submit(100)
|
|
142
144
|
* } catch (error) {
|
|
143
145
|
* const info = extractApiErrorInfo(error)
|
|
144
146
|
* if (info) {
|
|
145
|
-
*
|
|
147
|
+
* console.error(`Error: ${info.message}`)
|
|
146
148
|
* }
|
|
147
149
|
* }
|
|
148
150
|
* ```
|
|
@@ -150,828 +152,235 @@ interface ApiErrorInfo {
|
|
|
150
152
|
declare function extractApiErrorInfo(error: unknown): ApiErrorInfo | null;
|
|
151
153
|
|
|
152
154
|
/**
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
* Type definitions for connection state, configuration, and callbacks.
|
|
155
|
+
* OAuth 2.0 implementation for the Playcademy SDK
|
|
156
156
|
*/
|
|
157
|
+
|
|
157
158
|
/**
|
|
158
|
-
*
|
|
159
|
+
* Parses an OAuth state parameter to extract CSRF token and any encoded data.
|
|
159
160
|
*
|
|
160
|
-
* -
|
|
161
|
-
*
|
|
162
|
-
|
|
161
|
+
* @param state - The OAuth state parameter to parse
|
|
162
|
+
* @returns Object containing CSRF token and optional decoded data
|
|
163
|
+
*/
|
|
164
|
+
declare function parseOAuthState(state: string): {
|
|
165
|
+
csrfToken: string;
|
|
166
|
+
data?: Record<string, string>;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/** Permitted HTTP verbs */
|
|
170
|
+
type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
171
|
+
interface RetryPolicy {
|
|
172
|
+
retryableMethods?: readonly Method[];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Cache configuration types for runtime customization
|
|
163
177
|
*/
|
|
164
|
-
type ConnectionState = 'online' | 'offline' | 'degraded';
|
|
165
178
|
/**
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* @see {@link ConnectionMonitor} for usage
|
|
179
|
+
* Runtime configuration for TTL cache behavior
|
|
169
180
|
*/
|
|
170
|
-
interface
|
|
171
|
-
/**
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
|
|
177
|
-
/** Number of consecutive failures before triggering disconnect (default: 2) */
|
|
178
|
-
failureThreshold?: number;
|
|
179
|
-
/** Enable periodic heartbeat monitoring (default: true) */
|
|
180
|
-
enableHeartbeat?: boolean;
|
|
181
|
-
/** Enable browser online/offline event listeners (default: true) */
|
|
182
|
-
enableOfflineEvents?: boolean;
|
|
181
|
+
interface TTLCacheConfig {
|
|
182
|
+
/** Time-to-live in milliseconds. Set to 0 to disable caching for this call. */
|
|
183
|
+
ttl?: number;
|
|
184
|
+
/** Force refresh, bypassing cache */
|
|
185
|
+
force?: boolean;
|
|
186
|
+
/** Skip cache and fetch fresh data (alias for force) */
|
|
187
|
+
skipCache?: boolean;
|
|
183
188
|
}
|
|
189
|
+
|
|
184
190
|
/**
|
|
185
|
-
*
|
|
191
|
+
* @fileoverview Authentication Strategy Pattern
|
|
186
192
|
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
193
|
+
* Provides different authentication strategies for the Playcademy SDK.
|
|
194
|
+
* Each strategy knows how to add its authentication headers to requests.
|
|
189
195
|
*/
|
|
190
|
-
type ConnectionChangeCallback = (state: ConnectionState, reason: string) => void;
|
|
191
196
|
|
|
192
197
|
/**
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
* Monitors network connectivity using multiple signals:
|
|
196
|
-
* 1. navigator.onLine - Instant offline detection
|
|
197
|
-
* 2. Periodic heartbeat - Detects slow/degraded connections
|
|
198
|
-
* 3. Request failure tracking - Piggybacks on actual API calls
|
|
199
|
-
*
|
|
200
|
-
* Designed for school WiFi environments where connections may be
|
|
201
|
-
* unstable or degraded without fully disconnecting.
|
|
198
|
+
* Base interface for authentication strategies
|
|
202
199
|
*/
|
|
200
|
+
interface AuthStrategy {
|
|
201
|
+
/** Get the token value */
|
|
202
|
+
getToken(): string | null;
|
|
203
|
+
/** Get the token type */
|
|
204
|
+
getType(): TokenType;
|
|
205
|
+
/** Get authentication headers for a request */
|
|
206
|
+
getHeaders(): Record<string, string>;
|
|
207
|
+
}
|
|
203
208
|
|
|
204
209
|
/**
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
* 1. **navigator.onLine events** - Instant detection of hard disconnects
|
|
210
|
-
* 2. **Heartbeat pings** - Periodic checks to detect slow/degraded connections
|
|
211
|
-
* 3. **Request failure tracking** - Piggybacks on actual API calls
|
|
212
|
-
*
|
|
213
|
-
* This comprehensive approach ensures reliable detection across different network
|
|
214
|
-
* failure modes common in school WiFi environments (hard disconnect, slow connection,
|
|
215
|
-
* intermittent failures).
|
|
216
|
-
*
|
|
217
|
-
* @example
|
|
218
|
-
* ```typescript
|
|
219
|
-
* const monitor = new ConnectionMonitor({
|
|
220
|
-
* baseUrl: 'https://api.playcademy.com',
|
|
221
|
-
* heartbeatInterval: 10000, // Check every 10s
|
|
222
|
-
* failureThreshold: 2 // Trigger after 2 failures
|
|
223
|
-
* })
|
|
224
|
-
*
|
|
225
|
-
* monitor.onChange((state, reason) => {
|
|
226
|
-
* console.log(`Connection: ${state} - ${reason}`)
|
|
227
|
-
* })
|
|
228
|
-
*
|
|
229
|
-
* monitor.start()
|
|
230
|
-
* ```
|
|
210
|
+
* Base Playcademy SDK client with shared infrastructure.
|
|
211
|
+
* Provides authentication, HTTP requests, events,
|
|
212
|
+
* and fundamental namespaces used by all clients.
|
|
231
213
|
*
|
|
232
|
-
*
|
|
214
|
+
* Extended by PlaycademyClient (game SDK) and PlaycademyInternalClient (platform SDK).
|
|
233
215
|
*/
|
|
234
|
-
declare class
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
216
|
+
declare abstract class PlaycademyBaseClient {
|
|
217
|
+
baseUrl: string;
|
|
218
|
+
gameUrl?: string;
|
|
219
|
+
mode: PlaycademyMode;
|
|
220
|
+
protected authStrategy: AuthStrategy;
|
|
221
|
+
protected gameId?: string;
|
|
222
|
+
protected config: Partial<ClientConfig>;
|
|
223
|
+
protected listeners: EventListeners;
|
|
224
|
+
protected authContext?: {
|
|
225
|
+
isInIframe: boolean;
|
|
226
|
+
};
|
|
227
|
+
protected initPayload?: InitPayload;
|
|
228
|
+
protected launchId?: string;
|
|
229
|
+
constructor(config?: Partial<ClientConfig>);
|
|
241
230
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
* The monitor starts in a stopped state. Call `start()` to begin monitoring.
|
|
245
|
-
*
|
|
246
|
-
* @param config - Configuration options
|
|
247
|
-
* @param config.baseUrl - Base URL for heartbeat pings
|
|
248
|
-
* @param config.heartbeatInterval - How often to check (default: 10000ms)
|
|
249
|
-
* @param config.heartbeatTimeout - Request timeout (default: 5000ms)
|
|
250
|
-
* @param config.failureThreshold - Failures before triggering disconnect (default: 2)
|
|
251
|
-
* @param config.enableHeartbeat - Enable periodic checks (default: true)
|
|
252
|
-
* @param config.enableOfflineEvents - Listen to browser events (default: true)
|
|
231
|
+
* Gets the effective base URL for API requests.
|
|
253
232
|
*/
|
|
254
|
-
|
|
233
|
+
getBaseUrl(): string;
|
|
255
234
|
/**
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
* Sets up event listeners and begins heartbeat checks based on configuration.
|
|
259
|
-
* Idempotent - safe to call multiple times.
|
|
235
|
+
* Gets the effective game backend URL for integration requests.
|
|
260
236
|
*/
|
|
261
|
-
|
|
237
|
+
protected getGameBackendUrl(): string;
|
|
262
238
|
/**
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
* Removes event listeners and clears heartbeat intervals.
|
|
266
|
-
* Idempotent - safe to call multiple times.
|
|
239
|
+
* Simple ping method for testing connectivity.
|
|
267
240
|
*/
|
|
268
|
-
|
|
241
|
+
ping(): string;
|
|
269
242
|
/**
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
* The callback fires for all state transitions: online → offline,
|
|
273
|
-
* offline → degraded, degraded → online, etc.
|
|
274
|
-
*
|
|
275
|
-
* @param callback - Function called with (state, reason) when connection changes
|
|
276
|
-
* @returns Cleanup function to unregister the callback
|
|
277
|
-
*
|
|
278
|
-
* @example
|
|
279
|
-
* ```typescript
|
|
280
|
-
* const cleanup = monitor.onChange((state, reason) => {
|
|
281
|
-
* console.log(`Connection: ${state}`)
|
|
282
|
-
* if (state === 'offline') {
|
|
283
|
-
* showReconnectingUI()
|
|
284
|
-
* }
|
|
285
|
-
* })
|
|
286
|
-
*
|
|
287
|
-
* // Later: cleanup() to unregister
|
|
288
|
-
* ```
|
|
243
|
+
* Sets the authentication token for API requests.
|
|
289
244
|
*/
|
|
290
|
-
|
|
245
|
+
setToken(token: string | null, tokenType?: TokenType): void;
|
|
246
|
+
setLaunchId(launchId: string | null | undefined): void;
|
|
291
247
|
/**
|
|
292
|
-
* Gets the current
|
|
293
|
-
*
|
|
294
|
-
* @returns The current state ('online', 'offline', or 'degraded')
|
|
248
|
+
* Gets the current token type.
|
|
295
249
|
*/
|
|
296
|
-
|
|
250
|
+
getTokenType(): TokenType;
|
|
297
251
|
/**
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
* Forces a heartbeat ping to verify connectivity right now, bypassing
|
|
301
|
-
* the normal interval. Useful before critical operations.
|
|
302
|
-
*
|
|
303
|
-
* @returns Promise resolving to the current connection state after the check
|
|
304
|
-
*
|
|
305
|
-
* @example
|
|
306
|
-
* ```typescript
|
|
307
|
-
* const state = await monitor.checkNow()
|
|
308
|
-
* if (state !== 'online') {
|
|
309
|
-
* alert('Please check your internet connection')
|
|
310
|
-
* }
|
|
311
|
-
* ```
|
|
252
|
+
* Gets the current authentication token.
|
|
312
253
|
*/
|
|
313
|
-
|
|
254
|
+
getToken(): string | null;
|
|
314
255
|
/**
|
|
315
|
-
*
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
*
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
*
|
|
324
|
-
* @
|
|
325
|
-
*
|
|
326
|
-
* @example
|
|
327
|
-
* ```typescript
|
|
328
|
-
* try {
|
|
329
|
-
* await fetch('/api/data')
|
|
330
|
-
* } catch (error) {
|
|
331
|
-
* monitor.reportRequestFailure(error)
|
|
332
|
-
* throw error
|
|
333
|
-
* }
|
|
334
|
-
* ```
|
|
256
|
+
* Checks if the client has a valid API token.
|
|
257
|
+
*/
|
|
258
|
+
isAuthenticated(): boolean;
|
|
259
|
+
/**
|
|
260
|
+
* Registers a callback to be called when authentication state changes.
|
|
261
|
+
*/
|
|
262
|
+
onAuthChange(callback: (token: string | null) => void): void;
|
|
263
|
+
/**
|
|
264
|
+
* Sets the authentication context for the client.
|
|
265
|
+
* @internal
|
|
335
266
|
*/
|
|
336
|
-
|
|
267
|
+
_setAuthContext(context: {
|
|
268
|
+
isInIframe: boolean;
|
|
269
|
+
}): void;
|
|
337
270
|
/**
|
|
338
|
-
*
|
|
271
|
+
* Registers an event listener for client events.
|
|
339
272
|
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
273
|
+
* @param event - The event name to listen for.
|
|
274
|
+
* @param callback - The handler invoked when the event fires.
|
|
275
|
+
* @returns A cleanup function that removes this specific listener.
|
|
276
|
+
*/
|
|
277
|
+
on<E extends keyof ClientEvents>(event: E, callback: (payload: ClientEvents[E]) => void): () => void;
|
|
278
|
+
/**
|
|
279
|
+
* Removes a previously registered event listener.
|
|
343
280
|
*
|
|
344
|
-
* @
|
|
345
|
-
*
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
*
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
*
|
|
354
|
-
|
|
281
|
+
* @param event - The event name to stop listening for.
|
|
282
|
+
* @param callback - The exact function reference passed to {@link on}.
|
|
283
|
+
*/
|
|
284
|
+
off<E extends keyof ClientEvents>(event: E, callback: (payload: ClientEvents[E]) => void): void;
|
|
285
|
+
/**
|
|
286
|
+
* Emits an event to all registered listeners.
|
|
287
|
+
*/
|
|
288
|
+
protected emit<E extends keyof ClientEvents>(event: E, payload: ClientEvents[E]): void;
|
|
289
|
+
/**
|
|
290
|
+
* Makes an authenticated HTTP request to the platform API.
|
|
291
|
+
*/
|
|
292
|
+
protected request<T>(path: string, method: Method, options?: {
|
|
293
|
+
body?: unknown;
|
|
294
|
+
headers?: Record<string, string>;
|
|
295
|
+
raw?: boolean;
|
|
296
|
+
retryPolicy?: RetryPolicy;
|
|
297
|
+
}): Promise<T>;
|
|
298
|
+
/**
|
|
299
|
+
* Makes an authenticated HTTP request to the game's backend Worker.
|
|
300
|
+
*/
|
|
301
|
+
protected requestGameBackend<T>(path: string, method: Method, body?: unknown, headers?: Record<string, string>, options?: {
|
|
302
|
+
raw?: boolean;
|
|
303
|
+
retryPolicy?: RetryPolicy;
|
|
304
|
+
}): Promise<T>;
|
|
305
|
+
/**
|
|
306
|
+
* Ensures a gameId is available, throwing an error if not.
|
|
307
|
+
*/
|
|
308
|
+
protected _ensureGameId(): string;
|
|
309
|
+
/**
|
|
310
|
+
* Detects and sets the authentication context (iframe vs standalone).
|
|
311
|
+
*/
|
|
312
|
+
private _detectAuthContext;
|
|
313
|
+
/**
|
|
314
|
+
* Current user data.
|
|
315
|
+
* - `me()` - Get authenticated user profile
|
|
355
316
|
*/
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
private _handleOffline;
|
|
360
|
-
private _startHeartbeat;
|
|
361
|
-
private _performHeartbeat;
|
|
362
|
-
private _handleHeartbeatFailure;
|
|
363
|
-
private _setState;
|
|
317
|
+
users: {
|
|
318
|
+
me: () => Promise<_playcademy_types.AuthenticatedUser>;
|
|
319
|
+
};
|
|
364
320
|
}
|
|
365
321
|
|
|
366
322
|
/**
|
|
367
|
-
*
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Parses an OAuth state parameter to extract CSRF token and any encoded data.
|
|
323
|
+
* Auto-initializes a PlaycademyClient with context from the environment.
|
|
324
|
+
* Works in both iframe mode (production/development) and standalone mode (local dev).
|
|
372
325
|
*
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
data?: Record<string, string>;
|
|
379
|
-
};
|
|
380
|
-
|
|
381
|
-
/** Permitted HTTP verbs */
|
|
382
|
-
type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
383
|
-
interface RetryPolicy {
|
|
384
|
-
retryableMethods?: readonly Method[];
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
/**
|
|
388
|
-
* TimeBack Enums & Literal Types
|
|
326
|
+
* This is the recommended way to initialize the SDK as it automatically:
|
|
327
|
+
* - Detects the runtime environment (iframe vs standalone)
|
|
328
|
+
* - Configures the client with the appropriate context
|
|
329
|
+
* - Sets up event listeners for token refresh
|
|
330
|
+
* - Exposes the client for debugging in development mode
|
|
389
331
|
*
|
|
390
|
-
*
|
|
332
|
+
* @param options - Optional configuration overrides
|
|
333
|
+
* @param options.baseUrl - Override the base URL for API requests
|
|
334
|
+
* @returns Promise resolving to a fully initialized PlaycademyClient
|
|
335
|
+
* @throws Error if not running in a browser context
|
|
391
336
|
*
|
|
392
|
-
* @
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
* Grade levels per AE OneRoster GradeEnum.
|
|
401
|
-
* -1 = Pre-K, 0 = Kindergarten, 1-12 = Grades 1-12, 13 = AP
|
|
402
|
-
*/
|
|
403
|
-
type TimebackGrade = -1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13;
|
|
404
|
-
/**
|
|
405
|
-
* Valid Caliper subject values.
|
|
406
|
-
* Matches OneRoster subjects, with "None" as a Caliper-specific fallback.
|
|
337
|
+
* @example
|
|
338
|
+
* ```typescript
|
|
339
|
+
* // Default initialization
|
|
340
|
+
* const client = await PlaycademyClient.init()
|
|
341
|
+
*
|
|
342
|
+
* // With custom base URL
|
|
343
|
+
* const client = await PlaycademyClient.init({ baseUrl: 'https://custom.api.com' })
|
|
344
|
+
* ```
|
|
407
345
|
*/
|
|
408
|
-
|
|
346
|
+
declare function init<T extends PlaycademyBaseClient = PlaycademyBaseClient>(this: new (config?: Partial<ClientConfig>) => T, options?: {
|
|
347
|
+
baseUrl?: string;
|
|
348
|
+
allowedParentOrigins?: string[];
|
|
349
|
+
}): Promise<T>;
|
|
409
350
|
|
|
410
351
|
/**
|
|
411
|
-
*
|
|
352
|
+
* Authenticates a user with email and password.
|
|
353
|
+
*
|
|
354
|
+
* This is a standalone authentication method that doesn't require an initialized client.
|
|
355
|
+
* Use this for login flows before creating a client instance.
|
|
412
356
|
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
357
|
+
* @deprecated Use client.auth.login() instead for better error handling and automatic token management
|
|
358
|
+
*
|
|
359
|
+
* @param baseUrl - The base URL of the Playcademy API
|
|
360
|
+
* @param email - User's email address
|
|
361
|
+
* @param password - User's password
|
|
362
|
+
* @returns Promise resolving to authentication response with token
|
|
363
|
+
* @throws PlaycademyError if authentication fails or network error occurs
|
|
415
364
|
*
|
|
416
|
-
*
|
|
417
|
-
*
|
|
365
|
+
* @example
|
|
366
|
+
* ```typescript
|
|
367
|
+
* // Preferred approach:
|
|
368
|
+
* const client = new PlaycademyClient({ baseUrl: '/api' })
|
|
369
|
+
* const result = await client.auth.login({
|
|
370
|
+
* email: 'user@example.com',
|
|
371
|
+
* password: 'password'
|
|
372
|
+
* })
|
|
418
373
|
*
|
|
419
|
-
*
|
|
374
|
+
* // Legacy approach (still works):
|
|
375
|
+
* try {
|
|
376
|
+
* const response = await PlaycademyClient.login('/api', 'user@example.com', 'password')
|
|
377
|
+
* const client = new PlaycademyClient({ token: response.token })
|
|
378
|
+
* } catch (error) {
|
|
379
|
+
* console.error('Login failed:', error.message)
|
|
380
|
+
* }
|
|
381
|
+
* ```
|
|
420
382
|
*/
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Known extensions for TimeBack Activity Metrics Collection
|
|
424
|
-
*/
|
|
425
|
-
interface TimebackActivityExtensions {
|
|
426
|
-
/** Percentage complete (0-100) for the app course */
|
|
427
|
-
pctCompleteApp?: number;
|
|
428
|
-
/** Allow other arbitrary extensions */
|
|
429
|
-
[key: string]: unknown;
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Activity data for ending an activity
|
|
433
|
-
*/
|
|
434
|
-
interface ActivityData {
|
|
435
|
-
/** Unique activity identifier (required) */
|
|
436
|
-
activityId: string;
|
|
437
|
-
/** Grade level for this activity (required for multi-grade course routing) */
|
|
438
|
-
grade: number;
|
|
439
|
-
/** Subject area (required for multi-grade course routing) */
|
|
440
|
-
subject: CaliperSubject;
|
|
441
|
-
/** Activity display name (optional) */
|
|
442
|
-
activityName?: string;
|
|
443
|
-
/** Course identifier (auto-filled from config if not provided) */
|
|
444
|
-
courseId?: string;
|
|
445
|
-
/** Course display name (auto-filled from config if not provided) */
|
|
446
|
-
courseName?: string;
|
|
447
|
-
/** Student email address (optional) */
|
|
448
|
-
studentEmail?: string;
|
|
449
|
-
/** Application name for Caliper events (defaults to 'Game') */
|
|
450
|
-
appName?: string;
|
|
451
|
-
/** Sensor URL for Caliper events (defaults to baseUrl) */
|
|
452
|
-
sensorUrl?: string;
|
|
453
|
-
}
|
|
454
|
-
/**
|
|
455
|
-
* Score data with optional XP override for ending an activity
|
|
456
|
-
*/
|
|
457
|
-
interface EndActivityScoreData {
|
|
458
|
-
/** Number of questions answered correctly */
|
|
459
|
-
correctQuestions: number;
|
|
460
|
-
/** Total number of questions */
|
|
461
|
-
totalQuestions: number;
|
|
462
|
-
/** Optional XP override - bypasses automatic XP calculation */
|
|
463
|
-
xpAwarded?: number;
|
|
464
|
-
/** Number of learning units mastered */
|
|
465
|
-
masteredUnits?: number;
|
|
466
|
-
/** Optional arbitrary extensions to include in the Caliper event */
|
|
467
|
-
extensions?: TimebackActivityExtensions;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
/**
|
|
471
|
-
* TimeBack API Request/Response Types
|
|
472
|
-
*
|
|
473
|
-
* Types for TimeBack API endpoints including XP tracking,
|
|
474
|
-
* setup, verification, and activity completion.
|
|
475
|
-
*
|
|
476
|
-
* @module types/timeback/api
|
|
477
|
-
*/
|
|
478
|
-
|
|
479
|
-
type TimebackPromotionStatus = 'promoted' | 'no-next-course' | 'already-promoted' | 'not-enrolled' | 'not-mastered';
|
|
480
|
-
interface TimebackPromotionResult {
|
|
481
|
-
status: TimebackPromotionStatus;
|
|
482
|
-
currentCourseId: string;
|
|
483
|
-
nextCourseId?: string;
|
|
484
|
-
masteredUnits?: number;
|
|
485
|
-
masterableUnits?: number;
|
|
486
|
-
}
|
|
487
|
-
interface EndActivityResponse {
|
|
488
|
-
status: 'ok';
|
|
489
|
-
courseId: string;
|
|
490
|
-
xpAwarded: number;
|
|
491
|
-
masteredUnits?: number;
|
|
492
|
-
pctCompleteApp?: number;
|
|
493
|
-
scoreStatus?: string;
|
|
494
|
-
inProgress?: string;
|
|
495
|
-
}
|
|
496
|
-
interface AdvanceCourseResponse {
|
|
497
|
-
status: 'ok';
|
|
498
|
-
promotion: TimebackPromotionResult;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
/**
|
|
502
|
-
* Cache configuration types for runtime customization
|
|
503
|
-
*/
|
|
504
|
-
/**
|
|
505
|
-
* Runtime configuration for TTL cache behavior
|
|
506
|
-
*/
|
|
507
|
-
interface TTLCacheConfig {
|
|
508
|
-
/** Time-to-live in milliseconds. Set to 0 to disable caching for this call. */
|
|
509
|
-
ttl?: number;
|
|
510
|
-
/** Force refresh, bypassing cache */
|
|
511
|
-
force?: boolean;
|
|
512
|
-
/** Skip cache and fetch fresh data (alias for force) */
|
|
513
|
-
skipCache?: boolean;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
/**
|
|
517
|
-
* User Types
|
|
518
|
-
*
|
|
519
|
-
* Enums, DTOs and API response types. Database row types are in @playcademy/data/types.
|
|
520
|
-
*
|
|
521
|
-
* @module types/user
|
|
522
|
-
*/
|
|
523
|
-
|
|
524
|
-
type UserRoleEnumType = UserRole;
|
|
525
|
-
type DeveloperStatusEnumType = 'none' | 'pending' | 'approved';
|
|
526
|
-
type TimebackUserRole = 'administrator' | 'aide' | 'guardian' | 'parent' | 'proctor' | 'relative' | 'student' | 'teacher';
|
|
527
|
-
type TimebackOrgType = 'department' | 'school' | 'district' | 'local' | 'state' | 'national';
|
|
528
|
-
interface UserEnrollment {
|
|
529
|
-
gameId?: string;
|
|
530
|
-
courseId: string;
|
|
531
|
-
enrollmentIds?: {
|
|
532
|
-
active: string;
|
|
533
|
-
inactive?: string[];
|
|
534
|
-
};
|
|
535
|
-
grade: number;
|
|
536
|
-
subject: string;
|
|
537
|
-
orgId?: string;
|
|
538
|
-
}
|
|
539
|
-
interface UserOrganization {
|
|
540
|
-
id: string;
|
|
541
|
-
name: string | null;
|
|
542
|
-
type: TimebackOrgType | string;
|
|
543
|
-
isPrimary: boolean;
|
|
544
|
-
}
|
|
545
|
-
interface TimebackStudentProfile {
|
|
546
|
-
role: TimebackUserRole;
|
|
547
|
-
organizations: UserOrganization[];
|
|
548
|
-
}
|
|
549
|
-
interface UserTimebackData extends TimebackStudentProfile {
|
|
550
|
-
id: string;
|
|
551
|
-
enrollments: UserEnrollment[];
|
|
552
|
-
}
|
|
553
|
-
/**
|
|
554
|
-
* OpenID Connect UserInfo claims (NOT a database row).
|
|
555
|
-
*/
|
|
556
|
-
interface UserInfo {
|
|
557
|
-
sub: string;
|
|
558
|
-
email: string;
|
|
559
|
-
name: string | null;
|
|
560
|
-
email_verified?: boolean;
|
|
561
|
-
given_name?: string;
|
|
562
|
-
family_name?: string;
|
|
563
|
-
issuer?: string;
|
|
564
|
-
lti_roles?: unknown;
|
|
565
|
-
lti_context?: unknown;
|
|
566
|
-
lti_resource_link?: unknown;
|
|
567
|
-
timeback_id?: string;
|
|
568
|
-
}
|
|
569
|
-
interface DemoProfile {
|
|
570
|
-
displayName: string;
|
|
571
|
-
isDefault: boolean;
|
|
572
|
-
}
|
|
573
|
-
/**
|
|
574
|
-
* Update shape for `client.demo.profile.update(...)`.
|
|
575
|
-
*
|
|
576
|
-
* Kept as a named type so callers typed against it pick up new fields
|
|
577
|
-
* automatically, but `displayName` is the only updatable field today and
|
|
578
|
-
* the server's `DemoProfileSchema` requires it — a no-field payload would
|
|
579
|
-
* 400 at runtime, so we model that at the type level too. When additional
|
|
580
|
-
* fields land, make them required/optional individually based on server
|
|
581
|
-
* validation, rather than blanket-optional.
|
|
582
|
-
*/
|
|
583
|
-
interface DemoProfileUpdate {
|
|
584
|
-
displayName: string;
|
|
585
|
-
}
|
|
586
|
-
/**
|
|
587
|
-
* Authenticated user for API responses.
|
|
588
|
-
* Differs from UserRow: omits timebackId, adds hasTimebackAccount and timeback.
|
|
589
|
-
*/
|
|
590
|
-
interface AuthenticatedUser {
|
|
591
|
-
id: string;
|
|
592
|
-
email: string;
|
|
593
|
-
emailVerified: boolean;
|
|
594
|
-
name: string | null;
|
|
595
|
-
image: string | null;
|
|
596
|
-
username: string | null;
|
|
597
|
-
role: UserRoleEnumType;
|
|
598
|
-
developerStatus: DeveloperStatusEnumType;
|
|
599
|
-
characterCreated: boolean;
|
|
600
|
-
createdAt: Date;
|
|
601
|
-
updatedAt: Date;
|
|
602
|
-
hasTimebackAccount: boolean;
|
|
603
|
-
timeback?: UserTimebackData;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
/**
|
|
607
|
-
* Leaderboard Types
|
|
608
|
-
*
|
|
609
|
-
* @module types/leaderboard
|
|
610
|
-
*/
|
|
611
|
-
type LeaderboardTimeframe = 'all_time' | 'monthly' | 'weekly' | 'daily';
|
|
612
|
-
interface LeaderboardOptions {
|
|
613
|
-
timeframe?: LeaderboardTimeframe;
|
|
614
|
-
limit?: number;
|
|
615
|
-
offset?: number;
|
|
616
|
-
gameId?: string;
|
|
617
|
-
}
|
|
618
|
-
/**
|
|
619
|
-
* Leaderboard entry with required game context.
|
|
620
|
-
* Used when fetching leaderboards for a specific game.
|
|
621
|
-
*/
|
|
622
|
-
interface GameLeaderboardEntry {
|
|
623
|
-
rank: number;
|
|
624
|
-
userId: string;
|
|
625
|
-
username: string;
|
|
626
|
-
userImage?: string | null;
|
|
627
|
-
score: number;
|
|
628
|
-
achievedAt: Date;
|
|
629
|
-
metadata?: Record<string, unknown>;
|
|
630
|
-
gameId: string;
|
|
631
|
-
gameTitle: string;
|
|
632
|
-
gameSlug: string;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
declare const items: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
636
|
-
name: "items";
|
|
637
|
-
schema: undefined;
|
|
638
|
-
columns: {
|
|
639
|
-
id: drizzle_orm_pg_core.PgColumn<{
|
|
640
|
-
name: "id";
|
|
641
|
-
tableName: "items";
|
|
642
|
-
dataType: "string";
|
|
643
|
-
columnType: "PgUUID";
|
|
644
|
-
data: string;
|
|
645
|
-
driverParam: string;
|
|
646
|
-
notNull: true;
|
|
647
|
-
hasDefault: true;
|
|
648
|
-
isPrimaryKey: true;
|
|
649
|
-
isAutoincrement: false;
|
|
650
|
-
hasRuntimeDefault: false;
|
|
651
|
-
enumValues: undefined;
|
|
652
|
-
baseColumn: never;
|
|
653
|
-
identity: undefined;
|
|
654
|
-
generated: undefined;
|
|
655
|
-
}, {}, {}>;
|
|
656
|
-
slug: drizzle_orm_pg_core.PgColumn<{
|
|
657
|
-
name: "slug";
|
|
658
|
-
tableName: "items";
|
|
659
|
-
dataType: "string";
|
|
660
|
-
columnType: "PgText";
|
|
661
|
-
data: string;
|
|
662
|
-
driverParam: string;
|
|
663
|
-
notNull: true;
|
|
664
|
-
hasDefault: false;
|
|
665
|
-
isPrimaryKey: false;
|
|
666
|
-
isAutoincrement: false;
|
|
667
|
-
hasRuntimeDefault: false;
|
|
668
|
-
enumValues: [string, ...string[]];
|
|
669
|
-
baseColumn: never;
|
|
670
|
-
identity: undefined;
|
|
671
|
-
generated: undefined;
|
|
672
|
-
}, {}, {}>;
|
|
673
|
-
gameId: drizzle_orm_pg_core.PgColumn<{
|
|
674
|
-
name: "game_id";
|
|
675
|
-
tableName: "items";
|
|
676
|
-
dataType: "string";
|
|
677
|
-
columnType: "PgUUID";
|
|
678
|
-
data: string;
|
|
679
|
-
driverParam: string;
|
|
680
|
-
notNull: false;
|
|
681
|
-
hasDefault: false;
|
|
682
|
-
isPrimaryKey: false;
|
|
683
|
-
isAutoincrement: false;
|
|
684
|
-
hasRuntimeDefault: false;
|
|
685
|
-
enumValues: undefined;
|
|
686
|
-
baseColumn: never;
|
|
687
|
-
identity: undefined;
|
|
688
|
-
generated: undefined;
|
|
689
|
-
}, {}, {}>;
|
|
690
|
-
displayName: drizzle_orm_pg_core.PgColumn<{
|
|
691
|
-
name: "display_name";
|
|
692
|
-
tableName: "items";
|
|
693
|
-
dataType: "string";
|
|
694
|
-
columnType: "PgText";
|
|
695
|
-
data: string;
|
|
696
|
-
driverParam: string;
|
|
697
|
-
notNull: true;
|
|
698
|
-
hasDefault: false;
|
|
699
|
-
isPrimaryKey: false;
|
|
700
|
-
isAutoincrement: false;
|
|
701
|
-
hasRuntimeDefault: false;
|
|
702
|
-
enumValues: [string, ...string[]];
|
|
703
|
-
baseColumn: never;
|
|
704
|
-
identity: undefined;
|
|
705
|
-
generated: undefined;
|
|
706
|
-
}, {}, {}>;
|
|
707
|
-
description: drizzle_orm_pg_core.PgColumn<{
|
|
708
|
-
name: "description";
|
|
709
|
-
tableName: "items";
|
|
710
|
-
dataType: "string";
|
|
711
|
-
columnType: "PgText";
|
|
712
|
-
data: string;
|
|
713
|
-
driverParam: string;
|
|
714
|
-
notNull: false;
|
|
715
|
-
hasDefault: false;
|
|
716
|
-
isPrimaryKey: false;
|
|
717
|
-
isAutoincrement: false;
|
|
718
|
-
hasRuntimeDefault: false;
|
|
719
|
-
enumValues: [string, ...string[]];
|
|
720
|
-
baseColumn: never;
|
|
721
|
-
identity: undefined;
|
|
722
|
-
generated: undefined;
|
|
723
|
-
}, {}, {}>;
|
|
724
|
-
type: drizzle_orm_pg_core.PgColumn<{
|
|
725
|
-
name: "type";
|
|
726
|
-
tableName: "items";
|
|
727
|
-
dataType: "string";
|
|
728
|
-
columnType: "PgEnumColumn";
|
|
729
|
-
data: "accessory" | "badge" | "collectible" | "consumable" | "currency" | "other" | "trophy" | "unlock" | "upgrade";
|
|
730
|
-
driverParam: string;
|
|
731
|
-
notNull: true;
|
|
732
|
-
hasDefault: true;
|
|
733
|
-
isPrimaryKey: false;
|
|
734
|
-
isAutoincrement: false;
|
|
735
|
-
hasRuntimeDefault: false;
|
|
736
|
-
enumValues: ["currency", "badge", "trophy", "collectible", "consumable", "unlock", "upgrade", "accessory", "other"];
|
|
737
|
-
baseColumn: never;
|
|
738
|
-
identity: undefined;
|
|
739
|
-
generated: undefined;
|
|
740
|
-
}, {}, {}>;
|
|
741
|
-
isPlaceable: drizzle_orm_pg_core.PgColumn<{
|
|
742
|
-
name: "is_placeable";
|
|
743
|
-
tableName: "items";
|
|
744
|
-
dataType: "boolean";
|
|
745
|
-
columnType: "PgBoolean";
|
|
746
|
-
data: boolean;
|
|
747
|
-
driverParam: boolean;
|
|
748
|
-
notNull: true;
|
|
749
|
-
hasDefault: true;
|
|
750
|
-
isPrimaryKey: false;
|
|
751
|
-
isAutoincrement: false;
|
|
752
|
-
hasRuntimeDefault: false;
|
|
753
|
-
enumValues: undefined;
|
|
754
|
-
baseColumn: never;
|
|
755
|
-
identity: undefined;
|
|
756
|
-
generated: undefined;
|
|
757
|
-
}, {}, {}>;
|
|
758
|
-
imageUrl: drizzle_orm_pg_core.PgColumn<{
|
|
759
|
-
name: "image_url";
|
|
760
|
-
tableName: "items";
|
|
761
|
-
dataType: "string";
|
|
762
|
-
columnType: "PgText";
|
|
763
|
-
data: string;
|
|
764
|
-
driverParam: string;
|
|
765
|
-
notNull: false;
|
|
766
|
-
hasDefault: false;
|
|
767
|
-
isPrimaryKey: false;
|
|
768
|
-
isAutoincrement: false;
|
|
769
|
-
hasRuntimeDefault: false;
|
|
770
|
-
enumValues: [string, ...string[]];
|
|
771
|
-
baseColumn: never;
|
|
772
|
-
identity: undefined;
|
|
773
|
-
generated: undefined;
|
|
774
|
-
}, {}, {}>;
|
|
775
|
-
metadata: drizzle_orm_pg_core.PgColumn<{
|
|
776
|
-
name: "metadata";
|
|
777
|
-
tableName: "items";
|
|
778
|
-
dataType: "json";
|
|
779
|
-
columnType: "PgJsonb";
|
|
780
|
-
data: unknown;
|
|
781
|
-
driverParam: unknown;
|
|
782
|
-
notNull: false;
|
|
783
|
-
hasDefault: true;
|
|
784
|
-
isPrimaryKey: false;
|
|
785
|
-
isAutoincrement: false;
|
|
786
|
-
hasRuntimeDefault: false;
|
|
787
|
-
enumValues: undefined;
|
|
788
|
-
baseColumn: never;
|
|
789
|
-
identity: undefined;
|
|
790
|
-
generated: undefined;
|
|
791
|
-
}, {}, {}>;
|
|
792
|
-
createdAt: drizzle_orm_pg_core.PgColumn<{
|
|
793
|
-
name: "created_at";
|
|
794
|
-
tableName: "items";
|
|
795
|
-
dataType: "date";
|
|
796
|
-
columnType: "PgTimestamp";
|
|
797
|
-
data: Date;
|
|
798
|
-
driverParam: string;
|
|
799
|
-
notNull: true;
|
|
800
|
-
hasDefault: true;
|
|
801
|
-
isPrimaryKey: false;
|
|
802
|
-
isAutoincrement: false;
|
|
803
|
-
hasRuntimeDefault: false;
|
|
804
|
-
enumValues: undefined;
|
|
805
|
-
baseColumn: never;
|
|
806
|
-
identity: undefined;
|
|
807
|
-
generated: undefined;
|
|
808
|
-
}, {}, {}>;
|
|
809
|
-
};
|
|
810
|
-
dialect: 'pg';
|
|
811
|
-
}>;
|
|
812
|
-
declare const inventoryItems: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
813
|
-
name: "inventory_items";
|
|
814
|
-
schema: undefined;
|
|
815
|
-
columns: {
|
|
816
|
-
id: drizzle_orm_pg_core.PgColumn<{
|
|
817
|
-
name: "id";
|
|
818
|
-
tableName: "inventory_items";
|
|
819
|
-
dataType: "string";
|
|
820
|
-
columnType: "PgUUID";
|
|
821
|
-
data: string;
|
|
822
|
-
driverParam: string;
|
|
823
|
-
notNull: true;
|
|
824
|
-
hasDefault: true;
|
|
825
|
-
isPrimaryKey: true;
|
|
826
|
-
isAutoincrement: false;
|
|
827
|
-
hasRuntimeDefault: false;
|
|
828
|
-
enumValues: undefined;
|
|
829
|
-
baseColumn: never;
|
|
830
|
-
identity: undefined;
|
|
831
|
-
generated: undefined;
|
|
832
|
-
}, {}, {}>;
|
|
833
|
-
userId: drizzle_orm_pg_core.PgColumn<{
|
|
834
|
-
name: "user_id";
|
|
835
|
-
tableName: "inventory_items";
|
|
836
|
-
dataType: "string";
|
|
837
|
-
columnType: "PgText";
|
|
838
|
-
data: string;
|
|
839
|
-
driverParam: string;
|
|
840
|
-
notNull: true;
|
|
841
|
-
hasDefault: false;
|
|
842
|
-
isPrimaryKey: false;
|
|
843
|
-
isAutoincrement: false;
|
|
844
|
-
hasRuntimeDefault: false;
|
|
845
|
-
enumValues: [string, ...string[]];
|
|
846
|
-
baseColumn: never;
|
|
847
|
-
identity: undefined;
|
|
848
|
-
generated: undefined;
|
|
849
|
-
}, {}, {}>;
|
|
850
|
-
itemId: drizzle_orm_pg_core.PgColumn<{
|
|
851
|
-
name: "item_id";
|
|
852
|
-
tableName: "inventory_items";
|
|
853
|
-
dataType: "string";
|
|
854
|
-
columnType: "PgUUID";
|
|
855
|
-
data: string;
|
|
856
|
-
driverParam: string;
|
|
857
|
-
notNull: true;
|
|
858
|
-
hasDefault: false;
|
|
859
|
-
isPrimaryKey: false;
|
|
860
|
-
isAutoincrement: false;
|
|
861
|
-
hasRuntimeDefault: false;
|
|
862
|
-
enumValues: undefined;
|
|
863
|
-
baseColumn: never;
|
|
864
|
-
identity: undefined;
|
|
865
|
-
generated: undefined;
|
|
866
|
-
}, {}, {}>;
|
|
867
|
-
quantity: drizzle_orm_pg_core.PgColumn<{
|
|
868
|
-
name: "quantity";
|
|
869
|
-
tableName: "inventory_items";
|
|
870
|
-
dataType: "number";
|
|
871
|
-
columnType: "PgInteger";
|
|
872
|
-
data: number;
|
|
873
|
-
driverParam: string | number;
|
|
874
|
-
notNull: true;
|
|
875
|
-
hasDefault: true;
|
|
876
|
-
isPrimaryKey: false;
|
|
877
|
-
isAutoincrement: false;
|
|
878
|
-
hasRuntimeDefault: false;
|
|
879
|
-
enumValues: undefined;
|
|
880
|
-
baseColumn: never;
|
|
881
|
-
identity: undefined;
|
|
882
|
-
generated: undefined;
|
|
883
|
-
}, {}, {}>;
|
|
884
|
-
updatedAt: drizzle_orm_pg_core.PgColumn<{
|
|
885
|
-
name: "updated_at";
|
|
886
|
-
tableName: "inventory_items";
|
|
887
|
-
dataType: "date";
|
|
888
|
-
columnType: "PgTimestamp";
|
|
889
|
-
data: Date;
|
|
890
|
-
driverParam: string;
|
|
891
|
-
notNull: false;
|
|
892
|
-
hasDefault: true;
|
|
893
|
-
isPrimaryKey: false;
|
|
894
|
-
isAutoincrement: false;
|
|
895
|
-
hasRuntimeDefault: false;
|
|
896
|
-
enumValues: undefined;
|
|
897
|
-
baseColumn: never;
|
|
898
|
-
identity: undefined;
|
|
899
|
-
generated: undefined;
|
|
900
|
-
}, {}, {}>;
|
|
901
|
-
};
|
|
902
|
-
dialect: 'pg';
|
|
903
|
-
}>;
|
|
904
|
-
|
|
905
|
-
type ItemRow = typeof items.$inferSelect;
|
|
906
|
-
type InventoryItemRow = typeof inventoryItems.$inferSelect;
|
|
907
|
-
type InventoryItemWithItem = InventoryItemRow & {
|
|
908
|
-
item: ItemRow;
|
|
909
|
-
};
|
|
910
|
-
|
|
911
|
-
/**
|
|
912
|
-
* Auto-initializes a PlaycademyClient with context from the environment.
|
|
913
|
-
* Works in both iframe mode (production/development) and standalone mode (local dev).
|
|
914
|
-
*
|
|
915
|
-
* This is the recommended way to initialize the SDK as it automatically:
|
|
916
|
-
* - Detects the runtime environment (iframe vs standalone)
|
|
917
|
-
* - Configures the client with the appropriate context
|
|
918
|
-
* - Sets up event listeners for token refresh
|
|
919
|
-
* - Exposes the client for debugging in development mode
|
|
920
|
-
*
|
|
921
|
-
* @param options - Optional configuration overrides
|
|
922
|
-
* @param options.baseUrl - Override the base URL for API requests
|
|
923
|
-
* @returns Promise resolving to a fully initialized PlaycademyClient
|
|
924
|
-
* @throws Error if not running in a browser context
|
|
925
|
-
*
|
|
926
|
-
* @example
|
|
927
|
-
* ```typescript
|
|
928
|
-
* // Default initialization
|
|
929
|
-
* const client = await PlaycademyClient.init()
|
|
930
|
-
*
|
|
931
|
-
* // With custom base URL
|
|
932
|
-
* const client = await PlaycademyClient.init({ baseUrl: 'https://custom.api.com' })
|
|
933
|
-
* ```
|
|
934
|
-
*/
|
|
935
|
-
declare function init<T extends PlaycademyBaseClient = PlaycademyBaseClient>(this: new (config?: Partial<ClientConfig>) => T, options?: {
|
|
936
|
-
baseUrl?: string;
|
|
937
|
-
allowedParentOrigins?: string[];
|
|
938
|
-
onDisconnect?: DisconnectHandler;
|
|
939
|
-
enableConnectionMonitoring?: boolean;
|
|
940
|
-
}): Promise<T>;
|
|
941
|
-
|
|
942
|
-
/**
|
|
943
|
-
* Authenticates a user with email and password.
|
|
944
|
-
*
|
|
945
|
-
* This is a standalone authentication method that doesn't require an initialized client.
|
|
946
|
-
* Use this for login flows before creating a client instance.
|
|
947
|
-
*
|
|
948
|
-
* @deprecated Use client.auth.login() instead for better error handling and automatic token management
|
|
949
|
-
*
|
|
950
|
-
* @param baseUrl - The base URL of the Playcademy API
|
|
951
|
-
* @param email - User's email address
|
|
952
|
-
* @param password - User's password
|
|
953
|
-
* @returns Promise resolving to authentication response with token
|
|
954
|
-
* @throws PlaycademyError if authentication fails or network error occurs
|
|
955
|
-
*
|
|
956
|
-
* @example
|
|
957
|
-
* ```typescript
|
|
958
|
-
* // Preferred approach:
|
|
959
|
-
* const client = new PlaycademyClient({ baseUrl: '/api' })
|
|
960
|
-
* const result = await client.auth.login({
|
|
961
|
-
* email: 'user@example.com',
|
|
962
|
-
* password: 'password'
|
|
963
|
-
* })
|
|
964
|
-
*
|
|
965
|
-
* // Legacy approach (still works):
|
|
966
|
-
* try {
|
|
967
|
-
* const response = await PlaycademyClient.login('/api', 'user@example.com', 'password')
|
|
968
|
-
* const client = new PlaycademyClient({ token: response.token })
|
|
969
|
-
* } catch (error) {
|
|
970
|
-
* console.error('Login failed:', error.message)
|
|
971
|
-
* }
|
|
972
|
-
* ```
|
|
973
|
-
*/
|
|
974
|
-
declare function login(baseUrl: string, email: string, password: string): Promise<LoginResponse>;
|
|
383
|
+
declare function login(baseUrl: string, email: string, password: string): Promise<LoginResponse>;
|
|
975
384
|
|
|
976
385
|
/**
|
|
977
386
|
* @fileoverview Playcademy Messaging System
|
|
@@ -1054,14 +463,6 @@ declare enum MessageEvents {
|
|
|
1054
463
|
* Payload: boolean (true = show overlay, false = hide overlay)
|
|
1055
464
|
*/
|
|
1056
465
|
OVERLAY = "PLAYCADEMY_OVERLAY",
|
|
1057
|
-
/**
|
|
1058
|
-
* Broadcasts connection state changes to games.
|
|
1059
|
-
* Sent by platform when network connectivity changes.
|
|
1060
|
-
* Payload:
|
|
1061
|
-
* - `state`: 'online' | 'offline' | 'degraded'
|
|
1062
|
-
* - `reason`: string
|
|
1063
|
-
*/
|
|
1064
|
-
CONNECTION_STATE = "PLAYCADEMY_CONNECTION_STATE",
|
|
1065
466
|
/**
|
|
1066
467
|
* Game has finished loading and is ready to receive messages.
|
|
1067
468
|
* Sent once after game initialization is complete.
|
|
@@ -1099,14 +500,6 @@ declare enum MessageEvents {
|
|
|
1099
500
|
* - `type`: 'keydown' | 'keyup'
|
|
1100
501
|
*/
|
|
1101
502
|
KEY_EVENT = "PLAYCADEMY_KEY_EVENT",
|
|
1102
|
-
/**
|
|
1103
|
-
* Game requests platform to display an alert.
|
|
1104
|
-
* Sent when connection issues are detected or other important events occur.
|
|
1105
|
-
* Payload:
|
|
1106
|
-
* - `message`: string
|
|
1107
|
-
* - `options`: `{ type?: 'info' | 'warning' | 'error', duration?: number }`
|
|
1108
|
-
*/
|
|
1109
|
-
DISPLAY_ALERT = "PLAYCADEMY_DISPLAY_ALERT",
|
|
1110
503
|
/**
|
|
1111
504
|
* Game signals that demo mode has ended.
|
|
1112
505
|
* Sent when a demo experience reaches its CTA/upgrade boundary.
|
|
@@ -1171,8 +564,6 @@ interface MessageEventMap {
|
|
|
1171
564
|
[MessageEvents.FORCE_EXIT]: void;
|
|
1172
565
|
/** Overlay visibility state (true = show, false = hide) */
|
|
1173
566
|
[MessageEvents.OVERLAY]: boolean;
|
|
1174
|
-
/** Connection state change from platform */
|
|
1175
|
-
[MessageEvents.CONNECTION_STATE]: ConnectionStatePayload;
|
|
1176
567
|
/** Ready message has no payload data */
|
|
1177
568
|
[MessageEvents.READY]: void;
|
|
1178
569
|
/** SDK init error data */
|
|
@@ -1183,8 +574,6 @@ interface MessageEventMap {
|
|
|
1183
574
|
[MessageEvents.TELEMETRY]: TelemetryPayload;
|
|
1184
575
|
/** Key event data */
|
|
1185
576
|
[MessageEvents.KEY_EVENT]: KeyEventPayload;
|
|
1186
|
-
/** Display alert request from game */
|
|
1187
|
-
[MessageEvents.DISPLAY_ALERT]: DisplayAlertPayload;
|
|
1188
577
|
/** Demo end signal from game */
|
|
1189
578
|
[MessageEvents.DEMO_END]: DemoEndPayload;
|
|
1190
579
|
/** Authentication state change notification */
|
|
@@ -1460,322 +849,103 @@ declare class PlaycademyMessaging {
|
|
|
1460
849
|
*/
|
|
1461
850
|
private sendViaPostMessage;
|
|
1462
851
|
/**
|
|
1463
|
-
* **Send Via CustomEvent Method**
|
|
1464
|
-
*
|
|
1465
|
-
* Sends a message using the browser's CustomEvent API for local same-context communication.
|
|
1466
|
-
* This method is used when both the sender and receiver are in the same window context,
|
|
1467
|
-
* typically during local development or when the parent needs to send messages to the game.
|
|
1468
|
-
*
|
|
1469
|
-
* **CustomEvent Protocol**:
|
|
1470
|
-
* CustomEvent is a browser API for creating and dispatching custom events within the same
|
|
1471
|
-
* window context. It's simpler than postMessage but only works within the same origin/context.
|
|
1472
|
-
*
|
|
1473
|
-
* **Event Structure**:
|
|
1474
|
-
* - **type**: The event name (e.g., 'PLAYCADEMY_INIT')
|
|
1475
|
-
* - **detail**: The payload data attached to the event
|
|
1476
|
-
*
|
|
1477
|
-
* **When This Is Used**:
|
|
1478
|
-
* - Local development when game and shell run in the same context
|
|
1479
|
-
* - Parent-to-game communication (INIT, TOKEN_REFRESH, PAUSE, etc.)
|
|
1480
|
-
* - Any scenario where postMessage isn't needed
|
|
1481
|
-
*
|
|
1482
|
-
* **Event Bubbling**:
|
|
1483
|
-
* CustomEvents are dispatched on the window object and can be listened to by any
|
|
1484
|
-
* code in the same context using `addEventListener(type, handler)`.
|
|
1485
|
-
*
|
|
1486
|
-
* @template K - The message event type (ensures type safety)
|
|
1487
|
-
* @param type - The message event type to send (becomes the event name)
|
|
1488
|
-
* @param payload - The data to send with the message (stored in event.detail)
|
|
1489
|
-
*
|
|
1490
|
-
* @example
|
|
1491
|
-
* ```typescript
|
|
1492
|
-
* // Send initialization data
|
|
1493
|
-
* sendViaCustomEvent(MessageEvents.INIT, {
|
|
1494
|
-
* baseUrl: '/api',
|
|
1495
|
-
* token: 'abc123',
|
|
1496
|
-
* gameId: 'game-456'
|
|
1497
|
-
* })
|
|
1498
|
-
* // Creates: CustomEvent('PLAYCADEMY_INIT', { detail: { baseUrl, token, gameId } })
|
|
1499
|
-
*
|
|
1500
|
-
* // Send pause signal
|
|
1501
|
-
* sendViaCustomEvent(MessageEvents.PAUSE, undefined)
|
|
1502
|
-
* // Creates: CustomEvent('PLAYCADEMY_PAUSE', { detail: undefined })
|
|
1503
|
-
*
|
|
1504
|
-
* // Listeners can access the data via event.detail:
|
|
1505
|
-
* window.addEventListener('PLAYCADEMY_INIT', (event) => {
|
|
1506
|
-
* console.log(event.detail.gameId) // 'game-456'
|
|
1507
|
-
* })
|
|
1508
|
-
* ```
|
|
1509
|
-
*/
|
|
1510
|
-
private sendViaCustomEvent;
|
|
1511
|
-
}
|
|
1512
|
-
/**
|
|
1513
|
-
* **Playcademy Messaging Singleton**
|
|
1514
|
-
*
|
|
1515
|
-
* This is the main messaging instance used throughout the Playcademy platform.
|
|
1516
|
-
* It's exported as a singleton to ensure consistent communication across all parts
|
|
1517
|
-
* of the application.
|
|
1518
|
-
*
|
|
1519
|
-
* **Why a Singleton?**:
|
|
1520
|
-
* - Ensures all parts of the app use the same messaging instance
|
|
1521
|
-
* - Prevents conflicts between multiple messaging systems
|
|
1522
|
-
* - Simplifies the API - no need to pass instances around
|
|
1523
|
-
* - Maintains consistent event listener management
|
|
1524
|
-
*
|
|
1525
|
-
* **Usage in Different Contexts**:
|
|
1526
|
-
*
|
|
1527
|
-
* **In Games**:
|
|
1528
|
-
* ```typescript
|
|
1529
|
-
* import { messaging, MessageEvents } from '@playcademy/sdk'
|
|
1530
|
-
*
|
|
1531
|
-
* // Tell parent we're ready
|
|
1532
|
-
* messaging.send(MessageEvents.READY, undefined)
|
|
1533
|
-
*
|
|
1534
|
-
* // Listen for pause/resume
|
|
1535
|
-
* messaging.listen(MessageEvents.PAUSE, () => game.pause())
|
|
1536
|
-
* messaging.listen(MessageEvents.RESUME, () => game.resume())
|
|
1537
|
-
* ```
|
|
1538
|
-
*
|
|
1539
|
-
* **In Parent Shell**:
|
|
1540
|
-
* ```typescript
|
|
1541
|
-
* import { messaging, MessageEvents } from '@playcademy/sdk'
|
|
1542
|
-
*
|
|
1543
|
-
* // Send initialization data to game
|
|
1544
|
-
* messaging.send(MessageEvents.INIT, { baseUrl, token, gameId })
|
|
1545
|
-
*
|
|
1546
|
-
* // Listen for game events
|
|
1547
|
-
* messaging.listen(MessageEvents.EXIT, () => closeGame())
|
|
1548
|
-
* messaging.listen(MessageEvents.READY, () => showGame())
|
|
1549
|
-
* ```
|
|
1550
|
-
*
|
|
1551
|
-
* **Automatic Transport Selection**:
|
|
1552
|
-
* The messaging system automatically chooses the right transport method:
|
|
1553
|
-
* - Uses postMessage when game is in iframe sending to parent
|
|
1554
|
-
* - Uses CustomEvent for local development and parent-to-game communication
|
|
1555
|
-
*
|
|
1556
|
-
* **Type Safety**:
|
|
1557
|
-
* All message sending and receiving is fully type-safe with TypeScript.
|
|
1558
|
-
*/
|
|
1559
|
-
declare const messaging: PlaycademyMessaging;
|
|
1560
|
-
|
|
1561
|
-
/**
|
|
1562
|
-
* @fileoverview Authentication Strategy Pattern
|
|
1563
|
-
*
|
|
1564
|
-
* Provides different authentication strategies for the Playcademy SDK.
|
|
1565
|
-
* Each strategy knows how to add its authentication headers to requests.
|
|
1566
|
-
*/
|
|
1567
|
-
|
|
1568
|
-
/**
|
|
1569
|
-
* Base interface for authentication strategies
|
|
1570
|
-
*/
|
|
1571
|
-
interface AuthStrategy {
|
|
1572
|
-
/** Get the token value */
|
|
1573
|
-
getToken(): string | null;
|
|
1574
|
-
/** Get the token type */
|
|
1575
|
-
getType(): TokenType;
|
|
1576
|
-
/** Get authentication headers for a request */
|
|
1577
|
-
getHeaders(): Record<string, string>;
|
|
1578
|
-
}
|
|
1579
|
-
|
|
1580
|
-
/**
|
|
1581
|
-
* Base Playcademy SDK client with shared infrastructure.
|
|
1582
|
-
* Provides authentication, HTTP requests, events, connection monitoring,
|
|
1583
|
-
* and fundamental namespaces used by all clients.
|
|
1584
|
-
*
|
|
1585
|
-
* Extended by PlaycademyClient (game SDK) and PlaycademyInternalClient (platform SDK).
|
|
1586
|
-
*/
|
|
1587
|
-
declare abstract class PlaycademyBaseClient {
|
|
1588
|
-
baseUrl: string;
|
|
1589
|
-
gameUrl?: string;
|
|
1590
|
-
mode: PlaycademyMode;
|
|
1591
|
-
protected authStrategy: AuthStrategy;
|
|
1592
|
-
protected gameId?: string;
|
|
1593
|
-
protected config: Partial<ClientConfig>;
|
|
1594
|
-
protected listeners: EventListeners;
|
|
1595
|
-
protected internalClientSessionId?: string;
|
|
1596
|
-
protected authContext?: {
|
|
1597
|
-
isInIframe: boolean;
|
|
1598
|
-
};
|
|
1599
|
-
protected initPayload?: InitPayload;
|
|
1600
|
-
protected connectionManager?: ConnectionManager;
|
|
1601
|
-
protected launchId?: string;
|
|
1602
|
-
/**
|
|
1603
|
-
* Internal session manager for automatic session lifecycle.
|
|
1604
|
-
* @private
|
|
1605
|
-
* @internal
|
|
1606
|
-
*/
|
|
1607
|
-
protected _sessionManager: {
|
|
1608
|
-
startSession: (gameId: string) => Promise<{
|
|
1609
|
-
sessionId: string;
|
|
1610
|
-
}>;
|
|
1611
|
-
endSession: (sessionId: string, gameId: string) => Promise<void>;
|
|
1612
|
-
};
|
|
1613
|
-
constructor(config?: Partial<ClientConfig>);
|
|
1614
|
-
/**
|
|
1615
|
-
* Gets the effective base URL for API requests.
|
|
1616
|
-
*/
|
|
1617
|
-
getBaseUrl(): string;
|
|
1618
|
-
/**
|
|
1619
|
-
* Gets the effective game backend URL for integration requests.
|
|
1620
|
-
*/
|
|
1621
|
-
protected getGameBackendUrl(): string;
|
|
1622
|
-
/**
|
|
1623
|
-
* Simple ping method for testing connectivity.
|
|
1624
|
-
*/
|
|
1625
|
-
ping(): string;
|
|
1626
|
-
/**
|
|
1627
|
-
* Sets the authentication token for API requests.
|
|
1628
|
-
*/
|
|
1629
|
-
setToken(token: string | null, tokenType?: TokenType): void;
|
|
1630
|
-
setLaunchId(launchId: string | null | undefined): void;
|
|
1631
|
-
/**
|
|
1632
|
-
* Gets the current token type.
|
|
1633
|
-
*/
|
|
1634
|
-
getTokenType(): TokenType;
|
|
1635
|
-
/**
|
|
1636
|
-
* Gets the current authentication token.
|
|
1637
|
-
*/
|
|
1638
|
-
getToken(): string | null;
|
|
1639
|
-
/**
|
|
1640
|
-
* Checks if the client has a valid API token.
|
|
1641
|
-
*/
|
|
1642
|
-
isAuthenticated(): boolean;
|
|
1643
|
-
/**
|
|
1644
|
-
* Registers a callback to be called when authentication state changes.
|
|
1645
|
-
*/
|
|
1646
|
-
onAuthChange(callback: (token: string | null) => void): void;
|
|
1647
|
-
/**
|
|
1648
|
-
* Registers a callback to be called when connection issues are detected.
|
|
1649
|
-
*/
|
|
1650
|
-
onDisconnect(callback: (context: DisconnectContext) => void | Promise<void>): () => void;
|
|
1651
|
-
/**
|
|
1652
|
-
* Gets the current connection state.
|
|
1653
|
-
*/
|
|
1654
|
-
getConnectionState(): ConnectionState | 'unknown';
|
|
1655
|
-
/**
|
|
1656
|
-
* Manually triggers a connection check immediately.
|
|
1657
|
-
*/
|
|
1658
|
-
checkConnection(): Promise<ConnectionState | 'unknown'>;
|
|
1659
|
-
/**
|
|
1660
|
-
* Sets the authentication context for the client.
|
|
1661
|
-
* @internal
|
|
1662
|
-
*/
|
|
1663
|
-
_setAuthContext(context: {
|
|
1664
|
-
isInIframe: boolean;
|
|
1665
|
-
}): void;
|
|
1666
|
-
/**
|
|
1667
|
-
* Registers an event listener for client events.
|
|
1668
|
-
*
|
|
1669
|
-
* @param event - The event name to listen for.
|
|
1670
|
-
* @param callback - The handler invoked when the event fires.
|
|
1671
|
-
* @returns A cleanup function that removes this specific listener.
|
|
1672
|
-
*/
|
|
1673
|
-
on<E extends keyof ClientEvents>(event: E, callback: (payload: ClientEvents[E]) => void): () => void;
|
|
1674
|
-
/**
|
|
1675
|
-
* Removes a previously registered event listener.
|
|
1676
|
-
*
|
|
1677
|
-
* @param event - The event name to stop listening for.
|
|
1678
|
-
* @param callback - The exact function reference passed to {@link on}.
|
|
1679
|
-
*/
|
|
1680
|
-
off<E extends keyof ClientEvents>(event: E, callback: (payload: ClientEvents[E]) => void): void;
|
|
1681
|
-
/**
|
|
1682
|
-
* Emits an event to all registered listeners.
|
|
1683
|
-
*/
|
|
1684
|
-
protected emit<E extends keyof ClientEvents>(event: E, payload: ClientEvents[E]): void;
|
|
1685
|
-
/**
|
|
1686
|
-
* Makes an authenticated HTTP request to the platform API.
|
|
1687
|
-
*/
|
|
1688
|
-
protected request<T>(path: string, method: Method, options?: {
|
|
1689
|
-
body?: unknown;
|
|
1690
|
-
headers?: Record<string, string>;
|
|
1691
|
-
raw?: boolean;
|
|
1692
|
-
retryPolicy?: RetryPolicy;
|
|
1693
|
-
}): Promise<T>;
|
|
1694
|
-
/**
|
|
1695
|
-
* Makes an authenticated HTTP request to the game's backend Worker.
|
|
1696
|
-
*/
|
|
1697
|
-
protected requestGameBackend<T>(path: string, method: Method, body?: unknown, headers?: Record<string, string>, options?: {
|
|
1698
|
-
raw?: boolean;
|
|
1699
|
-
retryPolicy?: RetryPolicy;
|
|
1700
|
-
}): Promise<T>;
|
|
1701
|
-
/**
|
|
1702
|
-
* Ensures a gameId is available, throwing an error if not.
|
|
1703
|
-
*/
|
|
1704
|
-
protected _ensureGameId(): string;
|
|
1705
|
-
/**
|
|
1706
|
-
* Detects and sets the authentication context (iframe vs standalone).
|
|
1707
|
-
*/
|
|
1708
|
-
private _detectAuthContext;
|
|
1709
|
-
/**
|
|
1710
|
-
* Initializes connection monitoring if enabled.
|
|
1711
|
-
*/
|
|
1712
|
-
private _initializeConnectionMonitor;
|
|
1713
|
-
private _initializeInternalSession;
|
|
1714
|
-
/**
|
|
1715
|
-
* Current user data and inventory management.
|
|
1716
|
-
* - `me()` - Get authenticated user profile
|
|
1717
|
-
* - `inventory.get()` - List user's items
|
|
1718
|
-
* - `inventory.add(slug, qty)` - Award items to user
|
|
1719
|
-
*/
|
|
1720
|
-
users: {
|
|
1721
|
-
me: () => Promise<AuthenticatedUser>;
|
|
1722
|
-
inventory: {
|
|
1723
|
-
get: () => Promise<InventoryItemWithItem[]>;
|
|
1724
|
-
add: (identifier: string, qty: number) => Promise<InventoryMutationResponse>;
|
|
1725
|
-
remove: (identifier: string, qty: number) => Promise<InventoryMutationResponse>;
|
|
1726
|
-
quantity: (identifier: string) => Promise<number>;
|
|
1727
|
-
has: (identifier: string, minQuantity?: number) => Promise<boolean>;
|
|
1728
|
-
};
|
|
1729
|
-
};
|
|
1730
|
-
}
|
|
1731
|
-
|
|
1732
|
-
/**
|
|
1733
|
-
* Options for configuring activity tracking behavior.
|
|
1734
|
-
*/
|
|
1735
|
-
interface StartActivityOptions {
|
|
1736
|
-
/**
|
|
1737
|
-
* How long heartbeats continue after the activity is automatically paused
|
|
1738
|
-
* because the tab is hidden or the player is inactive while visible.
|
|
1739
|
-
* Defaults to 10 minutes. Set to `Infinity` to keep heartbeats running
|
|
1740
|
-
* indefinitely during automatic pauses. Invalid values fall back to the
|
|
1741
|
-
* 10-minute default.
|
|
1742
|
-
*/
|
|
1743
|
-
pausedHeartbeatTimeoutMs?: number;
|
|
1744
|
-
/**
|
|
1745
|
-
* @deprecated Use `pausedHeartbeatTimeoutMs` instead.
|
|
1746
|
-
*
|
|
1747
|
-
* Backward-compatible alias for callers that still use the old option
|
|
1748
|
-
* name from earlier SDK releases.
|
|
1749
|
-
*/
|
|
1750
|
-
hiddenTimeoutMs?: number;
|
|
1751
|
-
/**
|
|
1752
|
-
* How often to flush periodic heartbeats with accumulated time data.
|
|
1753
|
-
* Defaults to 15 seconds. Set to `Infinity` to disable the interval;
|
|
1754
|
-
* final unload/endActivity flushes still run. Values must be greater than
|
|
1755
|
-
* 0 or `Infinity`; invalid values fall back to the 15-second default.
|
|
1756
|
-
*/
|
|
1757
|
-
heartbeatIntervalMs?: number;
|
|
1758
|
-
/**
|
|
1759
|
-
* How long the tab can remain visible without keyboard or mouse activity
|
|
1760
|
-
* before the activity is marked inactive. Defaults to 10 minutes. Set to
|
|
1761
|
-
* `Infinity` to disable keyboard/mouse inactivity tracking. Invalid values
|
|
1762
|
-
* fall back to the 10-minute default.
|
|
1763
|
-
*/
|
|
1764
|
-
inactivityTimeoutMs?: number;
|
|
1765
|
-
/**
|
|
1766
|
-
* Stable identifier for this activity run. When provided, it is used on
|
|
1767
|
-
* every heartbeat and on endActivity instead of a freshly-generated UUID.
|
|
852
|
+
* **Send Via CustomEvent Method**
|
|
1768
853
|
*
|
|
1769
|
-
*
|
|
1770
|
-
*
|
|
1771
|
-
*
|
|
854
|
+
* Sends a message using the browser's CustomEvent API for local same-context communication.
|
|
855
|
+
* This method is used when both the sender and receiver are in the same window context,
|
|
856
|
+
* typically during local development or when the parent needs to send messages to the game.
|
|
1772
857
|
*
|
|
1773
|
-
*
|
|
1774
|
-
*
|
|
1775
|
-
*
|
|
858
|
+
* **CustomEvent Protocol**:
|
|
859
|
+
* CustomEvent is a browser API for creating and dispatching custom events within the same
|
|
860
|
+
* window context. It's simpler than postMessage but only works within the same origin/context.
|
|
861
|
+
*
|
|
862
|
+
* **Event Structure**:
|
|
863
|
+
* - **type**: The event name (e.g., 'PLAYCADEMY_INIT')
|
|
864
|
+
* - **detail**: The payload data attached to the event
|
|
865
|
+
*
|
|
866
|
+
* **When This Is Used**:
|
|
867
|
+
* - Local development when game and shell run in the same context
|
|
868
|
+
* - Parent-to-game communication (INIT, TOKEN_REFRESH, PAUSE, etc.)
|
|
869
|
+
* - Any scenario where postMessage isn't needed
|
|
870
|
+
*
|
|
871
|
+
* **Event Bubbling**:
|
|
872
|
+
* CustomEvents are dispatched on the window object and can be listened to by any
|
|
873
|
+
* code in the same context using `addEventListener(type, handler)`.
|
|
874
|
+
*
|
|
875
|
+
* @template K - The message event type (ensures type safety)
|
|
876
|
+
* @param type - The message event type to send (becomes the event name)
|
|
877
|
+
* @param payload - The data to send with the message (stored in event.detail)
|
|
878
|
+
*
|
|
879
|
+
* @example
|
|
880
|
+
* ```typescript
|
|
881
|
+
* // Send initialization data
|
|
882
|
+
* sendViaCustomEvent(MessageEvents.INIT, {
|
|
883
|
+
* baseUrl: '/api',
|
|
884
|
+
* token: 'abc123',
|
|
885
|
+
* gameId: 'game-456'
|
|
886
|
+
* })
|
|
887
|
+
* // Creates: CustomEvent('PLAYCADEMY_INIT', { detail: { baseUrl, token, gameId } })
|
|
888
|
+
*
|
|
889
|
+
* // Send pause signal
|
|
890
|
+
* sendViaCustomEvent(MessageEvents.PAUSE, undefined)
|
|
891
|
+
* // Creates: CustomEvent('PLAYCADEMY_PAUSE', { detail: undefined })
|
|
892
|
+
*
|
|
893
|
+
* // Listeners can access the data via event.detail:
|
|
894
|
+
* window.addEventListener('PLAYCADEMY_INIT', (event) => {
|
|
895
|
+
* console.log(event.detail.gameId) // 'game-456'
|
|
896
|
+
* })
|
|
897
|
+
* ```
|
|
1776
898
|
*/
|
|
1777
|
-
|
|
899
|
+
private sendViaCustomEvent;
|
|
1778
900
|
}
|
|
901
|
+
/**
|
|
902
|
+
* **Playcademy Messaging Singleton**
|
|
903
|
+
*
|
|
904
|
+
* This is the main messaging instance used throughout the Playcademy platform.
|
|
905
|
+
* It's exported as a singleton to ensure consistent communication across all parts
|
|
906
|
+
* of the application.
|
|
907
|
+
*
|
|
908
|
+
* **Why a Singleton?**:
|
|
909
|
+
* - Ensures all parts of the app use the same messaging instance
|
|
910
|
+
* - Prevents conflicts between multiple messaging systems
|
|
911
|
+
* - Simplifies the API - no need to pass instances around
|
|
912
|
+
* - Maintains consistent event listener management
|
|
913
|
+
*
|
|
914
|
+
* **Usage in Different Contexts**:
|
|
915
|
+
*
|
|
916
|
+
* **In Games**:
|
|
917
|
+
* ```typescript
|
|
918
|
+
* import { messaging, MessageEvents } from '@playcademy/sdk'
|
|
919
|
+
*
|
|
920
|
+
* // Tell parent we're ready
|
|
921
|
+
* messaging.send(MessageEvents.READY, undefined)
|
|
922
|
+
*
|
|
923
|
+
* // Listen for pause/resume
|
|
924
|
+
* messaging.listen(MessageEvents.PAUSE, () => game.pause())
|
|
925
|
+
* messaging.listen(MessageEvents.RESUME, () => game.resume())
|
|
926
|
+
* ```
|
|
927
|
+
*
|
|
928
|
+
* **In Parent Shell**:
|
|
929
|
+
* ```typescript
|
|
930
|
+
* import { messaging, MessageEvents } from '@playcademy/sdk'
|
|
931
|
+
*
|
|
932
|
+
* // Send initialization data to game
|
|
933
|
+
* messaging.send(MessageEvents.INIT, { baseUrl, token, gameId })
|
|
934
|
+
*
|
|
935
|
+
* // Listen for game events
|
|
936
|
+
* messaging.listen(MessageEvents.EXIT, () => closeGame())
|
|
937
|
+
* messaging.listen(MessageEvents.READY, () => showGame())
|
|
938
|
+
* ```
|
|
939
|
+
*
|
|
940
|
+
* **Automatic Transport Selection**:
|
|
941
|
+
* The messaging system automatically chooses the right transport method:
|
|
942
|
+
* - Uses postMessage when game is in iframe sending to parent
|
|
943
|
+
* - Uses CustomEvent for local development and parent-to-game communication
|
|
944
|
+
*
|
|
945
|
+
* **Type Safety**:
|
|
946
|
+
* All message sending and receiving is fully type-safe with TypeScript.
|
|
947
|
+
*/
|
|
948
|
+
declare const messaging: PlaycademyMessaging;
|
|
1779
949
|
|
|
1780
950
|
/**
|
|
1781
951
|
* Playcademy SDK client for game developers.
|
|
@@ -1803,7 +973,7 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
|
|
|
1803
973
|
getGameToken: (gameId: string, options?: {
|
|
1804
974
|
apply?: boolean;
|
|
1805
975
|
}) => Promise<GameTokenResponse>;
|
|
1806
|
-
exit: () =>
|
|
976
|
+
exit: () => void;
|
|
1807
977
|
onInit: (handler: (context: GameContextPayload) => void) => void;
|
|
1808
978
|
onTokenRefresh: (handler: (data: {
|
|
1809
979
|
token: string;
|
|
@@ -1844,31 +1014,23 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
|
|
|
1844
1014
|
* - `user.fetch()` - Refresh user context from server
|
|
1845
1015
|
*
|
|
1846
1016
|
* Activity tracking:
|
|
1847
|
-
* - `
|
|
1848
|
-
*
|
|
1849
|
-
*
|
|
1017
|
+
* - `currentRunId` - Current activity run ID, or undefined when inactive
|
|
1018
|
+
* - `startActivity(metadata)` - Begin tracking an activity, return its run
|
|
1019
|
+
* ID, and automatically handle hidden-tab and visible-tab inactivity
|
|
1020
|
+
* with configurable paused-heartbeat timeout behavior
|
|
1850
1021
|
* - `pauseActivity()` / `resumeActivity()` - Pause/resume timer
|
|
1851
1022
|
* - `endActivity(scoreData)` - Submit activity results to TimeBack
|
|
1852
1023
|
*/
|
|
1853
1024
|
timeback: {
|
|
1854
1025
|
readonly user: TimebackUser;
|
|
1855
|
-
|
|
1026
|
+
readonly currentRunId: string | undefined;
|
|
1027
|
+
startActivity: (metadata: _playcademy_types.ActivityData, options?: StartActivityOptions) => StartActivityResult;
|
|
1856
1028
|
pauseActivity: () => void;
|
|
1857
1029
|
resumeActivity: () => void;
|
|
1858
|
-
endActivity: (data: EndActivityScoreData) => Promise<EndActivityResponse>;
|
|
1030
|
+
endActivity: (data: _playcademy_types.EndActivityScoreData) => Promise<_playcademy_types.EndActivityResponse>;
|
|
1859
1031
|
advanceCourse: (options?: {
|
|
1860
|
-
subject?: TimebackSubject;
|
|
1861
|
-
}) => Promise<AdvanceCourseResponse>;
|
|
1862
|
-
};
|
|
1863
|
-
/**
|
|
1864
|
-
* Playcademy Credits (platform currency) management.
|
|
1865
|
-
* - `get()` - Get user's credit balance
|
|
1866
|
-
* - `add(amount)` - Award credits to user
|
|
1867
|
-
*/
|
|
1868
|
-
credits: {
|
|
1869
|
-
balance: () => Promise<number>;
|
|
1870
|
-
add: (amount: number) => Promise<number>;
|
|
1871
|
-
spend: (amount: number) => Promise<number>;
|
|
1032
|
+
subject?: _playcademy_types.TimebackSubject;
|
|
1033
|
+
}) => Promise<_playcademy_types.AdvanceCourseResponse>;
|
|
1872
1034
|
};
|
|
1873
1035
|
/**
|
|
1874
1036
|
* Game score submission and leaderboards.
|
|
@@ -1882,7 +1044,7 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
|
|
|
1882
1044
|
* - `fetch(options?)` - Fetch leaderboard entries
|
|
1883
1045
|
*/
|
|
1884
1046
|
leaderboard: {
|
|
1885
|
-
fetch: (options?: LeaderboardOptions) => Promise<GameLeaderboardEntry[]>;
|
|
1047
|
+
fetch: (options?: _playcademy_types.LeaderboardOptions) => Promise<_playcademy_types.GameLeaderboardEntry[]>;
|
|
1886
1048
|
};
|
|
1887
1049
|
/**
|
|
1888
1050
|
* Demo-mode helpers. Methods throw when called outside `client.mode === 'demo'`,
|
|
@@ -1893,20 +1055,11 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
|
|
|
1893
1055
|
*/
|
|
1894
1056
|
demo: {
|
|
1895
1057
|
profile: {
|
|
1896
|
-
get: () => Promise<DemoProfile>;
|
|
1897
|
-
update: (updates: DemoProfileUpdate) => Promise<DemoProfile>;
|
|
1058
|
+
get: () => Promise<_playcademy_types.DemoProfile>;
|
|
1059
|
+
update: (updates: _playcademy_types.DemoProfileUpdate) => Promise<_playcademy_types.DemoProfile>;
|
|
1898
1060
|
};
|
|
1899
1061
|
end: (score: number, options?: DemoEndOptions) => void;
|
|
1900
1062
|
};
|
|
1901
|
-
/**
|
|
1902
|
-
* Realtime multiplayer authentication.
|
|
1903
|
-
* - `getToken()` - Get token for WebSocket/realtime connections
|
|
1904
|
-
*/
|
|
1905
|
-
realtime: {
|
|
1906
|
-
token: {
|
|
1907
|
-
get: () => Promise<RealtimeTokenResponse>;
|
|
1908
|
-
};
|
|
1909
|
-
};
|
|
1910
1063
|
/**
|
|
1911
1064
|
* Make requests to your game's custom backend API routes.
|
|
1912
1065
|
* - `get(path)`, `post(path, body)`, `put()`, `delete()` - HTTP methods
|
|
@@ -1932,6 +1085,57 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
|
|
|
1932
1085
|
};
|
|
1933
1086
|
}
|
|
1934
1087
|
|
|
1088
|
+
/**
|
|
1089
|
+
* Options for configuring activity tracking behavior.
|
|
1090
|
+
*/
|
|
1091
|
+
interface StartActivityOptions {
|
|
1092
|
+
/**
|
|
1093
|
+
* How long heartbeats continue after the activity is automatically paused
|
|
1094
|
+
* because the tab is hidden or the player is inactive while visible.
|
|
1095
|
+
* Defaults to 10 minutes. Set to `Infinity` to keep heartbeats running
|
|
1096
|
+
* indefinitely during automatic pauses. Invalid values fall back to the
|
|
1097
|
+
* 10-minute default.
|
|
1098
|
+
*/
|
|
1099
|
+
pausedHeartbeatTimeoutMs?: number;
|
|
1100
|
+
/**
|
|
1101
|
+
* @deprecated Use `pausedHeartbeatTimeoutMs` instead.
|
|
1102
|
+
*
|
|
1103
|
+
* Backward-compatible alias for callers that still use the old option
|
|
1104
|
+
* name from earlier SDK releases.
|
|
1105
|
+
*/
|
|
1106
|
+
hiddenTimeoutMs?: number;
|
|
1107
|
+
/**
|
|
1108
|
+
* How often to flush periodic heartbeats with accumulated time data.
|
|
1109
|
+
* Defaults to 15 seconds. Set to `Infinity` to disable the interval;
|
|
1110
|
+
* final unload/endActivity flushes still run. Values must be greater than
|
|
1111
|
+
* 0 or `Infinity`; invalid values fall back to the 15-second default.
|
|
1112
|
+
*/
|
|
1113
|
+
heartbeatIntervalMs?: number;
|
|
1114
|
+
/**
|
|
1115
|
+
* How long the tab can remain visible without keyboard or mouse activity
|
|
1116
|
+
* before the activity is marked inactive. Defaults to 10 minutes. Set to
|
|
1117
|
+
* `Infinity` to disable keyboard/mouse inactivity tracking. Invalid values
|
|
1118
|
+
* fall back to the 10-minute default.
|
|
1119
|
+
*/
|
|
1120
|
+
inactivityTimeoutMs?: number;
|
|
1121
|
+
/**
|
|
1122
|
+
* Stable identifier for this activity run. When provided, it is used on
|
|
1123
|
+
* every heartbeat and on endActivity instead of a freshly-generated UUID.
|
|
1124
|
+
*
|
|
1125
|
+
* Pass the same `runId` across multiple `startActivity()` calls (for
|
|
1126
|
+
* example, after the player closes and reopens a resumable activity) so
|
|
1127
|
+
* downstream systems can correlate related sessions into a single run.
|
|
1128
|
+
*
|
|
1129
|
+
* Must be a UUID (the backend validates it as such) and unique per
|
|
1130
|
+
* logical run. If omitted, the SDK generates a new UUID on each call,
|
|
1131
|
+
* which means every session is treated as its own run.
|
|
1132
|
+
*/
|
|
1133
|
+
runId?: string;
|
|
1134
|
+
}
|
|
1135
|
+
interface StartActivityResult {
|
|
1136
|
+
runId: string;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1935
1139
|
/**
|
|
1936
1140
|
* Type definitions for the game timeback namespace.
|
|
1937
1141
|
*
|
|
@@ -2108,32 +1312,8 @@ interface ClientConfig {
|
|
|
2108
1312
|
tokenType?: TokenType;
|
|
2109
1313
|
gameId?: string;
|
|
2110
1314
|
launchId?: string;
|
|
2111
|
-
autoStartSession?: boolean;
|
|
2112
|
-
onDisconnect?: DisconnectHandler;
|
|
2113
|
-
enableConnectionMonitoring?: boolean;
|
|
2114
1315
|
mode?: PlaycademyMode;
|
|
2115
1316
|
}
|
|
2116
|
-
/**
|
|
2117
|
-
* Handler called when connection state changes to offline or degraded.
|
|
2118
|
-
* Games can implement this to handle disconnects gracefully.
|
|
2119
|
-
*/
|
|
2120
|
-
type DisconnectHandler = (context: DisconnectContext) => void | Promise<void>;
|
|
2121
|
-
/**
|
|
2122
|
-
* Context provided to disconnect handlers
|
|
2123
|
-
*/
|
|
2124
|
-
interface DisconnectContext {
|
|
2125
|
-
/** Current connection state */
|
|
2126
|
-
state: 'offline' | 'degraded';
|
|
2127
|
-
/** Reason for the disconnect */
|
|
2128
|
-
reason: string;
|
|
2129
|
-
/** Timestamp when disconnect was detected */
|
|
2130
|
-
timestamp: number;
|
|
2131
|
-
/** Utility to display a platform-level alert */
|
|
2132
|
-
displayAlert: (message: string, options?: {
|
|
2133
|
-
type?: 'info' | 'warning' | 'error';
|
|
2134
|
-
duration?: number;
|
|
2135
|
-
}) => void;
|
|
2136
|
-
}
|
|
2137
1317
|
interface InitPayload {
|
|
2138
1318
|
/** Hub API base URL */
|
|
2139
1319
|
baseUrl: string;
|
|
@@ -2143,8 +1323,6 @@ interface InitPayload {
|
|
|
2143
1323
|
token: string;
|
|
2144
1324
|
/** Game ID */
|
|
2145
1325
|
gameId: string;
|
|
2146
|
-
/** Realtime WebSocket URL */
|
|
2147
|
-
realtimeUrl?: string;
|
|
2148
1326
|
/** Timeback context (if user has a Timeback account) */
|
|
2149
1327
|
timeback?: TimebackInitContext;
|
|
2150
1328
|
/** Runtime mode for the game client */
|
|
@@ -2153,7 +1331,6 @@ interface InitPayload {
|
|
|
2153
1331
|
interface GameContextPayload {
|
|
2154
1332
|
token: string;
|
|
2155
1333
|
baseUrl: string;
|
|
2156
|
-
realtimeUrl: string;
|
|
2157
1334
|
gameId: string;
|
|
2158
1335
|
forwardKeys?: string[];
|
|
2159
1336
|
mode?: PlaycademyMode;
|
|
@@ -2165,38 +1342,12 @@ interface ClientEvents {
|
|
|
2165
1342
|
authChange: {
|
|
2166
1343
|
token: string | null;
|
|
2167
1344
|
};
|
|
2168
|
-
inventoryChange: {
|
|
2169
|
-
itemId: string;
|
|
2170
|
-
delta: number;
|
|
2171
|
-
newTotal: number;
|
|
2172
|
-
};
|
|
2173
|
-
levelUp: {
|
|
2174
|
-
oldLevel: number;
|
|
2175
|
-
newLevel: number;
|
|
2176
|
-
creditsAwarded: number;
|
|
2177
|
-
};
|
|
2178
|
-
xpGained: {
|
|
2179
|
-
amount: number;
|
|
2180
|
-
totalXP: number;
|
|
2181
|
-
leveledUp: boolean;
|
|
2182
|
-
};
|
|
2183
|
-
connectionChange: {
|
|
2184
|
-
state: 'online' | 'offline' | 'degraded';
|
|
2185
|
-
reason: string;
|
|
2186
|
-
};
|
|
2187
1345
|
}
|
|
2188
1346
|
|
|
2189
1347
|
/**
|
|
2190
1348
|
* Event and message payload types for SDK messaging system
|
|
2191
1349
|
*/
|
|
2192
1350
|
|
|
2193
|
-
interface DisplayAlertPayload {
|
|
2194
|
-
message: string;
|
|
2195
|
-
options?: {
|
|
2196
|
-
type?: 'info' | 'warning' | 'error';
|
|
2197
|
-
duration?: number;
|
|
2198
|
-
};
|
|
2199
|
-
}
|
|
2200
1351
|
/**
|
|
2201
1352
|
* Authentication state change event payload.
|
|
2202
1353
|
* Used when authentication state changes in the application.
|
|
@@ -2253,14 +1404,6 @@ interface KeyEventPayload {
|
|
|
2253
1404
|
/** Event type */
|
|
2254
1405
|
type: 'keydown' | 'keyup';
|
|
2255
1406
|
}
|
|
2256
|
-
/**
|
|
2257
|
-
* Connection state payload.
|
|
2258
|
-
* Broadcast from platform to games when connection changes.
|
|
2259
|
-
*/
|
|
2260
|
-
interface ConnectionStatePayload {
|
|
2261
|
-
state: 'online' | 'offline' | 'degraded';
|
|
2262
|
-
reason: string;
|
|
2263
|
-
}
|
|
2264
1407
|
/**
|
|
2265
1408
|
* Init error payload.
|
|
2266
1409
|
* Sent from game iframe to parent when SDK initialization fails
|
|
@@ -2301,19 +1444,6 @@ interface GameTokenResponse {
|
|
|
2301
1444
|
exp: number;
|
|
2302
1445
|
baseUrl?: string;
|
|
2303
1446
|
}
|
|
2304
|
-
interface InventoryMutationResponse {
|
|
2305
|
-
newTotal: number;
|
|
2306
|
-
}
|
|
2307
|
-
|
|
2308
|
-
/**
|
|
2309
|
-
* Realtime namespace types
|
|
2310
|
-
*/
|
|
2311
|
-
/**
|
|
2312
|
-
* Response type for the realtime token API
|
|
2313
|
-
*/
|
|
2314
|
-
interface RealtimeTokenResponse {
|
|
2315
|
-
token: string;
|
|
2316
|
-
}
|
|
2317
1447
|
|
|
2318
1448
|
/**
|
|
2319
1449
|
* Scores namespace types
|
|
@@ -2395,179 +1525,5 @@ interface DevUploadHooks {
|
|
|
2395
1525
|
onClose?: () => void;
|
|
2396
1526
|
}
|
|
2397
1527
|
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
*
|
|
2401
|
-
* Manages connection monitoring and integrates it with the Playcademy client.
|
|
2402
|
-
* Handles event wiring, state management, and disconnect callbacks.
|
|
2403
|
-
*
|
|
2404
|
-
* In iframe mode, disables local monitoring and listens to platform connection
|
|
2405
|
-
* state broadcasts instead (avoids duplicate heartbeats).
|
|
2406
|
-
*/
|
|
2407
|
-
|
|
2408
|
-
/**
|
|
2409
|
-
* Configuration for the ConnectionManager.
|
|
2410
|
-
*/
|
|
2411
|
-
interface ConnectionManagerConfig {
|
|
2412
|
-
/** Base URL for API requests (used for heartbeat pings) */
|
|
2413
|
-
baseUrl: string;
|
|
2414
|
-
/** Authentication context (iframe vs standalone) for alert routing */
|
|
2415
|
-
authContext?: {
|
|
2416
|
-
isInIframe: boolean;
|
|
2417
|
-
};
|
|
2418
|
-
/** Handler to call when connection issues are detected */
|
|
2419
|
-
onDisconnect?: DisconnectHandler;
|
|
2420
|
-
/** Callback to emit connection change events to the client */
|
|
2421
|
-
onConnectionChange?: (state: ConnectionState, reason: string) => void;
|
|
2422
|
-
}
|
|
2423
|
-
/**
|
|
2424
|
-
* Manages connection monitoring for the Playcademy client.
|
|
2425
|
-
*
|
|
2426
|
-
* The ConnectionManager serves as an integration layer between the low-level
|
|
2427
|
-
* ConnectionMonitor and the PlaycademyClient. It handles:
|
|
2428
|
-
* - Event wiring and coordination
|
|
2429
|
-
* - Disconnect callbacks with context
|
|
2430
|
-
* - Platform-level alert integration
|
|
2431
|
-
* - Request success/failure tracking
|
|
2432
|
-
*
|
|
2433
|
-
* This class is used internally by PlaycademyClient and typically not
|
|
2434
|
-
* instantiated directly by game developers.
|
|
2435
|
-
*
|
|
2436
|
-
* @see {@link ConnectionMonitor} for the underlying monitoring implementation
|
|
2437
|
-
* @see {@link PlaycademyClient.onDisconnect} for the public API
|
|
2438
|
-
*/
|
|
2439
|
-
declare class ConnectionManager {
|
|
2440
|
-
private monitor?;
|
|
2441
|
-
private authContext?;
|
|
2442
|
-
private disconnectHandler?;
|
|
2443
|
-
private connectionChangeCallback?;
|
|
2444
|
-
private currentState;
|
|
2445
|
-
private additionalDisconnectHandlers;
|
|
2446
|
-
/**
|
|
2447
|
-
* Creates a new ConnectionManager instance.
|
|
2448
|
-
*
|
|
2449
|
-
* @param config - Configuration options for the manager
|
|
2450
|
-
*
|
|
2451
|
-
* @example
|
|
2452
|
-
* ```typescript
|
|
2453
|
-
* const manager = new ConnectionManager({
|
|
2454
|
-
* baseUrl: 'https://api.playcademy.com',
|
|
2455
|
-
* authContext: { isInIframe: false },
|
|
2456
|
-
* onDisconnect: (context) => {
|
|
2457
|
-
* console.log(`Disconnected: ${context.state}`)
|
|
2458
|
-
* },
|
|
2459
|
-
* onConnectionChange: (state, reason) => {
|
|
2460
|
-
* console.log(`Connection changed: ${state}`)
|
|
2461
|
-
* }
|
|
2462
|
-
* })
|
|
2463
|
-
* ```
|
|
2464
|
-
*/
|
|
2465
|
-
constructor(config: ConnectionManagerConfig);
|
|
2466
|
-
/**
|
|
2467
|
-
* Gets the current connection state.
|
|
2468
|
-
*
|
|
2469
|
-
* @returns The current connection state ('online', 'offline', or 'degraded')
|
|
2470
|
-
*
|
|
2471
|
-
* @example
|
|
2472
|
-
* ```typescript
|
|
2473
|
-
* const state = manager.getState()
|
|
2474
|
-
* if (state === 'offline') {
|
|
2475
|
-
* console.log('No connection')
|
|
2476
|
-
* }
|
|
2477
|
-
* ```
|
|
2478
|
-
*/
|
|
2479
|
-
getState(): ConnectionState;
|
|
2480
|
-
/**
|
|
2481
|
-
* Manually triggers a connection check immediately.
|
|
2482
|
-
*
|
|
2483
|
-
* Forces a heartbeat ping to verify the current connection status.
|
|
2484
|
-
* Useful when you need to check connectivity before a critical operation.
|
|
2485
|
-
*
|
|
2486
|
-
* In iframe mode, this returns the last known state from platform.
|
|
2487
|
-
*
|
|
2488
|
-
* @returns Promise resolving to the current connection state
|
|
2489
|
-
*
|
|
2490
|
-
* @example
|
|
2491
|
-
* ```typescript
|
|
2492
|
-
* const state = await manager.checkNow()
|
|
2493
|
-
* if (state === 'online') {
|
|
2494
|
-
* await performCriticalOperation()
|
|
2495
|
-
* }
|
|
2496
|
-
* ```
|
|
2497
|
-
*/
|
|
2498
|
-
checkNow(): Promise<ConnectionState>;
|
|
2499
|
-
/**
|
|
2500
|
-
* Reports a successful API request to the connection monitor.
|
|
2501
|
-
*
|
|
2502
|
-
* This resets the consecutive failure counter and transitions from
|
|
2503
|
-
* 'degraded' to 'online' state if applicable.
|
|
2504
|
-
*
|
|
2505
|
-
* Typically called automatically by the SDK's request wrapper.
|
|
2506
|
-
* No-op in iframe mode (platform handles monitoring).
|
|
2507
|
-
*/
|
|
2508
|
-
reportRequestSuccess(): void;
|
|
2509
|
-
/**
|
|
2510
|
-
* Reports a failed API request to the connection monitor.
|
|
2511
|
-
*
|
|
2512
|
-
* Only network errors are tracked (not 4xx/5xx HTTP responses).
|
|
2513
|
-
* After consecutive failures exceed the threshold, the state transitions
|
|
2514
|
-
* to 'degraded' or 'offline'.
|
|
2515
|
-
*
|
|
2516
|
-
* Typically called automatically by the SDK's request wrapper.
|
|
2517
|
-
* No-op in iframe mode (platform handles monitoring).
|
|
2518
|
-
*
|
|
2519
|
-
* @param error - The error from the failed request
|
|
2520
|
-
*/
|
|
2521
|
-
reportRequestFailure(error: unknown): void;
|
|
2522
|
-
/**
|
|
2523
|
-
* Registers a callback to be called when connection issues are detected.
|
|
2524
|
-
*
|
|
2525
|
-
* The callback only fires for 'offline' and 'degraded' states, not when
|
|
2526
|
-
* recovering to 'online'. This provides a clean API for games to handle
|
|
2527
|
-
* disconnect scenarios without being notified of every state change.
|
|
2528
|
-
*
|
|
2529
|
-
* Works in both iframe and standalone modes transparently.
|
|
2530
|
-
*
|
|
2531
|
-
* @param callback - Function to call when connection degrades
|
|
2532
|
-
* @returns Cleanup function to unregister the callback
|
|
2533
|
-
*
|
|
2534
|
-
* @example
|
|
2535
|
-
* ```typescript
|
|
2536
|
-
* const cleanup = manager.onDisconnect(({ state, reason, displayAlert }) => {
|
|
2537
|
-
* if (state === 'offline') {
|
|
2538
|
-
* displayAlert?.('Connection lost. Saving your progress...', { type: 'error' })
|
|
2539
|
-
* saveGameState()
|
|
2540
|
-
* }
|
|
2541
|
-
* })
|
|
2542
|
-
*
|
|
2543
|
-
* // Later: cleanup() to unregister
|
|
2544
|
-
* ```
|
|
2545
|
-
*/
|
|
2546
|
-
onDisconnect(callback: DisconnectHandler): () => void;
|
|
2547
|
-
/**
|
|
2548
|
-
* Stops connection monitoring and performs cleanup.
|
|
2549
|
-
*
|
|
2550
|
-
* Removes event listeners and clears heartbeat intervals.
|
|
2551
|
-
* Should be called when the client is being destroyed.
|
|
2552
|
-
*/
|
|
2553
|
-
stop(): void;
|
|
2554
|
-
/**
|
|
2555
|
-
* Sets up listener for platform connection state broadcasts (iframe mode only).
|
|
2556
|
-
*/
|
|
2557
|
-
private _setupPlatformListener;
|
|
2558
|
-
/**
|
|
2559
|
-
* Handles connection state changes from the monitor or platform.
|
|
2560
|
-
*
|
|
2561
|
-
* Coordinates between:
|
|
2562
|
-
* 1. Emitting events to the client (for client.on('connectionChange'))
|
|
2563
|
-
* 2. Calling the disconnect handler if configured
|
|
2564
|
-
* 3. Calling any additional handlers registered via onDisconnect()
|
|
2565
|
-
*
|
|
2566
|
-
* @param state - The new connection state
|
|
2567
|
-
* @param reason - Human-readable reason for the state change
|
|
2568
|
-
*/
|
|
2569
|
-
private _handleConnectionChange;
|
|
2570
|
-
}
|
|
2571
|
-
|
|
2572
|
-
export { ApiError, ConnectionManager, ConnectionMonitor, MessageEvents, PlaycademyClient, PlaycademyError, extractApiErrorInfo, messaging };
|
|
2573
|
-
export type { ApiErrorCode, ApiErrorInfo, ConnectionMonitorConfig, ConnectionState, ConnectionStatePayload, DevUploadEvent, DevUploadHooks, DisconnectContext, DisconnectHandler, DisplayAlertPayload, ErrorResponseBody, PlaycademyMode };
|
|
1528
|
+
export { ApiError, MessageEvents, PlaycademyClient, PlaycademyError, extractApiErrorInfo, messaging };
|
|
1529
|
+
export type { ApiErrorCode, ApiErrorInfo, DevUploadEvent, DevUploadHooks, ErrorResponseBody, PlaycademyMode };
|