@playcademy/sdk 0.9.1-beta.1 → 0.9.1-beta.2
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 +5 -2
- package/dist/index.d.ts +364 -359
- package/dist/index.js +12 -2
- package/dist/internal.d.ts +5506 -5454
- package/dist/internal.js +16 -3
- package/dist/types.d.ts +1182 -1177
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -384,6 +384,125 @@ interface RetryPolicy {
|
|
|
384
384
|
retryableMethods?: readonly Method[];
|
|
385
385
|
}
|
|
386
386
|
|
|
387
|
+
/**
|
|
388
|
+
* User Types
|
|
389
|
+
*
|
|
390
|
+
* Enums, DTOs and API response types. Database row types are in @playcademy/data/types.
|
|
391
|
+
*
|
|
392
|
+
* @module types/user
|
|
393
|
+
*/
|
|
394
|
+
|
|
395
|
+
type UserRoleEnumType = UserRole;
|
|
396
|
+
type DeveloperStatusEnumType = 'none' | 'pending' | 'approved';
|
|
397
|
+
type TimebackUserRole = 'administrator' | 'aide' | 'guardian' | 'parent' | 'proctor' | 'relative' | 'student' | 'teacher';
|
|
398
|
+
type TimebackOrgType = 'department' | 'school' | 'district' | 'local' | 'state' | 'national';
|
|
399
|
+
interface UserEnrollment {
|
|
400
|
+
gameId?: string;
|
|
401
|
+
courseId: string;
|
|
402
|
+
enrollmentIds?: {
|
|
403
|
+
active: string;
|
|
404
|
+
inactive?: string[];
|
|
405
|
+
};
|
|
406
|
+
grade: number;
|
|
407
|
+
subject: string;
|
|
408
|
+
orgId?: string;
|
|
409
|
+
}
|
|
410
|
+
interface UserOrganization {
|
|
411
|
+
id: string;
|
|
412
|
+
name: string | null;
|
|
413
|
+
type: TimebackOrgType | string;
|
|
414
|
+
isPrimary: boolean;
|
|
415
|
+
}
|
|
416
|
+
interface TimebackStudentProfile {
|
|
417
|
+
role: TimebackUserRole;
|
|
418
|
+
organizations: UserOrganization[];
|
|
419
|
+
}
|
|
420
|
+
interface UserTimebackData extends TimebackStudentProfile {
|
|
421
|
+
id: string;
|
|
422
|
+
enrollments: UserEnrollment[];
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* OpenID Connect UserInfo claims (NOT a database row).
|
|
426
|
+
*/
|
|
427
|
+
interface UserInfo {
|
|
428
|
+
sub: string;
|
|
429
|
+
email: string;
|
|
430
|
+
name: string | null;
|
|
431
|
+
email_verified?: boolean;
|
|
432
|
+
given_name?: string;
|
|
433
|
+
family_name?: string;
|
|
434
|
+
issuer?: string;
|
|
435
|
+
lti_roles?: unknown;
|
|
436
|
+
lti_context?: unknown;
|
|
437
|
+
lti_resource_link?: unknown;
|
|
438
|
+
timeback_id?: string;
|
|
439
|
+
}
|
|
440
|
+
interface DemoProfile {
|
|
441
|
+
displayName: string;
|
|
442
|
+
isDefault: boolean;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Update shape for `client.demo.profile.update(...)`.
|
|
446
|
+
*
|
|
447
|
+
* Kept as a named type so callers typed against it pick up new fields
|
|
448
|
+
* automatically, but `displayName` is the only updatable field today and
|
|
449
|
+
* the server's `DemoProfileSchema` requires it — a no-field payload would
|
|
450
|
+
* 400 at runtime, so we model that at the type level too. When additional
|
|
451
|
+
* fields land, make them required/optional individually based on server
|
|
452
|
+
* validation, rather than blanket-optional.
|
|
453
|
+
*/
|
|
454
|
+
interface DemoProfileUpdate {
|
|
455
|
+
displayName: string;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Authenticated user for API responses.
|
|
459
|
+
* Differs from UserRow: omits timebackId, adds hasTimebackAccount and timeback.
|
|
460
|
+
*/
|
|
461
|
+
interface AuthenticatedUser {
|
|
462
|
+
id: string;
|
|
463
|
+
email: string;
|
|
464
|
+
emailVerified: boolean;
|
|
465
|
+
name: string | null;
|
|
466
|
+
image: string | null;
|
|
467
|
+
username: string | null;
|
|
468
|
+
role: UserRoleEnumType;
|
|
469
|
+
developerStatus: DeveloperStatusEnumType;
|
|
470
|
+
characterCreated: boolean;
|
|
471
|
+
createdAt: Date;
|
|
472
|
+
updatedAt: Date;
|
|
473
|
+
hasTimebackAccount: boolean;
|
|
474
|
+
timeback?: UserTimebackData;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Leaderboard Types
|
|
479
|
+
*
|
|
480
|
+
* @module types/leaderboard
|
|
481
|
+
*/
|
|
482
|
+
type LeaderboardTimeframe = 'all_time' | 'monthly' | 'weekly' | 'daily';
|
|
483
|
+
interface LeaderboardOptions {
|
|
484
|
+
timeframe?: LeaderboardTimeframe;
|
|
485
|
+
limit?: number;
|
|
486
|
+
offset?: number;
|
|
487
|
+
gameId?: string;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Leaderboard entry with required game context.
|
|
491
|
+
* Used when fetching leaderboards for a specific game.
|
|
492
|
+
*/
|
|
493
|
+
interface GameLeaderboardEntry {
|
|
494
|
+
rank: number;
|
|
495
|
+
userId: string;
|
|
496
|
+
username: string;
|
|
497
|
+
userImage?: string | null;
|
|
498
|
+
score: number;
|
|
499
|
+
achievedAt: Date;
|
|
500
|
+
metadata?: Record<string, unknown>;
|
|
501
|
+
gameId: string;
|
|
502
|
+
gameTitle: string;
|
|
503
|
+
gameSlug: string;
|
|
504
|
+
}
|
|
505
|
+
|
|
387
506
|
/**
|
|
388
507
|
* TimeBack Enums & Literal Types
|
|
389
508
|
*
|
|
@@ -513,125 +632,6 @@ interface TTLCacheConfig {
|
|
|
513
632
|
skipCache?: boolean;
|
|
514
633
|
}
|
|
515
634
|
|
|
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
635
|
declare const items: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
636
636
|
name: "items";
|
|
637
637
|
schema: undefined;
|
|
@@ -909,24 +909,195 @@ type InventoryItemWithItem = InventoryItemRow & {
|
|
|
909
909
|
};
|
|
910
910
|
|
|
911
911
|
/**
|
|
912
|
-
*
|
|
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
|
|
912
|
+
* @fileoverview Authentication Strategy Pattern
|
|
925
913
|
*
|
|
926
|
-
*
|
|
927
|
-
*
|
|
928
|
-
|
|
929
|
-
|
|
914
|
+
* Provides different authentication strategies for the Playcademy SDK.
|
|
915
|
+
* Each strategy knows how to add its authentication headers to requests.
|
|
916
|
+
*/
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* Base interface for authentication strategies
|
|
920
|
+
*/
|
|
921
|
+
interface AuthStrategy {
|
|
922
|
+
/** Get the token value */
|
|
923
|
+
getToken(): string | null;
|
|
924
|
+
/** Get the token type */
|
|
925
|
+
getType(): TokenType;
|
|
926
|
+
/** Get authentication headers for a request */
|
|
927
|
+
getHeaders(): Record<string, string>;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* Base Playcademy SDK client with shared infrastructure.
|
|
932
|
+
* Provides authentication, HTTP requests, events, connection monitoring,
|
|
933
|
+
* and fundamental namespaces used by all clients.
|
|
934
|
+
*
|
|
935
|
+
* Extended by PlaycademyClient (game SDK) and PlaycademyInternalClient (platform SDK).
|
|
936
|
+
*/
|
|
937
|
+
declare abstract class PlaycademyBaseClient {
|
|
938
|
+
baseUrl: string;
|
|
939
|
+
gameUrl?: string;
|
|
940
|
+
mode: PlaycademyMode;
|
|
941
|
+
protected authStrategy: AuthStrategy;
|
|
942
|
+
protected gameId?: string;
|
|
943
|
+
protected config: Partial<ClientConfig>;
|
|
944
|
+
protected listeners: EventListeners;
|
|
945
|
+
protected internalClientSessionId?: string;
|
|
946
|
+
protected authContext?: {
|
|
947
|
+
isInIframe: boolean;
|
|
948
|
+
};
|
|
949
|
+
protected initPayload?: InitPayload;
|
|
950
|
+
protected connectionManager?: ConnectionManager;
|
|
951
|
+
protected launchId?: string;
|
|
952
|
+
/**
|
|
953
|
+
* Internal session manager for automatic session lifecycle.
|
|
954
|
+
* @private
|
|
955
|
+
* @internal
|
|
956
|
+
*/
|
|
957
|
+
protected _sessionManager: {
|
|
958
|
+
startSession: (gameId: string) => Promise<{
|
|
959
|
+
sessionId: string;
|
|
960
|
+
}>;
|
|
961
|
+
endSession: (sessionId: string, gameId: string) => Promise<void>;
|
|
962
|
+
};
|
|
963
|
+
constructor(config?: Partial<ClientConfig>);
|
|
964
|
+
/**
|
|
965
|
+
* Gets the effective base URL for API requests.
|
|
966
|
+
*/
|
|
967
|
+
getBaseUrl(): string;
|
|
968
|
+
/**
|
|
969
|
+
* Gets the effective game backend URL for integration requests.
|
|
970
|
+
*/
|
|
971
|
+
protected getGameBackendUrl(): string;
|
|
972
|
+
/**
|
|
973
|
+
* Simple ping method for testing connectivity.
|
|
974
|
+
*/
|
|
975
|
+
ping(): string;
|
|
976
|
+
/**
|
|
977
|
+
* Sets the authentication token for API requests.
|
|
978
|
+
*/
|
|
979
|
+
setToken(token: string | null, tokenType?: TokenType): void;
|
|
980
|
+
setLaunchId(launchId: string | null | undefined): void;
|
|
981
|
+
/**
|
|
982
|
+
* Gets the current token type.
|
|
983
|
+
*/
|
|
984
|
+
getTokenType(): TokenType;
|
|
985
|
+
/**
|
|
986
|
+
* Gets the current authentication token.
|
|
987
|
+
*/
|
|
988
|
+
getToken(): string | null;
|
|
989
|
+
/**
|
|
990
|
+
* Checks if the client has a valid API token.
|
|
991
|
+
*/
|
|
992
|
+
isAuthenticated(): boolean;
|
|
993
|
+
/**
|
|
994
|
+
* Registers a callback to be called when authentication state changes.
|
|
995
|
+
*/
|
|
996
|
+
onAuthChange(callback: (token: string | null) => void): void;
|
|
997
|
+
/**
|
|
998
|
+
* Registers a callback to be called when connection issues are detected.
|
|
999
|
+
*/
|
|
1000
|
+
onDisconnect(callback: (context: DisconnectContext) => void | Promise<void>): () => void;
|
|
1001
|
+
/**
|
|
1002
|
+
* Gets the current connection state.
|
|
1003
|
+
*/
|
|
1004
|
+
getConnectionState(): ConnectionState | 'unknown';
|
|
1005
|
+
/**
|
|
1006
|
+
* Manually triggers a connection check immediately.
|
|
1007
|
+
*/
|
|
1008
|
+
checkConnection(): Promise<ConnectionState | 'unknown'>;
|
|
1009
|
+
/**
|
|
1010
|
+
* Sets the authentication context for the client.
|
|
1011
|
+
* @internal
|
|
1012
|
+
*/
|
|
1013
|
+
_setAuthContext(context: {
|
|
1014
|
+
isInIframe: boolean;
|
|
1015
|
+
}): void;
|
|
1016
|
+
/**
|
|
1017
|
+
* Registers an event listener for client events.
|
|
1018
|
+
*
|
|
1019
|
+
* @param event - The event name to listen for.
|
|
1020
|
+
* @param callback - The handler invoked when the event fires.
|
|
1021
|
+
* @returns A cleanup function that removes this specific listener.
|
|
1022
|
+
*/
|
|
1023
|
+
on<E extends keyof ClientEvents>(event: E, callback: (payload: ClientEvents[E]) => void): () => void;
|
|
1024
|
+
/**
|
|
1025
|
+
* Removes a previously registered event listener.
|
|
1026
|
+
*
|
|
1027
|
+
* @param event - The event name to stop listening for.
|
|
1028
|
+
* @param callback - The exact function reference passed to {@link on}.
|
|
1029
|
+
*/
|
|
1030
|
+
off<E extends keyof ClientEvents>(event: E, callback: (payload: ClientEvents[E]) => void): void;
|
|
1031
|
+
/**
|
|
1032
|
+
* Emits an event to all registered listeners.
|
|
1033
|
+
*/
|
|
1034
|
+
protected emit<E extends keyof ClientEvents>(event: E, payload: ClientEvents[E]): void;
|
|
1035
|
+
/**
|
|
1036
|
+
* Makes an authenticated HTTP request to the platform API.
|
|
1037
|
+
*/
|
|
1038
|
+
protected request<T>(path: string, method: Method, options?: {
|
|
1039
|
+
body?: unknown;
|
|
1040
|
+
headers?: Record<string, string>;
|
|
1041
|
+
raw?: boolean;
|
|
1042
|
+
retryPolicy?: RetryPolicy;
|
|
1043
|
+
}): Promise<T>;
|
|
1044
|
+
/**
|
|
1045
|
+
* Makes an authenticated HTTP request to the game's backend Worker.
|
|
1046
|
+
*/
|
|
1047
|
+
protected requestGameBackend<T>(path: string, method: Method, body?: unknown, headers?: Record<string, string>, options?: {
|
|
1048
|
+
raw?: boolean;
|
|
1049
|
+
retryPolicy?: RetryPolicy;
|
|
1050
|
+
}): Promise<T>;
|
|
1051
|
+
/**
|
|
1052
|
+
* Ensures a gameId is available, throwing an error if not.
|
|
1053
|
+
*/
|
|
1054
|
+
protected _ensureGameId(): string;
|
|
1055
|
+
/**
|
|
1056
|
+
* Detects and sets the authentication context (iframe vs standalone).
|
|
1057
|
+
*/
|
|
1058
|
+
private _detectAuthContext;
|
|
1059
|
+
/**
|
|
1060
|
+
* Initializes connection monitoring if enabled.
|
|
1061
|
+
*/
|
|
1062
|
+
private _initializeConnectionMonitor;
|
|
1063
|
+
private _initializeInternalSession;
|
|
1064
|
+
/**
|
|
1065
|
+
* Current user data and inventory management.
|
|
1066
|
+
* - `me()` - Get authenticated user profile
|
|
1067
|
+
* - `inventory.get()` - List user's items
|
|
1068
|
+
* - `inventory.add(slug, qty)` - Award items to user
|
|
1069
|
+
*/
|
|
1070
|
+
users: {
|
|
1071
|
+
me: () => Promise<AuthenticatedUser>;
|
|
1072
|
+
inventory: {
|
|
1073
|
+
get: () => Promise<InventoryItemWithItem[]>;
|
|
1074
|
+
add: (identifier: string, qty: number) => Promise<InventoryMutationResponse>;
|
|
1075
|
+
remove: (identifier: string, qty: number) => Promise<InventoryMutationResponse>;
|
|
1076
|
+
quantity: (identifier: string) => Promise<number>;
|
|
1077
|
+
has: (identifier: string, minQuantity?: number) => Promise<boolean>;
|
|
1078
|
+
};
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
/**
|
|
1083
|
+
* Auto-initializes a PlaycademyClient with context from the environment.
|
|
1084
|
+
* Works in both iframe mode (production/development) and standalone mode (local dev).
|
|
1085
|
+
*
|
|
1086
|
+
* This is the recommended way to initialize the SDK as it automatically:
|
|
1087
|
+
* - Detects the runtime environment (iframe vs standalone)
|
|
1088
|
+
* - Configures the client with the appropriate context
|
|
1089
|
+
* - Sets up event listeners for token refresh
|
|
1090
|
+
* - Exposes the client for debugging in development mode
|
|
1091
|
+
*
|
|
1092
|
+
* @param options - Optional configuration overrides
|
|
1093
|
+
* @param options.baseUrl - Override the base URL for API requests
|
|
1094
|
+
* @returns Promise resolving to a fully initialized PlaycademyClient
|
|
1095
|
+
* @throws Error if not running in a browser context
|
|
1096
|
+
*
|
|
1097
|
+
* @example
|
|
1098
|
+
* ```typescript
|
|
1099
|
+
* // Default initialization
|
|
1100
|
+
* const client = await PlaycademyClient.init()
|
|
930
1101
|
*
|
|
931
1102
|
* // With custom base URL
|
|
932
1103
|
* const client = await PlaycademyClient.init({ baseUrl: 'https://custom.api.com' })
|
|
@@ -1558,225 +1729,6 @@ declare class PlaycademyMessaging {
|
|
|
1558
1729
|
*/
|
|
1559
1730
|
declare const messaging: PlaycademyMessaging;
|
|
1560
1731
|
|
|
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.
|
|
1768
|
-
*
|
|
1769
|
-
* Pass the same `runId` across multiple `startActivity()` calls (for
|
|
1770
|
-
* example, after the player closes and reopens a resumable activity) so
|
|
1771
|
-
* downstream systems can correlate related sessions into a single run.
|
|
1772
|
-
*
|
|
1773
|
-
* Must be a UUID (the backend validates it as such) and unique per
|
|
1774
|
-
* logical run. If omitted, the SDK generates a new UUID on each call,
|
|
1775
|
-
* which means every session is treated as its own run.
|
|
1776
|
-
*/
|
|
1777
|
-
runId?: string;
|
|
1778
|
-
}
|
|
1779
|
-
|
|
1780
1732
|
/**
|
|
1781
1733
|
* Playcademy SDK client for game developers.
|
|
1782
1734
|
* Provides namespaced access to platform features for games running inside Cademy.
|
|
@@ -1844,15 +1796,17 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
|
|
|
1844
1796
|
* - `user.fetch()` - Refresh user context from server
|
|
1845
1797
|
*
|
|
1846
1798
|
* Activity tracking:
|
|
1847
|
-
* - `
|
|
1848
|
-
*
|
|
1849
|
-
*
|
|
1799
|
+
* - `currentRunId` - Current activity run ID, or undefined when inactive
|
|
1800
|
+
* - `startActivity(metadata)` - Begin tracking an activity, return its run
|
|
1801
|
+
* ID, and automatically handle hidden-tab and visible-tab inactivity
|
|
1802
|
+
* with configurable paused-heartbeat timeout behavior
|
|
1850
1803
|
* - `pauseActivity()` / `resumeActivity()` - Pause/resume timer
|
|
1851
1804
|
* - `endActivity(scoreData)` - Submit activity results to TimeBack
|
|
1852
1805
|
*/
|
|
1853
1806
|
timeback: {
|
|
1854
1807
|
readonly user: TimebackUser;
|
|
1855
|
-
|
|
1808
|
+
readonly currentRunId: string | undefined;
|
|
1809
|
+
startActivity: (metadata: ActivityData, options?: StartActivityOptions) => StartActivityResult;
|
|
1856
1810
|
pauseActivity: () => void;
|
|
1857
1811
|
resumeActivity: () => void;
|
|
1858
1812
|
endActivity: (data: EndActivityScoreData) => Promise<EndActivityResponse>;
|
|
@@ -1932,6 +1886,57 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
|
|
|
1932
1886
|
};
|
|
1933
1887
|
}
|
|
1934
1888
|
|
|
1889
|
+
/**
|
|
1890
|
+
* Options for configuring activity tracking behavior.
|
|
1891
|
+
*/
|
|
1892
|
+
interface StartActivityOptions {
|
|
1893
|
+
/**
|
|
1894
|
+
* How long heartbeats continue after the activity is automatically paused
|
|
1895
|
+
* because the tab is hidden or the player is inactive while visible.
|
|
1896
|
+
* Defaults to 10 minutes. Set to `Infinity` to keep heartbeats running
|
|
1897
|
+
* indefinitely during automatic pauses. Invalid values fall back to the
|
|
1898
|
+
* 10-minute default.
|
|
1899
|
+
*/
|
|
1900
|
+
pausedHeartbeatTimeoutMs?: number;
|
|
1901
|
+
/**
|
|
1902
|
+
* @deprecated Use `pausedHeartbeatTimeoutMs` instead.
|
|
1903
|
+
*
|
|
1904
|
+
* Backward-compatible alias for callers that still use the old option
|
|
1905
|
+
* name from earlier SDK releases.
|
|
1906
|
+
*/
|
|
1907
|
+
hiddenTimeoutMs?: number;
|
|
1908
|
+
/**
|
|
1909
|
+
* How often to flush periodic heartbeats with accumulated time data.
|
|
1910
|
+
* Defaults to 15 seconds. Set to `Infinity` to disable the interval;
|
|
1911
|
+
* final unload/endActivity flushes still run. Values must be greater than
|
|
1912
|
+
* 0 or `Infinity`; invalid values fall back to the 15-second default.
|
|
1913
|
+
*/
|
|
1914
|
+
heartbeatIntervalMs?: number;
|
|
1915
|
+
/**
|
|
1916
|
+
* How long the tab can remain visible without keyboard or mouse activity
|
|
1917
|
+
* before the activity is marked inactive. Defaults to 10 minutes. Set to
|
|
1918
|
+
* `Infinity` to disable keyboard/mouse inactivity tracking. Invalid values
|
|
1919
|
+
* fall back to the 10-minute default.
|
|
1920
|
+
*/
|
|
1921
|
+
inactivityTimeoutMs?: number;
|
|
1922
|
+
/**
|
|
1923
|
+
* Stable identifier for this activity run. When provided, it is used on
|
|
1924
|
+
* every heartbeat and on endActivity instead of a freshly-generated UUID.
|
|
1925
|
+
*
|
|
1926
|
+
* Pass the same `runId` across multiple `startActivity()` calls (for
|
|
1927
|
+
* example, after the player closes and reopens a resumable activity) so
|
|
1928
|
+
* downstream systems can correlate related sessions into a single run.
|
|
1929
|
+
*
|
|
1930
|
+
* Must be a UUID (the backend validates it as such) and unique per
|
|
1931
|
+
* logical run. If omitted, the SDK generates a new UUID on each call,
|
|
1932
|
+
* which means every session is treated as its own run.
|
|
1933
|
+
*/
|
|
1934
|
+
runId?: string;
|
|
1935
|
+
}
|
|
1936
|
+
interface StartActivityResult {
|
|
1937
|
+
runId: string;
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1935
1940
|
/**
|
|
1936
1941
|
* Type definitions for the game timeback namespace.
|
|
1937
1942
|
*
|