@playcademy/vite-plugin 0.2.26-beta.4 → 0.2.26-beta.6

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 CHANGED
@@ -24333,10 +24333,10 @@ var init_typescript = __esm(() => {
24333
24333
  TypeScriptPackages = {
24334
24334
  tsc: "tsc",
24335
24335
  nativePreview: "@typescript/native-preview",
24336
- nativePreviewPinned: "@typescript/native-preview@7.0.0-dev.20260221.1"
24336
+ nativePreviewBeta: "@typescript/native-preview@beta"
24337
24337
  };
24338
24338
  TYPESCRIPT_RUNNER = {
24339
- package: TypeScriptPackages.nativePreviewPinned,
24339
+ package: TypeScriptPackages.nativePreviewBeta,
24340
24340
  bin: "tsgo"
24341
24341
  };
24342
24342
  });
@@ -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.19",
25373
+ version: "0.3.17-beta.21",
25374
25374
  description: "Local development server for Playcademy game development",
25375
25375
  type: "module",
25376
25376
  exports: {
@@ -25707,7 +25707,7 @@ function formatJSONSingleLine(level, message, context, scope) {
25707
25707
  ...context && Object.keys(context).length > 0 && { context }
25708
25708
  };
25709
25709
  const consoleMethod = getConsoleMethod(level);
25710
- consoleMethod(JSON.stringify(logEntry));
25710
+ consoleMethod(safeJSONStringify(logEntry));
25711
25711
  }
25712
25712
  function formatJSONPretty(level, message, context, scope) {
25713
25713
  const timestamp = new Date().toISOString();
@@ -25719,7 +25719,30 @@ function formatJSONPretty(level, message, context, scope) {
25719
25719
  ...context && Object.keys(context).length > 0 && { context }
25720
25720
  };
25721
25721
  const consoleMethod = getConsoleMethod(level);
25722
- consoleMethod(JSON.stringify(logEntry, null, 2));
25722
+ consoleMethod(safeJSONStringify(logEntry, 2));
25723
+ }
25724
+ function safeJSONStringify(value, space) {
25725
+ const seen = new WeakSet;
25726
+ try {
25727
+ return JSON.stringify(value, (_key, currentValue) => {
25728
+ if (typeof currentValue === "bigint") {
25729
+ return currentValue.toString();
25730
+ }
25731
+ if (typeof currentValue === "object" && currentValue !== null) {
25732
+ if (seen.has(currentValue)) {
25733
+ return "[Circular]";
25734
+ }
25735
+ seen.add(currentValue);
25736
+ }
25737
+ return currentValue;
25738
+ }, space);
25739
+ } catch {
25740
+ return JSON.stringify({
25741
+ timestamp: new Date().toISOString(),
25742
+ level: "ERROR",
25743
+ message: "[Logger] Failed to serialize log entry"
25744
+ });
25745
+ }
25723
25746
  }
25724
25747
  function getConsoleMethod(level) {
25725
25748
  switch (level) {
@@ -59106,7 +59129,6 @@ async function request({
59106
59129
  method,
59107
59130
  headers,
59108
59131
  body: payload,
59109
- credentials: "omit",
59110
59132
  signal: controller.signal
59111
59133
  });
59112
59134
  clearTimeout(timeoutId);
@@ -59690,10 +59712,11 @@ function createOneRosterNamespace(client) {
59690
59712
  const url = `${ONEROSTER_ENDPOINTS4.assessmentResults}?filter=${encodeURIComponent(filter)}`;
59691
59713
  const response = await client["request"](url, "GET");
59692
59714
  const results = response.assessmentResults || [];
59693
- if (results.length === 0) {
59715
+ const firstResult = results[0];
59716
+ if (!firstResult) {
59694
59717
  return null;
59695
59718
  }
59696
- let maxAttemptResult = results[0];
59719
+ let maxAttemptResult = firstResult;
59697
59720
  let maxAttemptNumber = maxAttemptResult.metadata?.attemptNumber || 0;
59698
59721
  let activeAttemptCount = 0;
59699
59722
  for (const result of results) {
@@ -59727,10 +59750,11 @@ function createOneRosterNamespace(client) {
59727
59750
  if (!response || !response.users || !Array.isArray(response.users)) {
59728
59751
  throw new Error(`Invalid response format from OneRoster API when searching for user with email: ${email}. Expected { users: [...] } but received: ${JSON.stringify(response)}`);
59729
59752
  }
59730
- if (response.users.length === 0) {
59753
+ const user = response.users[0];
59754
+ if (!user) {
59731
59755
  throw new Error(`User not found with email: ${email}. Ensure the user exists in OneRoster and has a valid email address. If this is a new user, they must be created in OneRoster first.`);
59732
59756
  }
59733
- return response.users[0];
59757
+ return user;
59734
59758
  },
59735
59759
  listBySourcedIds: async (sourcedIds, batchSize = 50) => {
59736
59760
  if (sourcedIds.length === 0) {
@@ -60012,6 +60036,9 @@ class TimebackCache {
60012
60036
  return;
60013
60037
  }
60014
60038
  const oldestKey = this.accessOrder[0];
60039
+ if (!oldestKey) {
60040
+ return;
60041
+ }
60015
60042
  this.delete(oldestKey);
60016
60043
  log.debug(`[${this.name}] Evicted LRU entry`, { key: oldestKey });
60017
60044
  }
@@ -60106,7 +60133,7 @@ class MasteryTracker {
60106
60133
  }
60107
60134
  async checkProgress(input) {
60108
60135
  const { studentId, courseId, resourceId, masteredUnits } = input;
60109
- if (typeof masteredUnits !== "number" || masteredUnits <= 0) {
60136
+ if (typeof masteredUnits !== "number" || masteredUnits === 0) {
60110
60137
  return;
60111
60138
  }
60112
60139
  const status = await this.calculateStatus({
@@ -60118,9 +60145,11 @@ class MasteryTracker {
60118
60145
  if (!status) {
60119
60146
  return;
60120
60147
  }
60148
+ const wasComplete = status.historicalMasteredUnits >= status.masterableUnits;
60121
60149
  return {
60122
60150
  pctCompleteApp: status.pctCompleteApp,
60123
- masteryAchieved: status.historicalMasteredUnits < status.masterableUnits && status.isComplete
60151
+ masteryAchieved: !wasComplete && status.isComplete,
60152
+ masteryRevoked: wasComplete && !status.isComplete
60124
60153
  };
60125
60154
  }
60126
60155
  async getStatus(input) {
@@ -60161,7 +60190,7 @@ class MasteryTracker {
60161
60190
  return;
60162
60191
  }
60163
60192
  const historicalMasteredUnits = this.sumAnalyticsMetric(facts, "masteredUnits");
60164
- const totalMastered = historicalMasteredUnits + additionalMasteredUnits;
60193
+ const totalMastered = Math.max(0, historicalMasteredUnits + additionalMasteredUnits);
60165
60194
  const rawPct = totalMastered / masterableUnits * 100;
60166
60195
  const pctCompleteApp = Math.min(100, Math.max(0, Math.round(rawPct)));
60167
60196
  return {
@@ -60211,6 +60240,45 @@ class MasteryTracker {
60211
60240
  });
60212
60241
  }
60213
60242
  }
60243
+ async revokeCompletionEntry(studentId, courseId, classId, appName) {
60244
+ const ids = deriveSourcedIds2(courseId);
60245
+ const lineItemId = `${ids.course}-mastery-completion-assessment`;
60246
+ const resultId = `${lineItemId}:${studentId}:completion`;
60247
+ try {
60248
+ await this.onerosterNamespace.assessmentLineItems.findOrCreate(lineItemId, {
60249
+ sourcedId: lineItemId,
60250
+ title: "Mastery Completion",
60251
+ status: ONEROSTER_STATUS4.active,
60252
+ ...classId ? { class: { sourcedId: classId } } : { course: { sourcedId: ids.course } },
60253
+ ...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
60254
+ });
60255
+ await this.onerosterNamespace.assessmentResults.upsert(resultId, {
60256
+ sourcedId: resultId,
60257
+ status: ONEROSTER_STATUS4.active,
60258
+ assessmentLineItem: { sourcedId: lineItemId },
60259
+ student: { sourcedId: studentId },
60260
+ score: 0,
60261
+ scoreDate: new Date().toISOString(),
60262
+ scoreStatus: SCORE_STATUS4.notSubmitted,
60263
+ inProgress: "true",
60264
+ metadata: {
60265
+ isMasteryCompletion: true,
60266
+ appName
60267
+ }
60268
+ });
60269
+ log.info("[MasteryTracker] Revoked mastery completion entry", {
60270
+ studentId,
60271
+ lineItemId,
60272
+ resultId
60273
+ });
60274
+ } catch (error) {
60275
+ log.error("[MasteryTracker] Failed to revoke mastery completion entry", {
60276
+ studentId,
60277
+ lineItemId,
60278
+ error
60279
+ });
60280
+ }
60281
+ }
60214
60282
  async resolveMasterableUnits(resourceId) {
60215
60283
  if (!resourceId) {
60216
60284
  return;
@@ -60420,6 +60488,9 @@ class ProgressRecorder {
60420
60488
  sensorUrl: progressData.sensorUrl
60421
60489
  });
60422
60490
  }
60491
+ if (masteryProgress?.masteryRevoked) {
60492
+ await this.masteryTracker.revokeCompletionEntry(studentId, courseId, progressData.classId, progressData.appName);
60493
+ }
60423
60494
  await this.emitCaliperEvent({
60424
60495
  studentId,
60425
60496
  studentEmail,
@@ -120715,7 +120786,7 @@ var init_schemas11 = __esm(() => {
120715
120786
  inactiveSeconds: exports_external.number().nonnegative().optional()
120716
120787
  }).optional(),
120717
120788
  xpEarned: exports_external.number().optional(),
120718
- masteredUnits: exports_external.number().nonnegative().optional(),
120789
+ masteredUnits: exports_external.number().optional(),
120719
120790
  extensions: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
120720
120791
  });
120721
120792
  AdvanceCourseRequestSchema = exports_external.object({
@@ -125267,10 +125338,10 @@ var ACHIEVEMENT_DEFINITIONS2 = [
125267
125338
  var TypeScriptPackages2 = {
125268
125339
  tsc: "tsc",
125269
125340
  nativePreview: "@typescript/native-preview",
125270
- nativePreviewPinned: "@typescript/native-preview@7.0.0-dev.20260221.1"
125341
+ nativePreviewBeta: "@typescript/native-preview@beta"
125271
125342
  };
125272
125343
  var TYPESCRIPT_RUNNER2 = {
125273
- package: TypeScriptPackages2.nativePreviewPinned,
125344
+ package: TypeScriptPackages2.nativePreviewBeta,
125274
125345
  bin: "tsgo"
125275
125346
  };
125276
125347
  // ../constants/src/overworld.ts
@@ -125579,10 +125650,10 @@ var init_typescript2 = __esm7(() => {
125579
125650
  TypeScriptPackages3 = {
125580
125651
  tsc: "tsc",
125581
125652
  nativePreview: "@typescript/native-preview",
125582
- nativePreviewPinned: "@typescript/native-preview@7.0.0-dev.20260221.1"
125653
+ nativePreviewBeta: "@typescript/native-preview@beta"
125583
125654
  };
125584
125655
  TYPESCRIPT_RUNNER3 = {
125585
- package: TypeScriptPackages3.nativePreviewPinned,
125656
+ package: TypeScriptPackages3.nativePreviewBeta,
125586
125657
  bin: "tsgo"
125587
125658
  };
125588
125659
  });
@@ -126342,7 +126413,7 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
126342
126413
  // package.json
126343
126414
  var package_default2 = {
126344
126415
  name: "@playcademy/vite-plugin",
126345
- version: "0.2.26-beta.4",
126416
+ version: "0.2.26-beta.6",
126346
126417
  type: "module",
126347
126418
  exports: {
126348
126419
  ".": {
@@ -6,6 +6,6 @@ import type { ResolvedConfig } from 'vite';
6
6
  * Creates hot reload callbacks for logging backend updates.
7
7
  */
8
8
  export declare function createHotReloadCallbacks(viteConfig: ResolvedConfig): {
9
- onSuccess: (changedPath?: string | undefined) => void;
9
+ onSuccess: (changedPath?: string) => void;
10
10
  onError: (error: unknown) => void;
11
11
  };
@@ -17,8 +17,8 @@ export declare const serverState: {
17
17
  backend: CliServerManager | null;
18
18
  viteServer: ViteDevServer | null;
19
19
  currentMode: PlaycademyMode;
20
- timebackRoleOverride: "administrator" | "parent" | "student" | "teacher" | null;
21
- platformRoleOverride: "admin" | "developer" | "player" | null;
20
+ timebackRoleOverride: TimebackRoleOverride | null;
21
+ platformRoleOverride: PlatformRoleOverride | null;
22
22
  };
23
23
  /**
24
24
  * Get sandbox server reference
@@ -6,12 +6,12 @@ import type { PlaycademyMode, PlaycademyTimebackOptions } from './options';
6
6
  /**
7
7
  * TimeBack roles that can be cycled through in dev mode
8
8
  */
9
- export declare const TIMEBACK_ROLES: readonly ["student", "parent", "teacher", "administrator"];
9
+ export declare const TIMEBACK_ROLES: readonly ['student', 'parent', 'teacher', 'administrator'];
10
10
  export type TimebackRoleOverride = (typeof TIMEBACK_ROLES)[number];
11
11
  /**
12
12
  * Platform roles that can be cycled through in dev mode
13
13
  */
14
- export declare const PLATFORM_ROLES: readonly ["player", "developer", "admin"];
14
+ export declare const PLATFORM_ROLES: readonly ['player', 'developer', 'admin'];
15
15
  export type PlatformRoleOverride = (typeof PLATFORM_ROLES)[number];
16
16
  /**
17
17
  * Internal resolved plugin options
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/vite-plugin",
3
- "version": "0.2.26-beta.4",
3
+ "version": "0.2.26-beta.6",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {