@playcademy/sdk 0.1.18 → 0.2.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/server.d.ts CHANGED
@@ -1,7 +1,51 @@
1
1
  import { SchemaInfo } from '@playcademy/cloudflare';
2
2
  import * as _playcademy_timeback_types from '@playcademy/timeback/types';
3
- import { OrganizationConfig, CourseConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig } from '@playcademy/timeback/types';
4
- export { ActivityData, ComponentConfig, ComponentResourceConfig, CourseConfig, EndActivityPayload, OrganizationConfig, ResourceConfig, TimebackGrade, TimebackSubject } from '@playcademy/timeback/types';
3
+ import { CourseConfig, OrganizationConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig } from '@playcademy/timeback/types';
4
+ export { ActivityData, ComponentConfig, ComponentResourceConfig, EndActivityPayload, OrganizationConfig, ResourceConfig, TimebackGrade, TimebackSubject } from '@playcademy/timeback/types';
5
+
6
+ /**
7
+ * Basic user information in the shape of the claims from identity providers
8
+ */
9
+ interface UserInfo {
10
+ /** Unique user identifier (sub claim from JWT) */
11
+ sub: string;
12
+ /** User's email address */
13
+ email: string;
14
+ /** User's display name */
15
+ name: string;
16
+ /** Whether the email has been verified */
17
+ email_verified: boolean;
18
+ /** Optional given name (first name) */
19
+ given_name?: string;
20
+ /** Optional family name (last name) */
21
+ family_name?: string;
22
+ /** TimeBack student ID (if user has TimeBack integration) */
23
+ timeback_id?: string;
24
+ /** Additional user attributes from the identity provider */
25
+ [key: string]: unknown;
26
+ }
27
+ /**
28
+ * Minimal course configuration for TimeBack integration (used in user-facing config).
29
+ *
30
+ * NOTE: Per-course overrides (title, courseCode, level, metadata) are defined
31
+ * in @playcademy/sdk/server as TimebackCourseConfigWithOverrides.
32
+ * This base type only includes the minimal required fields.
33
+ *
34
+ * For totalXp, use metadata.metrics.totalXp (aligns with upstream TimeBack structure).
35
+ */
36
+ type TimebackCourseConfig = {
37
+ subject: string;
38
+ grade: number;
39
+ };
40
+ type EndActivityResponse = {
41
+ status: 'ok';
42
+ courseId: string;
43
+ xpAwarded: number;
44
+ masteredUnits?: number;
45
+ pctCompleteApp?: number;
46
+ scoreStatus?: string;
47
+ inProgress?: string;
48
+ };
5
49
 
6
50
  /**
7
51
  * @fileoverview Server SDK Type Definitions
@@ -11,20 +55,50 @@ export { ActivityData, ComponentConfig, ComponentResourceConfig, CourseConfig, E
11
55
  */
12
56
 
13
57
  /**
14
- * TimeBack integration configuration for Playcademy config file
58
+ * Base configuration for TimeBack integration (shared across all courses).
59
+ * References upstream TimeBack types from @playcademy/timeback.
60
+ *
61
+ * All fields are optional and support template variables: {grade}, {subject}, {gameSlug}
15
62
  */
16
- interface TimebackIntegrationConfig {
17
- /** Organization overrides */
63
+ interface TimebackBaseConfig {
64
+ /** Organization configuration (shared across all courses) */
18
65
  organization?: Partial<OrganizationConfig>;
19
- /** Course configuration (subjects and grades REQUIRED) */
20
- course: CourseConfig;
21
- /** Component overrides */
66
+ /** Course defaults (can be overridden per-course) */
67
+ course?: Partial<CourseConfig>;
68
+ /** Component defaults */
22
69
  component?: Partial<ComponentConfig>;
23
- /** Resource overrides */
70
+ /** Resource defaults */
24
71
  resource?: Partial<ResourceConfig>;
25
- /** Component-Resource link overrides */
72
+ /** ComponentResource defaults */
26
73
  componentResource?: Partial<ComponentResourceConfig>;
27
74
  }
75
+ /**
76
+ * Extended course configuration that merges TimebackCourseConfig with per-course overrides.
77
+ * Used in playcademy.config.* to allow per-course customization.
78
+ */
79
+ interface TimebackCourseConfigWithOverrides extends TimebackCourseConfig {
80
+ title?: string;
81
+ courseCode?: string;
82
+ level?: string;
83
+ metadata?: CourseConfig['metadata'];
84
+ totalXp?: number | null;
85
+ masterableUnits?: number | null;
86
+ }
87
+ /**
88
+ * TimeBack integration configuration for Playcademy config file.
89
+ *
90
+ * Supports two levels of customization:
91
+ * 1. `base`: Shared defaults for all courses (organization, course, component, resource, componentResource)
92
+ * 2. Per-course overrides in the `courses` array (title, courseCode, level, gradingScheme, metadata)
93
+ *
94
+ * Template variables ({grade}, {subject}, {gameSlug}) can be used in string fields.
95
+ */
96
+ interface TimebackIntegrationConfig {
97
+ /** Multi-grade course configuration (array of grade/subject/totalXp with optional per-course overrides) */
98
+ courses: TimebackCourseConfigWithOverrides[];
99
+ /** Optional base configuration (shared across all courses, can be overridden per-course) */
100
+ base?: TimebackBaseConfig;
101
+ }
28
102
  /**
29
103
  * Custom API routes integration
30
104
  */
@@ -45,7 +119,7 @@ interface DatabaseIntegration {
45
119
  */
46
120
  interface IntegrationsConfig {
47
121
  /** TimeBack integration (optional) */
48
- timeback?: TimebackIntegrationConfig;
122
+ timeback?: TimebackIntegrationConfig | null;
49
123
  /** Custom API routes (optional) */
50
124
  customRoutes?: CustomRoutesIntegration | boolean;
51
125
  /** Database (optional) */
@@ -179,33 +253,6 @@ interface BackendDeploymentBundle {
179
253
  secrets?: Record<string, string>;
180
254
  }
181
255
 
182
- /**
183
- * Basic user information in the shape of the claims from identity providers
184
- */
185
- interface UserInfo {
186
- /** Unique user identifier (sub claim from JWT) */
187
- sub: string;
188
- /** User's email address */
189
- email: string;
190
- /** User's display name */
191
- name: string;
192
- /** Whether the email has been verified */
193
- email_verified: boolean;
194
- /** Optional given name (first name) */
195
- given_name?: string;
196
- /** Optional family name (last name) */
197
- family_name?: string;
198
- /** TimeBack student ID (if user has TimeBack integration) */
199
- timeback_id?: string;
200
- /** Additional user attributes from the identity provider */
201
- [key: string]: unknown;
202
- }
203
- type EndActivityResponse = {
204
- status: 'ok';
205
- courseId: string;
206
- xpAwarded: number;
207
- };
208
-
209
256
  /**
210
257
  * Server-side Playcademy client for recording student activity to TimeBack.
211
258
  *
@@ -310,7 +357,6 @@ declare class PlaycademyClient {
310
357
  get config(): PlaycademyServerClientState['config'];
311
358
  /** TimeBack integration methods (endActivity) */
312
359
  timeback: {
313
- readonly courseId: string | undefined;
314
360
  endActivity: (studentId: string, payload: _playcademy_timeback_types.EndActivityPayload) => Promise<EndActivityResponse>;
315
361
  };
316
362
  }
@@ -373,4 +419,4 @@ declare function verifyGameToken(gameToken: string, options?: {
373
419
  }>;
374
420
 
375
421
  export { PlaycademyClient, verifyGameToken };
376
- export type { BackendDeploymentBundle, BackendResourceBindings, IntegrationsConfig, PlaycademyConfig, PlaycademyServerClientConfig, PlaycademyServerClientState, TimebackIntegrationConfig, UserInfo };
422
+ export type { BackendDeploymentBundle, BackendResourceBindings, IntegrationsConfig, PlaycademyConfig, PlaycademyServerClientConfig, PlaycademyServerClientState, TimebackBaseConfig, TimebackCourseConfigWithOverrides, TimebackIntegrationConfig, UserInfo };
package/dist/server.js CHANGED
@@ -1,46 +1,19 @@
1
- var __defProp = Object.defineProperty;
2
- var __export = (target, all) => {
3
- for (var name in all)
4
- __defProp(target, name, {
5
- get: all[name],
6
- enumerable: true,
7
- configurable: true,
8
- set: (newValue) => all[name] = () => newValue
9
- });
10
- };
11
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
-
13
1
  // src/server/namespaces/timeback.ts
14
2
  function createTimebackNamespace(client) {
15
- let courseId;
16
- async function ensureCourseId() {
17
- if (courseId)
18
- return courseId;
19
- try {
20
- const integration = await client["request"](`/api/timeback/integrations/${client.gameId}`, "GET");
21
- if (!integration || !integration.courseId) {
22
- throw new Error("No TimeBack integration found for this game. Please run TimeBack setup first.");
23
- }
24
- courseId = integration.courseId;
25
- return courseId;
26
- } catch (error) {
27
- throw new Error(`Failed to fetch courseId: ${error instanceof Error ? error.message : String(error)}`);
28
- }
29
- }
30
3
  function enrichActivityData(data) {
31
4
  return {
32
5
  ...data,
33
- subject: data.subject || client.config.integrations?.timeback?.course.subjects?.[0],
34
- appName: data.appName || client.config.name,
35
- courseName: data.courseName || client.config.integrations?.timeback?.course.title
6
+ appName: data.appName || client.config.name
36
7
  };
37
8
  }
38
9
  return {
39
- get courseId() {
40
- return courseId;
41
- },
42
10
  endActivity: async (studentId, payload) => {
43
- await ensureCourseId();
11
+ if (!payload.activityData.grade) {
12
+ throw new Error("activityData.grade is required for TimeBack integration");
13
+ }
14
+ if (!payload.activityData.subject) {
15
+ throw new Error("activityData.subject is required for TimeBack integration");
16
+ }
44
17
  const enrichedActivityData = enrichActivityData(payload.activityData);
45
18
  return client["request"]("/api/timeback/end-activity", "POST", {
46
19
  gameId: client.gameId,
@@ -48,7 +21,8 @@ function createTimebackNamespace(client) {
48
21
  activityData: enrichedActivityData,
49
22
  scoreData: payload.scoreData,
50
23
  timingData: payload.timingData,
51
- xpEarned: payload.xpEarned
24
+ xpEarned: payload.xpEarned,
25
+ masteredUnits: payload.masteredUnits
52
26
  });
53
27
  }
54
28
  };