@playcademy/sdk 0.16.0 → 0.16.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +99 -21
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +108 -28
- package/dist/server/edge.d.ts +9 -0
- package/dist/server/edge.js +69 -4
- package/dist/server.d.ts +9 -0
- package/dist/server.js +69 -4
- package/dist/types.d.ts +7 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -116,6 +116,44 @@ await client.timeback.startActivity(
|
|
|
116
116
|
)
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
Hosted assessments use the same methods locally and when deployed:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const attempt = await client.timeback.assessments.start({
|
|
123
|
+
activityId: 'math-diagnostic',
|
|
124
|
+
purpose: 'diagnostic',
|
|
125
|
+
subject: 'Math',
|
|
126
|
+
grade: 5,
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const saved = await client.timeback.assessments.save(attempt.attemptId, {
|
|
130
|
+
expectedResponseVersion: attempt.responseVersion,
|
|
131
|
+
responses: {
|
|
132
|
+
[attempt.assessment.items[0].identifier]: { RESPONSE: 'A' },
|
|
133
|
+
},
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
const completed = await client.timeback.assessments.submit(attempt.attemptId, {
|
|
137
|
+
expectedResponseVersion: saved.responseVersion,
|
|
138
|
+
submissionId: crypto.randomUUID(),
|
|
139
|
+
})
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`start()` resumes an unfinished attempt or selects the next live test. Save payloads are
|
|
143
|
+
question deltas, but each included question replaces its complete response state; use `null` to
|
|
144
|
+
clear an answer. Keep the returned `responseVersion` and send it with the next mutation.
|
|
145
|
+
|
|
146
|
+
For local development, import the current ordered catalog before starting the dev host:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
playcademy timeback assessments import
|
|
150
|
+
playcademy dev
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The host reads `.playcademy/timeback/assessment-fixtures.json` and keeps local attempts in memory.
|
|
154
|
+
Restarting the dev host resets mutable attempt state. Deployed games use TimeBack automatically;
|
|
155
|
+
game code never selects the provider or reads fixture content.
|
|
156
|
+
|
|
119
157
|
### `client.backend`
|
|
120
158
|
|
|
121
159
|
HTTP client for game-specific backend functions deployed via `playcademy deploy`.
|
package/dist/index.d.ts
CHANGED
|
@@ -1037,6 +1037,13 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
|
|
|
1037
1037
|
* - `endActivity(scoreData)` - Submit activity results to TimeBack
|
|
1038
1038
|
*/
|
|
1039
1039
|
timeback: {
|
|
1040
|
+
assessments: {
|
|
1041
|
+
start: (input: _playcademy_types.StartAssessmentInput) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
|
|
1042
|
+
latest: (options: _playcademy_types.GetLatestAssessmentOptions) => Promise<_playcademy_types.LatestAssessmentResult | null>;
|
|
1043
|
+
get: (attemptId: string) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
|
|
1044
|
+
save: (attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
|
|
1045
|
+
submit: (attemptId: string, input: _playcademy_types.SubmitAssessmentInput) => Promise<_playcademy_types.AssessmentSubmitResult>;
|
|
1046
|
+
};
|
|
1040
1047
|
readonly user: TimebackUser;
|
|
1041
1048
|
readonly currentRunId: string | undefined;
|
|
1042
1049
|
startActivity: (metadata: _playcademy_types.ActivityData, options?: StartActivityOptions) => StartActivityResult;
|
package/dist/index.js
CHANGED
|
@@ -1118,25 +1118,12 @@ function createScoresNamespace(client) {
|
|
|
1118
1118
|
}
|
|
1119
1119
|
};
|
|
1120
1120
|
}
|
|
1121
|
-
// src/
|
|
1122
|
-
var
|
|
1123
|
-
|
|
1124
|
-
"
|
|
1125
|
-
"
|
|
1126
|
-
|
|
1127
|
-
"Social Studies",
|
|
1128
|
-
"Writing",
|
|
1129
|
-
"Science",
|
|
1130
|
-
"FastMath",
|
|
1131
|
-
"Math",
|
|
1132
|
-
"None"
|
|
1133
|
-
];
|
|
1134
|
-
function isValidGrade(value) {
|
|
1135
|
-
return typeof value === "number" && Number.isInteger(value) && VALID_GRADES.includes(value);
|
|
1136
|
-
}
|
|
1137
|
-
function isValidSubject(value) {
|
|
1138
|
-
return typeof value === "string" && VALID_SUBJECTS.includes(value);
|
|
1139
|
-
}
|
|
1121
|
+
// ../constants/src/auth.ts
|
|
1122
|
+
var DEFAULT_PERSONAL_API_KEY_PERMISSIONS = {
|
|
1123
|
+
games: ["read", "write", "delete"],
|
|
1124
|
+
users: ["read:self", "write:self"],
|
|
1125
|
+
dev: ["read", "write"]
|
|
1126
|
+
};
|
|
1140
1127
|
// ../constants/src/platform.ts
|
|
1141
1128
|
var PLAYCADEMY_BROWSER_TIME_ZONE_HEADER = "x-playcademy-browser-time-zone";
|
|
1142
1129
|
// ../constants/src/timeback.ts
|
|
@@ -1147,8 +1134,22 @@ var TIMEBACK_ROUTES = {
|
|
|
1147
1134
|
GET_HIGHEST_GRADE_MASTERED: "/integrations/timeback/highest-grade-mastered",
|
|
1148
1135
|
HEARTBEAT: "/integrations/timeback/heartbeat",
|
|
1149
1136
|
ADVANCE_COURSE: "/integrations/timeback/advance-course",
|
|
1150
|
-
UNENROLL_COURSE: "/integrations/timeback/unenroll-course"
|
|
1137
|
+
UNENROLL_COURSE: "/integrations/timeback/unenroll-course",
|
|
1138
|
+
ASSESSMENTS: "/integrations/timeback/assessments"
|
|
1151
1139
|
};
|
|
1140
|
+
var TIMEBACK_GRADES = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
|
1141
|
+
var TIMEBACK_SUBJECTS = [
|
|
1142
|
+
"Reading",
|
|
1143
|
+
"Language",
|
|
1144
|
+
"Vocabulary",
|
|
1145
|
+
"Social Studies",
|
|
1146
|
+
"Writing",
|
|
1147
|
+
"Science",
|
|
1148
|
+
"FastMath",
|
|
1149
|
+
"Math",
|
|
1150
|
+
"None"
|
|
1151
|
+
];
|
|
1152
|
+
var ASSESSMENT_PURPOSES = ["end_of_course", "diagnostic"];
|
|
1152
1153
|
var TIMEBACK_GAME_METRIC_DECIMAL_PLACES = {
|
|
1153
1154
|
xp: 1,
|
|
1154
1155
|
mastery: 0,
|
|
@@ -1160,6 +1161,19 @@ var TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE = {
|
|
|
1160
1161
|
time: 60,
|
|
1161
1162
|
score: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.score
|
|
1162
1163
|
};
|
|
1164
|
+
// src/core/guards.ts
|
|
1165
|
+
var VALID_GRADES = TIMEBACK_GRADES;
|
|
1166
|
+
var VALID_SUBJECTS = TIMEBACK_SUBJECTS;
|
|
1167
|
+
function isValidGrade(value) {
|
|
1168
|
+
return typeof value === "number" && Number.isInteger(value) && VALID_GRADES.includes(value);
|
|
1169
|
+
}
|
|
1170
|
+
function isValidSubject(value) {
|
|
1171
|
+
return typeof value === "string" && VALID_SUBJECTS.includes(value);
|
|
1172
|
+
}
|
|
1173
|
+
function isAssessmentPurpose(value) {
|
|
1174
|
+
return typeof value === "string" && ASSESSMENT_PURPOSES.includes(value);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1163
1177
|
// src/core/cache/ttl-cache.ts
|
|
1164
1178
|
function createTTLCache(options) {
|
|
1165
1179
|
const cache = new Map;
|
|
@@ -2003,9 +2017,73 @@ function createTimebackEngine(client) {
|
|
|
2003
2017
|
// src/namespaces/game/timeback.ts
|
|
2004
2018
|
var VALID_XP_INCLUDE_OPTIONS = ["perCourse", "today"];
|
|
2005
2019
|
var VALID_MASTERY_INCLUDE_OPTIONS = ["perCourse"];
|
|
2020
|
+
var ASSESSMENTS_ROUTE = TIMEBACK_ROUTES.ASSESSMENTS;
|
|
2021
|
+
function validateAssessmentFilters(options) {
|
|
2022
|
+
if (!isAssessmentPurpose(options?.purpose)) {
|
|
2023
|
+
throw new Error("purpose must be end_of_course or diagnostic");
|
|
2024
|
+
}
|
|
2025
|
+
if (options.grade !== undefined && !isValidGrade(options.grade)) {
|
|
2026
|
+
throw new Error(`Invalid grade: ${options.grade}. Valid grades: ${VALID_GRADES.join(", ")}`);
|
|
2027
|
+
}
|
|
2028
|
+
if (options.subject !== undefined && !isValidSubject(options.subject)) {
|
|
2029
|
+
throw new Error(`Invalid subject: ${options.subject}. Valid subjects: ${VALID_SUBJECTS.join(", ")}`);
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2006
2032
|
function createTimebackNamespace(client) {
|
|
2007
2033
|
const engine = createTimebackEngine(client);
|
|
2008
2034
|
return {
|
|
2035
|
+
assessments: {
|
|
2036
|
+
start: async (input) => {
|
|
2037
|
+
assertPlatformMode(client, "timeback.assessments.start()");
|
|
2038
|
+
if (!input.activityId?.trim()) {
|
|
2039
|
+
throw new Error("activityId is required");
|
|
2040
|
+
}
|
|
2041
|
+
validateAssessmentFilters(input);
|
|
2042
|
+
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/start`, "POST", input);
|
|
2043
|
+
},
|
|
2044
|
+
latest: async (options) => {
|
|
2045
|
+
assertPlatformMode(client, "timeback.assessments.latest()");
|
|
2046
|
+
validateAssessmentFilters(options);
|
|
2047
|
+
const params = new URLSearchParams({ purpose: options.purpose });
|
|
2048
|
+
if (options.subject !== undefined) {
|
|
2049
|
+
params.set("subject", options.subject);
|
|
2050
|
+
}
|
|
2051
|
+
if (options.grade !== undefined) {
|
|
2052
|
+
params.set("grade", String(options.grade));
|
|
2053
|
+
}
|
|
2054
|
+
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/latest?${params.toString()}`, "GET");
|
|
2055
|
+
},
|
|
2056
|
+
get: async (attemptId) => {
|
|
2057
|
+
assertPlatformMode(client, "timeback.assessments.get()");
|
|
2058
|
+
if (!attemptId?.trim()) {
|
|
2059
|
+
throw new Error("attemptId is required");
|
|
2060
|
+
}
|
|
2061
|
+
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}`, "GET");
|
|
2062
|
+
},
|
|
2063
|
+
save: async (attemptId, input) => {
|
|
2064
|
+
assertPlatformMode(client, "timeback.assessments.save()");
|
|
2065
|
+
if (!attemptId?.trim()) {
|
|
2066
|
+
throw new Error("attemptId is required");
|
|
2067
|
+
}
|
|
2068
|
+
if (!Number.isInteger(input.expectedResponseVersion) || input.expectedResponseVersion < 0) {
|
|
2069
|
+
throw new Error("expectedResponseVersion must be a non-negative integer");
|
|
2070
|
+
}
|
|
2071
|
+
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/save`, "POST", input);
|
|
2072
|
+
},
|
|
2073
|
+
submit: async (attemptId, input) => {
|
|
2074
|
+
assertPlatformMode(client, "timeback.assessments.submit()");
|
|
2075
|
+
if (!attemptId?.trim()) {
|
|
2076
|
+
throw new Error("attemptId is required");
|
|
2077
|
+
}
|
|
2078
|
+
if (!Number.isInteger(input.expectedResponseVersion) || input.expectedResponseVersion < 0) {
|
|
2079
|
+
throw new Error("expectedResponseVersion must be a non-negative integer");
|
|
2080
|
+
}
|
|
2081
|
+
if (!input.submissionId?.trim()) {
|
|
2082
|
+
throw new Error("submissionId is required");
|
|
2083
|
+
}
|
|
2084
|
+
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/submit`, "POST", input);
|
|
2085
|
+
}
|
|
2086
|
+
},
|
|
2009
2087
|
get user() {
|
|
2010
2088
|
assertPlatformMode(client, "timeback.user");
|
|
2011
2089
|
return {
|
|
@@ -2391,7 +2469,7 @@ async function request({
|
|
|
2391
2469
|
return rawText && rawText.length > 0 ? rawText : undefined;
|
|
2392
2470
|
}
|
|
2393
2471
|
// src/version.ts
|
|
2394
|
-
var SDK_VERSION = "0.16.
|
|
2472
|
+
var SDK_VERSION = "0.16.1-beta.2";
|
|
2395
2473
|
|
|
2396
2474
|
// src/clients/base.ts
|
|
2397
2475
|
class PlaycademyBaseClient {
|
package/dist/internal.d.ts
CHANGED
|
@@ -3483,6 +3483,7 @@ declare class PlaycademyInternalClient extends PlaycademyBaseClient {
|
|
|
3483
3483
|
reactivateCourse: (gameId: string, courseId: string) => Promise<_playcademy_types.GameTimebackIntegration>;
|
|
3484
3484
|
getIntegrationConfig: (gameId: string, courseId: string) => Promise<_playcademy_types.GameTimebackIntegrationConfig>;
|
|
3485
3485
|
getConfig: (gameId: string) => Promise<_playcademy_types.TimebackSetupRequest['config']>;
|
|
3486
|
+
exportAssessmentFixtures: (gameId: string) => Promise<_playcademy_types.AssessmentRuntimeFixtureBundle>;
|
|
3486
3487
|
};
|
|
3487
3488
|
students: {
|
|
3488
3489
|
get: (timebackId: string, options?: TTLCacheConfig) => Promise<PlatformTimebackUserContext>;
|
package/dist/internal.js
CHANGED
|
@@ -1118,25 +1118,12 @@ function createScoresNamespace(client) {
|
|
|
1118
1118
|
}
|
|
1119
1119
|
};
|
|
1120
1120
|
}
|
|
1121
|
-
// src/
|
|
1122
|
-
var
|
|
1123
|
-
|
|
1124
|
-
"
|
|
1125
|
-
"
|
|
1126
|
-
|
|
1127
|
-
"Social Studies",
|
|
1128
|
-
"Writing",
|
|
1129
|
-
"Science",
|
|
1130
|
-
"FastMath",
|
|
1131
|
-
"Math",
|
|
1132
|
-
"None"
|
|
1133
|
-
];
|
|
1134
|
-
function isValidGrade(value) {
|
|
1135
|
-
return typeof value === "number" && Number.isInteger(value) && VALID_GRADES.includes(value);
|
|
1136
|
-
}
|
|
1137
|
-
function isValidSubject(value) {
|
|
1138
|
-
return typeof value === "string" && VALID_SUBJECTS.includes(value);
|
|
1139
|
-
}
|
|
1121
|
+
// ../constants/src/auth.ts
|
|
1122
|
+
var DEFAULT_PERSONAL_API_KEY_PERMISSIONS = {
|
|
1123
|
+
games: ["read", "write", "delete"],
|
|
1124
|
+
users: ["read:self", "write:self"],
|
|
1125
|
+
dev: ["read", "write"]
|
|
1126
|
+
};
|
|
1140
1127
|
// ../constants/src/platform.ts
|
|
1141
1128
|
var PLAYCADEMY_BROWSER_TIME_ZONE_HEADER = "x-playcademy-browser-time-zone";
|
|
1142
1129
|
// ../constants/src/timeback.ts
|
|
@@ -1147,8 +1134,22 @@ var TIMEBACK_ROUTES = {
|
|
|
1147
1134
|
GET_HIGHEST_GRADE_MASTERED: "/integrations/timeback/highest-grade-mastered",
|
|
1148
1135
|
HEARTBEAT: "/integrations/timeback/heartbeat",
|
|
1149
1136
|
ADVANCE_COURSE: "/integrations/timeback/advance-course",
|
|
1150
|
-
UNENROLL_COURSE: "/integrations/timeback/unenroll-course"
|
|
1137
|
+
UNENROLL_COURSE: "/integrations/timeback/unenroll-course",
|
|
1138
|
+
ASSESSMENTS: "/integrations/timeback/assessments"
|
|
1151
1139
|
};
|
|
1140
|
+
var TIMEBACK_GRADES = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
|
1141
|
+
var TIMEBACK_SUBJECTS = [
|
|
1142
|
+
"Reading",
|
|
1143
|
+
"Language",
|
|
1144
|
+
"Vocabulary",
|
|
1145
|
+
"Social Studies",
|
|
1146
|
+
"Writing",
|
|
1147
|
+
"Science",
|
|
1148
|
+
"FastMath",
|
|
1149
|
+
"Math",
|
|
1150
|
+
"None"
|
|
1151
|
+
];
|
|
1152
|
+
var ASSESSMENT_PURPOSES = ["end_of_course", "diagnostic"];
|
|
1152
1153
|
var TIMEBACK_GAME_METRIC_DECIMAL_PLACES = {
|
|
1153
1154
|
xp: 1,
|
|
1154
1155
|
mastery: 0,
|
|
@@ -1160,6 +1161,19 @@ var TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE = {
|
|
|
1160
1161
|
time: 60,
|
|
1161
1162
|
score: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.score
|
|
1162
1163
|
};
|
|
1164
|
+
// src/core/guards.ts
|
|
1165
|
+
var VALID_GRADES = TIMEBACK_GRADES;
|
|
1166
|
+
var VALID_SUBJECTS = TIMEBACK_SUBJECTS;
|
|
1167
|
+
function isValidGrade(value) {
|
|
1168
|
+
return typeof value === "number" && Number.isInteger(value) && VALID_GRADES.includes(value);
|
|
1169
|
+
}
|
|
1170
|
+
function isValidSubject(value) {
|
|
1171
|
+
return typeof value === "string" && VALID_SUBJECTS.includes(value);
|
|
1172
|
+
}
|
|
1173
|
+
function isAssessmentPurpose(value) {
|
|
1174
|
+
return typeof value === "string" && ASSESSMENT_PURPOSES.includes(value);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1163
1177
|
// src/core/cache/ttl-cache.ts
|
|
1164
1178
|
function createTTLCache(options) {
|
|
1165
1179
|
const cache = new Map;
|
|
@@ -2003,9 +2017,73 @@ function createTimebackEngine(client) {
|
|
|
2003
2017
|
// src/namespaces/game/timeback.ts
|
|
2004
2018
|
var VALID_XP_INCLUDE_OPTIONS = ["perCourse", "today"];
|
|
2005
2019
|
var VALID_MASTERY_INCLUDE_OPTIONS = ["perCourse"];
|
|
2020
|
+
var ASSESSMENTS_ROUTE = TIMEBACK_ROUTES.ASSESSMENTS;
|
|
2021
|
+
function validateAssessmentFilters(options) {
|
|
2022
|
+
if (!isAssessmentPurpose(options?.purpose)) {
|
|
2023
|
+
throw new Error("purpose must be end_of_course or diagnostic");
|
|
2024
|
+
}
|
|
2025
|
+
if (options.grade !== undefined && !isValidGrade(options.grade)) {
|
|
2026
|
+
throw new Error(`Invalid grade: ${options.grade}. Valid grades: ${VALID_GRADES.join(", ")}`);
|
|
2027
|
+
}
|
|
2028
|
+
if (options.subject !== undefined && !isValidSubject(options.subject)) {
|
|
2029
|
+
throw new Error(`Invalid subject: ${options.subject}. Valid subjects: ${VALID_SUBJECTS.join(", ")}`);
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2006
2032
|
function createTimebackNamespace(client) {
|
|
2007
2033
|
const engine = createTimebackEngine(client);
|
|
2008
2034
|
return {
|
|
2035
|
+
assessments: {
|
|
2036
|
+
start: async (input) => {
|
|
2037
|
+
assertPlatformMode(client, "timeback.assessments.start()");
|
|
2038
|
+
if (!input.activityId?.trim()) {
|
|
2039
|
+
throw new Error("activityId is required");
|
|
2040
|
+
}
|
|
2041
|
+
validateAssessmentFilters(input);
|
|
2042
|
+
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/start`, "POST", input);
|
|
2043
|
+
},
|
|
2044
|
+
latest: async (options) => {
|
|
2045
|
+
assertPlatformMode(client, "timeback.assessments.latest()");
|
|
2046
|
+
validateAssessmentFilters(options);
|
|
2047
|
+
const params = new URLSearchParams({ purpose: options.purpose });
|
|
2048
|
+
if (options.subject !== undefined) {
|
|
2049
|
+
params.set("subject", options.subject);
|
|
2050
|
+
}
|
|
2051
|
+
if (options.grade !== undefined) {
|
|
2052
|
+
params.set("grade", String(options.grade));
|
|
2053
|
+
}
|
|
2054
|
+
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/latest?${params.toString()}`, "GET");
|
|
2055
|
+
},
|
|
2056
|
+
get: async (attemptId) => {
|
|
2057
|
+
assertPlatformMode(client, "timeback.assessments.get()");
|
|
2058
|
+
if (!attemptId?.trim()) {
|
|
2059
|
+
throw new Error("attemptId is required");
|
|
2060
|
+
}
|
|
2061
|
+
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}`, "GET");
|
|
2062
|
+
},
|
|
2063
|
+
save: async (attemptId, input) => {
|
|
2064
|
+
assertPlatformMode(client, "timeback.assessments.save()");
|
|
2065
|
+
if (!attemptId?.trim()) {
|
|
2066
|
+
throw new Error("attemptId is required");
|
|
2067
|
+
}
|
|
2068
|
+
if (!Number.isInteger(input.expectedResponseVersion) || input.expectedResponseVersion < 0) {
|
|
2069
|
+
throw new Error("expectedResponseVersion must be a non-negative integer");
|
|
2070
|
+
}
|
|
2071
|
+
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/save`, "POST", input);
|
|
2072
|
+
},
|
|
2073
|
+
submit: async (attemptId, input) => {
|
|
2074
|
+
assertPlatformMode(client, "timeback.assessments.submit()");
|
|
2075
|
+
if (!attemptId?.trim()) {
|
|
2076
|
+
throw new Error("attemptId is required");
|
|
2077
|
+
}
|
|
2078
|
+
if (!Number.isInteger(input.expectedResponseVersion) || input.expectedResponseVersion < 0) {
|
|
2079
|
+
throw new Error("expectedResponseVersion must be a non-negative integer");
|
|
2080
|
+
}
|
|
2081
|
+
if (!input.submissionId?.trim()) {
|
|
2082
|
+
throw new Error("submissionId is required");
|
|
2083
|
+
}
|
|
2084
|
+
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/submit`, "POST", input);
|
|
2085
|
+
}
|
|
2086
|
+
},
|
|
2009
2087
|
get user() {
|
|
2010
2088
|
assertPlatformMode(client, "timeback.user");
|
|
2011
2089
|
return {
|
|
@@ -2146,6 +2224,11 @@ function createAdminNamespace(client) {
|
|
|
2146
2224
|
}
|
|
2147
2225
|
};
|
|
2148
2226
|
}
|
|
2227
|
+
// ../utils/src/error.ts
|
|
2228
|
+
function errorMessage(err) {
|
|
2229
|
+
return err instanceof Error ? err.message : String(err);
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2149
2232
|
// src/namespaces/platform/auth.ts
|
|
2150
2233
|
function createAuthNamespace(client) {
|
|
2151
2234
|
return {
|
|
@@ -2162,7 +2245,7 @@ function createAuthNamespace(client) {
|
|
|
2162
2245
|
} catch (error) {
|
|
2163
2246
|
return {
|
|
2164
2247
|
success: false,
|
|
2165
|
-
error: error
|
|
2248
|
+
error: errorMessage(error)
|
|
2166
2249
|
};
|
|
2167
2250
|
}
|
|
2168
2251
|
},
|
|
@@ -2177,11 +2260,7 @@ function createAuthNamespace(client) {
|
|
|
2177
2260
|
body: {
|
|
2178
2261
|
name: options?.name || `SDK Key - ${new Date().toISOString()}`,
|
|
2179
2262
|
expiresIn: options?.expiresIn !== undefined ? options.expiresIn : null,
|
|
2180
|
-
permissions: options?.permissions ||
|
|
2181
|
-
games: ["read", "write", "delete"],
|
|
2182
|
-
users: ["read:self", "write:self"],
|
|
2183
|
-
dev: ["read", "write"]
|
|
2184
|
-
}
|
|
2263
|
+
permissions: options?.permissions || DEFAULT_PERSONAL_API_KEY_PERMISSIONS
|
|
2185
2264
|
}
|
|
2186
2265
|
}),
|
|
2187
2266
|
list: async () => client["request"]("/auth/api-key/list", "GET"),
|
|
@@ -2914,7 +2993,8 @@ function createTimebackNamespace2(client) {
|
|
|
2914
2993
|
deactivateCourse: (gameId, courseId) => client["request"](`/timeback/integrations/${gameId}/${courseId}`, "DELETE"),
|
|
2915
2994
|
reactivateCourse: (gameId, courseId) => client["request"](`/timeback/integrations/${gameId}/${courseId}/reactivate`, "POST"),
|
|
2916
2995
|
getIntegrationConfig: (gameId, courseId) => client["request"](`/timeback/integrations/${gameId}/${courseId}`, "GET"),
|
|
2917
|
-
getConfig: (gameId) => client["request"](`/timeback/config/${gameId}`, "GET")
|
|
2996
|
+
getConfig: (gameId) => client["request"](`/timeback/config/${gameId}`, "GET"),
|
|
2997
|
+
exportAssessmentFixtures: (gameId) => client["request"](`/timeback/assessments/fixtures/${gameId}`, "GET")
|
|
2918
2998
|
},
|
|
2919
2999
|
students: {
|
|
2920
3000
|
get: async (timebackId, options) => studentCache.get(timebackId, async () => client["request"](`/timeback/user/${timebackId}`, "GET"), options),
|
|
@@ -3239,7 +3319,7 @@ async function request({
|
|
|
3239
3319
|
return rawText && rawText.length > 0 ? rawText : undefined;
|
|
3240
3320
|
}
|
|
3241
3321
|
// src/version.ts
|
|
3242
|
-
var SDK_VERSION = "0.16.
|
|
3322
|
+
var SDK_VERSION = "0.16.1-beta.2";
|
|
3243
3323
|
|
|
3244
3324
|
// src/clients/base.ts
|
|
3245
3325
|
class PlaycademyBaseClient {
|
package/dist/server/edge.d.ts
CHANGED
|
@@ -346,6 +346,15 @@ declare class PlaycademyClient {
|
|
|
346
346
|
get config(): PlaycademyServerClientState['config'];
|
|
347
347
|
/** TimeBack integration methods (endActivity) */
|
|
348
348
|
timeback: {
|
|
349
|
+
assessments: {
|
|
350
|
+
start: (studentId: string, input: _playcademy_types.StartAssessmentInput) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
|
|
351
|
+
latest: (studentId: string, options: _playcademy_types.GetLatestAssessmentOptions) => Promise<_playcademy_types.LatestAssessmentResult | null>;
|
|
352
|
+
get: (studentId: string, attemptId: string) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
|
|
353
|
+
save: (studentId: string, attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
|
|
354
|
+
submit: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentInput, context: {
|
|
355
|
+
sensorUrl: string;
|
|
356
|
+
}) => Promise<_playcademy_types.AssessmentSubmitResult>;
|
|
357
|
+
};
|
|
349
358
|
endActivity: (studentId: string, payload: _playcademy_types.EndActivityPayload) => Promise<_playcademy_types.EndActivityResponse>;
|
|
350
359
|
getStudentXp: (studentId: string, options?: {
|
|
351
360
|
grade?: number;
|
package/dist/server/edge.js
CHANGED
|
@@ -10,9 +10,27 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
12
|
|
|
13
|
-
// src/
|
|
14
|
-
var
|
|
15
|
-
|
|
13
|
+
// ../constants/src/auth.ts
|
|
14
|
+
var DEFAULT_PERSONAL_API_KEY_PERMISSIONS = {
|
|
15
|
+
games: ["read", "write", "delete"],
|
|
16
|
+
users: ["read:self", "write:self"],
|
|
17
|
+
dev: ["read", "write"]
|
|
18
|
+
};
|
|
19
|
+
// ../constants/src/platform.ts
|
|
20
|
+
var PLAYCADEMY_BROWSER_TIME_ZONE_HEADER = "x-playcademy-browser-time-zone";
|
|
21
|
+
// ../constants/src/timeback.ts
|
|
22
|
+
var TIMEBACK_ROUTES = {
|
|
23
|
+
END_ACTIVITY: "/integrations/timeback/end-activity",
|
|
24
|
+
GET_XP: "/integrations/timeback/xp",
|
|
25
|
+
GET_MASTERY: "/integrations/timeback/mastery",
|
|
26
|
+
GET_HIGHEST_GRADE_MASTERED: "/integrations/timeback/highest-grade-mastered",
|
|
27
|
+
HEARTBEAT: "/integrations/timeback/heartbeat",
|
|
28
|
+
ADVANCE_COURSE: "/integrations/timeback/advance-course",
|
|
29
|
+
UNENROLL_COURSE: "/integrations/timeback/unenroll-course",
|
|
30
|
+
ASSESSMENTS: "/integrations/timeback/assessments"
|
|
31
|
+
};
|
|
32
|
+
var TIMEBACK_GRADES = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
|
33
|
+
var TIMEBACK_SUBJECTS = [
|
|
16
34
|
"Reading",
|
|
17
35
|
"Language",
|
|
18
36
|
"Vocabulary",
|
|
@@ -23,12 +41,30 @@ var VALID_SUBJECTS = [
|
|
|
23
41
|
"Math",
|
|
24
42
|
"None"
|
|
25
43
|
];
|
|
44
|
+
var ASSESSMENT_PURPOSES = ["end_of_course", "diagnostic"];
|
|
45
|
+
var TIMEBACK_GAME_METRIC_DECIMAL_PLACES = {
|
|
46
|
+
xp: 1,
|
|
47
|
+
mastery: 0,
|
|
48
|
+
score: 2
|
|
49
|
+
};
|
|
50
|
+
var TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE = {
|
|
51
|
+
xp: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.xp,
|
|
52
|
+
mastery: 0,
|
|
53
|
+
time: 60,
|
|
54
|
+
score: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.score
|
|
55
|
+
};
|
|
56
|
+
// src/core/guards.ts
|
|
57
|
+
var VALID_GRADES = TIMEBACK_GRADES;
|
|
58
|
+
var VALID_SUBJECTS = TIMEBACK_SUBJECTS;
|
|
26
59
|
function isValidGrade(value) {
|
|
27
60
|
return typeof value === "number" && Number.isInteger(value) && VALID_GRADES.includes(value);
|
|
28
61
|
}
|
|
29
62
|
function isValidSubject(value) {
|
|
30
63
|
return typeof value === "string" && VALID_SUBJECTS.includes(value);
|
|
31
64
|
}
|
|
65
|
+
function isAssessmentPurpose(value) {
|
|
66
|
+
return typeof value === "string" && ASSESSMENT_PURPOSES.includes(value);
|
|
67
|
+
}
|
|
32
68
|
// src/server/namespaces/timeback.ts
|
|
33
69
|
function createTimebackNamespace(client) {
|
|
34
70
|
function enrichActivityData(data) {
|
|
@@ -38,6 +74,35 @@ function createTimebackNamespace(client) {
|
|
|
38
74
|
};
|
|
39
75
|
}
|
|
40
76
|
return {
|
|
77
|
+
assessments: {
|
|
78
|
+
start: (studentId, input) => client["request"]("/api/timeback/assessments/start", "POST", { ...input, gameId: client.gameId, studentId }),
|
|
79
|
+
latest: (studentId, options) => {
|
|
80
|
+
const params = new URLSearchParams({
|
|
81
|
+
gameId: client.gameId,
|
|
82
|
+
studentId,
|
|
83
|
+
purpose: options.purpose
|
|
84
|
+
});
|
|
85
|
+
if (options.subject !== undefined) {
|
|
86
|
+
params.set("subject", options.subject);
|
|
87
|
+
}
|
|
88
|
+
if (options.grade !== undefined) {
|
|
89
|
+
params.set("grade", String(options.grade));
|
|
90
|
+
}
|
|
91
|
+
return client["request"](`/api/timeback/assessments/latest?${params.toString()}`, "GET");
|
|
92
|
+
},
|
|
93
|
+
get: (studentId, attemptId) => {
|
|
94
|
+
const params = new URLSearchParams({ gameId: client.gameId, studentId });
|
|
95
|
+
return client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}?${params.toString()}`, "GET");
|
|
96
|
+
},
|
|
97
|
+
save: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/save`, "POST", { ...input, gameId: client.gameId, studentId }),
|
|
98
|
+
submit: (studentId, attemptId, input, context) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit`, "POST", {
|
|
99
|
+
...input,
|
|
100
|
+
gameId: client.gameId,
|
|
101
|
+
studentId,
|
|
102
|
+
appName: client.config.name,
|
|
103
|
+
sensorUrl: context.sensorUrl
|
|
104
|
+
})
|
|
105
|
+
},
|
|
41
106
|
endActivity: async (studentId, payload) => {
|
|
42
107
|
if (!isValidGrade(payload.activityData.grade)) {
|
|
43
108
|
throw new Error("activityData.grade must be a valid grade level (-1 to 13)");
|
|
@@ -234,7 +299,7 @@ function extractApiErrorInfo(error) {
|
|
|
234
299
|
}
|
|
235
300
|
|
|
236
301
|
// src/version.ts
|
|
237
|
-
var SDK_VERSION = "0.16.
|
|
302
|
+
var SDK_VERSION = "0.16.1-beta.2";
|
|
238
303
|
|
|
239
304
|
// src/server/request.ts
|
|
240
305
|
async function makeApiRequest(opts) {
|
package/dist/server.d.ts
CHANGED
|
@@ -346,6 +346,15 @@ declare class PlaycademyClient$1 {
|
|
|
346
346
|
get config(): PlaycademyServerClientState['config'];
|
|
347
347
|
/** TimeBack integration methods (endActivity) */
|
|
348
348
|
timeback: {
|
|
349
|
+
assessments: {
|
|
350
|
+
start: (studentId: string, input: _playcademy_types.StartAssessmentInput) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
|
|
351
|
+
latest: (studentId: string, options: _playcademy_types.GetLatestAssessmentOptions) => Promise<_playcademy_types.LatestAssessmentResult | null>;
|
|
352
|
+
get: (studentId: string, attemptId: string) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
|
|
353
|
+
save: (studentId: string, attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
|
|
354
|
+
submit: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentInput, context: {
|
|
355
|
+
sensorUrl: string;
|
|
356
|
+
}) => Promise<_playcademy_types.AssessmentSubmitResult>;
|
|
357
|
+
};
|
|
349
358
|
endActivity: (studentId: string, payload: _playcademy_types.EndActivityPayload) => Promise<_playcademy_types.EndActivityResponse>;
|
|
350
359
|
getStudentXp: (studentId: string, options?: {
|
|
351
360
|
grade?: number;
|
package/dist/server.js
CHANGED
|
@@ -199,9 +199,27 @@ var init_config_loader = __esm(() => {
|
|
|
199
199
|
init_file_loader();
|
|
200
200
|
});
|
|
201
201
|
|
|
202
|
-
// src/
|
|
203
|
-
var
|
|
204
|
-
|
|
202
|
+
// ../constants/src/auth.ts
|
|
203
|
+
var DEFAULT_PERSONAL_API_KEY_PERMISSIONS = {
|
|
204
|
+
games: ["read", "write", "delete"],
|
|
205
|
+
users: ["read:self", "write:self"],
|
|
206
|
+
dev: ["read", "write"]
|
|
207
|
+
};
|
|
208
|
+
// ../constants/src/platform.ts
|
|
209
|
+
var PLAYCADEMY_BROWSER_TIME_ZONE_HEADER = "x-playcademy-browser-time-zone";
|
|
210
|
+
// ../constants/src/timeback.ts
|
|
211
|
+
var TIMEBACK_ROUTES = {
|
|
212
|
+
END_ACTIVITY: "/integrations/timeback/end-activity",
|
|
213
|
+
GET_XP: "/integrations/timeback/xp",
|
|
214
|
+
GET_MASTERY: "/integrations/timeback/mastery",
|
|
215
|
+
GET_HIGHEST_GRADE_MASTERED: "/integrations/timeback/highest-grade-mastered",
|
|
216
|
+
HEARTBEAT: "/integrations/timeback/heartbeat",
|
|
217
|
+
ADVANCE_COURSE: "/integrations/timeback/advance-course",
|
|
218
|
+
UNENROLL_COURSE: "/integrations/timeback/unenroll-course",
|
|
219
|
+
ASSESSMENTS: "/integrations/timeback/assessments"
|
|
220
|
+
};
|
|
221
|
+
var TIMEBACK_GRADES = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
|
|
222
|
+
var TIMEBACK_SUBJECTS = [
|
|
205
223
|
"Reading",
|
|
206
224
|
"Language",
|
|
207
225
|
"Vocabulary",
|
|
@@ -212,12 +230,30 @@ var VALID_SUBJECTS = [
|
|
|
212
230
|
"Math",
|
|
213
231
|
"None"
|
|
214
232
|
];
|
|
233
|
+
var ASSESSMENT_PURPOSES = ["end_of_course", "diagnostic"];
|
|
234
|
+
var TIMEBACK_GAME_METRIC_DECIMAL_PLACES = {
|
|
235
|
+
xp: 1,
|
|
236
|
+
mastery: 0,
|
|
237
|
+
score: 2
|
|
238
|
+
};
|
|
239
|
+
var TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE = {
|
|
240
|
+
xp: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.xp,
|
|
241
|
+
mastery: 0,
|
|
242
|
+
time: 60,
|
|
243
|
+
score: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.score
|
|
244
|
+
};
|
|
245
|
+
// src/core/guards.ts
|
|
246
|
+
var VALID_GRADES = TIMEBACK_GRADES;
|
|
247
|
+
var VALID_SUBJECTS = TIMEBACK_SUBJECTS;
|
|
215
248
|
function isValidGrade(value) {
|
|
216
249
|
return typeof value === "number" && Number.isInteger(value) && VALID_GRADES.includes(value);
|
|
217
250
|
}
|
|
218
251
|
function isValidSubject(value) {
|
|
219
252
|
return typeof value === "string" && VALID_SUBJECTS.includes(value);
|
|
220
253
|
}
|
|
254
|
+
function isAssessmentPurpose(value) {
|
|
255
|
+
return typeof value === "string" && ASSESSMENT_PURPOSES.includes(value);
|
|
256
|
+
}
|
|
221
257
|
// src/server/namespaces/timeback.ts
|
|
222
258
|
function createTimebackNamespace(client) {
|
|
223
259
|
function enrichActivityData(data) {
|
|
@@ -227,6 +263,35 @@ function createTimebackNamespace(client) {
|
|
|
227
263
|
};
|
|
228
264
|
}
|
|
229
265
|
return {
|
|
266
|
+
assessments: {
|
|
267
|
+
start: (studentId, input) => client["request"]("/api/timeback/assessments/start", "POST", { ...input, gameId: client.gameId, studentId }),
|
|
268
|
+
latest: (studentId, options) => {
|
|
269
|
+
const params = new URLSearchParams({
|
|
270
|
+
gameId: client.gameId,
|
|
271
|
+
studentId,
|
|
272
|
+
purpose: options.purpose
|
|
273
|
+
});
|
|
274
|
+
if (options.subject !== undefined) {
|
|
275
|
+
params.set("subject", options.subject);
|
|
276
|
+
}
|
|
277
|
+
if (options.grade !== undefined) {
|
|
278
|
+
params.set("grade", String(options.grade));
|
|
279
|
+
}
|
|
280
|
+
return client["request"](`/api/timeback/assessments/latest?${params.toString()}`, "GET");
|
|
281
|
+
},
|
|
282
|
+
get: (studentId, attemptId) => {
|
|
283
|
+
const params = new URLSearchParams({ gameId: client.gameId, studentId });
|
|
284
|
+
return client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}?${params.toString()}`, "GET");
|
|
285
|
+
},
|
|
286
|
+
save: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/save`, "POST", { ...input, gameId: client.gameId, studentId }),
|
|
287
|
+
submit: (studentId, attemptId, input, context) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit`, "POST", {
|
|
288
|
+
...input,
|
|
289
|
+
gameId: client.gameId,
|
|
290
|
+
studentId,
|
|
291
|
+
appName: client.config.name,
|
|
292
|
+
sensorUrl: context.sensorUrl
|
|
293
|
+
})
|
|
294
|
+
},
|
|
230
295
|
endActivity: async (studentId, payload) => {
|
|
231
296
|
if (!isValidGrade(payload.activityData.grade)) {
|
|
232
297
|
throw new Error("activityData.grade must be a valid grade level (-1 to 13)");
|
|
@@ -423,7 +488,7 @@ function extractApiErrorInfo(error) {
|
|
|
423
488
|
}
|
|
424
489
|
|
|
425
490
|
// src/version.ts
|
|
426
|
-
var SDK_VERSION = "0.16.
|
|
491
|
+
var SDK_VERSION = "0.16.1-beta.2";
|
|
427
492
|
|
|
428
493
|
// src/server/request.ts
|
|
429
494
|
async function makeApiRequest(opts) {
|
package/dist/types.d.ts
CHANGED
|
@@ -1465,6 +1465,13 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
|
|
|
1465
1465
|
* - `endActivity(scoreData)` - Submit activity results to TimeBack
|
|
1466
1466
|
*/
|
|
1467
1467
|
timeback: {
|
|
1468
|
+
assessments: {
|
|
1469
|
+
start: (input: _playcademy_types.StartAssessmentInput) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
|
|
1470
|
+
latest: (options: _playcademy_types.GetLatestAssessmentOptions) => Promise<_playcademy_types.LatestAssessmentResult | null>;
|
|
1471
|
+
get: (attemptId: string) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
|
|
1472
|
+
save: (attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
|
|
1473
|
+
submit: (attemptId: string, input: _playcademy_types.SubmitAssessmentInput) => Promise<_playcademy_types.AssessmentSubmitResult>;
|
|
1474
|
+
};
|
|
1468
1475
|
readonly user: TimebackUser;
|
|
1469
1476
|
readonly currentRunId: string | undefined;
|
|
1470
1477
|
startActivity: (metadata: _playcademy_types.ActivityData, options?: StartActivityOptions) => StartActivityResult;
|