@playcademy/sdk 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -152,6 +152,29 @@ console.log(`Level ${userLevel.currentLevel}, ${progress.xpToNextLevel} XP to ne
152
152
  // XP updates come from TimeBack webhooks only.
153
153
  ```
154
154
 
155
+ ### TimeBack Integration
156
+
157
+ Track learning activities and automatically calculate XP based on time spent and accuracy:
158
+
159
+ ```typescript
160
+ // Start tracking an activity (only activityId required!)
161
+ client.timeback.startActivity({
162
+ activityId: 'math-quiz-level-1',
163
+ })
164
+ // Auto-derived: activityName "Math Quiz Level 1"
165
+ // Auto-filled by backend: appName, subject, sensorUrl
166
+
167
+ // ... player completes activity ...
168
+
169
+ // End activity and submit results (XP calculated automatically)
170
+ await client.timeback.endActivity({
171
+ correctQuestions: 8,
172
+ totalQuestions: 10,
173
+ })
174
+ // XP calculation: base (1 min = 1 XP) × accuracy multiplier
175
+ // 100%: 1.25x | 80-99%: 1.0x | 65-79%: 0.5x | <65%: 0x
176
+ ```
177
+
155
178
  ### Real-time Communication
156
179
 
157
180
  Open a direct, low-latency communication channel for your game, perfect for multiplayer interactions.
@@ -228,6 +251,23 @@ channel.onMessage(data => {
228
251
  - `open(channelName?)`: Opens a game-scoped WebSocket channel.
229
252
  - `token.get()`: Retrieves a JWT for the real-time service.
230
253
 
254
+ #### **TimeBack** (`client.timeback`)
255
+
256
+ - `startActivity(metadata)`: Start tracking an activity (stores start time and metadata)
257
+ - `metadata.activityId`: Unique activity identifier (required)
258
+ - `metadata.activityName`: Human-readable activity name
259
+ - `metadata.subject`: Subject area (Math, Reading, Science, etc.)
260
+ - `metadata.appName`: Application name
261
+ - `metadata.sensorUrl`: Sensor URL for tracking
262
+ - `endActivity(scoreData)`: End activity and submit results
263
+ - `scoreData.correctQuestions`: Number of correct answers
264
+ - `scoreData.totalQuestions`: Total number of questions
265
+ - **XP Query** (`client.timeback.xp`):
266
+ - `today(options?)`: Get today's XP (supports timezone parameter)
267
+ - `total()`: Get total accumulated XP
268
+ - `history(options?)`: Get XP history with optional date filtering
269
+ - `summary(options?)`: Get both today's and total XP in one call
270
+
231
271
  #### **Leaderboard** (`client.leaderboard`) - Game-specific
232
272
 
233
273
  - `fetch(options?)`: Get leaderboard for a specific game
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import { InferSelectModel } from 'drizzle-orm';
3
3
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
4
4
  import * as drizzle_zod from 'drizzle-zod';
5
5
  import { z } from 'zod';
6
+ import * as _playcademy_timeback_types from '@playcademy/timeback/types';
6
7
  import { OrganizationConfig, CourseConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig } from '@playcademy/timeback/types';
7
8
  import { AUTH_PROVIDER_IDS } from '@playcademy/constants';
8
9
 
@@ -3022,7 +3023,6 @@ type XpHistoryResponse = {
3022
3023
  xp: number;
3023
3024
  }>;
3024
3025
  };
3025
- type TimebackSubject = 'Reading' | 'Language' | 'Vocabulary' | 'Social Studies' | 'Writing' | 'Science' | 'FastMath' | 'Math' | 'None';
3026
3026
  type TimebackSetupRequest = {
3027
3027
  gameId: string;
3028
3028
  config: {
@@ -3106,70 +3106,7 @@ type TimebackVerifyResponse = {
3106
3106
  };
3107
3107
  errors?: string[];
3108
3108
  };
3109
- type RecordProgressRequest = {
3110
- gameId: string;
3111
- studentId: string;
3112
- progressData: {
3113
- sensorUrl?: string;
3114
- subject?: TimebackSubject;
3115
- appName?: string;
3116
- score?: number;
3117
- totalQuestions?: number;
3118
- correctQuestions?: number;
3119
- xpEarned?: number;
3120
- masteredUnits?: number;
3121
- attemptNumber?: number;
3122
- activityId?: string;
3123
- activityName?: string;
3124
- courseId?: string;
3125
- classId?: string;
3126
- courseName?: string;
3127
- studentEmail?: string;
3128
- };
3129
- };
3130
- type RecordProgressResponse = {
3131
- status: 'ok';
3132
- courseId: string;
3133
- };
3134
- type RecordSessionEndRequest = {
3135
- gameId: string;
3136
- studentId: string;
3137
- sessionData: {
3138
- sensorUrl?: string;
3139
- subject?: TimebackSubject;
3140
- appName?: string;
3141
- activeTimeSeconds: number;
3142
- inactiveTimeSeconds?: number;
3143
- wasteTimeSeconds?: number;
3144
- activityId?: string;
3145
- activityName?: string;
3146
- courseId?: string;
3147
- courseName?: string;
3148
- studentEmail?: string;
3149
- };
3150
- };
3151
- type RecordSessionEndResponse = {
3152
- status: 'ok';
3153
- courseId: string;
3154
- };
3155
- type AwardXpRequest = {
3156
- gameId: string;
3157
- studentId: string;
3158
- xpAmount: number;
3159
- metadata: {
3160
- sensorUrl: string;
3161
- subject: TimebackSubject;
3162
- appName: string;
3163
- reason: string;
3164
- activityId?: string;
3165
- activityName?: string;
3166
- courseId?: string;
3167
- courseName?: string;
3168
- studentEmail?: string;
3169
- bonusType?: string;
3170
- };
3171
- };
3172
- type AwardXpResponse = {
3109
+ type EndActivityResponse = {
3173
3110
  status: 'ok';
3174
3111
  courseId: string;
3175
3112
  xpAwarded: number;
@@ -4077,9 +4014,10 @@ declare class PlaycademyClient {
4077
4014
  };
4078
4015
  /** TimeBack XP methods (today, total, history) */
4079
4016
  timeback: {
4080
- recordProgress: (progressData: RecordProgressRequest["progressData"]) => Promise<RecordProgressResponse>;
4081
- recordSessionEnd: (sessionData: RecordSessionEndRequest["sessionData"]) => Promise<RecordSessionEndResponse>;
4082
- awardXP: (xpAmount: number, metadata: AwardXpRequest["metadata"]) => Promise<AwardXpResponse>;
4017
+ startActivity: (metadata: _playcademy_timeback_types.ActivityData) => void;
4018
+ pauseActivity: () => void;
4019
+ resumeActivity: () => void;
4020
+ endActivity: (data: _playcademy_timeback_types.EndActivityScoreData) => Promise<EndActivityResponse>;
4083
4021
  management: {
4084
4022
  setup: (request: TimebackSetupRequest) => Promise<TimebackSetupResponse>;
4085
4023
  verify: (gameId: string) => Promise<TimebackVerifyResponse>;
package/dist/index.js CHANGED
@@ -110,10 +110,18 @@ var isBrowser = () => {
110
110
  default:
111
111
  return console.log;
112
112
  }
113
+ }, levelPriority, getMinimumLogLevel = () => {
114
+ const envLevel = (process.env.LOG_LEVEL ?? "").toLowerCase();
115
+ if (envLevel && ["debug", "info", "warn", "error"].includes(envLevel)) {
116
+ return envLevel;
117
+ }
118
+ return isProduction() ? "info" : "debug";
119
+ }, shouldLog = (level) => {
120
+ const minLevel = getMinimumLogLevel();
121
+ return levelPriority[level] >= levelPriority[minLevel];
113
122
  }, performLog = (level, message, context) => {
114
- if (level === "debug" && isProduction()) {
123
+ if (!shouldLog(level))
115
124
  return;
116
- }
117
125
  const outputFormat = detectOutputFormat();
118
126
  switch (outputFormat) {
119
127
  case "browser":
@@ -148,6 +156,12 @@ var init_src = __esm(() => {
148
156
  cyan: "\x1B[36m",
149
157
  gray: "\x1B[90m"
150
158
  };
159
+ levelPriority = {
160
+ debug: 0,
161
+ info: 1,
162
+ warn: 2,
163
+ error: 3
164
+ };
151
165
  log = createLogger();
152
166
  });
153
167
 
@@ -906,9 +920,16 @@ function checkDevWarnings(data) {
906
920
  if (!warningType)
907
921
  return;
908
922
  switch (warningType) {
909
- case "timeback-disabled":
910
- console.warn("%c⚠️ TimeBack Disabled in Dev", "background: #f59e0b; color: white; padding: 4px 8px; border-radius: 3px; font-weight: bold", `
911
- ` + (response.__playcademyDevMessage || "TimeBack is disabled in local development"));
923
+ case "timeback-not-configured":
924
+ console.warn("%c⚠️ TimeBack Not Configured", "background: #f59e0b; color: white; padding: 6px 12px; border-radius: 4px; font-weight: bold; font-size: 13px");
925
+ console.log("%cTimeBack is configured in playcademy.config.js but the sandbox does not have TimeBack credentials.", "color: #f59e0b; font-weight: 500");
926
+ console.log("To test TimeBack locally:");
927
+ console.log(" Set the following environment variables:");
928
+ console.log(" • %cTIMEBACK_ONEROSTER_API_URL", "color: #0ea5e9; font-weight: 600; font-family: monospace");
929
+ console.log(" • %cTIMEBACK_CALIPER_API_URL", "color: #0ea5e9; font-weight: 600; font-family: monospace");
930
+ console.log(" • %cTIMEBACK_API_CLIENT_ID/SECRET", "color: #0ea5e9; font-weight: 600; font-family: monospace");
931
+ console.log(" Or deploy your game: %cplaycademy deploy", "color: #10b981; font-weight: 600; font-family: monospace");
932
+ console.log(" Or wait for %c@superbuilders/timeback-local%c (coming soon)", "color: #8b5cf6; font-weight: 600; font-family: monospace", "color: inherit");
912
933
  break;
913
934
  default:
914
935
  console.warn(`[Playcademy Dev Warning] ${warningType}`);
@@ -1548,9 +1569,7 @@ var init_overworld = __esm(() => {
1548
1569
  var TIMEBACK_ROUTES;
1549
1570
  var init_timeback = __esm(() => {
1550
1571
  TIMEBACK_ROUTES = {
1551
- PROGRESS: "/integrations/timeback/progress",
1552
- SESSION_END: "/integrations/timeback/session-end",
1553
- AWARD_XP: "/integrations/timeback/award-xp"
1572
+ END_ACTIVITY: "/integrations/timeback/end-activity"
1554
1573
  };
1555
1574
  });
1556
1575
 
@@ -2039,18 +2058,69 @@ var init_achievements = () => {};
2039
2058
 
2040
2059
  // src/core/namespaces/timeback.ts
2041
2060
  function createTimebackNamespace(client) {
2061
+ let currentActivity = null;
2042
2062
  return {
2043
- recordProgress: (progressData) => {
2044
- return client["requestGameBackend"](TIMEBACK_ROUTES.PROGRESS, "POST", { progressData });
2063
+ startActivity: (metadata) => {
2064
+ currentActivity = {
2065
+ startTime: Date.now(),
2066
+ metadata,
2067
+ pausedTime: 0,
2068
+ pauseStartTime: null
2069
+ };
2070
+ },
2071
+ pauseActivity: () => {
2072
+ if (!currentActivity) {
2073
+ throw new Error("No activity in progress. Call startActivity() before pauseActivity().");
2074
+ }
2075
+ if (currentActivity.pauseStartTime !== null) {
2076
+ throw new Error("Activity is already paused.");
2077
+ }
2078
+ currentActivity.pauseStartTime = Date.now();
2045
2079
  },
2046
- recordSessionEnd: (sessionData) => {
2047
- return client["requestGameBackend"](TIMEBACK_ROUTES.SESSION_END, "POST", { sessionData });
2080
+ resumeActivity: () => {
2081
+ if (!currentActivity) {
2082
+ throw new Error("No activity in progress. Call startActivity() before resumeActivity().");
2083
+ }
2084
+ if (currentActivity.pauseStartTime === null) {
2085
+ throw new Error("Activity is not paused.");
2086
+ }
2087
+ const pauseDuration = Date.now() - currentActivity.pauseStartTime;
2088
+ currentActivity.pausedTime += pauseDuration;
2089
+ currentActivity.pauseStartTime = null;
2048
2090
  },
2049
- awardXP: (xpAmount, metadata) => {
2050
- return client["requestGameBackend"](TIMEBACK_ROUTES.AWARD_XP, "POST", {
2051
- xpAmount,
2052
- metadata
2053
- });
2091
+ endActivity: async (data) => {
2092
+ if (!currentActivity) {
2093
+ throw new Error("No activity in progress. Call startActivity() before endActivity().");
2094
+ }
2095
+ if (currentActivity.pauseStartTime !== null) {
2096
+ const pauseDuration = Date.now() - currentActivity.pauseStartTime;
2097
+ currentActivity.pausedTime += pauseDuration;
2098
+ currentActivity.pauseStartTime = null;
2099
+ }
2100
+ const endTime = Date.now();
2101
+ const totalElapsed = endTime - currentActivity.startTime;
2102
+ const activeTime = totalElapsed - currentActivity.pausedTime;
2103
+ const durationSeconds = Math.floor(activeTime / 1000);
2104
+ const { correctQuestions, totalQuestions } = data;
2105
+ const request2 = {
2106
+ activityData: currentActivity.metadata,
2107
+ scoreData: {
2108
+ correctQuestions,
2109
+ totalQuestions
2110
+ },
2111
+ timingData: {
2112
+ durationSeconds
2113
+ },
2114
+ xpEarned: data.xpAwarded
2115
+ };
2116
+ try {
2117
+ const response = await client["requestGameBackend"](TIMEBACK_ROUTES.END_ACTIVITY, "POST", request2);
2118
+ currentActivity = null;
2119
+ return response;
2120
+ } catch (error) {
2121
+ currentActivity = null;
2122
+ throw error;
2123
+ }
2054
2124
  },
2055
2125
  management: {
2056
2126
  setup: (request2) => {
package/dist/server.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as _playcademy_timeback_types from '@playcademy/timeback/types';
2
2
  import { OrganizationConfig, CourseConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig } from '@playcademy/timeback/types';
3
- export { ComponentConfig, ComponentResourceConfig, CourseConfig, OrganizationConfig, ProgressData, ResourceConfig, SessionData, TimebackGrade, TimebackSubject, XPAwardMetadata } from '@playcademy/timeback/types';
3
+ export { ActivityData, ComponentConfig, ComponentResourceConfig, CourseConfig, EndActivityPayload, OrganizationConfig, ResourceConfig, TimebackGrade, TimebackSubject } from '@playcademy/timeback/types';
4
4
 
5
5
  /**
6
6
  * @fileoverview Server SDK Type Definitions
@@ -161,22 +161,14 @@ interface UserInfo {
161
161
  /** Additional user attributes from the identity provider */
162
162
  [key: string]: unknown;
163
163
  }
164
- type RecordProgressResponse = {
165
- status: 'ok';
166
- courseId: string;
167
- };
168
- type RecordSessionEndResponse = {
169
- status: 'ok';
170
- courseId: string;
171
- };
172
- type AwardXpResponse = {
164
+ type EndActivityResponse = {
173
165
  status: 'ok';
174
166
  courseId: string;
175
167
  xpAwarded: number;
176
168
  };
177
169
 
178
170
  /**
179
- * Server-side Playcademy client for recording student progress to TimeBack.
171
+ * Server-side Playcademy client for recording student activity to TimeBack.
180
172
  *
181
173
  * This client automatically loads game configuration from playcademy.config.js
182
174
  * and uses it to auto-fill TimeBack metadata (subject, appName, courseId).
@@ -188,11 +180,12 @@ type AwardXpResponse = {
188
180
  * apiKey: process.env.PLAYCADEMY_API_KEY
189
181
  * })
190
182
  *
191
- * // Record progress (metadata auto-filled from config)
192
- * await client.timeback.recordProgress(studentId, {
193
- * score: 85,
194
- * totalQuestions: 20,
195
- * correctQuestions: 17
183
+ * // End an activity (metadata auto-filled from config)
184
+ * await client.timeback.endActivity(studentId, {
185
+ * activityData: { activityId: 'math-quiz-1' },
186
+ * scoreData: { correctQuestions: 17, totalQuestions: 20, accuracy: 0.85 },
187
+ * timingData: { durationSeconds: 300 },
188
+ * xpEarned: 5
196
189
  * })
197
190
  * ```
198
191
  */
@@ -276,12 +269,10 @@ declare class PlaycademyClient {
276
269
  * @returns The loaded configuration object
277
270
  */
278
271
  get config(): PlaycademyServerClientState['config'];
279
- /** TimeBack integration methods (recordProgress, recordSessionEnd, awardXP) */
272
+ /** TimeBack integration methods (endActivity) */
280
273
  timeback: {
281
274
  readonly courseId: string | undefined;
282
- recordProgress: (studentId: string, progressData: _playcademy_timeback_types.ProgressData) => Promise<RecordProgressResponse>;
283
- recordSessionEnd: (studentId: string, sessionData: _playcademy_timeback_types.SessionData) => Promise<RecordSessionEndResponse>;
284
- awardXP: (studentId: string, xpAmount: number, metadata: _playcademy_timeback_types.XPAwardMetadata) => Promise<AwardXpResponse>;
275
+ endActivity: (studentId: string, payload: _playcademy_timeback_types.EndActivityPayload) => Promise<EndActivityResponse>;
285
276
  };
286
277
  }
287
278
 
package/dist/server.js CHANGED
@@ -27,30 +27,11 @@ function createTimebackNamespace(client) {
27
27
  throw new Error(`Failed to fetch courseId: ${error instanceof Error ? error.message : String(error)}`);
28
28
  }
29
29
  }
30
- function enrichProgressData(data) {
30
+ function enrichActivityData(data) {
31
31
  return {
32
32
  ...data,
33
33
  subject: data.subject || client.config.integrations?.timeback?.course.subjects?.[0],
34
34
  appName: data.appName || client.config.name,
35
- activityName: data.activityName || client.config.name,
36
- courseName: data.courseName || client.config.integrations?.timeback?.course.title
37
- };
38
- }
39
- function enrichSessionData(data) {
40
- return {
41
- ...data,
42
- subject: data.subject || client.config.integrations?.timeback?.course.subjects?.[0],
43
- appName: data.appName || client.config.name,
44
- activityName: data.activityName || client.config.name,
45
- courseName: data.courseName || client.config.integrations?.timeback?.course.title
46
- };
47
- }
48
- function enrichXPMetadata(data) {
49
- return {
50
- ...data,
51
- subject: data.subject || client.config.integrations?.timeback?.course.subjects?.[0],
52
- appName: data.appName || client.config.name,
53
- activityName: data.activityName || client.config.name,
54
35
  courseName: data.courseName || client.config.integrations?.timeback?.course.title
55
36
  };
56
37
  }
@@ -58,35 +39,16 @@ function createTimebackNamespace(client) {
58
39
  get courseId() {
59
40
  return courseId;
60
41
  },
61
- recordProgress: async (studentId, progressData) => {
42
+ endActivity: async (studentId, payload) => {
62
43
  await ensureCourseId();
63
- const enrichedData = enrichProgressData(progressData);
64
- return client["request"]("/api/timeback/progress", "POST", {
44
+ const enrichedActivityData = enrichActivityData(payload.activityData);
45
+ return client["request"]("/api/timeback/end-activity", "POST", {
65
46
  gameId: client.gameId,
66
47
  studentId,
67
- progressData: enrichedData
68
- });
69
- },
70
- recordSessionEnd: async (studentId, sessionData) => {
71
- await ensureCourseId();
72
- const enrichedData = enrichSessionData(sessionData);
73
- return client["request"]("/api/timeback/session-end", "POST", {
74
- gameId: client.gameId,
75
- studentId,
76
- sessionData: enrichedData
77
- });
78
- },
79
- awardXP: async (studentId, xpAmount, metadata) => {
80
- await ensureCourseId();
81
- if (typeof xpAmount !== "number" || xpAmount <= 0) {
82
- throw new Error("[Playcademy SDK] xpAmount must be a positive number");
83
- }
84
- const enrichedMetadata = enrichXPMetadata(metadata);
85
- return client["request"]("/api/timeback/award-xp", "POST", {
86
- gameId: client.gameId,
87
- studentId,
88
- xpAmount,
89
- metadata: enrichedMetadata
48
+ activityData: enrichedActivityData,
49
+ scoreData: payload.scoreData,
50
+ timingData: payload.timingData,
51
+ xpEarned: payload.xpEarned
90
52
  });
91
53
  }
92
54
  };
@@ -348,8 +310,14 @@ Please set the PLAYCADEMY_BASE_URL environment variable`);
348
310
  body: JSON.stringify({ token: gameToken })
349
311
  });
350
312
  if (!response.ok) {
351
- const errorText = await response.text().catch(() => "Unknown error");
352
- throw new Error(`[Playcademy SDK] Token verification failed: ${response.status} ${errorText}`);
313
+ let errorMessage = "Unknown error";
314
+ try {
315
+ const data = await response.json();
316
+ errorMessage = data.error || data.message || "Unknown error";
317
+ } catch {
318
+ errorMessage = response.statusText || "Unknown error";
319
+ }
320
+ throw new Error(`[Playcademy SDK] Token verification failed: ${response.status} ${errorMessage}`);
353
321
  }
354
322
  const result = await response.json();
355
323
  return result;
package/dist/types.d.ts CHANGED
@@ -4,6 +4,7 @@ import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
4
4
  import * as drizzle_zod from 'drizzle-zod';
5
5
  import { z } from 'zod';
6
6
  import * as _playcademy_realtime_server_types from '@playcademy/realtime/server/types';
7
+ import * as _playcademy_timeback_types from '@playcademy/timeback/types';
7
8
  import { OrganizationConfig, CourseConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig } from '@playcademy/timeback/types';
8
9
 
9
10
  declare const userRoleEnum: drizzle_orm_pg_core.PgEnum<["admin", "player", "developer"]>;
@@ -3706,7 +3707,6 @@ type XpHistoryResponse = {
3706
3707
  xp: number;
3707
3708
  }>;
3708
3709
  };
3709
- type TimebackSubject = 'Reading' | 'Language' | 'Vocabulary' | 'Social Studies' | 'Writing' | 'Science' | 'FastMath' | 'Math' | 'None';
3710
3710
  type TimebackSetupRequest = {
3711
3711
  gameId: string;
3712
3712
  config: {
@@ -3790,70 +3790,7 @@ type TimebackVerifyResponse = {
3790
3790
  };
3791
3791
  errors?: string[];
3792
3792
  };
3793
- type RecordProgressRequest = {
3794
- gameId: string;
3795
- studentId: string;
3796
- progressData: {
3797
- sensorUrl?: string;
3798
- subject?: TimebackSubject;
3799
- appName?: string;
3800
- score?: number;
3801
- totalQuestions?: number;
3802
- correctQuestions?: number;
3803
- xpEarned?: number;
3804
- masteredUnits?: number;
3805
- attemptNumber?: number;
3806
- activityId?: string;
3807
- activityName?: string;
3808
- courseId?: string;
3809
- classId?: string;
3810
- courseName?: string;
3811
- studentEmail?: string;
3812
- };
3813
- };
3814
- type RecordProgressResponse = {
3815
- status: 'ok';
3816
- courseId: string;
3817
- };
3818
- type RecordSessionEndRequest = {
3819
- gameId: string;
3820
- studentId: string;
3821
- sessionData: {
3822
- sensorUrl?: string;
3823
- subject?: TimebackSubject;
3824
- appName?: string;
3825
- activeTimeSeconds: number;
3826
- inactiveTimeSeconds?: number;
3827
- wasteTimeSeconds?: number;
3828
- activityId?: string;
3829
- activityName?: string;
3830
- courseId?: string;
3831
- courseName?: string;
3832
- studentEmail?: string;
3833
- };
3834
- };
3835
- type RecordSessionEndResponse = {
3836
- status: 'ok';
3837
- courseId: string;
3838
- };
3839
- type AwardXpRequest = {
3840
- gameId: string;
3841
- studentId: string;
3842
- xpAmount: number;
3843
- metadata: {
3844
- sensorUrl: string;
3845
- subject: TimebackSubject;
3846
- appName: string;
3847
- reason: string;
3848
- activityId?: string;
3849
- activityName?: string;
3850
- courseId?: string;
3851
- courseName?: string;
3852
- studentEmail?: string;
3853
- bonusType?: string;
3854
- };
3855
- };
3856
- type AwardXpResponse = {
3793
+ type EndActivityResponse = {
3857
3794
  status: 'ok';
3858
3795
  courseId: string;
3859
3796
  xpAwarded: number;
@@ -4765,9 +4702,10 @@ declare class PlaycademyClient {
4765
4702
  };
4766
4703
  /** TimeBack XP methods (today, total, history) */
4767
4704
  timeback: {
4768
- recordProgress: (progressData: RecordProgressRequest["progressData"]) => Promise<RecordProgressResponse>;
4769
- recordSessionEnd: (sessionData: RecordSessionEndRequest["sessionData"]) => Promise<RecordSessionEndResponse>;
4770
- awardXP: (xpAmount: number, metadata: AwardXpRequest["metadata"]) => Promise<AwardXpResponse>;
4705
+ startActivity: (metadata: _playcademy_timeback_types.ActivityData) => void;
4706
+ pauseActivity: () => void;
4707
+ resumeActivity: () => void;
4708
+ endActivity: (data: _playcademy_timeback_types.EndActivityScoreData) => Promise<EndActivityResponse>;
4771
4709
  management: {
4772
4710
  setup: (request: TimebackSetupRequest) => Promise<TimebackSetupResponse>;
4773
4711
  verify: (gameId: string) => Promise<TimebackVerifyResponse>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -42,7 +42,7 @@
42
42
  "@playcademy/timeback": "0.0.1",
43
43
  "@playcademy/utils": "0.0.1",
44
44
  "@types/bun": "latest",
45
- "playcademy": "0.11.2",
45
+ "playcademy": "0.11.4",
46
46
  "rollup": "^4.50.2",
47
47
  "rollup-plugin-dts": "^6.2.3",
48
48
  "typescript": "^5.7.2",