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

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.
Files changed (2) hide show
  1. package/dist/index.js +78 -11
  2. package/package.json +3 -3
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.21",
25373
+ version: "0.3.17-beta.23",
25374
25374
  description: "Local development server for Playcademy game development",
25375
25375
  type: "module",
25376
25376
  exports: {
@@ -54822,21 +54822,25 @@ class TimebackAdminService {
54822
54822
  });
54823
54823
  return new Map(results);
54824
54824
  }
54825
+ async fetchCaliperEventsForStudent(client, studentId, source, limit) {
54826
+ const actorId = `${client.getBaseUrl().replace(/\/$/, "")}/ims/oneroster/rostering/v1p2/users/${studentId}`;
54827
+ const { events } = await client.caliper.events.list({
54828
+ limit,
54829
+ actorId,
54830
+ ...source.sourceMode === "production" ? { sensor: source.sensorUrl } : {},
54831
+ extensions: {
54832
+ gameId: source.gameId
54833
+ }
54834
+ });
54835
+ return events;
54836
+ }
54825
54837
  async listRecentActivityForStudent(client, studentId, source, relevantCourseIds, maxResults = TimebackAdminService.RECENT_ACTIVITY_LIMIT) {
54826
54838
  if (relevantCourseIds.size === 0) {
54827
54839
  return [];
54828
54840
  }
54829
54841
  try {
54830
- const actorId = `${client.getBaseUrl().replace(/\/$/, "")}/ims/oneroster/rostering/v1p2/users/${studentId}`;
54831
54842
  const eventLimit = Math.min(Math.max(200, maxResults * 20), TimebackAdminService.MAX_RECENT_ACTIVITY_EVENT_FETCH);
54832
- const { events } = await client.caliper.events.list({
54833
- limit: eventLimit,
54834
- actorId,
54835
- ...source.sourceMode === "production" ? { sensor: source.sensorUrl } : {},
54836
- extensions: {
54837
- gameId: source.gameId
54838
- }
54839
- });
54843
+ const events = await this.fetchCaliperEventsForStudent(client, studentId, source, eventLimit);
54840
54844
  return TimebackAdminService.mapRecentActivityItems(events, relevantCourseIds).slice(0, maxResults);
54841
54845
  } catch (error) {
54842
54846
  logger16.warn("Failed to load recent Caliper activity", {
@@ -54960,6 +54964,42 @@ class TimebackAdminService {
54960
54964
  const hasMore = allActivities.length > safeOffset + safeLimit;
54961
54965
  return { activities, hasMore };
54962
54966
  }
54967
+ async getActivityDetail(user, options) {
54968
+ const { gameId, studentId, courseId, activityId, runId } = options;
54969
+ const client = this.requireClient();
54970
+ await this.deps.validateGameManagementAccess(user, gameId);
54971
+ const [integration, gameSource] = await Promise.all([
54972
+ this.deps.db.query.gameTimebackIntegrations.findFirst({
54973
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
54974
+ }),
54975
+ this.getGameActivitySource(gameId)
54976
+ ]);
54977
+ if (!integration) {
54978
+ throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
54979
+ }
54980
+ await this.assertStudentEnrolledInCourse(client, studentId, courseId);
54981
+ const events = await this.fetchCaliperEventsForStudent(client, studentId, gameSource, TimebackAdminService.MAX_RECENT_ACTIVITY_EVENT_FETCH);
54982
+ const relevantCourseIds = new Set([courseId]);
54983
+ let matchedEvents;
54984
+ let activity;
54985
+ if (runId) {
54986
+ const gameplayEvents = events.filter((event) => (event.type === "ActivityEvent" || event.type === "TimeSpentEvent") && !isCaliperRemediationOrCompletionEvent(event));
54987
+ const groups = groupCaliperEventsByRun(gameplayEvents);
54988
+ matchedEvents = [...groups.values()].find((group) => group.some((event) => getCanonicalRunId(event.session) === runId && event.externalId === activityId)) ?? [];
54989
+ activity = mapCaliperEventGroupToActivity(matchedEvents, relevantCourseIds);
54990
+ } else {
54991
+ matchedEvents = events.filter((event) => event.externalId === activityId);
54992
+ if (matchedEvents.length > 0) {
54993
+ activity = mapCaliperEventToRemediationActivity(matchedEvents[0], relevantCourseIds) ?? mapCaliperEventGroupToActivity(matchedEvents, relevantCourseIds);
54994
+ } else {
54995
+ activity = null;
54996
+ }
54997
+ }
54998
+ if (!activity) {
54999
+ throw new NotFoundError("Activity", activityId);
55000
+ }
55001
+ return { activity, rawEvents: matchedEvents };
55002
+ }
54963
55003
  async grantManualXp(data, user) {
54964
55004
  const { client, sensorUrl, appName, actor } = await this.resolveAdminMutationContext(data.gameId, data.courseId, user, data.studentId);
54965
55005
  await client.recordAdminXpAdjustment({
@@ -123147,6 +123187,7 @@ var getStudentXp;
123147
123187
  var getRoster;
123148
123188
  var getStudentOverview;
123149
123189
  var getStudentActivity;
123190
+ var getActivityDetail;
123150
123191
  var grantXp;
123151
123192
  var adjustTime;
123152
123193
  var adjustMastery;
@@ -123490,6 +123531,31 @@ var init_timeback_controller = __esm(() => {
123490
123531
  offset
123491
123532
  });
123492
123533
  });
123534
+ getActivityDetail = requireGameManagementAccess(async (ctx) => {
123535
+ const timebackId = ctx.params.timebackId;
123536
+ const courseId = ctx.params.courseId;
123537
+ const activityId = ctx.params.activityId;
123538
+ const gameId = ctx.url.searchParams.get("gameId") || undefined;
123539
+ const runId = ctx.url.searchParams.get("runId") || undefined;
123540
+ if (!timebackId || !courseId || !activityId || !gameId) {
123541
+ throw ApiError.badRequest("Missing timebackId, courseId, or activityId path parameter, or gameId query parameter");
123542
+ }
123543
+ logger64.debug("Getting activity detail", {
123544
+ requesterId: ctx.user.id,
123545
+ timebackId,
123546
+ courseId,
123547
+ activityId,
123548
+ gameId,
123549
+ runId
123550
+ });
123551
+ return ctx.services.timebackAdmin.getActivityDetail(ctx.user, {
123552
+ gameId,
123553
+ studentId: timebackId,
123554
+ courseId,
123555
+ activityId,
123556
+ runId
123557
+ });
123558
+ });
123493
123559
  grantXp = requireDeveloper(async (ctx) => {
123494
123560
  const body2 = await parseRequestBody(ctx.request, GrantTimebackXpRequestSchema);
123495
123561
  logger64.debug("Granting manual XP", {
@@ -123592,6 +123658,7 @@ var init_timeback_controller = __esm(() => {
123592
123658
  getRoster,
123593
123659
  getStudentOverview,
123594
123660
  getStudentActivity,
123661
+ getActivityDetail,
123595
123662
  grantXp,
123596
123663
  adjustTime,
123597
123664
  adjustMastery,
@@ -126413,7 +126480,7 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
126413
126480
  // package.json
126414
126481
  var package_default2 = {
126415
126482
  name: "@playcademy/vite-plugin",
126416
- version: "0.2.26-beta.6",
126483
+ version: "0.2.26-beta.8",
126417
126484
  type: "module",
126418
126485
  exports: {
126419
126486
  ".": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/vite-plugin",
3
- "version": "0.2.26-beta.6",
3
+ "version": "0.2.26-beta.8",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -20,14 +20,14 @@
20
20
  "dependencies": {
21
21
  "archiver": "^7.0.1",
22
22
  "picocolors": "^1.1.1",
23
- "playcademy": "0.19.2"
23
+ "playcademy": "0.19.3"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@electric-sql/pglite": "^0.3.16",
27
27
  "@inquirer/prompts": "^7.8.6",
28
28
  "@playcademy/constants": "0.0.1",
29
29
  "@playcademy/sandbox": "0.3.16",
30
- "@playcademy/sdk": "0.6.0",
30
+ "@playcademy/sdk": "0.7.0",
31
31
  "@playcademy/types": "0.0.1",
32
32
  "@playcademy/utils": "0.0.1",
33
33
  "@types/archiver": "^6.0.3",