@playcademy/vite-plugin 0.2.30-beta.1 → 0.2.30-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/dist/index.js +95 -153
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25370,7 +25370,7 @@ var package_default;
|
|
|
25370
25370
|
var init_package = __esm(() => {
|
|
25371
25371
|
package_default = {
|
|
25372
25372
|
name: "@playcademy/sandbox",
|
|
25373
|
-
version: "0.3.17-beta.
|
|
25373
|
+
version: "0.3.17-beta.35",
|
|
25374
25374
|
description: "Local development server for Playcademy game development",
|
|
25375
25375
|
type: "module",
|
|
25376
25376
|
exports: {
|
|
@@ -54340,6 +54340,24 @@ function resolveAdminEventTime(data) {
|
|
|
54340
54340
|
}
|
|
54341
54341
|
return toAttributionEventTime(data.date);
|
|
54342
54342
|
}
|
|
54343
|
+
function validateMasteryAdjustment(delta, currentMastered, masterableUnits) {
|
|
54344
|
+
if (delta < 0 && currentMastered + delta < 0) {
|
|
54345
|
+
throw new ValidationError(`Adjustment would go below 0. Current: ${currentMastered}, adjustment: ${delta}`);
|
|
54346
|
+
}
|
|
54347
|
+
if (delta < 0 && typeof masterableUnits === "number" && masterableUnits > 0 && currentMastered > masterableUnits && currentMastered + delta > masterableUnits) {
|
|
54348
|
+
const minDelta = masterableUnits - currentMastered;
|
|
54349
|
+
throw new ValidationError(`Adjustment must reduce mastery to at most ${masterableUnits}. Current: ${currentMastered}/${masterableUnits}, minimum adjustment: ${minDelta}`);
|
|
54350
|
+
}
|
|
54351
|
+
if (delta > 0 && typeof masterableUnits === "number" && masterableUnits > 0) {
|
|
54352
|
+
if (currentMastered >= masterableUnits) {
|
|
54353
|
+
throw new ValidationError(`Mastery is already at maximum (${currentMastered}/${masterableUnits}). Only negative adjustments are allowed.`);
|
|
54354
|
+
}
|
|
54355
|
+
if (currentMastered + delta > masterableUnits) {
|
|
54356
|
+
const remaining = masterableUnits - currentMastered;
|
|
54357
|
+
throw new ValidationError(`Adjustment would exceed maximum. Current: ${currentMastered}/${masterableUnits}, max adjustment: +${remaining}`);
|
|
54358
|
+
}
|
|
54359
|
+
}
|
|
54360
|
+
}
|
|
54343
54361
|
function compareEnrollmentsByRecency(a, b) {
|
|
54344
54362
|
const dateCompare = (b.beginDate ?? "").localeCompare(a.beginDate ?? "");
|
|
54345
54363
|
if (dateCompare !== 0) {
|
|
@@ -54696,17 +54714,6 @@ class TimebackAdminService {
|
|
|
54696
54714
|
}
|
|
54697
54715
|
return this.deps.timeback;
|
|
54698
54716
|
}
|
|
54699
|
-
async recordCourseCompletionHistory(client, data) {
|
|
54700
|
-
await client.recordAdminCourseCompletionChange(data).catch((error) => {
|
|
54701
|
-
logger16.error("Failed to record admin course completion history event", {
|
|
54702
|
-
gameId: data.gameId,
|
|
54703
|
-
courseId: data.courseId,
|
|
54704
|
-
studentId: data.studentId,
|
|
54705
|
-
action: data.action,
|
|
54706
|
-
error: error instanceof Error ? error.message : String(error)
|
|
54707
|
-
});
|
|
54708
|
-
});
|
|
54709
|
-
}
|
|
54710
54717
|
async resolveAdminMutationContext(gameId, courseId, user, studentId, accessLevel = "developer") {
|
|
54711
54718
|
const client = this.requireClient();
|
|
54712
54719
|
if (accessLevel === "dashboard") {
|
|
@@ -54805,7 +54812,7 @@ class TimebackAdminService {
|
|
|
54805
54812
|
if (typeof masterableUnits !== "number" || masterableUnits <= 0) {
|
|
54806
54813
|
return;
|
|
54807
54814
|
}
|
|
54808
|
-
return Math.
|
|
54815
|
+
return Math.round(masteredUnits / masterableUnits * 100);
|
|
54809
54816
|
}
|
|
54810
54817
|
async getMasterableUnits(courseId) {
|
|
54811
54818
|
const client = this.requireClient();
|
|
@@ -55081,6 +55088,7 @@ class TimebackAdminService {
|
|
|
55081
55088
|
...enrollmentSummaries ? { enrollments: enrollmentSummaries } : {}
|
|
55082
55089
|
};
|
|
55083
55090
|
});
|
|
55091
|
+
courses.sort((a, b) => a.grade - b.grade);
|
|
55084
55092
|
return {
|
|
55085
55093
|
student: {
|
|
55086
55094
|
studentId,
|
|
@@ -55180,111 +55188,87 @@ class TimebackAdminService {
|
|
|
55180
55188
|
return { status: "ok" };
|
|
55181
55189
|
}
|
|
55182
55190
|
async adjustMasteredUnits(data, user) {
|
|
55183
|
-
const { client, sensorUrl, appName, actor } = await this.resolveAdminMutationContext(data.gameId, data.courseId, user
|
|
55191
|
+
const { client, sensorUrl, appName, actor } = await this.resolveAdminMutationContext(data.gameId, data.courseId, user);
|
|
55192
|
+
let currentMastered = 0;
|
|
55193
|
+
const masterableUnits = await this.getMasterableUnits(data.courseId);
|
|
55194
|
+
if (data.units !== 0) {
|
|
55195
|
+
const enrollment = await this.assertStudentEnrolledInCourse(client, data.studentId, data.courseId);
|
|
55196
|
+
try {
|
|
55197
|
+
const analytics = await client.edubridge.analytics.getEnrollmentFacts(enrollment.id, { timezone: PLATFORM_TIMEZONE });
|
|
55198
|
+
currentMastered = this.summarizeAnalyticsFacts(analytics.facts).masteredUnits;
|
|
55199
|
+
} catch {
|
|
55200
|
+
throw new ValidationError("Unable to validate mastery bounds — analytics unavailable. Please retry.");
|
|
55201
|
+
}
|
|
55202
|
+
validateMasteryAdjustment(data.units, currentMastered, masterableUnits);
|
|
55203
|
+
}
|
|
55204
|
+
const pctCompleteApp = typeof masterableUnits === "number" && masterableUnits > 0 ? Math.min(100, Math.max(0, Math.round((currentMastered + data.units) / masterableUnits * 100))) : undefined;
|
|
55184
55205
|
await client.recordAdminMasteryAdjustment({
|
|
55185
55206
|
gameId: data.gameId,
|
|
55186
55207
|
courseId: data.courseId,
|
|
55187
55208
|
studentId: data.studentId,
|
|
55188
55209
|
masteredUnits: data.units,
|
|
55210
|
+
pctCompleteApp,
|
|
55189
55211
|
eventTime: resolveAdminEventTime(data),
|
|
55190
55212
|
reason: data.reason,
|
|
55191
55213
|
actor,
|
|
55192
55214
|
appName,
|
|
55193
55215
|
sensorUrl
|
|
55194
55216
|
});
|
|
55195
|
-
|
|
55196
|
-
|
|
55197
|
-
|
|
55198
|
-
|
|
55199
|
-
|
|
55200
|
-
|
|
55201
|
-
|
|
55202
|
-
|
|
55203
|
-
|
|
55204
|
-
|
|
55205
|
-
|
|
55206
|
-
|
|
55207
|
-
|
|
55208
|
-
|
|
55209
|
-
});
|
|
55210
|
-
if (data.action === "complete") {
|
|
55211
|
-
const masterableUnits = await this.getMasterableUnits(data.courseId);
|
|
55212
|
-
if (masterableUnits && masterableUnits > 0) {
|
|
55213
|
-
const enrollment = await this.assertStudentEnrolledInCourse(client, data.studentId, data.courseId);
|
|
55214
|
-
let currentMastered = 0;
|
|
55215
|
-
try {
|
|
55216
|
-
const analytics = await client.edubridge.analytics.getEnrollmentFacts(enrollment.id, { timezone: PLATFORM_TIMEZONE });
|
|
55217
|
-
const summary = this.summarizeAnalyticsFacts(analytics.facts);
|
|
55218
|
-
currentMastered = summary.masteredUnits;
|
|
55219
|
-
} catch {
|
|
55220
|
-
logger16.warn("Failed to load analytics for mastery gap calculation", {
|
|
55221
|
-
studentId: data.studentId,
|
|
55222
|
-
courseId: data.courseId
|
|
55217
|
+
if (typeof masterableUnits === "number" && masterableUnits > 0) {
|
|
55218
|
+
const wasMastered = currentMastered >= masterableUnits;
|
|
55219
|
+
const willBeMastered = currentMastered + data.units >= masterableUnits;
|
|
55220
|
+
if (wasMastered !== willBeMastered) {
|
|
55221
|
+
const ids = deriveSourcedIds(data.courseId);
|
|
55222
|
+
const lineItemId = `${ids.course}-mastery-completion-assessment`;
|
|
55223
|
+
const resultId = `${lineItemId}:${data.studentId}:completion`;
|
|
55224
|
+
if (willBeMastered) {
|
|
55225
|
+
await client.oneroster.assessmentLineItems.findOrCreate(lineItemId, {
|
|
55226
|
+
sourcedId: lineItemId,
|
|
55227
|
+
title: "Mastery Completion",
|
|
55228
|
+
status: ONEROSTER_STATUS.active,
|
|
55229
|
+
course: { sourcedId: ids.course },
|
|
55230
|
+
...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
|
|
55223
55231
|
});
|
|
55224
|
-
|
|
55225
|
-
|
|
55226
|
-
|
|
55227
|
-
|
|
55228
|
-
|
|
55229
|
-
|
|
55230
|
-
|
|
55231
|
-
|
|
55232
|
-
|
|
55233
|
-
|
|
55234
|
-
|
|
55235
|
-
|
|
55232
|
+
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
55233
|
+
sourcedId: resultId,
|
|
55234
|
+
status: ONEROSTER_STATUS.active,
|
|
55235
|
+
assessmentLineItem: { sourcedId: lineItemId },
|
|
55236
|
+
student: { sourcedId: data.studentId },
|
|
55237
|
+
score: 100,
|
|
55238
|
+
scoreDate: new Date().toISOString(),
|
|
55239
|
+
scoreStatus: SCORE_STATUS.fullyGraded,
|
|
55240
|
+
inProgress: "false",
|
|
55241
|
+
metadata: {
|
|
55242
|
+
isMasteryCompletion: true,
|
|
55243
|
+
adminAction: true,
|
|
55244
|
+
appName
|
|
55245
|
+
}
|
|
55236
55246
|
});
|
|
55247
|
+
} else {
|
|
55248
|
+
try {
|
|
55249
|
+
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
55250
|
+
sourcedId: resultId,
|
|
55251
|
+
status: ONEROSTER_STATUS.active,
|
|
55252
|
+
assessmentLineItem: { sourcedId: lineItemId },
|
|
55253
|
+
student: { sourcedId: data.studentId },
|
|
55254
|
+
score: 0,
|
|
55255
|
+
scoreDate: new Date().toISOString(),
|
|
55256
|
+
scoreStatus: SCORE_STATUS.notSubmitted,
|
|
55257
|
+
inProgress: "true",
|
|
55258
|
+
metadata: {
|
|
55259
|
+
isMasteryCompletion: true,
|
|
55260
|
+
adminAction: true,
|
|
55261
|
+
appName
|
|
55262
|
+
}
|
|
55263
|
+
});
|
|
55264
|
+
} catch {
|
|
55265
|
+
logger16.debug("No completion entry to revoke", {
|
|
55266
|
+
studentId: data.studentId,
|
|
55267
|
+
courseId: data.courseId
|
|
55268
|
+
});
|
|
55269
|
+
}
|
|
55237
55270
|
}
|
|
55238
55271
|
}
|
|
55239
|
-
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
55240
|
-
sourcedId: resultId,
|
|
55241
|
-
status: ONEROSTER_STATUS.active,
|
|
55242
|
-
assessmentLineItem: { sourcedId: lineItemId },
|
|
55243
|
-
student: { sourcedId: data.studentId },
|
|
55244
|
-
score: 100,
|
|
55245
|
-
scoreDate: new Date().toISOString(),
|
|
55246
|
-
scoreStatus: SCORE_STATUS.fullyGraded,
|
|
55247
|
-
inProgress: "false",
|
|
55248
|
-
metadata: {
|
|
55249
|
-
isMasteryCompletion: true,
|
|
55250
|
-
adminAction: true,
|
|
55251
|
-
appName
|
|
55252
|
-
}
|
|
55253
|
-
});
|
|
55254
|
-
await this.recordCourseCompletionHistory(historyClient, {
|
|
55255
|
-
gameId: data.gameId,
|
|
55256
|
-
courseId: data.courseId,
|
|
55257
|
-
studentId: data.studentId,
|
|
55258
|
-
action: "complete",
|
|
55259
|
-
actor,
|
|
55260
|
-
appName,
|
|
55261
|
-
sensorUrl
|
|
55262
|
-
});
|
|
55263
|
-
} else {
|
|
55264
|
-
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
55265
|
-
sourcedId: resultId,
|
|
55266
|
-
status: ONEROSTER_STATUS.active,
|
|
55267
|
-
assessmentLineItem: { sourcedId: lineItemId },
|
|
55268
|
-
student: { sourcedId: data.studentId },
|
|
55269
|
-
score: 0,
|
|
55270
|
-
scoreDate: new Date().toISOString(),
|
|
55271
|
-
scoreStatus: SCORE_STATUS.notSubmitted,
|
|
55272
|
-
inProgress: "true",
|
|
55273
|
-
metadata: {
|
|
55274
|
-
isMasteryCompletion: true,
|
|
55275
|
-
adminAction: true,
|
|
55276
|
-
appName
|
|
55277
|
-
}
|
|
55278
|
-
});
|
|
55279
|
-
await this.recordCourseCompletionHistory(historyClient, {
|
|
55280
|
-
gameId: data.gameId,
|
|
55281
|
-
courseId: data.courseId,
|
|
55282
|
-
studentId: data.studentId,
|
|
55283
|
-
action: "resume",
|
|
55284
|
-
actor,
|
|
55285
|
-
appName,
|
|
55286
|
-
sensorUrl
|
|
55287
|
-
});
|
|
55288
55272
|
}
|
|
55289
55273
|
return { status: "ok" };
|
|
55290
55274
|
}
|
|
@@ -60927,6 +60911,7 @@ class AdminEventRecorder {
|
|
|
60927
60911
|
defaultActivityId: "playcademy-admin-mastery-adjustment",
|
|
60928
60912
|
eventKind: "remediation-mastery"
|
|
60929
60913
|
});
|
|
60914
|
+
const courseUrl = createOneRosterUrls(TIMEBACK_API_URLS5[this.environment]).course(data.courseId);
|
|
60930
60915
|
await this.caliper.emitActivityEvent({
|
|
60931
60916
|
studentId: ctx.student.id,
|
|
60932
60917
|
studentEmail: ctx.student.email,
|
|
@@ -60941,32 +60926,13 @@ class AdminEventRecorder {
|
|
|
60941
60926
|
appName: ctx.appName,
|
|
60942
60927
|
sensorUrl: ctx.sensorUrl,
|
|
60943
60928
|
process: true,
|
|
60944
|
-
generatedExtensions: ctx.metadata,
|
|
60945
|
-
eventExtensions: ctx.metadata
|
|
60946
|
-
});
|
|
60947
|
-
}
|
|
60948
|
-
async recordCourseCompletionChange(data) {
|
|
60949
|
-
const isResume = data.action === "resume";
|
|
60950
|
-
const ctx = await this.prepareAdminEvent({
|
|
60951
|
-
...data,
|
|
60952
|
-
defaultActivityId: isResume ? "playcademy-admin-course-resumed" : "playcademy-admin-course-completed",
|
|
60953
|
-
reason: "Admin action",
|
|
60954
|
-
eventKind: isResume ? "course-resumed" : "course-completed"
|
|
60955
|
-
});
|
|
60956
|
-
await this.caliper.emitActivityEvent({
|
|
60957
|
-
studentId: ctx.student.id,
|
|
60958
|
-
studentEmail: ctx.student.email,
|
|
60959
|
-
gameId: data.gameId,
|
|
60960
|
-
activityId: ctx.activityId,
|
|
60961
|
-
activityName: isResume ? "Course resumed" : "Course marked complete",
|
|
60962
|
-
courseId: data.courseId,
|
|
60963
|
-
courseName: ctx.courseContext.courseName,
|
|
60964
|
-
subject: ctx.courseContext.subject,
|
|
60965
|
-
appName: ctx.appName,
|
|
60966
|
-
sensorUrl: ctx.sensorUrl,
|
|
60967
|
-
process: false,
|
|
60968
60929
|
includeAttempt: false,
|
|
60969
|
-
|
|
60930
|
+
objectId: `${ctx.sensorUrl.replace(/\/$/, "")}/urn:uuid:${crypto.randomUUID()}`,
|
|
60931
|
+
generatedId: courseUrl,
|
|
60932
|
+
generatedExtensions: {
|
|
60933
|
+
...ctx.metadata,
|
|
60934
|
+
...data.pctCompleteApp !== undefined ? { pctCompleteApp: data.pctCompleteApp } : {}
|
|
60935
|
+
},
|
|
60970
60936
|
eventExtensions: ctx.metadata
|
|
60971
60937
|
});
|
|
60972
60938
|
}
|
|
@@ -62157,10 +62123,6 @@ class TimebackClient {
|
|
|
62157
62123
|
await this._ensureAuthenticated();
|
|
62158
62124
|
return this.adminEventRecorder.recordMasteryAdjustment(data);
|
|
62159
62125
|
}
|
|
62160
|
-
async recordAdminCourseCompletionChange(data) {
|
|
62161
|
-
await this._ensureAuthenticated();
|
|
62162
|
-
return this.adminEventRecorder.recordCourseCompletionChange(data);
|
|
62163
|
-
}
|
|
62164
62126
|
clearCaches() {
|
|
62165
62127
|
this.cacheManager.clearAll();
|
|
62166
62128
|
}
|
|
@@ -121794,7 +121756,6 @@ var AdminAttributionDateSchema;
|
|
|
121794
121756
|
var GrantTimebackXpRequestSchema;
|
|
121795
121757
|
var AdjustTimebackTimeRequestSchema;
|
|
121796
121758
|
var AdjustTimebackMasteryRequestSchema;
|
|
121797
|
-
var ToggleCourseCompletionRequestSchema;
|
|
121798
121759
|
var EnrollStudentRequestSchema;
|
|
121799
121760
|
var UnenrollStudentRequestSchema;
|
|
121800
121761
|
var ReactivateEnrollmentRequestSchema;
|
|
@@ -121972,12 +121933,6 @@ var init_schemas11 = __esm(() => {
|
|
|
121972
121933
|
date: AdminAttributionDateSchema.optional(),
|
|
121973
121934
|
useCurrentTime: exports_external.boolean().optional()
|
|
121974
121935
|
});
|
|
121975
|
-
ToggleCourseCompletionRequestSchema = exports_external.object({
|
|
121976
|
-
gameId: exports_external.string().uuid(),
|
|
121977
|
-
courseId: exports_external.string().min(1),
|
|
121978
|
-
studentId: exports_external.string().min(1),
|
|
121979
|
-
action: exports_external.enum(["complete", "resume"])
|
|
121980
|
-
});
|
|
121981
121936
|
EnrollStudentRequestSchema = exports_external.object({
|
|
121982
121937
|
gameId: exports_external.string().uuid(),
|
|
121983
121938
|
courseId: exports_external.string().min(1),
|
|
@@ -124243,7 +124198,6 @@ var getActivityDetail;
|
|
|
124243
124198
|
var grantXp;
|
|
124244
124199
|
var adjustTime;
|
|
124245
124200
|
var adjustMastery;
|
|
124246
|
-
var toggleCompletion;
|
|
124247
124201
|
var searchStudents;
|
|
124248
124202
|
var enrollStudent;
|
|
124249
124203
|
var unenrollStudent;
|
|
@@ -124662,17 +124616,6 @@ var init_timeback_controller = __esm(() => {
|
|
|
124662
124616
|
});
|
|
124663
124617
|
return ctx.services.timebackAdmin.adjustMasteredUnits(body2, ctx.user);
|
|
124664
124618
|
});
|
|
124665
|
-
toggleCompletion = requireGameManagementAccess(async (ctx) => {
|
|
124666
|
-
const body2 = await parseRequestBody(ctx.request, ToggleCourseCompletionRequestSchema);
|
|
124667
|
-
logger65.debug("Toggling course completion", {
|
|
124668
|
-
requesterId: ctx.user.id,
|
|
124669
|
-
gameId: body2.gameId,
|
|
124670
|
-
courseId: body2.courseId,
|
|
124671
|
-
studentId: body2.studentId,
|
|
124672
|
-
action: body2.action
|
|
124673
|
-
});
|
|
124674
|
-
return ctx.services.timebackAdmin.toggleCourseCompletion(body2, ctx.user);
|
|
124675
|
-
});
|
|
124676
124619
|
searchStudents = requireGameManagementAccess(async (ctx) => {
|
|
124677
124620
|
const gameId = ctx.params.gameId;
|
|
124678
124621
|
const courseId = ctx.params.courseId;
|
|
@@ -124864,7 +124807,6 @@ var init_timeback_controller = __esm(() => {
|
|
|
124864
124807
|
grantXp,
|
|
124865
124808
|
adjustTime,
|
|
124866
124809
|
adjustMastery,
|
|
124867
|
-
toggleCompletion,
|
|
124868
124810
|
searchStudents,
|
|
124869
124811
|
enrollStudent,
|
|
124870
124812
|
unenrollStudent,
|
|
@@ -127702,7 +127644,7 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
|
127702
127644
|
// package.json
|
|
127703
127645
|
var package_default2 = {
|
|
127704
127646
|
name: "@playcademy/vite-plugin",
|
|
127705
|
-
version: "0.2.30-beta.
|
|
127647
|
+
version: "0.2.30-beta.2",
|
|
127706
127648
|
type: "module",
|
|
127707
127649
|
exports: {
|
|
127708
127650
|
".": {
|