@playcademy/vite-plugin 0.2.10 → 0.2.12

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
@@ -41142,6 +41142,7 @@ import { homedir } from "node:os";
41142
41142
  import { join } from "node:path";
41143
41143
  import { stdout } from "process";
41144
41144
  import crypto3 from "node:crypto";
41145
+ import { stdout as stdout2 } from "process";
41145
41146
  import * as s3 from "fs";
41146
41147
  import * as o3 from "path";
41147
41148
  import fs22 from "node:fs";
@@ -41426,7 +41427,7 @@ var init_auth = __esm(() => {
41426
41427
  TIMEBACK_LTI: "timeback-lti"
41427
41428
  };
41428
41429
  });
41429
- var TSC_PACKAGE = "@typescript/native-preview";
41430
+ var TSC_PACKAGE = "typescript";
41430
41431
  var USE_NATIVE_TSC;
41431
41432
  var init_typescript = __esm(() => {
41432
41433
  USE_NATIVE_TSC = TSC_PACKAGE.includes("native-preview");
@@ -41490,9 +41491,16 @@ var init_overworld = __esm(() => {
41490
41491
  };
41491
41492
  });
41492
41493
  var PLATFORM_TIMEZONE = "America/New_York";
41494
+ var TIMEBACK_ROUTES;
41493
41495
  var TIMEBACK_ORG_SOURCED_ID = "PLAYCADEMY";
41494
- var init_timeback2 = () => {};
41496
+ var init_timeback2 = __esm(() => {
41497
+ TIMEBACK_ROUTES = {
41498
+ END_ACTIVITY: "/integrations/timeback/end-activity",
41499
+ GET_XP: "/integrations/timeback/xp"
41500
+ };
41501
+ });
41495
41502
  var WORKER_NAMING;
41503
+ var SECRETS_PREFIX = "secrets_";
41496
41504
  var init_workers = __esm(() => {
41497
41505
  WORKER_NAMING = {
41498
41506
  STAGING_PREFIX: "staging-",
@@ -42380,7 +42388,7 @@ var package_default;
42380
42388
  var init_package = __esm(() => {
42381
42389
  package_default = {
42382
42390
  name: "@playcademy/sandbox",
42383
- version: "0.3.12",
42391
+ version: "0.3.14",
42384
42392
  description: "Local development server for Playcademy game development",
42385
42393
  type: "module",
42386
42394
  exports: {
@@ -56963,9 +56971,9 @@ class SecretsService {
56963
56971
  }
56964
56972
  }
56965
56973
  var logger21;
56966
- var SECRETS_PREFIX = "secrets_";
56967
56974
  var INTERNAL_SECRET_KEYS;
56968
56975
  var init_secrets_service = __esm(() => {
56976
+ init_src();
56969
56977
  init_src2();
56970
56978
  init_config2();
56971
56979
  init_errors();
@@ -56973,6 +56981,29 @@ var init_secrets_service = __esm(() => {
56973
56981
  logger21 = log.scope("SecretsService");
56974
56982
  INTERNAL_SECRET_KEYS = ["PLAYCADEMY_API_KEY", "GAME_ID", "PLAYCADEMY_BASE_URL"];
56975
56983
  });
56984
+ var ROUTES;
56985
+ var init_constants2 = __esm(() => {
56986
+ init_src();
56987
+ ROUTES = {
56988
+ INDEX: "/api",
56989
+ HEALTH: "/api/health",
56990
+ TIMEBACK: {
56991
+ END_ACTIVITY: `/api${TIMEBACK_ROUTES.END_ACTIVITY}`,
56992
+ GET_XP: `/api${TIMEBACK_ROUTES.GET_XP}`
56993
+ }
56994
+ };
56995
+ });
56996
+ function prefixSecrets(secrets) {
56997
+ const prefixed = {};
56998
+ for (const [key, value] of Object.entries(secrets)) {
56999
+ prefixed[SECRETS_PREFIX + key] = value;
57000
+ }
57001
+ return prefixed;
57002
+ }
57003
+ var init_setup = __esm(() => {
57004
+ init_src();
57005
+ init_constants2();
57006
+ });
56976
57007
 
56977
57008
  class SeedService {
56978
57009
  ctx;
@@ -56987,7 +57018,7 @@ class SeedService {
56987
57018
  }
56988
57019
  return cf;
56989
57020
  }
56990
- async seed(slug2, code, user) {
57021
+ async seed(slug2, code, user, secrets) {
56991
57022
  const cf = this.getCloudflare();
56992
57023
  const game = await this.ctx.services.game.validateDeveloperAccessBySlug(user, slug2);
56993
57024
  const isProd = isProduction2(this.ctx.config);
@@ -56999,10 +57030,11 @@ class SeedService {
56999
57030
  gameId: game.id,
57000
57031
  slug: slug2,
57001
57032
  deploymentId,
57002
- codeLength: code.length
57033
+ codeLength: code.length,
57034
+ secretCount: secrets ? Object.keys(secrets).length : 0
57003
57035
  });
57004
57036
  try {
57005
- const workerResponse = await this.deployAndExecuteSeedWorker(cf, seedDeploymentId, game.id, deploymentId, code);
57037
+ const workerResponse = await this.deployAndExecuteSeedWorker(cf, seedDeploymentId, game.id, deploymentId, code, secrets);
57006
57038
  logger22.info("Seed completed", {
57007
57039
  gameId: game.id,
57008
57040
  slug: slug2,
@@ -57074,7 +57106,7 @@ class SeedService {
57074
57106
  });
57075
57107
  }
57076
57108
  }
57077
- async deployAndExecuteSeedWorker(cf, seedDeploymentId, gameId, deploymentId, workerCode) {
57109
+ async deployAndExecuteSeedWorker(cf, seedDeploymentId, gameId, deploymentId, workerCode, secrets) {
57078
57110
  try {
57079
57111
  const result = await cf.deploy(seedDeploymentId, workerCode, {
57080
57112
  GAME_ID: gameId,
@@ -57084,6 +57116,13 @@ class SeedService {
57084
57116
  keepAssets: false
57085
57117
  });
57086
57118
  logger22.info("Worker deployed", { seedDeploymentId, url: result.url });
57119
+ if (secrets && Object.keys(secrets).length > 0) {
57120
+ await cf.setSecrets(seedDeploymentId, prefixSecrets(secrets));
57121
+ logger22.info("Secrets bound to worker", {
57122
+ seedDeploymentId,
57123
+ count: Object.keys(secrets).length
57124
+ });
57125
+ }
57087
57126
  return await this.executeSeedWorker(result.url, seedDeploymentId);
57088
57127
  } finally {
57089
57128
  await this.cleanupSeedWorker(cf, seedDeploymentId);
@@ -57199,6 +57238,7 @@ class SeedService {
57199
57238
  }
57200
57239
  var logger22;
57201
57240
  var init_seed_service = __esm(() => {
57241
+ init_setup();
57202
57242
  init_src2();
57203
57243
  init_config2();
57204
57244
  init_errors();
@@ -57665,7 +57705,7 @@ var ACHIEVEMENT_IDS2;
57665
57705
  var ACHIEVEMENT_DEFINITIONS2;
57666
57706
  var init_achievements2;
57667
57707
  var init_auth2 = () => {};
57668
- var TSC_PACKAGE2 = "@typescript/native-preview";
57708
+ var TSC_PACKAGE2 = "typescript";
57669
57709
  var USE_NATIVE_TSC2;
57670
57710
  var init_typescript2;
57671
57711
  var init_character2 = () => {};
@@ -57713,7 +57753,7 @@ var PLAYCADEMY_DEFAULTS;
57713
57753
  var RESOURCE_DEFAULTS;
57714
57754
  var HTTP_STATUS;
57715
57755
  var ERROR_NAMES;
57716
- var init_constants2;
57756
+ var init_constants3;
57717
57757
  var isObject = (value) => typeof value === "object" && value !== null;
57718
57758
  var SUBJECT_VALUES;
57719
57759
  var GRADE_VALUES;
@@ -57893,7 +57933,7 @@ var init_types7 = __esm(() => {
57893
57933
  init_timeback3();
57894
57934
  init_workers2();
57895
57935
  });
57896
- init_constants2 = __esm2(() => {
57936
+ init_constants3 = __esm2(() => {
57897
57937
  init_src5();
57898
57938
  TIMEBACK_API_URLS = {
57899
57939
  production: "https://api.alpha-1edtech.ai",
@@ -58068,7 +58108,7 @@ var init_types7 = __esm(() => {
58068
58108
  timebackSdk: "TimebackSDKError"
58069
58109
  };
58070
58110
  });
58071
- init_constants2();
58111
+ init_constants3();
58072
58112
  SUBJECT_VALUES = TIMEBACK_SUBJECTS;
58073
58113
  GRADE_VALUES = TIMEBACK_GRADE_LEVELS;
58074
58114
  });
@@ -58630,6 +58670,48 @@ class TimebackService {
58630
58670
  inProgress: result.inProgress
58631
58671
  };
58632
58672
  }
58673
+ async getStudentXp(timebackId, options) {
58674
+ const client = this.requireClient();
58675
+ const db2 = this.ctx.db;
58676
+ let courseIds = [];
58677
+ if (options?.gameId) {
58678
+ const conditions2 = [eq(gameTimebackIntegrations.gameId, options.gameId)];
58679
+ if (options.grade !== undefined && options.subject) {
58680
+ conditions2.push(eq(gameTimebackIntegrations.grade, options.grade));
58681
+ conditions2.push(eq(gameTimebackIntegrations.subject, options.subject));
58682
+ }
58683
+ const integrations = await db2.query.gameTimebackIntegrations.findMany({
58684
+ where: and(...conditions2)
58685
+ });
58686
+ courseIds = integrations.map((i2) => i2.courseId);
58687
+ if (courseIds.length === 0) {
58688
+ logger27.debug("No integrations found for game, returning 0 XP", {
58689
+ timebackId,
58690
+ gameId: options.gameId,
58691
+ grade: options.grade,
58692
+ subject: options.subject
58693
+ });
58694
+ return {
58695
+ totalXp: 0,
58696
+ ...options?.include?.today && { todayXp: 0 },
58697
+ ...options?.include?.perCourse && { courses: [] }
58698
+ };
58699
+ }
58700
+ }
58701
+ const result = await client.getStudentXp(timebackId, {
58702
+ courseIds: courseIds.length > 0 ? courseIds : undefined,
58703
+ include: options?.include
58704
+ });
58705
+ logger27.debug("Retrieved student XP", {
58706
+ timebackId,
58707
+ gameId: options?.gameId,
58708
+ grade: options?.grade,
58709
+ subject: options?.subject,
58710
+ totalXp: result.totalXp,
58711
+ courseCount: result.courses?.length
58712
+ });
58713
+ return result;
58714
+ }
58633
58715
  }
58634
58716
  var logger27;
58635
58717
  var init_timeback_service = __esm(() => {
@@ -59042,6 +59124,117 @@ function isTimebackSubject2(value) {
59042
59124
  function isTimebackGrade2(value) {
59043
59125
  return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES2.includes(value);
59044
59126
  }
59127
+ function stripAnsi2(text3) {
59128
+ return text3.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "");
59129
+ }
59130
+
59131
+ class Spinner2 {
59132
+ tasks = new Map;
59133
+ frameIndex = 0;
59134
+ intervalId = null;
59135
+ renderCount = 0;
59136
+ previousLineCount = 0;
59137
+ printedTasks = new Set;
59138
+ indent;
59139
+ constructor(taskIds, texts, options) {
59140
+ this.indent = options?.indent ?? 0;
59141
+ taskIds.forEach((id, index2) => {
59142
+ this.tasks.set(id, {
59143
+ text: texts[index2] || "",
59144
+ status: "pending"
59145
+ });
59146
+ });
59147
+ }
59148
+ start() {
59149
+ if (isInteractive2) {
59150
+ stdout2.write(cursor2.hide);
59151
+ this.render();
59152
+ this.intervalId = setInterval(() => {
59153
+ this.frameIndex = (this.frameIndex + 1) % SPINNER_FRAMES2.length;
59154
+ this.render();
59155
+ }, SPINNER_INTERVAL2);
59156
+ }
59157
+ }
59158
+ updateTask(taskId, status, finalText) {
59159
+ const task = this.tasks.get(taskId);
59160
+ if (task) {
59161
+ task.status = status;
59162
+ if (finalText)
59163
+ task.finalText = finalText;
59164
+ if (!isInteractive2) {
59165
+ this.renderNonInteractive(taskId, task);
59166
+ }
59167
+ }
59168
+ }
59169
+ renderNonInteractive(taskId, task) {
59170
+ const key = `${taskId}-${task.status}`;
59171
+ if (this.printedTasks.has(key))
59172
+ return;
59173
+ this.printedTasks.add(key);
59174
+ const indentStr = " ".repeat(this.indent);
59175
+ let line3 = "";
59176
+ switch (task.status) {
59177
+ case "running":
59178
+ line3 = `${indentStr}[RUNNING] ${stripAnsi2(task.text)}`;
59179
+ break;
59180
+ case "success":
59181
+ line3 = `${indentStr}[SUCCESS] ${stripAnsi2(task.finalText || task.text)}`;
59182
+ break;
59183
+ case "error":
59184
+ line3 = `${indentStr}[ERROR] Failed: ${stripAnsi2(task.text)}`;
59185
+ break;
59186
+ }
59187
+ console.log(line3);
59188
+ }
59189
+ render() {
59190
+ if (this.previousLineCount > 0) {
59191
+ stdout2.write(cursor2.up(this.previousLineCount));
59192
+ }
59193
+ const spinner2 = SPINNER_FRAMES2[this.frameIndex];
59194
+ const indentStr = " ".repeat(this.indent);
59195
+ const visibleTasks = Array.from(this.tasks.values()).filter((task) => task.status !== "pending");
59196
+ for (const task of visibleTasks) {
59197
+ stdout2.write(`\r${cursor2.clearLine}`);
59198
+ let line3 = "";
59199
+ switch (task.status) {
59200
+ case "running":
59201
+ line3 = `${indentStr}${colors22.blue}${spinner2}${styles2.reset} ${task.text}`;
59202
+ break;
59203
+ case "success":
59204
+ line3 = `${indentStr}${colors22.green}${CHECK_MARK2}${styles2.reset} ${task.finalText || task.text}`;
59205
+ break;
59206
+ case "error":
59207
+ line3 = `${indentStr}${colors22.red}${CROSS_MARK2}${styles2.reset} Failed: ${task.text}`;
59208
+ break;
59209
+ }
59210
+ console.log(line3);
59211
+ }
59212
+ this.previousLineCount = visibleTasks.length;
59213
+ this.renderCount++;
59214
+ }
59215
+ stop() {
59216
+ if (this.intervalId) {
59217
+ clearInterval(this.intervalId);
59218
+ this.intervalId = null;
59219
+ }
59220
+ if (isInteractive2) {
59221
+ this.render();
59222
+ stdout2.write(cursor2.show);
59223
+ } else {
59224
+ this.tasks.forEach((task, taskId) => {
59225
+ if (task.status !== "pending") {
59226
+ this.renderNonInteractive(taskId, task);
59227
+ }
59228
+ });
59229
+ }
59230
+ }
59231
+ }
59232
+ function kebabToTitleCase(kebabStr) {
59233
+ return kebabStr.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
59234
+ }
59235
+ function formatDateYMD(date3 = new Date) {
59236
+ return date3.toISOString().split("T")[0];
59237
+ }
59045
59238
  async function deleteTimebackResources(client, courseId) {
59046
59239
  const sourcedIds = deriveSourcedIds(courseId);
59047
59240
  const { fetchTimebackConfig: fetchTimebackConfig2 } = await Promise.resolve().then(() => (init_verify(), exports_verify));
@@ -60201,9 +60394,6 @@ class MasteryTracker {
60201
60394
  return total;
60202
60395
  }
60203
60396
  }
60204
- function kebabToTitleCase(kebabStr) {
60205
- return kebabStr.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
60206
- }
60207
60397
  function validateProgressData(progressData) {
60208
60398
  if (!progressData.subject) {
60209
60399
  throw new ConfigurationError("subject", "Subject is required for Caliper events. Provide it in progressData.subject");
@@ -60226,30 +60416,39 @@ function validateSessionData(sessionData) {
60226
60416
  throw new ConfigurationError("sensorUrl", 'Sensor URL is required for Caliper events. Provide it in sessionData.sensorUrl (e.g., "https://hub.playcademy.net/p/your-game")');
60227
60417
  }
60228
60418
  }
60229
- function calculateXp(durationSeconds, accuracy, isFirstAttempt) {
60230
- const durationMinutes = durationSeconds / 60;
60231
- const baseXp = durationMinutes * 1;
60232
- let multiplier;
60233
- if (isFirstAttempt) {
60234
- if (accuracy === 1) {
60235
- multiplier = 1.25;
60236
- } else if (accuracy >= 0.8) {
60237
- multiplier = 1;
60238
- } else if (accuracy >= 0.65) {
60239
- multiplier = 0.5;
60240
- } else {
60241
- multiplier = 0;
60242
- }
60419
+ function getAttemptMultiplier(attemptNumber) {
60420
+ switch (attemptNumber) {
60421
+ case 1:
60422
+ return 1;
60423
+ case 2:
60424
+ return 0.5;
60425
+ case 3:
60426
+ return 0.25;
60427
+ default:
60428
+ return 0;
60429
+ }
60430
+ }
60431
+ function getAccuracyMultiplier(accuracy) {
60432
+ if (!Number.isFinite(accuracy) || accuracy < 0) {
60433
+ return 0;
60434
+ }
60435
+ if (accuracy >= PERFECT_ACCURACY_THRESHOLD) {
60436
+ return 1.25;
60437
+ } else if (accuracy >= 0.8) {
60438
+ return 1;
60243
60439
  } else {
60244
- if (accuracy === 1) {
60245
- multiplier = 1;
60246
- } else if (accuracy >= 0.8) {
60247
- multiplier = 0.5;
60248
- } else {
60249
- multiplier = 0;
60250
- }
60440
+ return 0;
60251
60441
  }
60252
- return Math.round(baseXp * multiplier * 10) / 10;
60442
+ }
60443
+ function calculateXp(durationSeconds, accuracy, attemptNumber) {
60444
+ if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) {
60445
+ return 0;
60446
+ }
60447
+ const durationMinutes = durationSeconds / 60;
60448
+ const baseXp = durationMinutes * 1;
60449
+ const accuracyMultiplier = getAccuracyMultiplier(accuracy);
60450
+ const attemptMultiplier = getAttemptMultiplier(attemptNumber);
60451
+ return Math.round(baseXp * accuracyMultiplier * attemptMultiplier * 10) / 10;
60253
60452
  }
60254
60453
 
60255
60454
  class ProgressRecorder {
@@ -60272,8 +60471,7 @@ class ProgressRecorder {
60272
60471
  const { score, totalQuestions, correctQuestions, xpEarned, masteredUnits, attemptNumber } = progressData;
60273
60472
  const actualLineItemId = await this.resolveAssessmentLineItem(activityId, activityName, progressData.classId, ids);
60274
60473
  const currentAttemptNumber = await this.resolveAttemptNumber(attemptNumber, score, studentId, actualLineItemId);
60275
- const isFirstActiveAttempt = currentAttemptNumber === 1;
60276
- const calculatedXp = this.calculateXpForProgress(progressData, totalQuestions, correctQuestions, xpEarned, isFirstActiveAttempt);
60474
+ const calculatedXp = this.calculateXpForProgress(progressData, totalQuestions, correctQuestions, xpEarned, currentAttemptNumber);
60277
60475
  let extensions = progressData.extensions;
60278
60476
  const masteryProgress = await this.masteryTracker.checkProgress({
60279
60477
  studentId,
@@ -60344,18 +60542,18 @@ class ProgressRecorder {
60344
60542
  }
60345
60543
  return 1;
60346
60544
  }
60347
- calculateXpForProgress(progressData, totalQuestions, correctQuestions, xpEarned, isFirstAttempt) {
60545
+ calculateXpForProgress(progressData, totalQuestions, correctQuestions, xpEarned, attemptNumber) {
60348
60546
  if (xpEarned !== undefined) {
60349
60547
  log3.debug("[ProgressRecorder] Using provided XP", { xpEarned });
60350
60548
  return xpEarned;
60351
60549
  }
60352
60550
  if (progressData.sessionDurationSeconds && totalQuestions && correctQuestions) {
60353
60551
  const accuracy = correctQuestions / totalQuestions;
60354
- const calculatedXp = calculateXp(progressData.sessionDurationSeconds, accuracy, isFirstAttempt);
60552
+ const calculatedXp = calculateXp(progressData.sessionDurationSeconds, accuracy, attemptNumber);
60355
60553
  log3.debug("[ProgressRecorder] Calculated XP", {
60356
60554
  durationSeconds: progressData.sessionDurationSeconds,
60357
60555
  accuracy,
60358
- isFirstAttempt,
60556
+ attemptNumber,
60359
60557
  calculatedXp
60360
60558
  });
60361
60559
  return calculatedXp;
@@ -61312,6 +61510,70 @@ class TimebackClient {
61312
61510
  this.cacheManager.setEnrollments(studentId, enrollments);
61313
61511
  return enrollments;
61314
61512
  }
61513
+ async getStudentXp(studentId, options) {
61514
+ await this._ensureAuthenticated();
61515
+ const enrollments = await this.edubridge.enrollments.listByUser(studentId);
61516
+ const filteredEnrollments = options?.courseIds?.length ? enrollments.filter((e) => options.courseIds.includes(e.course.id)) : enrollments;
61517
+ if (filteredEnrollments.length === 0) {
61518
+ return {
61519
+ totalXp: 0,
61520
+ ...options?.include?.today && { todayXp: 0 },
61521
+ ...options?.include?.perCourse && { courses: [] }
61522
+ };
61523
+ }
61524
+ const analyticsResults = await Promise.all(filteredEnrollments.map(async (enrollment) => {
61525
+ try {
61526
+ const analytics = await this.edubridge.analytics.getEnrollmentFacts(enrollment.id);
61527
+ return { enrollment, analytics };
61528
+ } catch (error) {
61529
+ log3.warn("[TimebackClient] Failed to fetch analytics for enrollment", {
61530
+ enrollmentId: enrollment.id,
61531
+ error
61532
+ });
61533
+ return { enrollment, analytics: null };
61534
+ }
61535
+ }));
61536
+ const today = formatDateYMD();
61537
+ let totalXp = 0;
61538
+ let todayXp = 0;
61539
+ const courses = [];
61540
+ for (const { enrollment, analytics } of analyticsResults) {
61541
+ let courseXp = 0;
61542
+ let courseTodayXp = 0;
61543
+ if (analytics?.facts) {
61544
+ for (const [date3, subjects] of Object.entries(analytics.facts)) {
61545
+ for (const subjectData of Object.values(subjects)) {
61546
+ const xp = subjectData.activityMetrics?.xpEarned ?? 0;
61547
+ courseXp += xp;
61548
+ if (date3 === today) {
61549
+ courseTodayXp += xp;
61550
+ }
61551
+ }
61552
+ }
61553
+ }
61554
+ totalXp += courseXp;
61555
+ todayXp += courseTodayXp;
61556
+ if (options?.include?.perCourse) {
61557
+ const gradeStr = enrollment.course.grades?.[0];
61558
+ const parsedGrade = gradeStr ? parseInt(gradeStr, 10) : 0;
61559
+ const grade = isTimebackGrade2(parsedGrade) ? parsedGrade : 0;
61560
+ const subjectStr = enrollment.course.subjects?.[0];
61561
+ const subject = subjectStr && isTimebackSubject2(subjectStr) ? subjectStr : "None";
61562
+ courses.push({
61563
+ grade,
61564
+ subject,
61565
+ title: enrollment.course.title,
61566
+ totalXp: courseXp,
61567
+ ...options?.include?.today && { todayXp: courseTodayXp }
61568
+ });
61569
+ }
61570
+ }
61571
+ return {
61572
+ totalXp,
61573
+ ...options?.include?.today && { todayXp },
61574
+ ...options?.include?.perCourse && { courses }
61575
+ };
61576
+ }
61315
61577
  clearCaches() {
61316
61578
  this.cacheManager.clearAll();
61317
61579
  }
@@ -61355,7 +61617,7 @@ var ACHIEVEMENT_IDS3;
61355
61617
  var ACHIEVEMENT_DEFINITIONS3;
61356
61618
  var init_achievements3;
61357
61619
  var init_auth3 = () => {};
61358
- var TSC_PACKAGE3 = "@typescript/native-preview";
61620
+ var TSC_PACKAGE3 = "typescript";
61359
61621
  var USE_NATIVE_TSC3;
61360
61622
  var init_typescript3;
61361
61623
  var init_character3 = () => {};
@@ -61412,7 +61674,7 @@ var PLAYCADEMY_DEFAULTS2;
61412
61674
  var RESOURCE_DEFAULTS2;
61413
61675
  var HTTP_STATUS2;
61414
61676
  var ERROR_NAMES2;
61415
- var init_constants3;
61677
+ var init_constants4;
61416
61678
  var exports_verify;
61417
61679
  var init_verify;
61418
61680
  var TimebackError;
@@ -61591,7 +61853,16 @@ var createLogger2 = (scopeName) => {
61591
61853
  };
61592
61854
  };
61593
61855
  var log3;
61856
+ var colors22;
61857
+ var styles2;
61858
+ var cursor2;
61859
+ var isInteractive2;
61860
+ var SPINNER_FRAMES2;
61861
+ var CHECK_MARK2;
61862
+ var CROSS_MARK2;
61863
+ var SPINNER_INTERVAL2 = 80;
61594
61864
  var TimebackAuthError;
61865
+ var PERFECT_ACCURACY_THRESHOLD = 0.999999;
61595
61866
  var exports_external2;
61596
61867
  var util3;
61597
61868
  var objectUtil2;
@@ -62106,7 +62377,7 @@ var init_dist3 = __esm(() => {
62106
62377
  init_timeback4();
62107
62378
  init_workers3();
62108
62379
  });
62109
- init_constants3 = __esm3(() => {
62380
+ init_constants4 = __esm3(() => {
62110
62381
  init_src6();
62111
62382
  TIMEBACK_API_URLS2 = {
62112
62383
  production: "https://api.alpha-1edtech.ai",
@@ -62287,9 +62558,9 @@ var init_dist3 = __esm(() => {
62287
62558
  fetchTimebackConfig: () => fetchTimebackConfig
62288
62559
  });
62289
62560
  init_verify = __esm3(() => {
62290
- init_constants3();
62561
+ init_constants4();
62291
62562
  });
62292
- init_constants3();
62563
+ init_constants4();
62293
62564
  TimebackError = class TimebackError2 extends Error {
62294
62565
  constructor(message) {
62295
62566
  super(message);
@@ -62346,7 +62617,7 @@ var init_dist3 = __esm(() => {
62346
62617
  Object.setPrototypeOf(this, ResourceNotFoundError2.prototype);
62347
62618
  }
62348
62619
  };
62349
- init_constants3();
62620
+ init_constants4();
62350
62621
  SUBJECT_VALUES2 = TIMEBACK_SUBJECTS2;
62351
62622
  GRADE_VALUES2 = TIMEBACK_GRADE_LEVELS2;
62352
62623
  colors3 = {
@@ -62366,9 +62637,53 @@ var init_dist3 = __esm(() => {
62366
62637
  error: 3
62367
62638
  };
62368
62639
  log3 = createLogger2();
62640
+ colors22 = {
62641
+ black: "\x1B[30m",
62642
+ red: "\x1B[31m",
62643
+ green: "\x1B[32m",
62644
+ yellow: "\x1B[33m",
62645
+ blue: "\x1B[34m",
62646
+ magenta: "\x1B[35m",
62647
+ cyan: "\x1B[36m",
62648
+ white: "\x1B[37m",
62649
+ gray: "\x1B[90m"
62650
+ };
62651
+ styles2 = {
62652
+ reset: "\x1B[0m",
62653
+ bold: "\x1B[1m",
62654
+ dim: "\x1B[2m",
62655
+ italic: "\x1B[3m",
62656
+ underline: "\x1B[4m"
62657
+ };
62658
+ cursor2 = {
62659
+ hide: "\x1B[?25l",
62660
+ show: "\x1B[?25h",
62661
+ up: (n) => `\x1B[${n}A`,
62662
+ down: (n) => `\x1B[${n}B`,
62663
+ forward: (n) => `\x1B[${n}C`,
62664
+ back: (n) => `\x1B[${n}D`,
62665
+ clearLine: "\x1B[K",
62666
+ clearScreen: "\x1B[2J",
62667
+ home: "\x1B[H"
62668
+ };
62669
+ isInteractive2 = typeof process !== "undefined" && process.stdout?.isTTY && !process.env.CI && process.env.TERM !== "dumb";
62670
+ SPINNER_FRAMES2 = [
62671
+ 10251,
62672
+ 10265,
62673
+ 10297,
62674
+ 10296,
62675
+ 10300,
62676
+ 10292,
62677
+ 10278,
62678
+ 10279,
62679
+ 10247,
62680
+ 10255
62681
+ ].map((code) => String.fromCodePoint(code));
62682
+ CHECK_MARK2 = String.fromCodePoint(10004);
62683
+ CROSS_MARK2 = String.fromCodePoint(10006);
62369
62684
  init_verify();
62370
- init_constants3();
62371
- init_constants3();
62685
+ init_constants4();
62686
+ init_constants4();
62372
62687
  if (process.env.DEBUG === "true") {
62373
62688
  process.env.TERM = "dumb";
62374
62689
  }
@@ -62380,13 +62695,13 @@ var init_dist3 = __esm(() => {
62380
62695
  this.name = ERROR_NAMES2.timebackAuth;
62381
62696
  }
62382
62697
  };
62383
- init_constants3();
62384
- init_constants3();
62385
- init_constants3();
62386
- init_constants3();
62387
- init_constants3();
62388
- init_constants3();
62389
- init_constants3();
62698
+ init_constants4();
62699
+ init_constants4();
62700
+ init_constants4();
62701
+ init_constants4();
62702
+ init_constants4();
62703
+ init_constants4();
62704
+ init_constants4();
62390
62705
  exports_external2 = {};
62391
62706
  __export2(exports_external2, {
62392
62707
  void: () => voidType2,
@@ -65926,7 +66241,7 @@ var compose = (middleware, onError, onNotFound) => {
65926
66241
  var init_compose = () => {};
65927
66242
  var init_http_exception = () => {};
65928
66243
  var GET_MATCH_RESULT;
65929
- var init_constants4 = __esm(() => {
66244
+ var init_constants5 = __esm(() => {
65930
66245
  GET_MATCH_RESULT = Symbol();
65931
66246
  });
65932
66247
  async function parseFormData(request2, options) {
@@ -66203,7 +66518,7 @@ var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
66203
66518
  var HonoRequest;
66204
66519
  var init_request = __esm(() => {
66205
66520
  init_http_exception();
66206
- init_constants4();
66521
+ init_constants5();
66207
66522
  init_body();
66208
66523
  init_url();
66209
66524
  HonoRequest = class {
@@ -66533,7 +66848,7 @@ var init_router = __esm(() => {
66533
66848
  };
66534
66849
  });
66535
66850
  var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
66536
- var init_constants5 = () => {};
66851
+ var init_constants6 = () => {};
66537
66852
  var notFoundHandler = (c) => {
66538
66853
  return c.text("404 Not Found", 404);
66539
66854
  };
@@ -66755,7 +67070,7 @@ var init_hono_base = __esm(() => {
66755
67070
  init_compose();
66756
67071
  init_context2();
66757
67072
  init_router();
66758
- init_constants5();
67073
+ init_constants6();
66759
67074
  init_url();
66760
67075
  });
66761
67076
  function match(method, path2) {
@@ -75346,29 +75661,29 @@ is not a problem with esbuild. You need to fix your environment instead.
75346
75661
  let responseCallbacks = {};
75347
75662
  let nextRequestID = 0;
75348
75663
  let nextBuildKey = 0;
75349
- let stdout2 = new Uint8Array(16384);
75664
+ let stdout3 = new Uint8Array(16384);
75350
75665
  let stdoutUsed = 0;
75351
75666
  let readFromStdout = (chunk) => {
75352
75667
  let limit = stdoutUsed + chunk.length;
75353
- if (limit > stdout2.length) {
75668
+ if (limit > stdout3.length) {
75354
75669
  let swap = new Uint8Array(limit * 2);
75355
- swap.set(stdout2);
75356
- stdout2 = swap;
75670
+ swap.set(stdout3);
75671
+ stdout3 = swap;
75357
75672
  }
75358
- stdout2.set(chunk, stdoutUsed);
75673
+ stdout3.set(chunk, stdoutUsed);
75359
75674
  stdoutUsed += chunk.length;
75360
75675
  let offset = 0;
75361
75676
  while (offset + 4 <= stdoutUsed) {
75362
- let length = readUInt32LE(stdout2, offset);
75677
+ let length = readUInt32LE(stdout3, offset);
75363
75678
  if (offset + 4 + length > stdoutUsed) {
75364
75679
  break;
75365
75680
  }
75366
75681
  offset += 4;
75367
- handleIncomingPacket(stdout2.subarray(offset, offset + length));
75682
+ handleIncomingPacket(stdout3.subarray(offset, offset + length));
75368
75683
  offset += length;
75369
75684
  }
75370
75685
  if (offset > 0) {
75371
- stdout2.copyWithin(0, offset, stdoutUsed);
75686
+ stdout3.copyWithin(0, offset, stdoutUsed);
75372
75687
  stdoutUsed -= offset;
75373
75688
  }
75374
75689
  };
@@ -76856,12 +77171,12 @@ More information: The file containing the code for esbuild's JavaScript API (${_
76856
77171
  child.stdin.on("error", afterClose);
76857
77172
  child.on("error", afterClose);
76858
77173
  const stdin = child.stdin;
76859
- const stdout2 = child.stdout;
76860
- stdout2.on("data", readFromStdout);
76861
- stdout2.on("end", afterClose);
77174
+ const stdout3 = child.stdout;
77175
+ stdout3.on("data", readFromStdout);
77176
+ stdout3.on("end", afterClose);
76862
77177
  stopService = () => {
76863
77178
  stdin.destroy();
76864
- stdout2.destroy();
77179
+ stdout3.destroy();
76865
77180
  child.kill();
76866
77181
  initializeWasCalled = false;
76867
77182
  longLivedService = undefined;
@@ -76872,8 +77187,8 @@ More information: The file containing the code for esbuild's JavaScript API (${_
76872
77187
  if (stdin.unref) {
76873
77188
  stdin.unref();
76874
77189
  }
76875
- if (stdout2.unref) {
76876
- stdout2.unref();
77190
+ if (stdout3.unref) {
77191
+ stdout3.unref();
76877
77192
  }
76878
77193
  const refs = {
76879
77194
  ref() {
@@ -76944,13 +77259,13 @@ More information: The file containing the code for esbuild's JavaScript API (${_
76944
77259
  esbuild: node_exports
76945
77260
  });
76946
77261
  callback(service);
76947
- let stdout2 = child_process.execFileSync(command, args2.concat("--service=0.25.10"), {
77262
+ let stdout3 = child_process.execFileSync(command, args2.concat("--service=0.25.10"), {
76948
77263
  cwd: defaultWD,
76949
77264
  windowsHide: true,
76950
77265
  input: stdin,
76951
77266
  maxBuffer: +process.env.ESBUILD_MAX_BUFFER || 16777216
76952
77267
  });
76953
- readFromStdout(stdout2);
77268
+ readFromStdout(stdout3);
76954
77269
  afterClose(null);
76955
77270
  };
76956
77271
  var randomFileName = () => {
@@ -82664,33 +82979,33 @@ __export(exports_api, {
82664
82979
  });
82665
82980
  function assembleStyles() {
82666
82981
  const codes = /* @__PURE__ */ new Map;
82667
- for (const [groupName, group] of Object.entries(styles2)) {
82982
+ for (const [groupName, group] of Object.entries(styles3)) {
82668
82983
  for (const [styleName, style] of Object.entries(group)) {
82669
- styles2[styleName] = {
82984
+ styles3[styleName] = {
82670
82985
  open: `\x1B[${style[0]}m`,
82671
82986
  close: `\x1B[${style[1]}m`
82672
82987
  };
82673
- group[styleName] = styles2[styleName];
82988
+ group[styleName] = styles3[styleName];
82674
82989
  codes.set(style[0], style[1]);
82675
82990
  }
82676
- Object.defineProperty(styles2, groupName, {
82991
+ Object.defineProperty(styles3, groupName, {
82677
82992
  value: group,
82678
82993
  enumerable: false
82679
82994
  });
82680
82995
  }
82681
- Object.defineProperty(styles2, "codes", {
82996
+ Object.defineProperty(styles3, "codes", {
82682
82997
  value: codes,
82683
82998
  enumerable: false
82684
82999
  });
82685
- styles2.color.close = "\x1B[39m";
82686
- styles2.bgColor.close = "\x1B[49m";
82687
- styles2.color.ansi = wrapAnsi16();
82688
- styles2.color.ansi256 = wrapAnsi256();
82689
- styles2.color.ansi16m = wrapAnsi16m();
82690
- styles2.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
82691
- styles2.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
82692
- styles2.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
82693
- Object.defineProperties(styles2, {
83000
+ styles3.color.close = "\x1B[39m";
83001
+ styles3.bgColor.close = "\x1B[49m";
83002
+ styles3.color.ansi = wrapAnsi16();
83003
+ styles3.color.ansi256 = wrapAnsi256();
83004
+ styles3.color.ansi16m = wrapAnsi16m();
83005
+ styles3.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
83006
+ styles3.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
83007
+ styles3.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
83008
+ Object.defineProperties(styles3, {
82694
83009
  rgbToAnsi256: {
82695
83010
  value(red, green, blue) {
82696
83011
  if (red === green && green === blue) {
@@ -82726,7 +83041,7 @@ function assembleStyles() {
82726
83041
  enumerable: false
82727
83042
  },
82728
83043
  hexToAnsi256: {
82729
- value: (hex) => styles2.rgbToAnsi256(...styles2.hexToRgb(hex)),
83044
+ value: (hex) => styles3.rgbToAnsi256(...styles3.hexToRgb(hex)),
82730
83045
  enumerable: false
82731
83046
  },
82732
83047
  ansi256ToAnsi: {
@@ -82764,15 +83079,15 @@ function assembleStyles() {
82764
83079
  enumerable: false
82765
83080
  },
82766
83081
  rgbToAnsi: {
82767
- value: (red, green, blue) => styles2.ansi256ToAnsi(styles2.rgbToAnsi256(red, green, blue)),
83082
+ value: (red, green, blue) => styles3.ansi256ToAnsi(styles3.rgbToAnsi256(red, green, blue)),
82768
83083
  enumerable: false
82769
83084
  },
82770
83085
  hexToAnsi: {
82771
- value: (hex) => styles2.ansi256ToAnsi(styles2.hexToAnsi256(hex)),
83086
+ value: (hex) => styles3.ansi256ToAnsi(styles3.hexToAnsi256(hex)),
82772
83087
  enumerable: false
82773
83088
  }
82774
83089
  });
82775
- return styles2;
83090
+ return styles3;
82776
83091
  }
82777
83092
  function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process2.argv) {
82778
83093
  const prefix2 = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
@@ -85354,7 +85669,7 @@ var ANSI_BACKGROUND_OFFSET;
85354
85669
  var wrapAnsi16;
85355
85670
  var wrapAnsi256;
85356
85671
  var wrapAnsi16m;
85357
- var styles2;
85672
+ var styles3;
85358
85673
  var modifierNames;
85359
85674
  var foregroundColorNames;
85360
85675
  var backgroundColorNames;
@@ -85731,7 +86046,7 @@ var tableKey;
85731
86046
  var ResolveSelectNamed;
85732
86047
  var ResolveSelect;
85733
86048
  var ResolveSchemasSelect;
85734
- var Spinner2;
86049
+ var Spinner3;
85735
86050
  var ProgressView;
85736
86051
  var init_views;
85737
86052
  var glob;
@@ -88232,7 +88547,7 @@ var init_api2 = __esm(() => {
88232
88547
  wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
88233
88548
  wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
88234
88549
  wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
88235
- styles2 = {
88550
+ styles3 = {
88236
88551
  modifier: {
88237
88552
  reset: [0, 0],
88238
88553
  bold: [1, 22],
@@ -88285,9 +88600,9 @@ var init_api2 = __esm(() => {
88285
88600
  bgWhiteBright: [107, 49]
88286
88601
  }
88287
88602
  };
88288
- modifierNames = Object.keys(styles2.modifier);
88289
- foregroundColorNames = Object.keys(styles2.color);
88290
- backgroundColorNames = Object.keys(styles2.bgColor);
88603
+ modifierNames = Object.keys(styles3.modifier);
88604
+ foregroundColorNames = Object.keys(styles3.color);
88605
+ backgroundColorNames = Object.keys(styles3.bgColor);
88291
88606
  colorNames = [...foregroundColorNames, ...backgroundColorNames];
88292
88607
  ansiStyles = assembleStyles();
88293
88608
  ansi_styles_default = ansiStyles;
@@ -90766,7 +91081,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
90766
91081
  exports.prepareReadLine = undefined;
90767
91082
  var prepareReadLine = () => {
90768
91083
  const stdin = process.stdin;
90769
- const stdout2 = process.stdout;
91084
+ const stdout3 = process.stdout;
90770
91085
  const readline = __require22("readline");
90771
91086
  const rl = readline.createInterface({
90772
91087
  input: stdin,
@@ -90775,7 +91090,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
90775
91090
  readline.emitKeypressEvents(stdin, rl);
90776
91091
  return {
90777
91092
  stdin,
90778
- stdout: stdout2,
91093
+ stdout: stdout3,
90779
91094
  closable: rl
90780
91095
  };
90781
91096
  };
@@ -90787,7 +91102,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
90787
91102
  var ESC = "\x1B";
90788
91103
  var CSI = `${ESC}[`;
90789
91104
  var beep = "\x07";
90790
- var cursor2 = {
91105
+ var cursor3 = {
90791
91106
  to(x5, y3) {
90792
91107
  if (!y3)
90793
91108
  return `${CSI}${x5 + 1}G`;
@@ -90831,13 +91146,13 @@ See: https://github.com/isaacs/node-glob/issues/167`);
90831
91146
  lines(count2) {
90832
91147
  let clear = "";
90833
91148
  for (let i3 = 0;i3 < count2; i3++)
90834
- clear += this.line + (i3 < count2 - 1 ? cursor2.up() : "");
91149
+ clear += this.line + (i3 < count2 - 1 ? cursor3.up() : "");
90835
91150
  if (count2)
90836
- clear += cursor2.left;
91151
+ clear += cursor3.left;
90837
91152
  return clear;
90838
91153
  }
90839
91154
  };
90840
- module2.exports = { cursor: cursor2, scroll, erase, beep };
91155
+ module2.exports = { cursor: cursor3, scroll, erase, beep };
90841
91156
  }
90842
91157
  });
90843
91158
  require_utils5 = __commonJS22({
@@ -91125,10 +91440,10 @@ See: https://github.com/isaacs/node-glob/issues/167`);
91125
91440
  };
91126
91441
  exports.deferred = deferred;
91127
91442
  var Terminal = class {
91128
- constructor(view5, stdin, stdout2, closable) {
91443
+ constructor(view5, stdin, stdout3, closable) {
91129
91444
  this.view = view5;
91130
91445
  this.stdin = stdin;
91131
- this.stdout = stdout2;
91446
+ this.stdout = stdout3;
91132
91447
  this.closable = closable;
91133
91448
  this.text = "";
91134
91449
  this.status = "idle";
@@ -91226,9 +91541,9 @@ See: https://github.com/isaacs/node-glob/issues/167`);
91226
91541
  };
91227
91542
  exports.TaskView = TaskView2;
91228
91543
  var TaskTerminal = class {
91229
- constructor(view5, stdout2) {
91544
+ constructor(view5, stdout3) {
91230
91545
  this.view = view5;
91231
- this.stdout = stdout2;
91546
+ this.stdout = stdout3;
91232
91547
  this.text = "";
91233
91548
  this.view.attach(this);
91234
91549
  }
@@ -91247,13 +91562,13 @@ See: https://github.com/isaacs/node-glob/issues/167`);
91247
91562
  };
91248
91563
  exports.TaskTerminal = TaskTerminal;
91249
91564
  function render7(view5) {
91250
- const { stdin, stdout: stdout2, closable } = (0, readline_1.prepareReadLine)();
91565
+ const { stdin, stdout: stdout3, closable } = (0, readline_1.prepareReadLine)();
91251
91566
  if (view5 instanceof Prompt3) {
91252
- const terminal = new Terminal(view5, stdin, stdout2, closable);
91567
+ const terminal = new Terminal(view5, stdin, stdout3, closable);
91253
91568
  terminal.requestLayout();
91254
91569
  return terminal.result();
91255
91570
  }
91256
- stdout2.write(`${view5}
91571
+ stdout3.write(`${view5}
91257
91572
  `);
91258
91573
  closable.close();
91259
91574
  return;
@@ -96911,7 +97226,7 @@ Is ${source_default.bold.blue(this.base.name)} schema created or renamed from an
96911
97226
  return this.state.items[this.state.selectedIdx];
96912
97227
  }
96913
97228
  };
96914
- Spinner2 = class {
97229
+ Spinner3 = class {
96915
97230
  constructor(frames) {
96916
97231
  this.frames = frames;
96917
97232
  this.offset = 0;
@@ -96932,7 +97247,7 @@ Is ${source_default.bold.blue(this.base.name)} schema created or renamed from an
96932
97247
  super();
96933
97248
  this.progressText = progressText;
96934
97249
  this.successText = successText;
96935
- this.spinner = new Spinner2("⣷⣯⣟⡿⢿⣻⣽⣾".split(""));
97250
+ this.spinner = new Spinner3("⣷⣯⣟⡿⢿⣻⣽⣾".split(""));
96936
97251
  this.timeout = setInterval(() => {
96937
97252
  this.spinner.tick();
96938
97253
  this.requestLayout();
@@ -98022,8 +98337,8 @@ Is ${source_default.bold.blue(this.base.name)} schema created or renamed from an
98022
98337
  });
98023
98338
  require_styles = __commonJS22({
98024
98339
  "../node_modules/.pnpm/colors@1.4.0/node_modules/colors/lib/styles.js"(exports, module2) {
98025
- var styles3 = {};
98026
- module2["exports"] = styles3;
98340
+ var styles32 = {};
98341
+ module2["exports"] = styles32;
98027
98342
  var codes = {
98028
98343
  reset: [0, 0],
98029
98344
  bold: [1, 22],
@@ -98078,7 +98393,7 @@ Is ${source_default.bold.blue(this.base.name)} schema created or renamed from an
98078
98393
  };
98079
98394
  Object.keys(codes).forEach(function(key) {
98080
98395
  var val = codes[key];
98081
- var style = styles3[key] = [];
98396
+ var style = styles32[key] = [];
98082
98397
  style.open = "\x1B[" + val[0] + "m";
98083
98398
  style.close = "\x1B[" + val[1] + "m";
98084
98399
  });
@@ -98556,7 +98871,7 @@ Is ${source_default.bold.blue(this.base.name)} schema created or renamed from an
98556
98871
  builder.__proto__ = proto2;
98557
98872
  return builder;
98558
98873
  }
98559
- var styles3 = function() {
98874
+ var styles32 = function() {
98560
98875
  var ret = {};
98561
98876
  ansiStyles2.grey = ansiStyles2.gray;
98562
98877
  Object.keys(ansiStyles2).forEach(function(key) {
@@ -98569,7 +98884,7 @@ Is ${source_default.bold.blue(this.base.name)} schema created or renamed from an
98569
98884
  });
98570
98885
  return ret;
98571
98886
  }();
98572
- var proto2 = defineProps(function colors2() {}, styles3);
98887
+ var proto2 = defineProps(function colors2() {}, styles32);
98573
98888
  function applyStyle2() {
98574
98889
  var args2 = Array.prototype.slice.call(arguments);
98575
98890
  var str = args2.map(function(arg) {
@@ -98619,7 +98934,7 @@ Is ${source_default.bold.blue(this.base.name)} schema created or renamed from an
98619
98934
  };
98620
98935
  function init2() {
98621
98936
  var ret = {};
98622
- Object.keys(styles3).forEach(function(name22) {
98937
+ Object.keys(styles32).forEach(function(name22) {
98623
98938
  ret[name22] = {
98624
98939
  get: function() {
98625
98940
  return build([name22]);
@@ -125887,23 +126202,23 @@ var require_lexer = __commonJS2((exports) => {
125887
126202
  ];
125888
126203
  function tokenize(input) {
125889
126204
  const tokens = [];
125890
- let cursor2 = 0;
125891
- while (cursor2 < input.length) {
126205
+ let cursor3 = 0;
126206
+ while (cursor3 < input.length) {
125892
126207
  let matched = false;
125893
126208
  for (const tokenType of tokenTypes) {
125894
- const match3 = input.slice(cursor2).match(tokenType.regex);
126209
+ const match3 = input.slice(cursor3).match(tokenType.regex);
125895
126210
  if (match3) {
125896
126211
  tokens.push({
125897
126212
  type: tokenType.tokenType,
125898
126213
  value: match3[0]
125899
126214
  });
125900
- cursor2 += match3[0].length;
126215
+ cursor3 += match3[0].length;
125901
126216
  matched = true;
125902
126217
  break;
125903
126218
  }
125904
126219
  }
125905
126220
  if (!matched) {
125906
- throw new Error(`Unexpected character at position ${cursor2}`);
126221
+ throw new Error(`Unexpected character at position ${cursor3}`);
125907
126222
  }
125908
126223
  }
125909
126224
  return tokens;
@@ -126160,13 +126475,13 @@ var require_picocolors2 = __commonJS2((exports, module2) => {
126160
126475
  return ~index6 ? open + replaceClose(string2, close, replace, index6) + close : open + string2 + close;
126161
126476
  };
126162
126477
  var replaceClose = (string2, close, replace, index6) => {
126163
- let result = "", cursor2 = 0;
126478
+ let result = "", cursor3 = 0;
126164
126479
  do {
126165
- result += string2.substring(cursor2, index6) + replace;
126166
- cursor2 = index6 + close.length;
126167
- index6 = string2.indexOf(close, cursor2);
126480
+ result += string2.substring(cursor3, index6) + replace;
126481
+ cursor3 = index6 + close.length;
126482
+ index6 = string2.indexOf(close, cursor3);
126168
126483
  } while (~index6);
126169
- return result + string2.substring(cursor2);
126484
+ return result + string2.substring(cursor3);
126170
126485
  };
126171
126486
  var createColors = (enabled = isColorSupported) => {
126172
126487
  let f3 = enabled ? formatter : () => String;
@@ -126728,7 +127043,8 @@ var init_schemas3 = __esm(() => {
126728
127043
  });
126729
127044
  SetSecretsRequestSchema = exports_external.record(exports_external.string().min(1), exports_external.string());
126730
127045
  SeedRequestSchema = exports_external.object({
126731
- code: exports_external.string().min(1, "Seed code is required")
127046
+ code: exports_external.string().min(1, "Seed code is required"),
127047
+ secrets: exports_external.record(exports_external.string(), exports_external.string()).optional()
126732
127048
  });
126733
127049
  SchemaInfoSchema = exports_external.object({
126734
127050
  sql: exports_external.string(),
@@ -126995,6 +127311,16 @@ var init_schemas11 = __esm(() => {
126995
127311
  offset: exports_external.number().int().min(0).default(0)
126996
127312
  });
126997
127313
  });
127314
+ function isTimebackGrade3(value) {
127315
+ return Number.isInteger(value) && TIMEBACK_GRADES.includes(value);
127316
+ }
127317
+ function isTimebackSubject3(value) {
127318
+ return TIMEBACK_SUBJECTS3.includes(value);
127319
+ }
127320
+ var TIMEBACK_GRADES;
127321
+ var TIMEBACK_SUBJECTS3;
127322
+ var TimebackGradeSchema;
127323
+ var TimebackSubjectSchema;
126998
127324
  var UpdateTimebackXpRequestSchema;
126999
127325
  var EndActivityRequestSchema;
127000
127326
  var PopulateStudentRequestSchema;
@@ -127003,6 +127329,22 @@ var TimebackBaseConfigSchema;
127003
127329
  var PlatformTimebackSetupRequestSchema;
127004
127330
  var init_schemas12 = __esm(() => {
127005
127331
  init_esm();
127332
+ TIMEBACK_GRADES = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
127333
+ TIMEBACK_SUBJECTS3 = [
127334
+ "Reading",
127335
+ "Language",
127336
+ "Vocabulary",
127337
+ "Social Studies",
127338
+ "Writing",
127339
+ "Science",
127340
+ "FastMath",
127341
+ "Math",
127342
+ "None"
127343
+ ];
127344
+ TimebackGradeSchema = exports_external.number().int().refine((val) => TIMEBACK_GRADES.includes(val), {
127345
+ message: `Grade must be one of: ${TIMEBACK_GRADES.join(", ")}`
127346
+ });
127347
+ TimebackSubjectSchema = exports_external.enum(TIMEBACK_SUBJECTS3);
127006
127348
  UpdateTimebackXpRequestSchema = exports_external.object({
127007
127349
  xp: exports_external.number().min(0, "XP must be a non-negative number"),
127008
127350
  userTimestamp: exports_external.string().datetime().optional()
@@ -137804,8 +138146,13 @@ var init_seed_controller = __esm(() => {
137804
138146
  }
137805
138147
  throw ApiError.badRequest("Invalid JSON body");
137806
138148
  }
137807
- logger55.debug("Seeding database", { userId: ctx.user.id, slug: slug2, codeLength: body2.code.length });
137808
- return ctx.services.seed.seed(slug2, body2.code, ctx.user);
138149
+ logger55.debug("Seeding database", {
138150
+ userId: ctx.user.id,
138151
+ slug: slug2,
138152
+ codeLength: body2.code.length,
138153
+ secretCount: body2.secrets ? Object.keys(body2.secrets).length : 0
138154
+ });
138155
+ return ctx.services.seed.seed(slug2, body2.code, ctx.user, body2.secrets);
137809
138156
  });
137810
138157
  });
137811
138158
  var logger56;
@@ -138120,6 +138467,7 @@ var verifyIntegration;
138120
138467
  var getConfig2;
138121
138468
  var deleteIntegrations;
138122
138469
  var endActivity;
138470
+ var getStudentXp;
138123
138471
  var timeback2;
138124
138472
  var init_timeback_controller = __esm(() => {
138125
138473
  init_esm();
@@ -138263,6 +138611,46 @@ var init_timeback_controller = __esm(() => {
138263
138611
  logger60.debug("Ending activity", { userId: ctx.user.id, gameId });
138264
138612
  return ctx.services.timeback.endActivity(gameId, studentId, activityData, scoreData, timingData, xpEarned, masteredUnits, ctx.user);
138265
138613
  });
138614
+ getStudentXp = requireDeveloper(async (ctx) => {
138615
+ const timebackId = ctx.params.timebackId;
138616
+ if (!timebackId) {
138617
+ throw ApiError.badRequest("Missing timebackId parameter");
138618
+ }
138619
+ const gameId = ctx.url.searchParams.get("gameId") || undefined;
138620
+ const gradeParam = ctx.url.searchParams.get("grade");
138621
+ const subjectParam = ctx.url.searchParams.get("subject");
138622
+ if (gradeParam !== null !== (subjectParam !== null)) {
138623
+ throw ApiError.badRequest("Both grade and subject must be provided together");
138624
+ }
138625
+ let grade;
138626
+ let subject;
138627
+ if (gradeParam !== null && subjectParam !== null) {
138628
+ const parsedGrade = parseInt(gradeParam, 10);
138629
+ if (!isTimebackGrade3(parsedGrade)) {
138630
+ throw ApiError.badRequest(`Invalid grade: ${gradeParam}. Valid grades: ${TIMEBACK_GRADES.join(", ")}`);
138631
+ }
138632
+ if (!isTimebackSubject3(subjectParam)) {
138633
+ throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS3.join(", ")}`);
138634
+ }
138635
+ grade = parsedGrade;
138636
+ subject = subjectParam;
138637
+ }
138638
+ const includeParam = ctx.url.searchParams.get("include");
138639
+ const includeOptions = includeParam ? includeParam.split(",").map((opt) => opt.trim().toLowerCase()) : [];
138640
+ const include = {
138641
+ perCourse: includeOptions.includes("percourse"),
138642
+ today: includeOptions.includes("today")
138643
+ };
138644
+ logger60.debug("Getting student XP", {
138645
+ requesterId: ctx.user.id,
138646
+ timebackId,
138647
+ gameId,
138648
+ grade,
138649
+ subject,
138650
+ include
138651
+ });
138652
+ return ctx.services.timeback.getStudentXp(timebackId, { gameId, grade, subject, include });
138653
+ });
138266
138654
  timeback2 = {
138267
138655
  getTodayXp,
138268
138656
  getTotalXp,
@@ -138276,7 +138664,8 @@ var init_timeback_controller = __esm(() => {
138276
138664
  verifyIntegration,
138277
138665
  getConfig: getConfig2,
138278
138666
  deleteIntegrations,
138279
- endActivity
138667
+ endActivity,
138668
+ getStudentXp
138280
138669
  };
138281
138670
  });
138282
138671
  var logger61;
@@ -139353,6 +139742,56 @@ var init_timeback8 = __esm(() => {
139353
139742
  }
139354
139743
  return handle2(timeback2.getUserById)(c2);
139355
139744
  });
139745
+ timebackRouter.get("/student-xp/:timebackId", async (c2) => {
139746
+ const user = c2.get("user");
139747
+ if (!user) {
139748
+ const error2 = ApiError.unauthorized("Must be logged in to get student XP");
139749
+ return c2.json(createErrorResponse(error2), error2.status);
139750
+ }
139751
+ if (shouldMockTimeback()) {
139752
+ const url = new URL(c2.req.url);
139753
+ const gradeParam = url.searchParams.get("grade");
139754
+ const subjectParam = url.searchParams.get("subject");
139755
+ const includeParam = url.searchParams.get("include") || "";
139756
+ const includeOptions = includeParam.split(",").map((opt) => opt.trim().toLowerCase());
139757
+ const includePerCourse = includeOptions.includes("percourse");
139758
+ const includeToday = includeOptions.includes("today");
139759
+ const db2 = c2.get("db");
139760
+ let enrollments = await getMockEnrollments(db2);
139761
+ if (gradeParam !== null && subjectParam !== null) {
139762
+ const grade = parseInt(gradeParam, 10);
139763
+ enrollments = enrollments.filter((e) => e.grade === grade && e.subject === subjectParam);
139764
+ }
139765
+ const hashCode = (str) => {
139766
+ let hash = 0;
139767
+ for (let i3 = 0;i3 < str.length; i3++) {
139768
+ hash = (hash << 5) - hash + str.charCodeAt(i3);
139769
+ hash |= 0;
139770
+ }
139771
+ return Math.abs(hash);
139772
+ };
139773
+ const mockCourses = enrollments.map((e) => {
139774
+ const seed3 = hashCode(`${e.grade}-${e.subject}`);
139775
+ const totalXp2 = 100 + seed3 % 900;
139776
+ const todayXp2 = seed3 % 50;
139777
+ return {
139778
+ grade: e.grade,
139779
+ subject: e.subject,
139780
+ title: `${e.subject} Grade ${e.grade}`,
139781
+ totalXp: totalXp2,
139782
+ ...includeToday && { todayXp: todayXp2 }
139783
+ };
139784
+ });
139785
+ const totalXp = mockCourses.reduce((sum3, c3) => sum3 + c3.totalXp, 0);
139786
+ const todayXp = includeToday ? mockCourses.reduce((sum3, c3) => sum3 + (c3.todayXp ?? 0), 0) : undefined;
139787
+ return c2.json({
139788
+ totalXp,
139789
+ ...includeToday && { todayXp },
139790
+ ...includePerCourse && { courses: mockCourses }
139791
+ });
139792
+ }
139793
+ return handle2(timeback2.getStudentXp)(c2);
139794
+ });
139356
139795
  });
139357
139796
  function verifyMockToken(idToken) {
139358
139797
  if (!idToken.startsWith("mock:")) {
@@ -139805,7 +140244,7 @@ var ACHIEVEMENT_DEFINITIONS4 = [
139805
140244
  }
139806
140245
  ];
139807
140246
  // ../constants/src/typescript.ts
139808
- var TSC_PACKAGE4 = "@typescript/native-preview";
140247
+ var TSC_PACKAGE4 = "typescript";
139809
140248
  var USE_NATIVE_TSC4 = TSC_PACKAGE4.includes("native-preview");
139810
140249
  // ../constants/src/overworld.ts
139811
140250
  var ITEM_SLUGS4 = {
@@ -140104,7 +140543,7 @@ var init_auth5 = __esm5(() => {
140104
140543
  TIMEBACK_LTI: "timeback-lti"
140105
140544
  };
140106
140545
  });
140107
- var TSC_PACKAGE6 = "@typescript/native-preview";
140546
+ var TSC_PACKAGE6 = "typescript";
140108
140547
  var USE_NATIVE_TSC6;
140109
140548
  var init_typescript4 = __esm5(() => {
140110
140549
  USE_NATIVE_TSC6 = TSC_PACKAGE6.includes("native-preview");
@@ -140166,7 +140605,13 @@ var init_overworld4 = __esm5(() => {
140166
140605
  PLAYGROUND: "00000000-0000-0000-0000-000000000001"
140167
140606
  };
140168
140607
  });
140169
- var init_timeback9 = () => {};
140608
+ var TIMEBACK_ROUTES2;
140609
+ var init_timeback9 = __esm5(() => {
140610
+ TIMEBACK_ROUTES2 = {
140611
+ END_ACTIVITY: "/integrations/timeback/end-activity",
140612
+ GET_XP: "/integrations/timeback/xp"
140613
+ };
140614
+ });
140170
140615
  var WORKER_NAMING2;
140171
140616
  var init_workers4 = __esm5(() => {
140172
140617
  WORKER_NAMING2 = {
@@ -140396,13 +140841,13 @@ var init_demo_items2 = __esm5(() => {
140396
140841
  }
140397
140842
  ];
140398
140843
  });
140399
- var init_constants6 = __esm5(() => {
140844
+ var init_constants7 = __esm5(() => {
140400
140845
  init_src7();
140401
140846
  init_demo_users2();
140402
140847
  init_demo_tokens2();
140403
140848
  init_demo_items2();
140404
140849
  });
140405
- init_constants6();
140850
+ init_constants7();
140406
140851
 
140407
140852
  // src/lib/sandbox/token.ts
140408
140853
  var ROLE_TO_USER_ID = {
@@ -140768,7 +141213,7 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
140768
141213
  // package.json
140769
141214
  var package_default2 = {
140770
141215
  name: "@playcademy/vite-plugin",
140771
- version: "0.2.10",
141216
+ version: "0.2.12",
140772
141217
  type: "module",
140773
141218
  exports: {
140774
141219
  ".": {
@@ -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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/vite-plugin",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -22,11 +22,11 @@
22
22
  "dependencies": {
23
23
  "archiver": "^7.0.1",
24
24
  "picocolors": "^1.1.1",
25
- "playcademy": "0.16.3"
25
+ "playcademy": "0.16.6"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@inquirer/prompts": "^7.8.6",
29
- "@playcademy/sandbox": "0.3.12",
29
+ "@playcademy/sandbox": "0.3.14",
30
30
  "@playcademy/utils": "0.0.1",
31
31
  "@types/archiver": "^6.0.3",
32
32
  "@types/bun": "latest"