@playcademy/sdk 0.0.9 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +46 -14
- package/dist/index.js +118 -31
- package/dist/types.d.ts +47 -14
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -3021,6 +3021,7 @@ type XpHistoryResponse = {
|
|
|
3021
3021
|
xp: number;
|
|
3022
3022
|
}>;
|
|
3023
3023
|
};
|
|
3024
|
+
type TimebackSubject = 'Reading' | 'Language' | 'Vocabulary' | 'Social Studies' | 'Writing' | 'Science' | 'FastMath' | 'Math' | 'None';
|
|
3024
3025
|
type TimebackSetupRequest = {
|
|
3025
3026
|
gameId: string;
|
|
3026
3027
|
config: {
|
|
@@ -3108,6 +3109,9 @@ type RecordProgressRequest = {
|
|
|
3108
3109
|
gameId: string;
|
|
3109
3110
|
studentId: string;
|
|
3110
3111
|
progressData: {
|
|
3112
|
+
sensorUrl?: string;
|
|
3113
|
+
subject?: TimebackSubject;
|
|
3114
|
+
appName?: string;
|
|
3111
3115
|
score?: number;
|
|
3112
3116
|
totalQuestions?: number;
|
|
3113
3117
|
correctQuestions?: number;
|
|
@@ -3120,9 +3124,6 @@ type RecordProgressRequest = {
|
|
|
3120
3124
|
classId?: string;
|
|
3121
3125
|
courseName?: string;
|
|
3122
3126
|
studentEmail?: string;
|
|
3123
|
-
subject?: 'Reading' | 'Language' | 'Vocabulary' | 'Social Studies' | 'Writing' | 'Science' | 'FastMath' | 'Math' | 'None';
|
|
3124
|
-
appName?: string;
|
|
3125
|
-
sensorUrl?: string;
|
|
3126
3127
|
};
|
|
3127
3128
|
};
|
|
3128
3129
|
type RecordProgressResponse = {
|
|
@@ -3133,6 +3134,9 @@ type RecordSessionEndRequest = {
|
|
|
3133
3134
|
gameId: string;
|
|
3134
3135
|
studentId: string;
|
|
3135
3136
|
sessionData: {
|
|
3137
|
+
sensorUrl?: string;
|
|
3138
|
+
subject?: TimebackSubject;
|
|
3139
|
+
appName?: string;
|
|
3136
3140
|
activeTimeSeconds: number;
|
|
3137
3141
|
inactiveTimeSeconds?: number;
|
|
3138
3142
|
wasteTimeSeconds?: number;
|
|
@@ -3141,9 +3145,6 @@ type RecordSessionEndRequest = {
|
|
|
3141
3145
|
courseId?: string;
|
|
3142
3146
|
courseName?: string;
|
|
3143
3147
|
studentEmail?: string;
|
|
3144
|
-
subject?: 'Reading' | 'Language' | 'Vocabulary' | 'Social Studies' | 'Writing' | 'Science' | 'FastMath' | 'Math' | 'None';
|
|
3145
|
-
appName?: string;
|
|
3146
|
-
sensorUrl?: string;
|
|
3147
3148
|
};
|
|
3148
3149
|
};
|
|
3149
3150
|
type RecordSessionEndResponse = {
|
|
@@ -3155,6 +3156,9 @@ type AwardXpRequest = {
|
|
|
3155
3156
|
studentId: string;
|
|
3156
3157
|
xpAmount: number;
|
|
3157
3158
|
metadata: {
|
|
3159
|
+
sensorUrl: string;
|
|
3160
|
+
subject: TimebackSubject;
|
|
3161
|
+
appName: string;
|
|
3158
3162
|
reason: string;
|
|
3159
3163
|
activityId?: string;
|
|
3160
3164
|
activityName?: string;
|
|
@@ -3162,9 +3166,6 @@ type AwardXpRequest = {
|
|
|
3162
3166
|
courseName?: string;
|
|
3163
3167
|
studentEmail?: string;
|
|
3164
3168
|
bonusType?: string;
|
|
3165
|
-
subject?: 'Reading' | 'Language' | 'Vocabulary' | 'Social Studies' | 'Writing' | 'Science' | 'FastMath' | 'Math' | 'None';
|
|
3166
|
-
appName?: string;
|
|
3167
|
-
sensorUrl?: string;
|
|
3168
3169
|
};
|
|
3169
3170
|
};
|
|
3170
3171
|
type AwardXpResponse = {
|
|
@@ -3263,6 +3264,7 @@ interface BackendDeploymentBundle {
|
|
|
3263
3264
|
type TokenType = 'session' | 'apiKey' | 'gameJwt';
|
|
3264
3265
|
interface ClientConfig {
|
|
3265
3266
|
baseUrl: string;
|
|
3267
|
+
gameUrl?: string;
|
|
3266
3268
|
token?: string;
|
|
3267
3269
|
tokenType?: TokenType;
|
|
3268
3270
|
gameId?: string;
|
|
@@ -3620,7 +3622,8 @@ type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
|
3620
3622
|
* Provides namespaced access to all platform features including games, users, inventory, and more.
|
|
3621
3623
|
*/
|
|
3622
3624
|
declare class PlaycademyClient {
|
|
3623
|
-
|
|
3625
|
+
baseUrl: string;
|
|
3626
|
+
gameUrl?: string;
|
|
3624
3627
|
private authStrategy;
|
|
3625
3628
|
private gameId?;
|
|
3626
3629
|
private config;
|
|
@@ -3632,7 +3635,7 @@ declare class PlaycademyClient {
|
|
|
3632
3635
|
* Creates a new PlaycademyClient instance.
|
|
3633
3636
|
*
|
|
3634
3637
|
* @param config - Optional configuration object
|
|
3635
|
-
* @param config.baseUrl - Base URL
|
|
3638
|
+
* @param config.baseUrl - Base URL (e.g., 'https://hub.playcademy.com' or '/'). SDK automatically appends /api
|
|
3636
3639
|
* @param config.token - Authentication token
|
|
3637
3640
|
* @param config.tokenType - Optional token type (auto-detected if not provided)
|
|
3638
3641
|
* @param config.gameId - Game ID for automatic session management
|
|
@@ -3642,10 +3645,19 @@ declare class PlaycademyClient {
|
|
|
3642
3645
|
/**
|
|
3643
3646
|
* Gets the effective base URL for API requests.
|
|
3644
3647
|
* Converts relative URLs to absolute URLs in browser environments.
|
|
3648
|
+
* Note: baseUrl already includes /api suffix from constructor.
|
|
3645
3649
|
*
|
|
3646
|
-
* @returns The complete base URL for API requests
|
|
3650
|
+
* @returns The complete base URL for API requests (with /api suffix)
|
|
3647
3651
|
*/
|
|
3648
3652
|
getBaseUrl(): string;
|
|
3653
|
+
/**
|
|
3654
|
+
* Gets the effective game backend URL for integration requests.
|
|
3655
|
+
* Throws if gameUrl is not configured.
|
|
3656
|
+
*
|
|
3657
|
+
* @returns The complete game backend URL for API requests (with /api suffix)
|
|
3658
|
+
* @throws PlaycademyError if gameUrl is not set
|
|
3659
|
+
*/
|
|
3660
|
+
private getGameBackendUrl;
|
|
3649
3661
|
/**
|
|
3650
3662
|
* Simple ping method for testing connectivity.
|
|
3651
3663
|
*
|
|
@@ -3733,7 +3745,7 @@ declare class PlaycademyClient {
|
|
|
3733
3745
|
*/
|
|
3734
3746
|
private emit;
|
|
3735
3747
|
/**
|
|
3736
|
-
* Makes an authenticated HTTP request to the API.
|
|
3748
|
+
* Makes an authenticated HTTP request to the platform API.
|
|
3737
3749
|
*
|
|
3738
3750
|
* @param path - API endpoint path
|
|
3739
3751
|
* @param method - HTTP method
|
|
@@ -3742,6 +3754,17 @@ declare class PlaycademyClient {
|
|
|
3742
3754
|
* @returns Promise resolving to the response data
|
|
3743
3755
|
*/
|
|
3744
3756
|
protected request<T>(path: string, method: Method, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
3757
|
+
/**
|
|
3758
|
+
* Makes an authenticated HTTP request to the game's backend Worker.
|
|
3759
|
+
* Uses gameUrl if set, otherwise falls back to platform API.
|
|
3760
|
+
*
|
|
3761
|
+
* @param path - API endpoint path
|
|
3762
|
+
* @param method - HTTP method
|
|
3763
|
+
* @param body - Request body (optional)
|
|
3764
|
+
* @param headers - Additional headers (optional)
|
|
3765
|
+
* @returns Promise resolving to the response data
|
|
3766
|
+
*/
|
|
3767
|
+
protected requestGameBackend<T>(path: string, method: Method, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
3745
3768
|
/**
|
|
3746
3769
|
* Ensures a gameId is available, throwing an error if not.
|
|
3747
3770
|
*
|
|
@@ -4088,7 +4111,7 @@ declare class PlaycademyClient {
|
|
|
4088
4111
|
}) => Promise<TodayXpResponse>;
|
|
4089
4112
|
total: () => Promise<TotalXpResponse>;
|
|
4090
4113
|
history: (options?: {
|
|
4091
|
-
startDate
|
|
4114
|
+
startDate?: string;
|
|
4092
4115
|
endDate?: string;
|
|
4093
4116
|
}) => Promise<XpHistoryResponse>;
|
|
4094
4117
|
summary: (options?: {
|
|
@@ -4180,6 +4203,15 @@ declare class PlaycademyClient {
|
|
|
4180
4203
|
}, cacheOptions?: TTLCacheConfig) => Promise<NotificationStats>;
|
|
4181
4204
|
};
|
|
4182
4205
|
};
|
|
4206
|
+
/** Backend methods for calling custom game API routes */
|
|
4207
|
+
backend: {
|
|
4208
|
+
get<T = unknown>(path: string, headers?: Record<string, string>): Promise<T>;
|
|
4209
|
+
post<T = unknown>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
4210
|
+
put<T = unknown>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
4211
|
+
patch<T = unknown>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
4212
|
+
delete<T = unknown>(path: string, headers?: Record<string, string>): Promise<T>;
|
|
4213
|
+
request<T = unknown>(path: string, method: Method, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
4214
|
+
};
|
|
4183
4215
|
/** Auto-initializes a PlaycademyClient with context from the environment */
|
|
4184
4216
|
static init: typeof init;
|
|
4185
4217
|
/** Authenticates a user with email and password */
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,9 @@ var __export = (target, all) => {
|
|
|
11
11
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
12
|
|
|
13
13
|
// ../logger/src/index.ts
|
|
14
|
-
var
|
|
14
|
+
var hasProcess = () => {
|
|
15
|
+
return typeof process !== "undefined";
|
|
16
|
+
}, isBrowser = () => {
|
|
15
17
|
const g = globalThis;
|
|
16
18
|
return typeof g.window !== "undefined" && typeof g.document !== "undefined";
|
|
17
19
|
}, colors, shouldUseColor = () => {
|
|
@@ -85,7 +87,9 @@ var isBrowser = () => {
|
|
|
85
87
|
}
|
|
86
88
|
return JSON.stringify(logEntry);
|
|
87
89
|
}, performLog = (level, message, context) => {
|
|
88
|
-
if (level === "debug" &&
|
|
90
|
+
if (level === "debug" && hasProcess() && process.env.PLAYCADEMY_EMBEDDED) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
89
93
|
if (isBrowser()) {
|
|
90
94
|
logInBrowser(level, message, context);
|
|
91
95
|
} else {
|
|
@@ -860,6 +864,22 @@ function createTTLCache(options) {
|
|
|
860
864
|
}
|
|
861
865
|
|
|
862
866
|
// src/core/request.ts
|
|
867
|
+
function checkDevWarnings(data) {
|
|
868
|
+
if (!data || typeof data !== "object")
|
|
869
|
+
return;
|
|
870
|
+
const response = data;
|
|
871
|
+
const warningType = response.__playcademyDevWarning;
|
|
872
|
+
if (!warningType)
|
|
873
|
+
return;
|
|
874
|
+
switch (warningType) {
|
|
875
|
+
case "timeback-disabled":
|
|
876
|
+
console.warn("%c⚠️ TimeBack Disabled in Dev", "background: #f59e0b; color: white; padding: 4px 8px; border-radius: 3px; font-weight: bold", `
|
|
877
|
+
` + (response.__playcademyDevMessage || "TimeBack is disabled in local development"));
|
|
878
|
+
break;
|
|
879
|
+
default:
|
|
880
|
+
console.warn(`[Playcademy Dev Warning] ${warningType}`);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
863
883
|
async function request({
|
|
864
884
|
path,
|
|
865
885
|
baseUrl,
|
|
@@ -894,7 +914,9 @@ async function request({
|
|
|
894
914
|
const contentType = res.headers.get("content-type") ?? "";
|
|
895
915
|
if (contentType.includes("application/json")) {
|
|
896
916
|
try {
|
|
897
|
-
|
|
917
|
+
const parsed = await res.json();
|
|
918
|
+
checkDevWarnings(parsed);
|
|
919
|
+
return parsed;
|
|
898
920
|
} catch (err) {
|
|
899
921
|
if (err instanceof SyntaxError)
|
|
900
922
|
return;
|
|
@@ -1185,15 +1207,7 @@ function createDevNamespace(client) {
|
|
|
1185
1207
|
throw new Error(`File upload failed: ${uploadResponse.status} ${uploadResponse.statusText}`);
|
|
1186
1208
|
}
|
|
1187
1209
|
}
|
|
1188
|
-
const
|
|
1189
|
-
const anyClient = client;
|
|
1190
|
-
try {
|
|
1191
|
-
return typeof anyClient.getBaseUrl === "function" ? anyClient.getBaseUrl() : "/api";
|
|
1192
|
-
} catch {
|
|
1193
|
-
return "/api";
|
|
1194
|
-
}
|
|
1195
|
-
})();
|
|
1196
|
-
const finalizeUrl = baseUrl.replace(/\/$/, "") + "/games/uploads/finalize/";
|
|
1210
|
+
const finalizeUrl = `${client.baseUrl}/games/uploads/finalize/`;
|
|
1197
1211
|
const authToken = client.getToken();
|
|
1198
1212
|
const tokenType = client.getTokenType();
|
|
1199
1213
|
const headers = {
|
|
@@ -2751,17 +2765,42 @@ function createAchievementsNamespace(client) {
|
|
|
2751
2765
|
}
|
|
2752
2766
|
var init_achievements = () => {};
|
|
2753
2767
|
|
|
2768
|
+
// src/constants.ts
|
|
2769
|
+
var CURRENCIES2, BADGES2, AuthProvider, TIMEBACK_ROUTES;
|
|
2770
|
+
var init_constants2 = __esm(() => {
|
|
2771
|
+
CURRENCIES2 = {
|
|
2772
|
+
PRIMARY: "PLAYCADEMY_CREDITS",
|
|
2773
|
+
XP: "PLAYCADEMY_XP"
|
|
2774
|
+
};
|
|
2775
|
+
BADGES2 = {
|
|
2776
|
+
FOUNDING_MEMBER: "FOUNDING_MEMBER_BADGE",
|
|
2777
|
+
EARLY_ADOPTER: "EARLY_ADOPTER_BADGE",
|
|
2778
|
+
FIRST_GAME: "FIRST_GAME_BADGE"
|
|
2779
|
+
};
|
|
2780
|
+
AuthProvider = {
|
|
2781
|
+
TIMEBACK: "TIMEBACK"
|
|
2782
|
+
};
|
|
2783
|
+
TIMEBACK_ROUTES = {
|
|
2784
|
+
PROGRESS: "/api/integrations/timeback/progress",
|
|
2785
|
+
SESSION_END: "/api/integrations/timeback/session-end",
|
|
2786
|
+
AWARD_XP: "/api/integrations/timeback/award-xp"
|
|
2787
|
+
};
|
|
2788
|
+
});
|
|
2789
|
+
|
|
2754
2790
|
// src/core/namespaces/timeback.ts
|
|
2755
2791
|
function createTimebackNamespace(client) {
|
|
2756
2792
|
return {
|
|
2757
2793
|
recordProgress: (progressData) => {
|
|
2758
|
-
return client["
|
|
2794
|
+
return client["requestGameBackend"](TIMEBACK_ROUTES.PROGRESS, "POST", { progressData });
|
|
2759
2795
|
},
|
|
2760
2796
|
recordSessionEnd: (sessionData) => {
|
|
2761
|
-
return client["
|
|
2797
|
+
return client["requestGameBackend"](TIMEBACK_ROUTES.SESSION_END, "POST", { sessionData });
|
|
2762
2798
|
},
|
|
2763
2799
|
awardXP: (xpAmount, metadata) => {
|
|
2764
|
-
return client["
|
|
2800
|
+
return client["requestGameBackend"](TIMEBACK_ROUTES.AWARD_XP, "POST", {
|
|
2801
|
+
xpAmount,
|
|
2802
|
+
metadata
|
|
2803
|
+
});
|
|
2765
2804
|
},
|
|
2766
2805
|
management: {
|
|
2767
2806
|
setup: (request2) => {
|
|
@@ -2822,6 +2861,9 @@ function createTimebackNamespace(client) {
|
|
|
2822
2861
|
}
|
|
2823
2862
|
};
|
|
2824
2863
|
}
|
|
2864
|
+
var init_timeback = __esm(() => {
|
|
2865
|
+
init_constants2();
|
|
2866
|
+
});
|
|
2825
2867
|
|
|
2826
2868
|
// src/core/namespaces/notifications.ts
|
|
2827
2869
|
function createNotificationsNamespace(client) {
|
|
@@ -2891,6 +2933,33 @@ function createNotificationsNamespace(client) {
|
|
|
2891
2933
|
}
|
|
2892
2934
|
var init_notifications = () => {};
|
|
2893
2935
|
|
|
2936
|
+
// src/core/namespaces/backend.ts
|
|
2937
|
+
function createBackendNamespace(client) {
|
|
2938
|
+
function normalizePath(path) {
|
|
2939
|
+
return path.startsWith("/") ? path : `/${path}`;
|
|
2940
|
+
}
|
|
2941
|
+
return {
|
|
2942
|
+
async get(path, headers) {
|
|
2943
|
+
return client["requestGameBackend"](normalizePath(path), "GET", undefined, headers);
|
|
2944
|
+
},
|
|
2945
|
+
async post(path, body, headers) {
|
|
2946
|
+
return client["requestGameBackend"](normalizePath(path), "POST", body, headers);
|
|
2947
|
+
},
|
|
2948
|
+
async put(path, body, headers) {
|
|
2949
|
+
return client["requestGameBackend"](normalizePath(path), "PUT", body, headers);
|
|
2950
|
+
},
|
|
2951
|
+
async patch(path, body, headers) {
|
|
2952
|
+
return client["requestGameBackend"](normalizePath(path), "PATCH", body, headers);
|
|
2953
|
+
},
|
|
2954
|
+
async delete(path, headers) {
|
|
2955
|
+
return client["requestGameBackend"](normalizePath(path), "DELETE", undefined, headers);
|
|
2956
|
+
},
|
|
2957
|
+
async request(path, method, body, headers) {
|
|
2958
|
+
return client["requestGameBackend"](normalizePath(path), method, body, headers);
|
|
2959
|
+
}
|
|
2960
|
+
};
|
|
2961
|
+
}
|
|
2962
|
+
|
|
2894
2963
|
// src/core/namespaces/index.ts
|
|
2895
2964
|
var init_namespaces = __esm(() => {
|
|
2896
2965
|
init_identity();
|
|
@@ -2904,6 +2973,7 @@ var init_namespaces = __esm(() => {
|
|
|
2904
2973
|
init_sprites();
|
|
2905
2974
|
init_realtime();
|
|
2906
2975
|
init_achievements();
|
|
2976
|
+
init_timeback();
|
|
2907
2977
|
init_notifications();
|
|
2908
2978
|
});
|
|
2909
2979
|
|
|
@@ -2933,6 +3003,9 @@ function buildAllowedOrigins(explicit) {
|
|
|
2933
3003
|
return ref ? [ref] : [];
|
|
2934
3004
|
}
|
|
2935
3005
|
function isOriginAllowed(origin, allowlist) {
|
|
3006
|
+
if (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1") {
|
|
3007
|
+
return true;
|
|
3008
|
+
}
|
|
2936
3009
|
if (!allowlist || allowlist.length === 0) {
|
|
2937
3010
|
console.error("[Playcademy SDK] No allowed origins configured. Consider passing allowedParentOrigins explicitly to init().");
|
|
2938
3011
|
return false;
|
|
@@ -2976,7 +3049,8 @@ async function waitForPlaycademyInit(allowedParentOrigins) {
|
|
|
2976
3049
|
function createStandaloneConfig() {
|
|
2977
3050
|
console.warn("[Playcademy SDK] Standalone mode detected, creating mock context for local development");
|
|
2978
3051
|
const mockConfig = {
|
|
2979
|
-
baseUrl: "
|
|
3052
|
+
baseUrl: "http://localhost:4321",
|
|
3053
|
+
gameUrl: "http://localhost:8788",
|
|
2980
3054
|
token: "mock-game-token-for-local-dev",
|
|
2981
3055
|
gameId: "mock-game-id-from-template",
|
|
2982
3056
|
realtimeUrl: undefined
|
|
@@ -2995,6 +3069,7 @@ async function init(options) {
|
|
|
2995
3069
|
}
|
|
2996
3070
|
const client = new PlaycademyClient({
|
|
2997
3071
|
baseUrl: config.baseUrl,
|
|
3072
|
+
gameUrl: config.gameUrl,
|
|
2998
3073
|
token: config.token,
|
|
2999
3074
|
gameId: config.gameId,
|
|
3000
3075
|
autoStartSession: window.self !== window.top
|
|
@@ -3072,6 +3147,7 @@ var init_client = __esm(() => {
|
|
|
3072
3147
|
init_static();
|
|
3073
3148
|
PlaycademyClient = class PlaycademyClient {
|
|
3074
3149
|
baseUrl;
|
|
3150
|
+
gameUrl;
|
|
3075
3151
|
authStrategy;
|
|
3076
3152
|
gameId;
|
|
3077
3153
|
config;
|
|
@@ -3080,7 +3156,8 @@ var init_client = __esm(() => {
|
|
|
3080
3156
|
authContext;
|
|
3081
3157
|
initPayload;
|
|
3082
3158
|
constructor(config) {
|
|
3083
|
-
this.baseUrl = config?.baseUrl
|
|
3159
|
+
this.baseUrl = config?.baseUrl?.endsWith("/api") ? config.baseUrl : `${config?.baseUrl}/api`;
|
|
3160
|
+
this.gameUrl = config?.gameUrl;
|
|
3084
3161
|
this.gameId = config?.gameId;
|
|
3085
3162
|
this.config = config || {};
|
|
3086
3163
|
this.authStrategy = createAuthStrategy(config?.token ?? null, config?.tokenType);
|
|
@@ -3092,6 +3169,15 @@ var init_client = __esm(() => {
|
|
|
3092
3169
|
const isBrowser2 = typeof window !== "undefined";
|
|
3093
3170
|
return isRelative && isBrowser2 ? `${window.location.origin}${this.baseUrl}` : this.baseUrl;
|
|
3094
3171
|
}
|
|
3172
|
+
getGameBackendUrl() {
|
|
3173
|
+
if (!this.gameUrl) {
|
|
3174
|
+
throw new PlaycademyError("Game backend URL not configured. gameUrl must be set to use game backend features.");
|
|
3175
|
+
}
|
|
3176
|
+
const isRelative = this.gameUrl.startsWith("/");
|
|
3177
|
+
const isBrowser2 = typeof window !== "undefined";
|
|
3178
|
+
const effectiveGameUrl = isRelative && isBrowser2 ? `${window.location.origin}${this.gameUrl}` : this.gameUrl;
|
|
3179
|
+
return `${effectiveGameUrl}/api`;
|
|
3180
|
+
}
|
|
3095
3181
|
ping() {
|
|
3096
3182
|
return "pong";
|
|
3097
3183
|
}
|
|
@@ -3136,6 +3222,19 @@ var init_client = __esm(() => {
|
|
|
3136
3222
|
extraHeaders: effectiveHeaders
|
|
3137
3223
|
});
|
|
3138
3224
|
}
|
|
3225
|
+
async requestGameBackend(path, method, body, headers) {
|
|
3226
|
+
const effectiveHeaders = {
|
|
3227
|
+
...headers,
|
|
3228
|
+
...this.authStrategy.getHeaders()
|
|
3229
|
+
};
|
|
3230
|
+
return request({
|
|
3231
|
+
path,
|
|
3232
|
+
method,
|
|
3233
|
+
body,
|
|
3234
|
+
baseUrl: this.getGameBackendUrl(),
|
|
3235
|
+
extraHeaders: effectiveHeaders
|
|
3236
|
+
});
|
|
3237
|
+
}
|
|
3139
3238
|
_ensureGameId() {
|
|
3140
3239
|
if (!this.gameId) {
|
|
3141
3240
|
throw new PlaycademyError("This operation requires a gameId, but none was provided when initializing the client.");
|
|
@@ -3185,6 +3284,7 @@ var init_client = __esm(() => {
|
|
|
3185
3284
|
realtime = createRealtimeNamespace(this);
|
|
3186
3285
|
achievements = createAchievementsNamespace(this);
|
|
3187
3286
|
notifications = createNotificationsNamespace(this);
|
|
3287
|
+
backend = createBackendNamespace(this);
|
|
3188
3288
|
static init = init;
|
|
3189
3289
|
static login = login2;
|
|
3190
3290
|
static identity = identity;
|
|
@@ -3194,20 +3294,7 @@ var init_client = __esm(() => {
|
|
|
3194
3294
|
// src/index.ts
|
|
3195
3295
|
init_client();
|
|
3196
3296
|
init_messaging();
|
|
3197
|
-
|
|
3198
|
-
// src/constants.ts
|
|
3199
|
-
var CURRENCIES2 = {
|
|
3200
|
-
PRIMARY: "PLAYCADEMY_CREDITS",
|
|
3201
|
-
XP: "PLAYCADEMY_XP"
|
|
3202
|
-
};
|
|
3203
|
-
var BADGES2 = {
|
|
3204
|
-
FOUNDING_MEMBER: "FOUNDING_MEMBER_BADGE",
|
|
3205
|
-
EARLY_ADOPTER: "EARLY_ADOPTER_BADGE",
|
|
3206
|
-
FIRST_GAME: "FIRST_GAME_BADGE"
|
|
3207
|
-
};
|
|
3208
|
-
var AuthProvider = {
|
|
3209
|
-
TIMEBACK: "TIMEBACK"
|
|
3210
|
-
};
|
|
3297
|
+
init_constants2();
|
|
3211
3298
|
export {
|
|
3212
3299
|
messaging,
|
|
3213
3300
|
PlaycademyClient,
|
package/dist/types.d.ts
CHANGED
|
@@ -3705,6 +3705,7 @@ type XpHistoryResponse = {
|
|
|
3705
3705
|
xp: number;
|
|
3706
3706
|
}>;
|
|
3707
3707
|
};
|
|
3708
|
+
type TimebackSubject = 'Reading' | 'Language' | 'Vocabulary' | 'Social Studies' | 'Writing' | 'Science' | 'FastMath' | 'Math' | 'None';
|
|
3708
3709
|
type TimebackSetupRequest = {
|
|
3709
3710
|
gameId: string;
|
|
3710
3711
|
config: {
|
|
@@ -3792,6 +3793,9 @@ type RecordProgressRequest = {
|
|
|
3792
3793
|
gameId: string;
|
|
3793
3794
|
studentId: string;
|
|
3794
3795
|
progressData: {
|
|
3796
|
+
sensorUrl?: string;
|
|
3797
|
+
subject?: TimebackSubject;
|
|
3798
|
+
appName?: string;
|
|
3795
3799
|
score?: number;
|
|
3796
3800
|
totalQuestions?: number;
|
|
3797
3801
|
correctQuestions?: number;
|
|
@@ -3804,9 +3808,6 @@ type RecordProgressRequest = {
|
|
|
3804
3808
|
classId?: string;
|
|
3805
3809
|
courseName?: string;
|
|
3806
3810
|
studentEmail?: string;
|
|
3807
|
-
subject?: 'Reading' | 'Language' | 'Vocabulary' | 'Social Studies' | 'Writing' | 'Science' | 'FastMath' | 'Math' | 'None';
|
|
3808
|
-
appName?: string;
|
|
3809
|
-
sensorUrl?: string;
|
|
3810
3811
|
};
|
|
3811
3812
|
};
|
|
3812
3813
|
type RecordProgressResponse = {
|
|
@@ -3817,6 +3818,9 @@ type RecordSessionEndRequest = {
|
|
|
3817
3818
|
gameId: string;
|
|
3818
3819
|
studentId: string;
|
|
3819
3820
|
sessionData: {
|
|
3821
|
+
sensorUrl?: string;
|
|
3822
|
+
subject?: TimebackSubject;
|
|
3823
|
+
appName?: string;
|
|
3820
3824
|
activeTimeSeconds: number;
|
|
3821
3825
|
inactiveTimeSeconds?: number;
|
|
3822
3826
|
wasteTimeSeconds?: number;
|
|
@@ -3825,9 +3829,6 @@ type RecordSessionEndRequest = {
|
|
|
3825
3829
|
courseId?: string;
|
|
3826
3830
|
courseName?: string;
|
|
3827
3831
|
studentEmail?: string;
|
|
3828
|
-
subject?: 'Reading' | 'Language' | 'Vocabulary' | 'Social Studies' | 'Writing' | 'Science' | 'FastMath' | 'Math' | 'None';
|
|
3829
|
-
appName?: string;
|
|
3830
|
-
sensorUrl?: string;
|
|
3831
3832
|
};
|
|
3832
3833
|
};
|
|
3833
3834
|
type RecordSessionEndResponse = {
|
|
@@ -3839,6 +3840,9 @@ type AwardXpRequest = {
|
|
|
3839
3840
|
studentId: string;
|
|
3840
3841
|
xpAmount: number;
|
|
3841
3842
|
metadata: {
|
|
3843
|
+
sensorUrl: string;
|
|
3844
|
+
subject: TimebackSubject;
|
|
3845
|
+
appName: string;
|
|
3842
3846
|
reason: string;
|
|
3843
3847
|
activityId?: string;
|
|
3844
3848
|
activityName?: string;
|
|
@@ -3846,9 +3850,6 @@ type AwardXpRequest = {
|
|
|
3846
3850
|
courseName?: string;
|
|
3847
3851
|
studentEmail?: string;
|
|
3848
3852
|
bonusType?: string;
|
|
3849
|
-
subject?: 'Reading' | 'Language' | 'Vocabulary' | 'Social Studies' | 'Writing' | 'Science' | 'FastMath' | 'Math' | 'None';
|
|
3850
|
-
appName?: string;
|
|
3851
|
-
sensorUrl?: string;
|
|
3852
3853
|
};
|
|
3853
3854
|
};
|
|
3854
3855
|
type AwardXpResponse = {
|
|
@@ -4295,7 +4296,8 @@ type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
|
4295
4296
|
* Provides namespaced access to all platform features including games, users, inventory, and more.
|
|
4296
4297
|
*/
|
|
4297
4298
|
declare class PlaycademyClient {
|
|
4298
|
-
|
|
4299
|
+
baseUrl: string;
|
|
4300
|
+
gameUrl?: string;
|
|
4299
4301
|
private authStrategy;
|
|
4300
4302
|
private gameId?;
|
|
4301
4303
|
private config;
|
|
@@ -4307,7 +4309,7 @@ declare class PlaycademyClient {
|
|
|
4307
4309
|
* Creates a new PlaycademyClient instance.
|
|
4308
4310
|
*
|
|
4309
4311
|
* @param config - Optional configuration object
|
|
4310
|
-
* @param config.baseUrl - Base URL
|
|
4312
|
+
* @param config.baseUrl - Base URL (e.g., 'https://hub.playcademy.com' or '/'). SDK automatically appends /api
|
|
4311
4313
|
* @param config.token - Authentication token
|
|
4312
4314
|
* @param config.tokenType - Optional token type (auto-detected if not provided)
|
|
4313
4315
|
* @param config.gameId - Game ID for automatic session management
|
|
@@ -4317,10 +4319,19 @@ declare class PlaycademyClient {
|
|
|
4317
4319
|
/**
|
|
4318
4320
|
* Gets the effective base URL for API requests.
|
|
4319
4321
|
* Converts relative URLs to absolute URLs in browser environments.
|
|
4322
|
+
* Note: baseUrl already includes /api suffix from constructor.
|
|
4320
4323
|
*
|
|
4321
|
-
* @returns The complete base URL for API requests
|
|
4324
|
+
* @returns The complete base URL for API requests (with /api suffix)
|
|
4322
4325
|
*/
|
|
4323
4326
|
getBaseUrl(): string;
|
|
4327
|
+
/**
|
|
4328
|
+
* Gets the effective game backend URL for integration requests.
|
|
4329
|
+
* Throws if gameUrl is not configured.
|
|
4330
|
+
*
|
|
4331
|
+
* @returns The complete game backend URL for API requests (with /api suffix)
|
|
4332
|
+
* @throws PlaycademyError if gameUrl is not set
|
|
4333
|
+
*/
|
|
4334
|
+
private getGameBackendUrl;
|
|
4324
4335
|
/**
|
|
4325
4336
|
* Simple ping method for testing connectivity.
|
|
4326
4337
|
*
|
|
@@ -4408,7 +4419,7 @@ declare class PlaycademyClient {
|
|
|
4408
4419
|
*/
|
|
4409
4420
|
private emit;
|
|
4410
4421
|
/**
|
|
4411
|
-
* Makes an authenticated HTTP request to the API.
|
|
4422
|
+
* Makes an authenticated HTTP request to the platform API.
|
|
4412
4423
|
*
|
|
4413
4424
|
* @param path - API endpoint path
|
|
4414
4425
|
* @param method - HTTP method
|
|
@@ -4417,6 +4428,17 @@ declare class PlaycademyClient {
|
|
|
4417
4428
|
* @returns Promise resolving to the response data
|
|
4418
4429
|
*/
|
|
4419
4430
|
protected request<T>(path: string, method: Method, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
4431
|
+
/**
|
|
4432
|
+
* Makes an authenticated HTTP request to the game's backend Worker.
|
|
4433
|
+
* Uses gameUrl if set, otherwise falls back to platform API.
|
|
4434
|
+
*
|
|
4435
|
+
* @param path - API endpoint path
|
|
4436
|
+
* @param method - HTTP method
|
|
4437
|
+
* @param body - Request body (optional)
|
|
4438
|
+
* @param headers - Additional headers (optional)
|
|
4439
|
+
* @returns Promise resolving to the response data
|
|
4440
|
+
*/
|
|
4441
|
+
protected requestGameBackend<T>(path: string, method: Method, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
4420
4442
|
/**
|
|
4421
4443
|
* Ensures a gameId is available, throwing an error if not.
|
|
4422
4444
|
*
|
|
@@ -4763,7 +4785,7 @@ declare class PlaycademyClient {
|
|
|
4763
4785
|
}) => Promise<TodayXpResponse>;
|
|
4764
4786
|
total: () => Promise<TotalXpResponse>;
|
|
4765
4787
|
history: (options?: {
|
|
4766
|
-
startDate
|
|
4788
|
+
startDate?: string;
|
|
4767
4789
|
endDate?: string;
|
|
4768
4790
|
}) => Promise<XpHistoryResponse>;
|
|
4769
4791
|
summary: (options?: {
|
|
@@ -4855,6 +4877,15 @@ declare class PlaycademyClient {
|
|
|
4855
4877
|
}, cacheOptions?: TTLCacheConfig) => Promise<NotificationStats>;
|
|
4856
4878
|
};
|
|
4857
4879
|
};
|
|
4880
|
+
/** Backend methods for calling custom game API routes */
|
|
4881
|
+
backend: {
|
|
4882
|
+
get<T = unknown>(path: string, headers?: Record<string, string>): Promise<T>;
|
|
4883
|
+
post<T = unknown>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
4884
|
+
put<T = unknown>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
4885
|
+
patch<T = unknown>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
4886
|
+
delete<T = unknown>(path: string, headers?: Record<string, string>): Promise<T>;
|
|
4887
|
+
request<T = unknown>(path: string, method: Method, body?: unknown, headers?: Record<string, string>): Promise<T>;
|
|
4888
|
+
};
|
|
4858
4889
|
/** Auto-initializes a PlaycademyClient with context from the environment */
|
|
4859
4890
|
static init: typeof init;
|
|
4860
4891
|
/** Authenticates a user with email and password */
|
|
@@ -4868,6 +4899,7 @@ declare class PlaycademyClient {
|
|
|
4868
4899
|
type TokenType = 'session' | 'apiKey' | 'gameJwt';
|
|
4869
4900
|
interface ClientConfig {
|
|
4870
4901
|
baseUrl: string;
|
|
4902
|
+
gameUrl?: string;
|
|
4871
4903
|
token?: string;
|
|
4872
4904
|
tokenType?: TokenType;
|
|
4873
4905
|
gameId?: string;
|
|
@@ -4875,6 +4907,7 @@ interface ClientConfig {
|
|
|
4875
4907
|
}
|
|
4876
4908
|
interface InitPayload {
|
|
4877
4909
|
baseUrl: string;
|
|
4910
|
+
gameUrl?: string;
|
|
4878
4911
|
token: string;
|
|
4879
4912
|
gameId: string;
|
|
4880
4913
|
realtimeUrl?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playcademy/sdk",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -27,21 +27,21 @@
|
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "bun build.js",
|
|
29
29
|
"lint": "bunx eslint . --fix --ignore-pattern dist",
|
|
30
|
-
"
|
|
31
|
-
"pub": "bun run build && bun run bump && bun publish --access public",
|
|
30
|
+
"pub": "bun publish.ts",
|
|
32
31
|
"test": "bun test",
|
|
33
32
|
"test:watch": "bun test --watch",
|
|
34
33
|
"docs": "typedoc"
|
|
35
34
|
},
|
|
36
35
|
"devDependencies": {
|
|
37
|
-
"
|
|
38
|
-
"@playcademy/timeback": "0.0.1",
|
|
39
|
-
"@playcademy/utils": "0.0.1",
|
|
36
|
+
"@inquirer/prompts": "^7.8.6",
|
|
40
37
|
"@playcademy/data": "0.0.1",
|
|
41
38
|
"@playcademy/logger": "0.0.1",
|
|
42
39
|
"@playcademy/sandbox": "0.1.0-beta.20",
|
|
43
40
|
"@playcademy/test": "0.0.1",
|
|
41
|
+
"@playcademy/timeback": "0.0.1",
|
|
42
|
+
"@playcademy/utils": "0.0.1",
|
|
44
43
|
"@types/bun": "latest",
|
|
44
|
+
"playcademy": "0.10.0",
|
|
45
45
|
"rollup": "^4.50.2",
|
|
46
46
|
"rollup-plugin-dts": "^6.2.3",
|
|
47
47
|
"typescript": "^5.7.2",
|