@playcademy/sandbox 0.3.4 → 0.3.5

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/README.md CHANGED
@@ -199,17 +199,17 @@ bunx @playcademy/sandbox \
199
199
  --timeback-student-id your-student-sourcedId
200
200
  ```
201
201
 
202
- | Option | Description |
203
- | :------------------------------- | :-------------------------------------------------------- |
204
- | `--timeback-local` | Enable local TimeBack mode (Docker) |
205
- | `--timeback-oneroster-url <url>` | OneRoster API URL |
206
- | `--timeback-caliper-url <url>` | Caliper API URL |
207
- | `--timeback-course-id <id>` | Course ID for enrollments |
208
- | `--timeback-student-id <id>` | Student ID to link to demo user |
209
- | `--timeback-role <role>` | User role (student, parent, teacher, administrator) |
210
- | `--timeback-org-id <id>` | Organization ID |
211
- | `--timeback-org-name <name>` | Organization display name |
212
- | `--timeback-org-type <type>` | Organization type (school, district, department, etc.) |
202
+ | Option | Description |
203
+ | :------------------------------- | :----------------------------------------------------- |
204
+ | `--timeback-local` | Enable local TimeBack mode (Docker) |
205
+ | `--timeback-oneroster-url <url>` | OneRoster API URL |
206
+ | `--timeback-caliper-url <url>` | Caliper API URL |
207
+ | `--timeback-course-id <id>` | Course ID for enrollments |
208
+ | `--timeback-student-id <id>` | Student ID to link to demo user |
209
+ | `--timeback-role <role>` | User role (student, parent, teacher, administrator) |
210
+ | `--timeback-org-id <id>` | Organization ID |
211
+ | `--timeback-org-name <name>` | Organization display name |
212
+ | `--timeback-org-type <type>` | Organization type (school, district, department, etc.) |
213
213
 
214
214
  ### Environment Variables
215
215
 
package/dist/cli.js CHANGED
@@ -120609,6 +120609,9 @@ function configureTimeback(options) {
120609
120609
  config.timeback.role = options.role;
120610
120610
  process.env.SANDBOX_TIMEBACK_ROLE = options.role;
120611
120611
  }
120612
+ if (options.courseOverrides) {
120613
+ config.timeback.courseOverrides = options.courseOverrides;
120614
+ }
120612
120615
  }
120613
120616
  function getTimebackDisplayMode() {
120614
120617
  const { timebackId, mode } = config.timeback;
@@ -121478,7 +121481,7 @@ async function requirePortAvailable(port, timeoutMs = 100) {
121478
121481
  // package.json
121479
121482
  var package_default = {
121480
121483
  name: "@playcademy/sandbox",
121481
- version: "0.3.4",
121484
+ version: "0.3.5",
121482
121485
  description: "Local development server for Playcademy game development",
121483
121486
  type: "module",
121484
121487
  exports: {
@@ -152337,7 +152340,14 @@ function getMockStudentProfile() {
152337
152340
  }
152338
152341
  async function getMockEnrollments(db) {
152339
152342
  const allIntegrations = await db.query.gameTimebackIntegrations.findMany();
152340
- return allIntegrations.map((i4) => ({
152343
+ const overrides = config.timeback.courseOverrides;
152344
+ return allIntegrations.filter((i4) => {
152345
+ if (!overrides)
152346
+ return true;
152347
+ const key = `${i4.subject}:${i4.grade}`;
152348
+ const override = overrides[key];
152349
+ return override !== null && override !== false;
152350
+ }).map((i4) => ({
152341
152351
  gameId: i4.gameId,
152342
152352
  grade: i4.grade,
152343
152353
  subject: i4.subject,
@@ -158318,7 +158328,7 @@ function printBanner(options) {
158318
158328
  console.log("");
158319
158329
  console.log(` ${import_picocolors.default.green(import_picocolors.default.bold("PLAYCADEMY SANDBOX"))} ${import_picocolors.default.green(`v${version4}`)} ${import_picocolors.default.dim("ready in")} ${import_picocolors.default.bold(startupTimeMs.toString())} ms`);
158320
158330
  console.log("");
158321
- console.log(` ${import_picocolors.default.green("➜")} ${import_picocolors.default.bold("Local:")} ${import_picocolors.default.cyan(`http://localhost:${import_picocolors.default.bold(port.toString())}/api`)}`);
158331
+ console.log(` ${import_picocolors.default.green("➜")} ${import_picocolors.default.bold("Local:")} ${import_picocolors.default.cyan(`http://localhost:${import_picocolors.default.bold(port.toString())}/api`)}`);
158322
158332
  if (timebackCourseCount && timebackCourseCount > 0) {
158323
158333
  const courseText = timebackCourseCount === 1 ? "course" : "courses";
158324
158334
  console.log(` ${import_picocolors.default.green("➜")} ${import_picocolors.default.bold("Timeback:")} ${import_picocolors.default.cyan(`${timebackCourseCount} ${courseText}`)}`);
@@ -158530,9 +158540,20 @@ function parseOrganization(options) {
158530
158540
  type: options.timebackOrgType
158531
158541
  };
158532
158542
  }
158543
+ function parseExcludedCourses(excludedCourses) {
158544
+ if (!excludedCourses)
158545
+ return;
158546
+ const overrides = {};
158547
+ const courses = excludedCourses.split(",").map((c3) => c3.trim()).filter(Boolean);
158548
+ for (const course of courses) {
158549
+ overrides[course] = false;
158550
+ }
158551
+ return Object.keys(overrides).length > 0 ? overrides : undefined;
158552
+ }
158533
158553
  function parseTimebackOptions(options) {
158534
158554
  const organization = parseOrganization(options);
158535
158555
  const role = options.timebackRole;
158556
+ const courseOverrides = parseExcludedCourses(options.timebackExcludedCourses);
158536
158557
  if (options.timebackLocal) {
158537
158558
  return {
158538
158559
  mode: "local",
@@ -158541,7 +158562,8 @@ function parseTimebackOptions(options) {
158541
158562
  courseId: options.timebackCourseId,
158542
158563
  timebackId: options.timebackStudentId,
158543
158564
  role,
158544
- organization
158565
+ organization,
158566
+ courseOverrides
158545
158567
  };
158546
158568
  }
158547
158569
  if (options.timebackOnerosterUrl) {
@@ -158552,14 +158574,16 @@ function parseTimebackOptions(options) {
158552
158574
  courseId: options.timebackCourseId,
158553
158575
  timebackId: options.timebackStudentId,
158554
158576
  role,
158555
- organization
158577
+ organization,
158578
+ courseOverrides
158556
158579
  };
158557
158580
  }
158558
- if (role || organization || options.timebackStudentId) {
158581
+ if (role || organization || options.timebackStudentId || courseOverrides) {
158559
158582
  return {
158560
158583
  timebackId: options.timebackStudentId,
158561
158584
  role,
158562
- organization
158585
+ organization,
158586
+ courseOverrides
158563
158587
  };
158564
158588
  }
158565
158589
  return;
@@ -158567,7 +158591,7 @@ function parseTimebackOptions(options) {
158567
158591
 
158568
158592
  // src/cli/index.ts
158569
158593
  var program2 = new Command;
158570
- program2.name("playcademy-sandbox").description("Local development server for Playcademy game development").version(version3).option("-p, --port <number>", "Port to run the server on", "4321").option("-v, --verbose", "Enable verbose logging", false).option("--project-name <name>", "Name of the current project").option("--project-slug <slug>", "Slug of the current project").option("--no-seed", "Do not seed the database with demo data").option("--recreate-db", "Recreate the on-disk database on start", false).option("--memory", "Use in-memory database (no persistence)", false).option("--db-path <path>", "Custom path for the database file (relative to cwd or absolute)").option("--config-path <path>", "Path to playcademy.config.json (defaults to cwd)").option("--timeback-local", "Use local TimeBack instance").option("--timeback-oneroster-url <url>", "TimeBack OneRoster API URL").option("--timeback-caliper-url <url>", "TimeBack Caliper API URL").option("--timeback-course-id <id>", "TimeBack course ID for seeding").option("--timeback-student-id <id>", "TimeBack student ID for demo user").option("--timeback-role <role>", "TimeBack user role (student, parent, teacher, administrator)").option("--timeback-org-id <id>", "TimeBack organization ID").option("--timeback-org-name <name>", "TimeBack organization name").option("--timeback-org-type <type>", "TimeBack organization type (school, district, department)").option("-q, --quiet", "Quiet mode (suppress interactive messages)", false).action(async (options) => {
158594
+ program2.name("playcademy-sandbox").description("Local development server for Playcademy game development").version(version3).option("-p, --port <number>", "Port to run the server on", "4321").option("-v, --verbose", "Enable verbose logging", false).option("--project-name <name>", "Name of the current project").option("--project-slug <slug>", "Slug of the current project").option("--no-seed", "Do not seed the database with demo data").option("--recreate-db", "Recreate the on-disk database on start", false).option("--memory", "Use in-memory database (no persistence)", false).option("--db-path <path>", "Custom path for the database file (relative to cwd or absolute)").option("--config-path <path>", "Path to playcademy.config.json (defaults to cwd)").option("--timeback-local", "Use local TimeBack instance").option("--timeback-oneroster-url <url>", "TimeBack OneRoster API URL").option("--timeback-caliper-url <url>", "TimeBack Caliper API URL").option("--timeback-course-id <id>", "TimeBack course ID for seeding").option("--timeback-student-id <id>", "TimeBack student ID for demo user").option("--timeback-role <role>", "TimeBack user role (student, parent, teacher, administrator)").option("--timeback-org-id <id>", "TimeBack organization ID").option("--timeback-org-name <name>", "TimeBack organization name").option("--timeback-org-type <type>", "TimeBack organization type (school, district, department)").option("--timeback-excluded-courses <courses>", 'Comma-separated courses to exclude from enrollment (e.g. "FastMath:3,FastMath:4")').option("-q, --quiet", "Quiet mode (suppress interactive messages)", false).action(async (options) => {
158571
158595
  try {
158572
158596
  const startTime = Date.now();
158573
158597
  const port = parseInt(options.port);
package/dist/config.d.ts CHANGED
@@ -14,6 +14,13 @@ interface TimebackOrganizationInput {
14
14
  name?: string;
15
15
  type?: TimebackOrgType;
16
16
  }
17
+ /**
18
+ * Course enrollment overrides.
19
+ * - `'mock'` or omit: Use mock ID
20
+ * - Real string: Use that course ID
21
+ * - `null` or `false`: Exclude from enrollment
22
+ */
23
+ type CourseEnrollmentOverrides = Record<string, 'mock' | string | null | false>;
17
24
  /**
18
25
  * Timeback configuration input for sandbox.
19
26
  * All fields optional since they can be derived from defaults.
@@ -29,6 +36,7 @@ interface TimebackConfig {
29
36
  timebackId?: string;
30
37
  organization?: TimebackOrganizationInput;
31
38
  role?: TimebackUserRole;
39
+ courseOverrides?: CourseEnrollmentOverrides;
32
40
  }
33
41
  /**
34
42
  * Authentication configuration input for sandbox.
@@ -76,4 +84,4 @@ declare function getTimebackDisplayMode(): 'mock' | 'remote' | 'local' | null;
76
84
  declare const config: SandboxConfig;
77
85
 
78
86
  export { config, configureTimeback, getTimebackDisplayMode, hasTimebackCredentials, hasTimebackFullConfig, isTimebackEnabled, requireTimebackCredentials, setEmbeddedMode };
79
- export type { AuthConfig, SandboxConfig, TimebackConfig, TimebackMode };
87
+ export type { AuthConfig, CourseEnrollmentOverrides, SandboxConfig, TimebackConfig, TimebackMode };
package/dist/config.js CHANGED
@@ -127,6 +127,9 @@ function configureTimeback(options) {
127
127
  config.timeback.role = options.role;
128
128
  process.env.SANDBOX_TIMEBACK_ROLE = options.role;
129
129
  }
130
+ if (options.courseOverrides) {
131
+ config.timeback.courseOverrides = options.courseOverrides;
132
+ }
130
133
  }
131
134
  function getTimebackDisplayMode() {
132
135
  const { timebackId, mode } = config.timeback;
@@ -17,6 +17,7 @@ export declare function shouldMockTimeback(): boolean;
17
17
  export declare function getMockStudentProfile(): TimebackStudentProfile;
18
18
  /**
19
19
  * Generate mock enrollments from seeded game integrations.
20
+ * Respects courseOverrides from config - null/false excludes the course.
20
21
  */
21
22
  export declare function getMockEnrollments(db: DatabaseInstance): Promise<UserEnrollment[]>;
22
23
  /**
package/dist/server.d.ts CHANGED
@@ -15,6 +15,13 @@ interface TimebackOrganizationInput {
15
15
  name?: string;
16
16
  type?: TimebackOrgType;
17
17
  }
18
+ /**
19
+ * Course enrollment overrides.
20
+ * - `'mock'` or omit: Use mock ID
21
+ * - Real string: Use that course ID
22
+ * - `null` or `false`: Exclude from enrollment
23
+ */
24
+ type CourseEnrollmentOverrides = Record<string, 'mock' | string | null | false>;
18
25
  /**
19
26
  * Timeback configuration input for sandbox.
20
27
  * All fields optional since they can be derived from defaults.
@@ -30,6 +37,7 @@ interface TimebackConfig {
30
37
  timebackId?: string;
31
38
  organization?: TimebackOrganizationInput;
32
39
  role?: TimebackUserRole;
40
+ courseOverrides?: CourseEnrollmentOverrides;
33
41
  }
34
42
 
35
43
  /**
package/dist/server.js CHANGED
@@ -118699,6 +118699,9 @@ function configureTimeback(options) {
118699
118699
  config.timeback.role = options.role;
118700
118700
  process.env.SANDBOX_TIMEBACK_ROLE = options.role;
118701
118701
  }
118702
+ if (options.courseOverrides) {
118703
+ config.timeback.courseOverrides = options.courseOverrides;
118704
+ }
118702
118705
  }
118703
118706
  function getTimebackDisplayMode() {
118704
118707
  const { timebackId, mode } = config.timeback;
@@ -119568,7 +119571,7 @@ async function requirePortAvailable(port, timeoutMs = 100) {
119568
119571
  // package.json
119569
119572
  var package_default = {
119570
119573
  name: "@playcademy/sandbox",
119571
- version: "0.3.4",
119574
+ version: "0.3.5",
119572
119575
  description: "Local development server for Playcademy game development",
119573
119576
  type: "module",
119574
119577
  exports: {
@@ -150427,7 +150430,14 @@ function getMockStudentProfile() {
150427
150430
  }
150428
150431
  async function getMockEnrollments(db) {
150429
150432
  const allIntegrations = await db.query.gameTimebackIntegrations.findMany();
150430
- return allIntegrations.map((i4) => ({
150433
+ const overrides = config.timeback.courseOverrides;
150434
+ return allIntegrations.filter((i4) => {
150435
+ if (!overrides)
150436
+ return true;
150437
+ const key = `${i4.subject}:${i4.grade}`;
150438
+ const override = overrides[key];
150439
+ return override !== null && override !== false;
150440
+ }).map((i4) => ({
150431
150441
  gameId: i4.gameId,
150432
150442
  grade: i4.grade,
150433
150443
  subject: i4.subject,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/sandbox",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "Local development server for Playcademy game development",
5
5
  "type": "module",
6
6
  "exports": {