@playcademy/vite-plugin 0.1.38 → 0.1.40

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
@@ -175686,7 +175686,7 @@ var serve = (options, listeningListener) => {
175686
175686
  };
175687
175687
  var package_default = {
175688
175688
  name: "@playcademy/sandbox",
175689
- version: "0.2.0",
175689
+ version: "0.2.3",
175690
175690
  description: "Local development server for Playcademy game development",
175691
175691
  type: "module",
175692
175692
  exports: {
@@ -199445,6 +199445,45 @@ var logger3 = {
199445
199445
  warn: (msg) => getLogger().warn(msg),
199446
199446
  error: (msg) => getLogger().error(msg)
199447
199447
  };
199448
+ function resolveStudentId(studentId) {
199449
+ if (!studentId)
199450
+ return null;
199451
+ if (studentId === "mock")
199452
+ return `mock-student-${crypto.randomUUID().slice(0, 8)}`;
199453
+ return studentId;
199454
+ }
199455
+ function getAdminTimebackId() {
199456
+ return resolveStudentId(config.timeback.studentId);
199457
+ }
199458
+ async function seedTimebackIntegrations(db, gameId, courses) {
199459
+ const now2 = new Date;
199460
+ let seededCount = 0;
199461
+ for (const course of courses) {
199462
+ const courseId = course.courseId || `mock-${course.subject.toLowerCase()}-g${course.grade}`;
199463
+ try {
199464
+ const existing = await db.query.gameTimebackIntegrations.findFirst({
199465
+ where: (table14, { and: and3, eq: eq3 }) => and3(eq3(table14.gameId, gameId), eq3(table14.grade, course.grade), eq3(table14.subject, course.subject))
199466
+ });
199467
+ if (existing) {
199468
+ continue;
199469
+ }
199470
+ await db.insert(gameTimebackIntegrations).values({
199471
+ gameId,
199472
+ courseId,
199473
+ grade: course.grade,
199474
+ subject: course.subject,
199475
+ totalXp: course.totalXp ?? 1000,
199476
+ lastVerifiedAt: now2
199477
+ });
199478
+ seededCount++;
199479
+ } catch (error2) {
199480
+ console.error(`❌ Error seeding TimeBack integration for ${course.subject}:${course.grade}:`, error2);
199481
+ }
199482
+ }
199483
+ if (seededCount > 0) {
199484
+ logger3.info(`\uD83D\uDCDA Seeded ${seededCount} TimeBack integration(s)`);
199485
+ }
199486
+ }
199448
199487
  async function seedCoreGames(db) {
199449
199488
  const now2 = new Date;
199450
199489
  const coreGames = [
@@ -199478,6 +199517,9 @@ async function seedCurrentProjectGame(db, project) {
199478
199517
  });
199479
199518
  if (existingGame) {
199480
199519
  logger3.info(`\uD83C\uDFAE Game "${project.displayName}" (${project.slug}) already exists`);
199520
+ if (project.timebackCourses && project.timebackCourses.length > 0) {
199521
+ await seedTimebackIntegrations(db, existingGame.id, project.timebackCourses);
199522
+ }
199481
199523
  return existingGame;
199482
199524
  }
199483
199525
  const gameRecord = {
@@ -199497,6 +199539,12 @@ async function seedCurrentProjectGame(db, project) {
199497
199539
  updatedAt: now2
199498
199540
  };
199499
199541
  const [newGame] = await db.insert(games).values(gameRecord).returning();
199542
+ if (!newGame) {
199543
+ throw new Error("Failed to create game record");
199544
+ }
199545
+ if (project.timebackCourses && project.timebackCourses.length > 0) {
199546
+ await seedTimebackIntegrations(db, newGame.id, project.timebackCourses);
199547
+ }
199500
199548
  return newGame;
199501
199549
  } catch (error2) {
199502
199550
  console.error("❌ Error seeding project game:", error2);
@@ -199553,16 +199601,6 @@ async function seedSpriteTemplates(db) {
199553
199601
  }
199554
199602
  }
199555
199603
  }
199556
- function resolveStudentId(studentId) {
199557
- if (!studentId)
199558
- return null;
199559
- if (studentId === "mock")
199560
- return `mock-student-${crypto.randomUUID().slice(0, 8)}`;
199561
- return studentId;
199562
- }
199563
- function getAdminTimebackId() {
199564
- return resolveStudentId(config.timeback.studentId);
199565
- }
199566
199604
  async function seedDemoData(db) {
199567
199605
  try {
199568
199606
  const adminTimebackId = getAdminTimebackId();
@@ -210896,13 +210934,29 @@ function printBanner(viteConfig, servers, projectInfo, pluginVersion) {
210896
210934
  import fs6 from "node:fs";
210897
210935
  import path5 from "node:path";
210898
210936
  import { loadPlaycademyConfig } from "playcademy/utils";
210899
- async function extractProjectInfo(viteConfig) {
210937
+ function extractTimebackCourses(config2, timebackOptions) {
210938
+ const courses = config2?.integrations?.timeback?.courses;
210939
+ if (!courses || courses.length === 0)
210940
+ return;
210941
+ return courses.map((course) => {
210942
+ const key = `${course.subject}:${course.grade}`;
210943
+ const overrideId = timebackOptions?.courses?.[key];
210944
+ const courseId = overrideId && overrideId !== "mock" ? overrideId : undefined;
210945
+ return {
210946
+ subject: course.subject,
210947
+ grade: course.grade,
210948
+ courseId,
210949
+ totalXp: course.totalXp,
210950
+ masterableUnits: course.masterableUnits
210951
+ };
210952
+ });
210953
+ }
210954
+ async function extractProjectInfo(viteConfig, timebackOptions) {
210900
210955
  const projectRoot = viteConfig.root;
210901
210956
  const directoryName = path5.basename(projectRoot);
210902
- let configName;
210957
+ let config2 = null;
210903
210958
  try {
210904
- const config2 = await loadPlaycademyConfig();
210905
- configName = config2?.name;
210959
+ config2 = await loadPlaycademyConfig();
210906
210960
  } catch {}
210907
210961
  let packageJson = {};
210908
210962
  try {
@@ -210912,7 +210966,7 @@ async function extractProjectInfo(viteConfig) {
210912
210966
  packageJson = JSON.parse(packageJsonContent);
210913
210967
  }
210914
210968
  } catch {}
210915
- const name3 = configName || (typeof packageJson.name === "string" ? packageJson.name : "");
210969
+ const name3 = config2?.name || packageJson.name || "";
210916
210970
  let slug = name3;
210917
210971
  if (slug.includes("/")) {
210918
210972
  slug = slug.split("/")[1] || slug;
@@ -210924,8 +210978,9 @@ async function extractProjectInfo(viteConfig) {
210924
210978
  return {
210925
210979
  slug,
210926
210980
  displayName,
210927
- version: (typeof packageJson.version === "string" ? packageJson.version : null) || "dev",
210928
- description: typeof packageJson.description === "string" ? packageJson.description : undefined
210981
+ version: packageJson.version || "dev",
210982
+ description: packageJson.description,
210983
+ timebackCourses: extractTimebackCourses(config2, timebackOptions)
210929
210984
  };
210930
210985
  }
210931
210986
 
@@ -211031,7 +211086,8 @@ async function startSandbox(viteConfig, autoStart = true, options = {}) {
211031
211086
  realtimeEnabled = false,
211032
211087
  realtimePort,
211033
211088
  logLevel = "info",
211034
- timebackId
211089
+ timebackId,
211090
+ timebackOptions
211035
211091
  } = options;
211036
211092
  if (!autoStart || viteConfig.command !== "serve") {
211037
211093
  const baseUrl = customUrl ?? `http://localhost:${DEFAULT_PORTS2.SANDBOX}`;
@@ -211057,11 +211113,11 @@ async function startSandbox(viteConfig, autoStart = true, options = {}) {
211057
211113
  try {
211058
211114
  const sandboxPort = await findAvailablePort(DEFAULT_PORTS2.SANDBOX);
211059
211115
  const baseUrl = `http://localhost:${sandboxPort}`;
211060
- const projectInfo = await extractProjectInfo(viteConfig);
211061
- let timebackOptions = detectTimebackOptions();
211116
+ const projectInfo = await extractProjectInfo(viteConfig, timebackOptions);
211117
+ let sandboxTimebackOptions = detectTimebackOptions();
211062
211118
  if (timebackId) {
211063
- timebackOptions = {
211064
- ...timebackOptions,
211119
+ sandboxTimebackOptions = {
211120
+ ...sandboxTimebackOptions,
211065
211121
  studentId: timebackId
211066
211122
  };
211067
211123
  }
@@ -211076,7 +211132,7 @@ async function startSandbox(viteConfig, autoStart = true, options = {}) {
211076
211132
  recreateDb,
211077
211133
  logLevel,
211078
211134
  realtime: { enabled: realtimeEnabled, port: finalRealtimePort },
211079
- timeback: timebackOptions,
211135
+ timeback: sandboxTimebackOptions,
211080
211136
  logger: createLoggerAdapter("sandbox")
211081
211137
  });
211082
211138
  writeServerInfo("sandbox", {
@@ -211489,6 +211545,9 @@ var shell_with_corner_badge_default = `<!doctype html>
211489
211545
  </script>
211490
211546
  </body>
211491
211547
  </html>
211548
+
211549
+
211550
+
211492
211551
  `;
211493
211552
 
211494
211553
  // src/server/middleware.ts
@@ -211579,7 +211638,7 @@ var import_picocolors10 = __toESM(require_picocolors(), 1);
211579
211638
  // package.json
211580
211639
  var package_default2 = {
211581
211640
  name: "@playcademy/vite-plugin",
211582
- version: "0.1.37",
211641
+ version: "0.1.40",
211583
211642
  type: "module",
211584
211643
  exports: {
211585
211644
  ".": {
@@ -211714,7 +211773,8 @@ async function configurePlatformMode(server, viteConfig, options) {
211714
211773
  databasePath: options.databasePath,
211715
211774
  realtimeEnabled: options.realtimeEnabled,
211716
211775
  realtimePort: options.realtimePort,
211717
- timebackId: getEffectiveTimebackId(options.timeback)
211776
+ timebackId: getEffectiveTimebackId(options.timeback),
211777
+ timebackOptions: options.timeback
211718
211778
  });
211719
211779
  serverState.sandbox = sandbox;
211720
211780
  const backend = await setupCliDevServer({
@@ -211734,7 +211794,7 @@ async function configurePlatformMode(server, viteConfig, options) {
211734
211794
  }
211735
211795
  server.httpServer?.once("listening", () => {
211736
211796
  setTimeout(async () => {
211737
- const projectInfo = await extractProjectInfo(viteConfig);
211797
+ const projectInfo = await extractProjectInfo(viteConfig, options.timeback);
211738
211798
  const vitePort = server.config.server.port;
211739
211799
  printBanner(viteConfig, {
211740
211800
  sandbox: sandbox.port,
@@ -3,8 +3,12 @@
3
3
  */
4
4
  import type { ResolvedConfig } from 'vite';
5
5
  import type { ProjectInfo } from '../../types';
6
+ import type { PlaycademyTimebackOptions } from '../../types/options';
6
7
  /**
7
8
  * Extracts project information from playcademy.config and package.json
8
9
  * Used to initialize sandbox with correct project metadata
10
+ *
11
+ * @param viteConfig - Resolved Vite configuration
12
+ * @param timebackOptions - Optional timeback options from vite.config.ts for courseId overrides
9
13
  */
10
- export declare function extractProjectInfo(viteConfig: ResolvedConfig): Promise<ProjectInfo>;
14
+ export declare function extractProjectInfo(viteConfig: ResolvedConfig, timebackOptions?: PlaycademyTimebackOptions): Promise<ProjectInfo>;
@@ -1,5 +1,6 @@
1
1
  import type { ResolvedConfig } from 'vite';
2
2
  import type { SandboxManager } from '../../types';
3
+ import type { PlaycademyTimebackOptions } from '../../types/options';
3
4
  export declare function startSandbox(viteConfig: ResolvedConfig, autoStart?: boolean, options?: {
4
5
  verbose?: boolean;
5
6
  customUrl?: string;
@@ -12,4 +13,5 @@ export declare function startSandbox(viteConfig: ResolvedConfig, autoStart?: boo
12
13
  realtimePort?: number;
13
14
  logLevel?: 'debug' | 'info' | 'warn' | 'error';
14
15
  timebackId?: string;
16
+ timebackOptions?: PlaycademyTimebackOptions;
15
17
  }): Promise<SandboxManager>;
@@ -2,5 +2,5 @@
2
2
  * Type exports for the Playcademy Vite Plugin
3
3
  */
4
4
  export type { PlaycademyExportOptions, PlaycademySandboxOptions, PlaycademyShellOptions, PlaycademyPluginOptions, PlaycademyMode, } from './options';
5
- export type { ResolvedPluginOptions, PluginContext, PlaycademyOutputData, ProjectInfo, SandboxManager, CliServerManager, CliDevServerOptions, PlatformModeOptions, StandaloneModeOptions, HotkeyOptions, TimebackRoleOverride, } from './internal';
5
+ export type { ResolvedPluginOptions, PluginContext, PlaycademyOutputData, ProjectInfo, TimebackCourseConfig, SandboxManager, CliServerManager, CliDevServerOptions, PlatformModeOptions, StandaloneModeOptions, HotkeyOptions, TimebackRoleOverride, } from './internal';
6
6
  export { TIMEBACK_ROLES } from './internal';
@@ -46,6 +46,16 @@ export interface PlaycademyOutputData {
46
46
  zipPath?: string;
47
47
  zipSizeKb?: string;
48
48
  }
49
+ /**
50
+ * TimeBack course configuration from playcademy.config
51
+ */
52
+ export interface TimebackCourseConfig {
53
+ subject: string;
54
+ grade: number;
55
+ courseId?: string;
56
+ totalXp?: number | null;
57
+ masterableUnits?: number | null;
58
+ }
49
59
  /**
50
60
  * Project information extracted from package.json and directory structure
51
61
  */
@@ -54,6 +64,7 @@ export interface ProjectInfo {
54
64
  displayName: string;
55
65
  version: string;
56
66
  description?: string;
67
+ timebackCourses?: TimebackCourseConfig[];
57
68
  }
58
69
  /**
59
70
  * Sandbox manager interface for controlling sandbox lifecycle
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/vite-plugin",
3
- "version": "0.1.38",
3
+ "version": "0.1.40",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "devDependencies": {
27
27
  "@inquirer/prompts": "^7.8.6",
28
- "@playcademy/sandbox": "0.2.0",
28
+ "@playcademy/sandbox": "0.2.3",
29
29
  "@types/archiver": "^6.0.3",
30
30
  "@types/bun": "latest"
31
31
  },