@playcademy/sdk 0.2.0 → 0.2.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 +20 -17
- package/dist/index.d.ts +245 -561
- package/dist/index.js +1275 -1435
- package/dist/internal.d.ts +2558 -2318
- package/dist/internal.js +2454 -2565
- package/dist/server.d.ts +6 -5
- package/dist/server.js +14 -1
- package/dist/types.d.ts +448 -549
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as _playcademy_realtime_server_types from '@playcademy/realtime/server/types';
|
|
2
1
|
import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
|
|
3
2
|
import * as _playcademy_timeback_types from '@playcademy/timeback/types';
|
|
4
3
|
import { AUTH_PROVIDER_IDS } from '@playcademy/constants';
|
|
@@ -736,177 +735,70 @@ declare const inventoryItems: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
736
735
|
};
|
|
737
736
|
dialect: "pg";
|
|
738
737
|
}>;
|
|
739
|
-
declare const gameTimebackIntegrations: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
740
|
-
name: "game_timeback_integrations";
|
|
741
|
-
schema: undefined;
|
|
742
|
-
columns: {
|
|
743
|
-
id: drizzle_orm_pg_core.PgColumn<{
|
|
744
|
-
name: "id";
|
|
745
|
-
tableName: "game_timeback_integrations";
|
|
746
|
-
dataType: "string";
|
|
747
|
-
columnType: "PgUUID";
|
|
748
|
-
data: string;
|
|
749
|
-
driverParam: string;
|
|
750
|
-
notNull: true;
|
|
751
|
-
hasDefault: true;
|
|
752
|
-
isPrimaryKey: true;
|
|
753
|
-
isAutoincrement: false;
|
|
754
|
-
hasRuntimeDefault: false;
|
|
755
|
-
enumValues: undefined;
|
|
756
|
-
baseColumn: never;
|
|
757
|
-
identity: undefined;
|
|
758
|
-
generated: undefined;
|
|
759
|
-
}, {}, {}>;
|
|
760
|
-
gameId: drizzle_orm_pg_core.PgColumn<{
|
|
761
|
-
name: "game_id";
|
|
762
|
-
tableName: "game_timeback_integrations";
|
|
763
|
-
dataType: "string";
|
|
764
|
-
columnType: "PgUUID";
|
|
765
|
-
data: string;
|
|
766
|
-
driverParam: string;
|
|
767
|
-
notNull: true;
|
|
768
|
-
hasDefault: false;
|
|
769
|
-
isPrimaryKey: false;
|
|
770
|
-
isAutoincrement: false;
|
|
771
|
-
hasRuntimeDefault: false;
|
|
772
|
-
enumValues: undefined;
|
|
773
|
-
baseColumn: never;
|
|
774
|
-
identity: undefined;
|
|
775
|
-
generated: undefined;
|
|
776
|
-
}, {}, {}>;
|
|
777
|
-
courseId: drizzle_orm_pg_core.PgColumn<{
|
|
778
|
-
name: "course_id";
|
|
779
|
-
tableName: "game_timeback_integrations";
|
|
780
|
-
dataType: "string";
|
|
781
|
-
columnType: "PgText";
|
|
782
|
-
data: string;
|
|
783
|
-
driverParam: string;
|
|
784
|
-
notNull: true;
|
|
785
|
-
hasDefault: false;
|
|
786
|
-
isPrimaryKey: false;
|
|
787
|
-
isAutoincrement: false;
|
|
788
|
-
hasRuntimeDefault: false;
|
|
789
|
-
enumValues: [string, ...string[]];
|
|
790
|
-
baseColumn: never;
|
|
791
|
-
identity: undefined;
|
|
792
|
-
generated: undefined;
|
|
793
|
-
}, {}, {}>;
|
|
794
|
-
grade: drizzle_orm_pg_core.PgColumn<{
|
|
795
|
-
name: "grade";
|
|
796
|
-
tableName: "game_timeback_integrations";
|
|
797
|
-
dataType: "number";
|
|
798
|
-
columnType: "PgInteger";
|
|
799
|
-
data: number;
|
|
800
|
-
driverParam: string | number;
|
|
801
|
-
notNull: true;
|
|
802
|
-
hasDefault: false;
|
|
803
|
-
isPrimaryKey: false;
|
|
804
|
-
isAutoincrement: false;
|
|
805
|
-
hasRuntimeDefault: false;
|
|
806
|
-
enumValues: undefined;
|
|
807
|
-
baseColumn: never;
|
|
808
|
-
identity: undefined;
|
|
809
|
-
generated: undefined;
|
|
810
|
-
}, {}, {}>;
|
|
811
|
-
subject: drizzle_orm_pg_core.PgColumn<{
|
|
812
|
-
name: "subject";
|
|
813
|
-
tableName: "game_timeback_integrations";
|
|
814
|
-
dataType: "string";
|
|
815
|
-
columnType: "PgText";
|
|
816
|
-
data: string;
|
|
817
|
-
driverParam: string;
|
|
818
|
-
notNull: true;
|
|
819
|
-
hasDefault: false;
|
|
820
|
-
isPrimaryKey: false;
|
|
821
|
-
isAutoincrement: false;
|
|
822
|
-
hasRuntimeDefault: false;
|
|
823
|
-
enumValues: [string, ...string[]];
|
|
824
|
-
baseColumn: never;
|
|
825
|
-
identity: undefined;
|
|
826
|
-
generated: undefined;
|
|
827
|
-
}, {}, {}>;
|
|
828
|
-
totalXp: drizzle_orm_pg_core.PgColumn<{
|
|
829
|
-
name: "total_xp";
|
|
830
|
-
tableName: "game_timeback_integrations";
|
|
831
|
-
dataType: "number";
|
|
832
|
-
columnType: "PgInteger";
|
|
833
|
-
data: number;
|
|
834
|
-
driverParam: string | number;
|
|
835
|
-
notNull: false;
|
|
836
|
-
hasDefault: false;
|
|
837
|
-
isPrimaryKey: false;
|
|
838
|
-
isAutoincrement: false;
|
|
839
|
-
hasRuntimeDefault: false;
|
|
840
|
-
enumValues: undefined;
|
|
841
|
-
baseColumn: never;
|
|
842
|
-
identity: undefined;
|
|
843
|
-
generated: undefined;
|
|
844
|
-
}, {}, {}>;
|
|
845
|
-
lastVerifiedAt: drizzle_orm_pg_core.PgColumn<{
|
|
846
|
-
name: "last_verified_at";
|
|
847
|
-
tableName: "game_timeback_integrations";
|
|
848
|
-
dataType: "date";
|
|
849
|
-
columnType: "PgTimestamp";
|
|
850
|
-
data: Date;
|
|
851
|
-
driverParam: string;
|
|
852
|
-
notNull: false;
|
|
853
|
-
hasDefault: false;
|
|
854
|
-
isPrimaryKey: false;
|
|
855
|
-
isAutoincrement: false;
|
|
856
|
-
hasRuntimeDefault: false;
|
|
857
|
-
enumValues: undefined;
|
|
858
|
-
baseColumn: never;
|
|
859
|
-
identity: undefined;
|
|
860
|
-
generated: undefined;
|
|
861
|
-
}, {}, {}>;
|
|
862
|
-
createdAt: drizzle_orm_pg_core.PgColumn<{
|
|
863
|
-
name: "created_at";
|
|
864
|
-
tableName: "game_timeback_integrations";
|
|
865
|
-
dataType: "date";
|
|
866
|
-
columnType: "PgTimestamp";
|
|
867
|
-
data: Date;
|
|
868
|
-
driverParam: string;
|
|
869
|
-
notNull: true;
|
|
870
|
-
hasDefault: true;
|
|
871
|
-
isPrimaryKey: false;
|
|
872
|
-
isAutoincrement: false;
|
|
873
|
-
hasRuntimeDefault: false;
|
|
874
|
-
enumValues: undefined;
|
|
875
|
-
baseColumn: never;
|
|
876
|
-
identity: undefined;
|
|
877
|
-
generated: undefined;
|
|
878
|
-
}, {}, {}>;
|
|
879
|
-
updatedAt: drizzle_orm_pg_core.PgColumn<{
|
|
880
|
-
name: "updated_at";
|
|
881
|
-
tableName: "game_timeback_integrations";
|
|
882
|
-
dataType: "date";
|
|
883
|
-
columnType: "PgTimestamp";
|
|
884
|
-
data: Date;
|
|
885
|
-
driverParam: string;
|
|
886
|
-
notNull: true;
|
|
887
|
-
hasDefault: true;
|
|
888
|
-
isPrimaryKey: false;
|
|
889
|
-
isAutoincrement: false;
|
|
890
|
-
hasRuntimeDefault: false;
|
|
891
|
-
enumValues: undefined;
|
|
892
|
-
baseColumn: never;
|
|
893
|
-
identity: undefined;
|
|
894
|
-
generated: undefined;
|
|
895
|
-
}, {}, {}>;
|
|
896
|
-
};
|
|
897
|
-
dialect: "pg";
|
|
898
|
-
}>;
|
|
899
738
|
type Item = typeof items.$inferSelect;
|
|
900
739
|
type InventoryItem = typeof inventoryItems.$inferSelect;
|
|
901
740
|
|
|
902
741
|
type User = typeof users.$inferSelect;
|
|
742
|
+
/**
|
|
743
|
+
* TimeBack enrollment information for a game.
|
|
744
|
+
*/
|
|
745
|
+
type UserEnrollment = {
|
|
746
|
+
gameId?: string;
|
|
747
|
+
courseId: string;
|
|
748
|
+
grade: number;
|
|
749
|
+
subject: string;
|
|
750
|
+
orgId?: string;
|
|
751
|
+
};
|
|
752
|
+
/**
|
|
753
|
+
* TimeBack user role (matches OneRoster spec).
|
|
754
|
+
*/
|
|
755
|
+
type TimebackUserRole = 'administrator' | 'aide' | 'guardian' | 'parent' | 'proctor' | 'relative' | 'student' | 'teacher';
|
|
756
|
+
/**
|
|
757
|
+
* Organization type (matches OneRoster spec).
|
|
758
|
+
*/
|
|
759
|
+
type TimebackOrgType = 'department' | 'school' | 'district' | 'local' | 'state' | 'national';
|
|
760
|
+
/**
|
|
761
|
+
* TimeBack organization data for a user.
|
|
762
|
+
* Represents schools, districts, or other educational organizations.
|
|
763
|
+
*/
|
|
764
|
+
type UserOrganization = {
|
|
765
|
+
/** Organization ID (OneRoster sourcedId) */
|
|
766
|
+
id: string;
|
|
767
|
+
/** Organization name */
|
|
768
|
+
name: string | null;
|
|
769
|
+
/** Organization type (school, district, etc.) */
|
|
770
|
+
type: TimebackOrgType | string;
|
|
771
|
+
/** Whether this is the user's primary organization */
|
|
772
|
+
isPrimary: boolean;
|
|
773
|
+
};
|
|
774
|
+
/**
|
|
775
|
+
* TimeBack student profile (role + organizations).
|
|
776
|
+
* Subset of UserTimebackData returned by OneRoster API.
|
|
777
|
+
*/
|
|
778
|
+
type TimebackStudentProfile = {
|
|
779
|
+
/** User's primary role in TimeBack (student, parent, teacher, etc.) */
|
|
780
|
+
role: TimebackUserRole;
|
|
781
|
+
/** User's organizations (schools/districts) */
|
|
782
|
+
organizations: UserOrganization[];
|
|
783
|
+
};
|
|
784
|
+
/**
|
|
785
|
+
* TimeBack-related data for a user.
|
|
786
|
+
*/
|
|
787
|
+
type UserTimebackData = TimebackStudentProfile & {
|
|
788
|
+
/** User's TimeBack ID (sourcedId) */
|
|
789
|
+
id: string;
|
|
790
|
+
/** Course enrollments */
|
|
791
|
+
enrollments: UserEnrollment[];
|
|
792
|
+
};
|
|
903
793
|
/**
|
|
904
794
|
* User data with authentication provider information.
|
|
905
795
|
* Returned by the /users/me endpoint with additional auth context.
|
|
906
796
|
*/
|
|
907
|
-
type AuthenticatedUser = User & {
|
|
797
|
+
type AuthenticatedUser = Omit<User, 'timebackId'> & {
|
|
908
798
|
/** Whether the user authenticated via Timeback SSO */
|
|
909
799
|
hasTimebackAccount: boolean;
|
|
800
|
+
/** TimeBack data (id, role, enrollments, organizations) - only present if user has a timeback account */
|
|
801
|
+
timeback?: UserTimebackData;
|
|
910
802
|
};
|
|
911
803
|
/**
|
|
912
804
|
* Basic user information in the shape of the claims from identity providers
|
|
@@ -932,177 +824,6 @@ interface UserInfo {
|
|
|
932
824
|
type InventoryItemWithItem = Omit<InventoryItem, 'itemId'> & {
|
|
933
825
|
item: Item;
|
|
934
826
|
};
|
|
935
|
-
type GameTimebackIntegration = typeof gameTimebackIntegrations.$inferSelect;
|
|
936
|
-
type TodayXpResponse = {
|
|
937
|
-
xp: number;
|
|
938
|
-
date: string;
|
|
939
|
-
};
|
|
940
|
-
type TotalXpResponse = {
|
|
941
|
-
totalXp: number;
|
|
942
|
-
};
|
|
943
|
-
type XpHistoryResponse = {
|
|
944
|
-
history: Array<{
|
|
945
|
-
date: string;
|
|
946
|
-
xp: number;
|
|
947
|
-
}>;
|
|
948
|
-
};
|
|
949
|
-
type TimebackSetupRequest = {
|
|
950
|
-
gameId: string;
|
|
951
|
-
config: {
|
|
952
|
-
organization: {
|
|
953
|
-
name: string;
|
|
954
|
-
type: string;
|
|
955
|
-
identifier: string;
|
|
956
|
-
};
|
|
957
|
-
course: {
|
|
958
|
-
title: string;
|
|
959
|
-
subjects: string[];
|
|
960
|
-
grades: number[];
|
|
961
|
-
courseCode: string;
|
|
962
|
-
level: string;
|
|
963
|
-
gradingScheme: string;
|
|
964
|
-
metadata?: Record<string, unknown>;
|
|
965
|
-
};
|
|
966
|
-
component: {
|
|
967
|
-
title: string;
|
|
968
|
-
sortOrder: number;
|
|
969
|
-
prerequisites: string[];
|
|
970
|
-
prerequisiteCriteria: string;
|
|
971
|
-
};
|
|
972
|
-
resource: {
|
|
973
|
-
title: string;
|
|
974
|
-
vendorResourceId: string;
|
|
975
|
-
vendorId: string;
|
|
976
|
-
applicationId: string;
|
|
977
|
-
roles: string[];
|
|
978
|
-
importance: string;
|
|
979
|
-
metadata: {
|
|
980
|
-
type?: string;
|
|
981
|
-
launchUrl?: string;
|
|
982
|
-
toolProvider?: string;
|
|
983
|
-
instructionalMethod?: string;
|
|
984
|
-
subject?: string;
|
|
985
|
-
grades?: number[];
|
|
986
|
-
language?: string;
|
|
987
|
-
xp?: number;
|
|
988
|
-
[key: string]: unknown;
|
|
989
|
-
};
|
|
990
|
-
};
|
|
991
|
-
componentResource: {
|
|
992
|
-
title: string;
|
|
993
|
-
sortOrder: number;
|
|
994
|
-
lessonType: string | null;
|
|
995
|
-
};
|
|
996
|
-
};
|
|
997
|
-
verbose?: boolean;
|
|
998
|
-
};
|
|
999
|
-
/**
|
|
1000
|
-
* Minimal course configuration for TimeBack integration (used in user-facing config).
|
|
1001
|
-
*
|
|
1002
|
-
* NOTE: Per-course overrides (title, courseCode, level, metadata) are defined
|
|
1003
|
-
* in @playcademy/sdk/server as TimebackCourseConfigWithOverrides.
|
|
1004
|
-
* This base type only includes the minimal required fields.
|
|
1005
|
-
*
|
|
1006
|
-
* For totalXp, use metadata.metrics.totalXp (aligns with upstream TimeBack structure).
|
|
1007
|
-
*/
|
|
1008
|
-
type TimebackCourseConfig = {
|
|
1009
|
-
subject: string;
|
|
1010
|
-
grade: number;
|
|
1011
|
-
};
|
|
1012
|
-
/**
|
|
1013
|
-
* Derived course configuration after merging base + per-course overrides + templating.
|
|
1014
|
-
* This is what the CLI sends to the Platform API in PlatformTimebackSetupRequest.
|
|
1015
|
-
*/
|
|
1016
|
-
type DerivedPlatformCourseConfig = TimebackCourseConfig & {
|
|
1017
|
-
title: string;
|
|
1018
|
-
courseCode: string;
|
|
1019
|
-
level: string;
|
|
1020
|
-
metadata?: Record<string, unknown>;
|
|
1021
|
-
totalXp?: number | null;
|
|
1022
|
-
masterableUnits?: number | null;
|
|
1023
|
-
};
|
|
1024
|
-
type PlatformTimebackSetupRequest = {
|
|
1025
|
-
gameId: string;
|
|
1026
|
-
courses: DerivedPlatformCourseConfig[];
|
|
1027
|
-
baseConfig: {
|
|
1028
|
-
organization: {
|
|
1029
|
-
name: string;
|
|
1030
|
-
type: string;
|
|
1031
|
-
identifier: string;
|
|
1032
|
-
};
|
|
1033
|
-
component: {
|
|
1034
|
-
title: string;
|
|
1035
|
-
titleSuffix?: string;
|
|
1036
|
-
sortOrder: number;
|
|
1037
|
-
prerequisites: string[];
|
|
1038
|
-
prerequisiteCriteria: string;
|
|
1039
|
-
};
|
|
1040
|
-
resource: {
|
|
1041
|
-
title: string;
|
|
1042
|
-
titleSuffix?: string;
|
|
1043
|
-
vendorResourceId: string;
|
|
1044
|
-
vendorId: string;
|
|
1045
|
-
applicationId: string;
|
|
1046
|
-
roles: string[];
|
|
1047
|
-
importance: string;
|
|
1048
|
-
metadata: {
|
|
1049
|
-
type?: string;
|
|
1050
|
-
launchUrl?: string;
|
|
1051
|
-
toolProvider?: string;
|
|
1052
|
-
instructionalMethod?: string;
|
|
1053
|
-
language?: string;
|
|
1054
|
-
[key: string]: unknown;
|
|
1055
|
-
};
|
|
1056
|
-
};
|
|
1057
|
-
componentResource: {
|
|
1058
|
-
title: string;
|
|
1059
|
-
titleSuffix?: string;
|
|
1060
|
-
sortOrder: number;
|
|
1061
|
-
lessonType: string | null;
|
|
1062
|
-
};
|
|
1063
|
-
};
|
|
1064
|
-
verbose?: boolean;
|
|
1065
|
-
};
|
|
1066
|
-
type PlatformTimebackSetupResponse = {
|
|
1067
|
-
integrations: GameTimebackIntegration[];
|
|
1068
|
-
verbose?: Array<{
|
|
1069
|
-
integration: GameTimebackIntegration;
|
|
1070
|
-
config: {
|
|
1071
|
-
course: unknown;
|
|
1072
|
-
component: unknown;
|
|
1073
|
-
resource: unknown;
|
|
1074
|
-
componentResource: unknown;
|
|
1075
|
-
};
|
|
1076
|
-
}>;
|
|
1077
|
-
};
|
|
1078
|
-
type TimebackVerificationResources = {
|
|
1079
|
-
course: {
|
|
1080
|
-
found: boolean;
|
|
1081
|
-
data?: unknown;
|
|
1082
|
-
};
|
|
1083
|
-
component: {
|
|
1084
|
-
found: boolean;
|
|
1085
|
-
data?: unknown;
|
|
1086
|
-
};
|
|
1087
|
-
resource: {
|
|
1088
|
-
found: boolean;
|
|
1089
|
-
data?: unknown;
|
|
1090
|
-
};
|
|
1091
|
-
componentResource: {
|
|
1092
|
-
found: boolean;
|
|
1093
|
-
data?: unknown;
|
|
1094
|
-
};
|
|
1095
|
-
};
|
|
1096
|
-
type TimebackVerifyCourseResult = {
|
|
1097
|
-
integration: GameTimebackIntegration;
|
|
1098
|
-
resources: TimebackVerificationResources;
|
|
1099
|
-
status: 'success' | 'error';
|
|
1100
|
-
errors?: string[];
|
|
1101
|
-
};
|
|
1102
|
-
type TimebackVerifyAllResponse = {
|
|
1103
|
-
status: 'success' | 'error';
|
|
1104
|
-
results: TimebackVerifyCourseResult[];
|
|
1105
|
-
};
|
|
1106
827
|
type EndActivityResponse = {
|
|
1107
828
|
status: 'ok';
|
|
1108
829
|
courseId: string;
|
|
@@ -1113,13 +834,8 @@ type EndActivityResponse = {
|
|
|
1113
834
|
inProgress?: string;
|
|
1114
835
|
};
|
|
1115
836
|
|
|
1116
|
-
/**
|
|
1117
|
-
|
|
1118
|
-
*/
|
|
1119
|
-
type XpSummaryResponse = {
|
|
1120
|
-
today: TodayXpResponse;
|
|
1121
|
-
total: TotalXpResponse;
|
|
1122
|
-
};
|
|
837
|
+
/** Permitted HTTP verbs */
|
|
838
|
+
type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
1123
839
|
|
|
1124
840
|
/**
|
|
1125
841
|
* Auto-initializes a PlaycademyClient with context from the environment.
|
|
@@ -1186,208 +902,103 @@ declare function init<T extends PlaycademyClient = PlaycademyClient>(this: new (
|
|
|
1186
902
|
*/
|
|
1187
903
|
declare function login(baseUrl: string, email: string, password: string): Promise<LoginResponse>;
|
|
1188
904
|
|
|
1189
|
-
/**
|
|
1190
|
-
|
|
905
|
+
/**
|
|
906
|
+
* @fileoverview Authentication Strategy Pattern
|
|
907
|
+
*
|
|
908
|
+
* Provides different authentication strategies for the Playcademy SDK.
|
|
909
|
+
* Each strategy knows how to add its authentication headers to requests.
|
|
910
|
+
*/
|
|
911
|
+
|
|
912
|
+
/**
|
|
913
|
+
* Base interface for authentication strategies
|
|
914
|
+
*/
|
|
915
|
+
interface AuthStrategy {
|
|
916
|
+
/** Get the token value */
|
|
917
|
+
getToken(): string | null;
|
|
918
|
+
/** Get the token type */
|
|
919
|
+
getType(): TokenType;
|
|
920
|
+
/** Get authentication headers for a request */
|
|
921
|
+
getHeaders(): Record<string, string>;
|
|
922
|
+
}
|
|
1191
923
|
|
|
1192
924
|
/**
|
|
1193
|
-
*
|
|
1194
|
-
* Provides
|
|
925
|
+
* Base Playcademy SDK client with shared infrastructure.
|
|
926
|
+
* Provides authentication, HTTP requests, events, connection monitoring,
|
|
927
|
+
* and fundamental namespaces used by all clients.
|
|
928
|
+
*
|
|
929
|
+
* Extended by PlaycademyClient (game SDK) and PlaycademyInternalClient (platform SDK).
|
|
1195
930
|
*/
|
|
1196
|
-
declare class
|
|
931
|
+
declare abstract class PlaycademyBaseClient {
|
|
1197
932
|
baseUrl: string;
|
|
1198
933
|
gameUrl?: string;
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
934
|
+
protected authStrategy: AuthStrategy;
|
|
935
|
+
protected gameId?: string;
|
|
936
|
+
protected config: Partial<ClientConfig>;
|
|
937
|
+
protected listeners: EventListeners;
|
|
938
|
+
protected internalClientSessionId?: string;
|
|
939
|
+
protected authContext?: {
|
|
940
|
+
isInIframe: boolean;
|
|
941
|
+
};
|
|
942
|
+
protected initPayload?: InitPayload;
|
|
943
|
+
protected connectionManager?: ConnectionManager;
|
|
1207
944
|
/**
|
|
1208
945
|
* Internal session manager for automatic session lifecycle.
|
|
1209
|
-
*
|
|
1210
|
-
* This manager handles starting and ending game sessions automatically.
|
|
1211
|
-
* Game developers don't need to call these methods directly - they're managed
|
|
1212
|
-
* by the SDK during initialization and cleanup.
|
|
1213
|
-
*
|
|
1214
946
|
* @private
|
|
1215
947
|
* @internal
|
|
1216
948
|
*/
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
* @param config.token - Authentication token
|
|
1224
|
-
* @param config.tokenType - Optional token type (auto-detected if not provided)
|
|
1225
|
-
* @param config.gameId - Game ID for automatic session management
|
|
1226
|
-
* @param config.autoStartSession - Automatically start a game session?
|
|
1227
|
-
*/
|
|
949
|
+
protected _sessionManager: {
|
|
950
|
+
startSession: (gameId: string) => Promise<{
|
|
951
|
+
sessionId: string;
|
|
952
|
+
}>;
|
|
953
|
+
endSession: (sessionId: string, gameId: string) => Promise<void>;
|
|
954
|
+
};
|
|
1228
955
|
constructor(config?: Partial<ClientConfig>);
|
|
1229
956
|
/**
|
|
1230
957
|
* Gets the effective base URL for API requests.
|
|
1231
|
-
* Converts relative URLs to absolute URLs in browser environments.
|
|
1232
|
-
* Note: baseUrl already includes /api suffix from constructor.
|
|
1233
|
-
*
|
|
1234
|
-
* @returns The complete base URL for API requests (with /api suffix)
|
|
1235
958
|
*/
|
|
1236
959
|
getBaseUrl(): string;
|
|
1237
960
|
/**
|
|
1238
961
|
* Gets the effective game backend URL for integration requests.
|
|
1239
|
-
* Throws if gameUrl is not configured.
|
|
1240
|
-
*
|
|
1241
|
-
* @returns The complete game backend URL for API requests (with /api suffix)
|
|
1242
|
-
* @throws PlaycademyError if gameUrl is not set
|
|
1243
962
|
*/
|
|
1244
|
-
|
|
963
|
+
protected getGameBackendUrl(): string;
|
|
1245
964
|
/**
|
|
1246
965
|
* Simple ping method for testing connectivity.
|
|
1247
|
-
*
|
|
1248
|
-
* @returns 'pong' string response
|
|
1249
966
|
*/
|
|
1250
967
|
ping(): string;
|
|
1251
968
|
/**
|
|
1252
969
|
* Sets the authentication token for API requests.
|
|
1253
|
-
* Emits an 'authChange' event when the token changes.
|
|
1254
|
-
*
|
|
1255
|
-
* @param token - The authentication token, or null to clear
|
|
1256
|
-
* @param tokenType - Optional token type (auto-detected if not provided)
|
|
1257
970
|
*/
|
|
1258
971
|
setToken(token: string | null, tokenType?: TokenType): void;
|
|
1259
972
|
/**
|
|
1260
973
|
* Gets the current token type.
|
|
1261
|
-
*
|
|
1262
|
-
* @returns The token type
|
|
1263
974
|
*/
|
|
1264
975
|
getTokenType(): TokenType;
|
|
1265
976
|
/**
|
|
1266
977
|
* Gets the current authentication token.
|
|
1267
|
-
*
|
|
1268
|
-
* @returns The current token or null if not authenticated
|
|
1269
|
-
*
|
|
1270
|
-
* @example
|
|
1271
|
-
* ```typescript
|
|
1272
|
-
* // Send token to your backend for verification
|
|
1273
|
-
* const token = client.getToken()
|
|
1274
|
-
* const response = await fetch('/api/auth/playcademy', {
|
|
1275
|
-
* method: 'POST',
|
|
1276
|
-
* body: JSON.stringify({ gameToken: token })
|
|
1277
|
-
* })
|
|
1278
|
-
* ```
|
|
1279
978
|
*/
|
|
1280
979
|
getToken(): string | null;
|
|
1281
980
|
/**
|
|
1282
|
-
* Checks if the client has a valid API token
|
|
1283
|
-
*
|
|
1284
|
-
* For games (iframe context): Checks if we have a valid token from the parent.
|
|
1285
|
-
* For Cademy (standalone): Checks if we have a token from better-auth.
|
|
1286
|
-
*
|
|
1287
|
-
* Note: This checks for API authentication, not whether a user has linked
|
|
1288
|
-
* their identity via OAuth.
|
|
1289
|
-
*
|
|
1290
|
-
* @returns true if API token exists, false otherwise
|
|
1291
|
-
*
|
|
1292
|
-
* @example
|
|
1293
|
-
* ```typescript
|
|
1294
|
-
* if (client.isAuthenticated()) {
|
|
1295
|
-
* // Can make API calls
|
|
1296
|
-
* const games = await client.games.list()
|
|
1297
|
-
* } else {
|
|
1298
|
-
* console.error('No API token available')
|
|
1299
|
-
* }
|
|
1300
|
-
* ```
|
|
981
|
+
* Checks if the client has a valid API token.
|
|
1301
982
|
*/
|
|
1302
983
|
isAuthenticated(): boolean;
|
|
1303
984
|
/**
|
|
1304
985
|
* Registers a callback to be called when authentication state changes.
|
|
1305
|
-
*
|
|
1306
|
-
* @param callback - Function to call when auth state changes
|
|
1307
986
|
*/
|
|
1308
987
|
onAuthChange(callback: (token: string | null) => void): void;
|
|
1309
988
|
/**
|
|
1310
989
|
* Registers a callback to be called when connection issues are detected.
|
|
1311
|
-
*
|
|
1312
|
-
* This is a convenience method that filters connection change events to only
|
|
1313
|
-
* fire when the connection degrades (offline or degraded states). Use this
|
|
1314
|
-
* when you want to handle disconnects without being notified of recoveries.
|
|
1315
|
-
*
|
|
1316
|
-
* For all connection state changes, use `client.on('connectionChange', ...)` instead.
|
|
1317
|
-
*
|
|
1318
|
-
* @param callback - Function to call when connection state changes to offline or degraded
|
|
1319
|
-
* @returns Cleanup function to unregister the callback
|
|
1320
|
-
*
|
|
1321
|
-
* @example
|
|
1322
|
-
* ```typescript
|
|
1323
|
-
* const cleanup = client.onDisconnect(({ state, reason, displayAlert }) => {
|
|
1324
|
-
* console.log(`Connection ${state}: ${reason}`)
|
|
1325
|
-
*
|
|
1326
|
-
* if (state === 'offline') {
|
|
1327
|
-
* // Save state and return to game lobby
|
|
1328
|
-
* displayAlert?.('Connection lost. Your progress has been saved.', { type: 'error' })
|
|
1329
|
-
* saveGameState()
|
|
1330
|
-
* returnToLobby()
|
|
1331
|
-
* } else if (state === 'degraded') {
|
|
1332
|
-
* displayAlert?.('Slow connection detected.', { type: 'warning' })
|
|
1333
|
-
* }
|
|
1334
|
-
* })
|
|
1335
|
-
*
|
|
1336
|
-
* // Later: cleanup() to unregister
|
|
1337
|
-
* ```
|
|
1338
|
-
*
|
|
1339
|
-
* @see Connection monitoring documentation in SDK Browser docs for detailed usage examples
|
|
1340
|
-
* @see {@link ConnectionManager.onDisconnect} for the underlying implementation
|
|
1341
990
|
*/
|
|
1342
991
|
onDisconnect(callback: (context: DisconnectContext) => void | Promise<void>): () => void;
|
|
1343
992
|
/**
|
|
1344
993
|
* Gets the current connection state.
|
|
1345
|
-
*
|
|
1346
|
-
* Returns the last known connection state without triggering a new check.
|
|
1347
|
-
* Use `checkConnection()` to force an immediate verification.
|
|
1348
|
-
*
|
|
1349
|
-
* @returns Current connection state ('online', 'offline', 'degraded') or 'unknown' if monitoring is disabled
|
|
1350
|
-
*
|
|
1351
|
-
* @example
|
|
1352
|
-
* ```typescript
|
|
1353
|
-
* const state = client.getConnectionState()
|
|
1354
|
-
* if (state === 'offline') {
|
|
1355
|
-
* console.log('No connection available')
|
|
1356
|
-
* }
|
|
1357
|
-
* ```
|
|
1358
|
-
*
|
|
1359
|
-
* @see {@link checkConnection} to trigger an immediate connection check
|
|
1360
|
-
* @see {@link ConnectionManager.getState} for the underlying implementation
|
|
1361
994
|
*/
|
|
1362
995
|
getConnectionState(): ConnectionState | 'unknown';
|
|
1363
996
|
/**
|
|
1364
997
|
* Manually triggers a connection check immediately.
|
|
1365
|
-
*
|
|
1366
|
-
* Forces a heartbeat ping to verify connectivity right now, bypassing the normal
|
|
1367
|
-
* interval. Useful when you need to verify connection status before a critical
|
|
1368
|
-
* operation (e.g., saving important game state).
|
|
1369
|
-
*
|
|
1370
|
-
* @returns Promise resolving to the current connection state after verification
|
|
1371
|
-
*
|
|
1372
|
-
* @example
|
|
1373
|
-
* ```typescript
|
|
1374
|
-
* // Check before critical operation
|
|
1375
|
-
* const state = await client.checkConnection()
|
|
1376
|
-
* if (state !== 'online') {
|
|
1377
|
-
* alert('Please check your internet connection before saving')
|
|
1378
|
-
* return
|
|
1379
|
-
* }
|
|
1380
|
-
*
|
|
1381
|
-
* await client.games.saveState(importantData)
|
|
1382
|
-
* ```
|
|
1383
|
-
*
|
|
1384
|
-
* @see {@link getConnectionState} to get the last known state without checking
|
|
1385
|
-
* @see {@link ConnectionManager.checkNow} for the underlying implementation
|
|
1386
998
|
*/
|
|
1387
999
|
checkConnection(): Promise<ConnectionState | 'unknown'>;
|
|
1388
1000
|
/**
|
|
1389
1001
|
* Sets the authentication context for the client.
|
|
1390
|
-
* This is called during initialization to store environment info.
|
|
1391
1002
|
* @internal
|
|
1392
1003
|
*/
|
|
1393
1004
|
_setAuthContext(context: {
|
|
@@ -1395,28 +1006,14 @@ declare class PlaycademyClient {
|
|
|
1395
1006
|
}): void;
|
|
1396
1007
|
/**
|
|
1397
1008
|
* Registers an event listener for client events.
|
|
1398
|
-
*
|
|
1399
|
-
* @param event - The event type to listen for
|
|
1400
|
-
* @param callback - Function to call when the event is emitted
|
|
1401
1009
|
*/
|
|
1402
1010
|
on<E extends keyof ClientEvents>(event: E, callback: (payload: ClientEvents[E]) => void): void;
|
|
1403
1011
|
/**
|
|
1404
1012
|
* Emits an event to all registered listeners.
|
|
1405
|
-
*
|
|
1406
|
-
* @param event - The event type to emit
|
|
1407
|
-
* @param payload - The event payload
|
|
1408
1013
|
*/
|
|
1409
|
-
|
|
1014
|
+
protected emit<E extends keyof ClientEvents>(event: E, payload: ClientEvents[E]): void;
|
|
1410
1015
|
/**
|
|
1411
1016
|
* Makes an authenticated HTTP request to the platform API.
|
|
1412
|
-
*
|
|
1413
|
-
* @param path - API endpoint path
|
|
1414
|
-
* @param method - HTTP method
|
|
1415
|
-
* @param options - Optional request configuration
|
|
1416
|
-
* @param options.body - Request body
|
|
1417
|
-
* @param options.headers - Additional headers
|
|
1418
|
-
* @param options.raw - If true, returns raw Response instead of parsing
|
|
1419
|
-
* @returns Promise resolving to the response data or raw Response
|
|
1420
1017
|
*/
|
|
1421
1018
|
protected request<T>(path: string, method: Method, options?: {
|
|
1422
1019
|
body?: unknown;
|
|
@@ -1425,49 +1022,64 @@ declare class PlaycademyClient {
|
|
|
1425
1022
|
}): Promise<T>;
|
|
1426
1023
|
/**
|
|
1427
1024
|
* Makes an authenticated HTTP request to the game's backend Worker.
|
|
1428
|
-
* Uses gameUrl if set, otherwise falls back to platform API.
|
|
1429
|
-
*
|
|
1430
|
-
* @param path - API endpoint path
|
|
1431
|
-
* @param method - HTTP method
|
|
1432
|
-
* @param body - Request body (optional)
|
|
1433
|
-
* @param headers - Additional headers (optional)
|
|
1434
|
-
* @param raw - If true, returns raw Response instead of parsing (optional)
|
|
1435
|
-
* @returns Promise resolving to the response data or raw Response
|
|
1436
1025
|
*/
|
|
1437
1026
|
protected requestGameBackend<T>(path: string, method: Method, body?: unknown, headers?: Record<string, string>, raw?: boolean): Promise<T>;
|
|
1438
1027
|
/**
|
|
1439
1028
|
* Ensures a gameId is available, throwing an error if not.
|
|
1440
|
-
*
|
|
1441
|
-
* @returns The gameId
|
|
1442
|
-
* @throws PlaycademyError if no gameId is configured
|
|
1443
1029
|
*/
|
|
1444
|
-
|
|
1030
|
+
protected _ensureGameId(): string;
|
|
1445
1031
|
/**
|
|
1446
1032
|
* Detects and sets the authentication context (iframe vs standalone).
|
|
1447
|
-
* Safe to call in any environment - isInIframe handles browser detection.
|
|
1448
1033
|
*/
|
|
1449
1034
|
private _detectAuthContext;
|
|
1450
1035
|
/**
|
|
1451
1036
|
* Initializes connection monitoring if enabled.
|
|
1452
|
-
* Safe to call in any environment - only runs in browser.
|
|
1453
1037
|
*/
|
|
1454
1038
|
private _initializeConnectionMonitor;
|
|
1455
1039
|
/**
|
|
1456
1040
|
* Initializes an internal game session for automatic session management.
|
|
1457
|
-
* Only starts a session if:
|
|
1458
|
-
* 1. A gameId is configured
|
|
1459
|
-
* 2. No session already exists
|
|
1460
|
-
* 3. autoStartSession is enabled (defaults to false)
|
|
1461
1041
|
*/
|
|
1462
1042
|
private _initializeInternalSession;
|
|
1463
|
-
/**
|
|
1043
|
+
/**
|
|
1044
|
+
* Current user data and inventory management.
|
|
1045
|
+
* - `me()` - Get authenticated user profile
|
|
1046
|
+
* - `inventory.get()` - List user's items
|
|
1047
|
+
* - `inventory.add(slug, qty)` - Award items to user
|
|
1048
|
+
*/
|
|
1049
|
+
users: {
|
|
1050
|
+
me: () => Promise<AuthenticatedUser>;
|
|
1051
|
+
inventory: {
|
|
1052
|
+
get: () => Promise<InventoryItemWithItem[]>;
|
|
1053
|
+
add: (identifier: string, qty: number) => Promise<InventoryMutationResponse>;
|
|
1054
|
+
remove: (identifier: string, qty: number) => Promise<InventoryMutationResponse>;
|
|
1055
|
+
quantity: (identifier: string) => Promise<number>;
|
|
1056
|
+
has: (identifier: string, minQuantity?: number) => Promise<boolean>;
|
|
1057
|
+
};
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
/**
|
|
1062
|
+
* Playcademy SDK client for game developers.
|
|
1063
|
+
* Provides namespaced access to platform features for games running inside Cademy.
|
|
1064
|
+
*/
|
|
1065
|
+
declare class PlaycademyClient extends PlaycademyBaseClient {
|
|
1066
|
+
/**
|
|
1067
|
+
* Connect external identity providers to the user's Playcademy account.
|
|
1068
|
+
* - `connect(provider)` - Link Discord, Google, etc. via OAuth popup
|
|
1069
|
+
*/
|
|
1464
1070
|
identity: {
|
|
1465
1071
|
connect: (options: AuthOptions) => Promise<AuthResult>;
|
|
1466
1072
|
_getContext: () => {
|
|
1467
1073
|
isInIframe: boolean;
|
|
1468
1074
|
};
|
|
1469
1075
|
};
|
|
1470
|
-
/**
|
|
1076
|
+
/**
|
|
1077
|
+
* Game runtime lifecycle and asset loading.
|
|
1078
|
+
* - `exit()` - Return to Cademy hub
|
|
1079
|
+
* - `getGameToken()` - Get short-lived auth token
|
|
1080
|
+
* - `assets.url()`, `assets.json()`, `assets.fetch()` - Load game assets
|
|
1081
|
+
* - `on('pause')`, `on('resume')` - Handle visibility changes
|
|
1082
|
+
*/
|
|
1471
1083
|
runtime: {
|
|
1472
1084
|
getGameToken: (gameId: string, options?: {
|
|
1473
1085
|
apply?: boolean;
|
|
@@ -1502,64 +1114,58 @@ declare class PlaycademyClient {
|
|
|
1502
1114
|
arrayBuffer: (path: string) => Promise<ArrayBuffer>;
|
|
1503
1115
|
};
|
|
1504
1116
|
};
|
|
1505
|
-
/**
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1117
|
+
/**
|
|
1118
|
+
* TimeBack integration for activity tracking and user context.
|
|
1119
|
+
*
|
|
1120
|
+
* User context (cached from init, refreshable):
|
|
1121
|
+
* - `user.role` - User's role (student, parent, teacher, etc.)
|
|
1122
|
+
* - `user.enrollments` - Courses the player is enrolled in for this game
|
|
1123
|
+
* - `user.organizations` - Schools/districts the player belongs to
|
|
1124
|
+
* - `user.fetch()` - Refresh user context from server
|
|
1125
|
+
*
|
|
1126
|
+
* Activity tracking:
|
|
1127
|
+
* - `startActivity(metadata)` - Begin tracking an activity
|
|
1128
|
+
* - `pauseActivity()` / `resumeActivity()` - Pause/resume timer
|
|
1129
|
+
* - `endActivity(scoreData)` - Submit activity results to TimeBack
|
|
1130
|
+
*/
|
|
1517
1131
|
timeback: {
|
|
1132
|
+
readonly user: TimebackUser;
|
|
1518
1133
|
startActivity: (metadata: _playcademy_timeback_types.ActivityData) => void;
|
|
1519
1134
|
pauseActivity: () => void;
|
|
1520
1135
|
resumeActivity: () => void;
|
|
1521
1136
|
endActivity: (data: _playcademy_timeback_types.EndActivityScoreData) => Promise<EndActivityResponse>;
|
|
1522
|
-
management: {
|
|
1523
|
-
setup: (request: PlatformTimebackSetupRequest) => Promise<PlatformTimebackSetupResponse>;
|
|
1524
|
-
verify: (gameId: string) => Promise<TimebackVerifyAllResponse>;
|
|
1525
|
-
cleanup: (gameId: string) => Promise<void>;
|
|
1526
|
-
get: (gameId: string) => Promise<GameTimebackIntegration[]>;
|
|
1527
|
-
getConfig: (gameId: string) => Promise<TimebackSetupRequest["config"]>;
|
|
1528
|
-
};
|
|
1529
|
-
xp: {
|
|
1530
|
-
today: (options?: {
|
|
1531
|
-
date?: string;
|
|
1532
|
-
timezone?: string;
|
|
1533
|
-
}) => Promise<TodayXpResponse>;
|
|
1534
|
-
total: () => Promise<TotalXpResponse>;
|
|
1535
|
-
history: (options?: {
|
|
1536
|
-
startDate?: string;
|
|
1537
|
-
endDate?: string;
|
|
1538
|
-
}) => Promise<XpHistoryResponse>;
|
|
1539
|
-
summary: (options?: {
|
|
1540
|
-
date?: string;
|
|
1541
|
-
timezone?: string;
|
|
1542
|
-
}) => Promise<XpSummaryResponse>;
|
|
1543
|
-
};
|
|
1544
1137
|
};
|
|
1545
|
-
/**
|
|
1138
|
+
/**
|
|
1139
|
+
* Playcademy Credits (platform currency) management.
|
|
1140
|
+
* - `get()` - Get user's credit balance
|
|
1141
|
+
* - `add(amount)` - Award credits to user
|
|
1142
|
+
*/
|
|
1546
1143
|
credits: {
|
|
1547
1144
|
balance: () => Promise<number>;
|
|
1548
1145
|
add: (amount: number) => Promise<number>;
|
|
1549
1146
|
spend: (amount: number) => Promise<number>;
|
|
1550
1147
|
};
|
|
1551
|
-
/**
|
|
1148
|
+
/**
|
|
1149
|
+
* Game score submission and leaderboards.
|
|
1150
|
+
* - `submit(gameId, score, metadata?)` - Record a game score
|
|
1151
|
+
*/
|
|
1552
1152
|
scores: {
|
|
1553
1153
|
submit: (gameId: string, score: number, metadata?: Record<string, unknown>) => Promise<ScoreSubmission>;
|
|
1554
1154
|
};
|
|
1555
|
-
/**
|
|
1155
|
+
/**
|
|
1156
|
+
* Realtime multiplayer authentication.
|
|
1157
|
+
* - `getToken()` - Get token for WebSocket/realtime connections
|
|
1158
|
+
*/
|
|
1556
1159
|
realtime: {
|
|
1557
1160
|
token: {
|
|
1558
1161
|
get: () => Promise<RealtimeTokenResponse>;
|
|
1559
1162
|
};
|
|
1560
|
-
open(channel?: string, url?: string): Promise<_playcademy_realtime_server_types.RealtimeChannel>;
|
|
1561
1163
|
};
|
|
1562
|
-
/**
|
|
1164
|
+
/**
|
|
1165
|
+
* Make requests to your game's custom backend API routes.
|
|
1166
|
+
* - `get(path)`, `post(path, body)`, `put()`, `delete()` - HTTP methods
|
|
1167
|
+
* - Routes are relative to your game's deployment (e.g., '/hello' → your-game.playcademy.gg/api/hello)
|
|
1168
|
+
*/
|
|
1563
1169
|
backend: {
|
|
1564
1170
|
get<T = unknown>(path: string, headers?: Record<string, string>): Promise<T>;
|
|
1565
1171
|
post<T = unknown>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
@@ -1580,9 +1186,70 @@ declare class PlaycademyClient {
|
|
|
1580
1186
|
};
|
|
1581
1187
|
}
|
|
1582
1188
|
|
|
1189
|
+
/**
|
|
1190
|
+
* Type definitions for the game timeback namespace.
|
|
1191
|
+
*
|
|
1192
|
+
* Re-exports core types from @playcademy/data for SDK consumers,
|
|
1193
|
+
* plus SDK-specific types like TimebackInitContext.
|
|
1194
|
+
*/
|
|
1195
|
+
|
|
1196
|
+
/**
|
|
1197
|
+
* A TimeBack enrollment for the current game session.
|
|
1198
|
+
* Alias for UserEnrollment without the optional gameId.
|
|
1199
|
+
*/
|
|
1200
|
+
type TimebackEnrollment = Omit<UserEnrollment, 'gameId'>;
|
|
1201
|
+
/**
|
|
1202
|
+
* A TimeBack organization (school/district) for the current user.
|
|
1203
|
+
* Alias for UserOrganization.
|
|
1204
|
+
*/
|
|
1205
|
+
type TimebackOrganization = UserOrganization;
|
|
1206
|
+
/**
|
|
1207
|
+
* TimeBack context passed during game initialization.
|
|
1208
|
+
* This is sent from the platform (cademy) to the game iframe via postMessage.
|
|
1209
|
+
*/
|
|
1210
|
+
interface TimebackInitContext {
|
|
1211
|
+
/** User's TimeBack ID */
|
|
1212
|
+
id: string;
|
|
1213
|
+
/** User's role in TimeBack (student, parent, teacher, etc.) */
|
|
1214
|
+
role: TimebackUserRole;
|
|
1215
|
+
/** User's enrollments for this game (one per grade/subject combo) */
|
|
1216
|
+
enrollments: TimebackEnrollment[];
|
|
1217
|
+
/** User's organizations (schools/districts) */
|
|
1218
|
+
organizations: TimebackOrganization[];
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* TimeBack user context with current data (may be stale from init).
|
|
1222
|
+
* Use `fetch()` to get fresh data from the server.
|
|
1223
|
+
*/
|
|
1224
|
+
interface TimebackUserContext {
|
|
1225
|
+
/** User's TimeBack ID */
|
|
1226
|
+
id: string | undefined;
|
|
1227
|
+
/** User's role in TimeBack (student, parent, teacher, etc.) */
|
|
1228
|
+
role: TimebackUserRole | undefined;
|
|
1229
|
+
/** User's enrollments for this game */
|
|
1230
|
+
enrollments: TimebackEnrollment[];
|
|
1231
|
+
/** User's organizations (schools/districts) */
|
|
1232
|
+
organizations: TimebackOrganization[];
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* TimeBack user object with both cached getters and fetch method.
|
|
1236
|
+
*/
|
|
1237
|
+
interface TimebackUser extends TimebackUserContext {
|
|
1238
|
+
/**
|
|
1239
|
+
* Fetch TimeBack data from the server (cached for 5 min).
|
|
1240
|
+
* Updates the cached values so subsequent property access returns fresh data.
|
|
1241
|
+
* @param options - Cache options (pass { force: true } to bypass cache)
|
|
1242
|
+
* @returns Promise resolving to fresh user context
|
|
1243
|
+
*/
|
|
1244
|
+
fetch(options?: {
|
|
1245
|
+
force?: boolean;
|
|
1246
|
+
}): Promise<TimebackUserContext>;
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1583
1249
|
/**
|
|
1584
1250
|
* Core client configuration and lifecycle types
|
|
1585
1251
|
*/
|
|
1252
|
+
|
|
1586
1253
|
type TokenType = 'session' | 'apiKey' | 'gameJwt';
|
|
1587
1254
|
interface ClientConfig {
|
|
1588
1255
|
baseUrl: string;
|
|
@@ -1615,6 +1282,20 @@ interface DisconnectContext {
|
|
|
1615
1282
|
duration?: number;
|
|
1616
1283
|
}) => void;
|
|
1617
1284
|
}
|
|
1285
|
+
interface InitPayload {
|
|
1286
|
+
/** Hub API base URL */
|
|
1287
|
+
baseUrl: string;
|
|
1288
|
+
/** Game deployment URL (serves both frontend assets and backend API) */
|
|
1289
|
+
gameUrl?: string;
|
|
1290
|
+
/** Short-lived game token */
|
|
1291
|
+
token: string;
|
|
1292
|
+
/** Game ID */
|
|
1293
|
+
gameId: string;
|
|
1294
|
+
/** Realtime WebSocket URL */
|
|
1295
|
+
realtimeUrl?: string;
|
|
1296
|
+
/** Timeback context (if user has a Timeback account) */
|
|
1297
|
+
timeback?: TimebackInitContext;
|
|
1298
|
+
}
|
|
1618
1299
|
type GameContextPayload = {
|
|
1619
1300
|
token: string;
|
|
1620
1301
|
baseUrl: string;
|
|
@@ -1622,6 +1303,9 @@ type GameContextPayload = {
|
|
|
1622
1303
|
gameId: string;
|
|
1623
1304
|
forwardKeys?: string[];
|
|
1624
1305
|
};
|
|
1306
|
+
type EventListeners = {
|
|
1307
|
+
[E in keyof ClientEvents]?: Array<(payload: ClientEvents[E]) => void>;
|
|
1308
|
+
};
|
|
1625
1309
|
interface ClientEvents {
|
|
1626
1310
|
authChange: {
|
|
1627
1311
|
token: string | null;
|