@playcademy/sandbox 0.3.11 → 0.3.13

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/cli.js CHANGED
@@ -351,11 +351,15 @@ var init_overworld = __esm(() => {
351
351
  var PLATFORM_TIMEZONE = "America/New_York";
352
352
 
353
353
  // ../constants/src/timeback.ts
354
- var TIMEBACK_ORG_SOURCED_ID = "PLAYCADEMY";
355
- var init_timeback2 = () => {};
354
+ var TIMEBACK_ROUTES, TIMEBACK_ORG_SOURCED_ID = "PLAYCADEMY";
355
+ var init_timeback2 = __esm(() => {
356
+ TIMEBACK_ROUTES = {
357
+ END_ACTIVITY: "/integrations/timeback/end-activity"
358
+ };
359
+ });
356
360
 
357
361
  // ../constants/src/workers.ts
358
- var WORKER_NAMING;
362
+ var WORKER_NAMING, SECRETS_PREFIX = "secrets_";
359
363
  var init_workers = __esm(() => {
360
364
  WORKER_NAMING = {
361
365
  STAGING_PREFIX: "staging-",
@@ -1225,7 +1229,7 @@ var package_default;
1225
1229
  var init_package = __esm(() => {
1226
1230
  package_default = {
1227
1231
  name: "@playcademy/sandbox",
1228
- version: "0.3.11",
1232
+ version: "0.3.13",
1229
1233
  description: "Local development server for Playcademy game development",
1230
1234
  type: "module",
1231
1235
  exports: {
@@ -1676,7 +1680,7 @@ function createHandle(buildContext) {
1676
1680
  try {
1677
1681
  const ctx = await buildContext(c);
1678
1682
  const result = await controller(ctx);
1679
- if (options?.status === 204 || result === undefined || result === null) {
1683
+ if (options?.status === 204 || result === undefined) {
1680
1684
  return new Response(null, { status: options?.status ?? 204 });
1681
1685
  }
1682
1686
  return new Response(JSON.stringify(result), {
@@ -13915,6 +13919,20 @@ class GameService {
13915
13919
  orderBy: [desc(games.createdAt)]
13916
13920
  });
13917
13921
  }
13922
+ async getSubjects() {
13923
+ const db2 = this.ctx.db;
13924
+ const integrations = await db2.query.gameTimebackIntegrations.findMany({
13925
+ columns: { gameId: true, subject: true },
13926
+ orderBy: [asc(gameTimebackIntegrations.createdAt)]
13927
+ });
13928
+ const subjectMap = {};
13929
+ for (const integration of integrations) {
13930
+ if (!(integration.gameId in subjectMap)) {
13931
+ subjectMap[integration.gameId] = integration.subject;
13932
+ }
13933
+ }
13934
+ return subjectMap;
13935
+ }
13918
13936
  async getById(gameId) {
13919
13937
  const db2 = this.ctx.db;
13920
13938
  const game = await db2.query.games.findFirst({
@@ -14909,13 +14927,13 @@ class LevelService {
14909
14927
  throw new BadRequestError("Level must be at least 1");
14910
14928
  }
14911
14929
  if (levelConfigCache?.has(level)) {
14912
- return levelConfigCache.get(level) || null;
14930
+ return levelConfigCache.get(level) ?? null;
14913
14931
  }
14914
14932
  const [config2] = await this.ctx.db.select().from(levelConfigs).where(eq(levelConfigs.level, level)).limit(1);
14915
14933
  if (levelConfigCache && config2) {
14916
14934
  levelConfigCache.set(level, config2);
14917
14935
  }
14918
- return config2 || null;
14936
+ return config2 ?? null;
14919
14937
  }
14920
14938
  async listConfigs() {
14921
14939
  return this.ctx.db.select().from(levelConfigs).orderBy(levelConfigs.level);
@@ -15802,8 +15820,9 @@ class SecretsService {
15802
15820
  }
15803
15821
  }
15804
15822
  }
15805
- var logger21, SECRETS_PREFIX = "secrets_", INTERNAL_SECRET_KEYS;
15823
+ var logger21, INTERNAL_SECRET_KEYS;
15806
15824
  var init_secrets_service = __esm(() => {
15825
+ init_src();
15807
15826
  init_src2();
15808
15827
  init_config2();
15809
15828
  init_errors();
@@ -15812,6 +15831,32 @@ var init_secrets_service = __esm(() => {
15812
15831
  INTERNAL_SECRET_KEYS = ["PLAYCADEMY_API_KEY", "GAME_ID", "PLAYCADEMY_BASE_URL"];
15813
15832
  });
15814
15833
 
15834
+ // ../edge-play/src/constants.ts
15835
+ var ROUTES;
15836
+ var init_constants2 = __esm(() => {
15837
+ init_src();
15838
+ ROUTES = {
15839
+ INDEX: "/api",
15840
+ HEALTH: "/api/health",
15841
+ TIMEBACK: {
15842
+ END_ACTIVITY: `/api${TIMEBACK_ROUTES.END_ACTIVITY}`
15843
+ }
15844
+ };
15845
+ });
15846
+
15847
+ // ../edge-play/src/entry/setup.ts
15848
+ function prefixSecrets(secrets) {
15849
+ const prefixed = {};
15850
+ for (const [key, value] of Object.entries(secrets)) {
15851
+ prefixed[SECRETS_PREFIX + key] = value;
15852
+ }
15853
+ return prefixed;
15854
+ }
15855
+ var init_setup = __esm(() => {
15856
+ init_src();
15857
+ init_constants2();
15858
+ });
15859
+
15815
15860
  // ../api-core/src/services/seed.service.ts
15816
15861
  class SeedService {
15817
15862
  ctx;
@@ -15826,7 +15871,7 @@ class SeedService {
15826
15871
  }
15827
15872
  return cf;
15828
15873
  }
15829
- async seed(slug2, code, user) {
15874
+ async seed(slug2, code, user, secrets) {
15830
15875
  const cf = this.getCloudflare();
15831
15876
  const game = await this.ctx.services.game.validateDeveloperAccessBySlug(user, slug2);
15832
15877
  const isProd = isProduction2(this.ctx.config);
@@ -15838,10 +15883,11 @@ class SeedService {
15838
15883
  gameId: game.id,
15839
15884
  slug: slug2,
15840
15885
  deploymentId,
15841
- codeLength: code.length
15886
+ codeLength: code.length,
15887
+ secretCount: secrets ? Object.keys(secrets).length : 0
15842
15888
  });
15843
15889
  try {
15844
- const workerResponse = await this.deployAndExecuteSeedWorker(cf, seedDeploymentId, game.id, deploymentId, code);
15890
+ const workerResponse = await this.deployAndExecuteSeedWorker(cf, seedDeploymentId, game.id, deploymentId, code, secrets);
15845
15891
  logger22.info("Seed completed", {
15846
15892
  gameId: game.id,
15847
15893
  slug: slug2,
@@ -15913,7 +15959,7 @@ class SeedService {
15913
15959
  });
15914
15960
  }
15915
15961
  }
15916
- async deployAndExecuteSeedWorker(cf, seedDeploymentId, gameId, deploymentId, workerCode) {
15962
+ async deployAndExecuteSeedWorker(cf, seedDeploymentId, gameId, deploymentId, workerCode, secrets) {
15917
15963
  try {
15918
15964
  const result = await cf.deploy(seedDeploymentId, workerCode, {
15919
15965
  GAME_ID: gameId,
@@ -15923,6 +15969,13 @@ class SeedService {
15923
15969
  keepAssets: false
15924
15970
  });
15925
15971
  logger22.info("Worker deployed", { seedDeploymentId, url: result.url });
15972
+ if (secrets && Object.keys(secrets).length > 0) {
15973
+ await cf.setSecrets(seedDeploymentId, prefixSecrets(secrets));
15974
+ logger22.info("Secrets bound to worker", {
15975
+ seedDeploymentId,
15976
+ count: Object.keys(secrets).length
15977
+ });
15978
+ }
15926
15979
  return await this.executeSeedWorker(result.url, seedDeploymentId);
15927
15980
  } finally {
15928
15981
  await this.cleanupSeedWorker(cf, seedDeploymentId);
@@ -16038,6 +16091,7 @@ class SeedService {
16038
16091
  }
16039
16092
  var logger22;
16040
16093
  var init_seed_service = __esm(() => {
16094
+ init_setup();
16041
16095
  init_src2();
16042
16096
  init_config2();
16043
16097
  init_errors();
@@ -16505,7 +16559,7 @@ function isTimebackSubject(value) {
16505
16559
  function isTimebackGrade(value) {
16506
16560
  return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES.includes(value);
16507
16561
  }
16508
- var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), ACHIEVEMENT_IDS2, ACHIEVEMENT_DEFINITIONS2, init_achievements2, init_auth2 = () => {}, TSC_PACKAGE2 = "@typescript/native-preview", USE_NATIVE_TSC2, init_typescript2, init_character2 = () => {}, PLAYCADEMY_BASE_URLS, init_domains2, init_env_vars2 = () => {}, ITEM_SLUGS2, CURRENCIES2, BADGES2, init_overworld2, TIMEBACK_CALIPER_SENSORS, TIMEBACK_ORG_SOURCED_ID2 = "PLAYCADEMY", TIMEBACK_ORG_NAME = "Playcademy Studios", TIMEBACK_ORG_TYPE = "department", TIMEBACK_COURSE_DEFAULTS, TIMEBACK_RESOURCE_DEFAULTS, TIMEBACK_COMPONENT_DEFAULTS, TIMEBACK_COMPONENT_RESOURCE_DEFAULTS, init_timeback3, init_workers2 = () => {}, init_src5, TIMEBACK_API_URLS, TIMEBACK_AUTH_URLS, CALIPER_API_URLS, ONEROSTER_ENDPOINTS, CALIPER_ENDPOINTS, CALIPER_CONSTANTS, TIMEBACK_EVENT_TYPES, TIMEBACK_ACTIONS, TIMEBACK_TYPES, ACTIVITY_METRIC_TYPES, TIME_METRIC_TYPES, TIMEBACK_SUBJECTS, TIMEBACK_GRADE_LEVELS, TIMEBACK_GRADE_LEVEL_LABELS, CALIPER_SUBJECTS, ONEROSTER_STATUS, SCORE_STATUS, ENV_VARS, HTTP_DEFAULTS, AUTH_DEFAULTS, CACHE_DEFAULTS, CONFIG_DEFAULTS, PLAYCADEMY_DEFAULTS, RESOURCE_DEFAULTS, HTTP_STATUS, ERROR_NAMES, init_constants2, isObject = (value) => typeof value === "object" && value !== null, SUBJECT_VALUES, GRADE_VALUES;
16562
+ var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), ACHIEVEMENT_IDS2, ACHIEVEMENT_DEFINITIONS2, init_achievements2, init_auth2 = () => {}, TSC_PACKAGE2 = "@typescript/native-preview", USE_NATIVE_TSC2, init_typescript2, init_character2 = () => {}, PLAYCADEMY_BASE_URLS, init_domains2, init_env_vars2 = () => {}, ITEM_SLUGS2, CURRENCIES2, BADGES2, init_overworld2, TIMEBACK_CALIPER_SENSORS, TIMEBACK_ORG_SOURCED_ID2 = "PLAYCADEMY", TIMEBACK_ORG_NAME = "Playcademy Studios", TIMEBACK_ORG_TYPE = "department", TIMEBACK_COURSE_DEFAULTS, TIMEBACK_RESOURCE_DEFAULTS, TIMEBACK_COMPONENT_DEFAULTS, TIMEBACK_COMPONENT_RESOURCE_DEFAULTS, init_timeback3, init_workers2 = () => {}, init_src5, TIMEBACK_API_URLS, TIMEBACK_AUTH_URLS, CALIPER_API_URLS, ONEROSTER_ENDPOINTS, CALIPER_ENDPOINTS, CALIPER_CONSTANTS, TIMEBACK_EVENT_TYPES, TIMEBACK_ACTIONS, TIMEBACK_TYPES, ACTIVITY_METRIC_TYPES, TIME_METRIC_TYPES, TIMEBACK_SUBJECTS, TIMEBACK_GRADE_LEVELS, TIMEBACK_GRADE_LEVEL_LABELS, CALIPER_SUBJECTS, ONEROSTER_STATUS, SCORE_STATUS, ENV_VARS, HTTP_DEFAULTS, AUTH_DEFAULTS, CACHE_DEFAULTS, CONFIG_DEFAULTS, PLAYCADEMY_DEFAULTS, RESOURCE_DEFAULTS, HTTP_STATUS, ERROR_NAMES, init_constants3, isObject = (value) => typeof value === "object" && value !== null, SUBJECT_VALUES, GRADE_VALUES;
16509
16563
  var init_types7 = __esm(() => {
16510
16564
  init_achievements2 = __esm2(() => {
16511
16565
  ACHIEVEMENT_IDS2 = {
@@ -16682,7 +16736,7 @@ var init_types7 = __esm(() => {
16682
16736
  init_timeback3();
16683
16737
  init_workers2();
16684
16738
  });
16685
- init_constants2 = __esm2(() => {
16739
+ init_constants3 = __esm2(() => {
16686
16740
  init_src5();
16687
16741
  TIMEBACK_API_URLS = {
16688
16742
  production: "https://api.alpha-1edtech.ai",
@@ -16857,7 +16911,7 @@ var init_types7 = __esm(() => {
16857
16911
  timebackSdk: "TimebackSDKError"
16858
16912
  };
16859
16913
  });
16860
- init_constants2();
16914
+ init_constants3();
16861
16915
  SUBJECT_VALUES = TIMEBACK_SUBJECTS;
16862
16916
  GRADE_VALUES = TIMEBACK_GRADE_LEVELS;
16863
16917
  });
@@ -20155,7 +20209,7 @@ var __defProp2, __export2 = (target, all) => {
20155
20209
  course: (courseId) => `${base}${ONEROSTER_ENDPOINTS2.courses}/${courseId}`,
20156
20210
  componentResource: (resourceId) => `${base}${ONEROSTER_ENDPOINTS2.componentResources}/${resourceId}`
20157
20211
  };
20158
- }, CALIPER_CONSTANTS2, TIMEBACK_EVENT_TYPES2, TIMEBACK_ACTIONS2, TIMEBACK_TYPES2, ACTIVITY_METRIC_TYPES2, TIME_METRIC_TYPES2, TIMEBACK_SUBJECTS2, TIMEBACK_GRADE_LEVELS2, TIMEBACK_GRADE_LEVEL_LABELS2, CALIPER_SUBJECTS2, ONEROSTER_STATUS2, SCORE_STATUS2, ENV_VARS2, HTTP_DEFAULTS2, AUTH_DEFAULTS2, CACHE_DEFAULTS2, CONFIG_DEFAULTS2, PLAYCADEMY_DEFAULTS2, RESOURCE_DEFAULTS2, HTTP_STATUS2, ERROR_NAMES2, init_constants3, exports_verify, init_verify, TimebackError, TimebackApiError, TimebackAuthenticationError, StudentNotFoundError, ConfigurationError, ResourceNotFoundError, isObject2 = (value) => typeof value === "object" && value !== null, SUBJECT_VALUES2, GRADE_VALUES2, isBrowser2 = () => {
20212
+ }, CALIPER_CONSTANTS2, TIMEBACK_EVENT_TYPES2, TIMEBACK_ACTIONS2, TIMEBACK_TYPES2, ACTIVITY_METRIC_TYPES2, TIME_METRIC_TYPES2, TIMEBACK_SUBJECTS2, TIMEBACK_GRADE_LEVELS2, TIMEBACK_GRADE_LEVEL_LABELS2, CALIPER_SUBJECTS2, ONEROSTER_STATUS2, SCORE_STATUS2, ENV_VARS2, HTTP_DEFAULTS2, AUTH_DEFAULTS2, CACHE_DEFAULTS2, CONFIG_DEFAULTS2, PLAYCADEMY_DEFAULTS2, RESOURCE_DEFAULTS2, HTTP_STATUS2, ERROR_NAMES2, init_constants4, exports_verify, init_verify, TimebackError, TimebackApiError, TimebackAuthenticationError, StudentNotFoundError, ConfigurationError, ResourceNotFoundError, isObject2 = (value) => typeof value === "object" && value !== null, SUBJECT_VALUES2, GRADE_VALUES2, isBrowser2 = () => {
20159
20213
  const g = globalThis;
20160
20214
  return typeof g.window !== "undefined" && typeof g.document !== "undefined";
20161
20215
  }, isProduction3 = () => {
@@ -20694,7 +20748,7 @@ var init_dist3 = __esm(() => {
20694
20748
  init_timeback4();
20695
20749
  init_workers3();
20696
20750
  });
20697
- init_constants3 = __esm3(() => {
20751
+ init_constants4 = __esm3(() => {
20698
20752
  init_src6();
20699
20753
  TIMEBACK_API_URLS2 = {
20700
20754
  production: "https://api.alpha-1edtech.ai",
@@ -20875,9 +20929,9 @@ var init_dist3 = __esm(() => {
20875
20929
  fetchTimebackConfig: () => fetchTimebackConfig
20876
20930
  });
20877
20931
  init_verify = __esm3(() => {
20878
- init_constants3();
20932
+ init_constants4();
20879
20933
  });
20880
- init_constants3();
20934
+ init_constants4();
20881
20935
  TimebackError = class TimebackError extends Error {
20882
20936
  constructor(message) {
20883
20937
  super(message);
@@ -20934,7 +20988,7 @@ var init_dist3 = __esm(() => {
20934
20988
  Object.setPrototypeOf(this, ResourceNotFoundError.prototype);
20935
20989
  }
20936
20990
  };
20937
- init_constants3();
20991
+ init_constants4();
20938
20992
  SUBJECT_VALUES2 = TIMEBACK_SUBJECTS2;
20939
20993
  GRADE_VALUES2 = TIMEBACK_GRADE_LEVELS2;
20940
20994
  colors3 = {
@@ -20955,8 +21009,8 @@ var init_dist3 = __esm(() => {
20955
21009
  };
20956
21010
  log3 = createLogger2();
20957
21011
  init_verify();
20958
- init_constants3();
20959
- init_constants3();
21012
+ init_constants4();
21013
+ init_constants4();
20960
21014
  if (process.env.DEBUG === "true") {
20961
21015
  process.env.TERM = "dumb";
20962
21016
  }
@@ -20968,13 +21022,13 @@ var init_dist3 = __esm(() => {
20968
21022
  this.name = ERROR_NAMES2.timebackAuth;
20969
21023
  }
20970
21024
  };
20971
- init_constants3();
20972
- init_constants3();
20973
- init_constants3();
20974
- init_constants3();
20975
- init_constants3();
20976
- init_constants3();
20977
- init_constants3();
21025
+ init_constants4();
21026
+ init_constants4();
21027
+ init_constants4();
21028
+ init_constants4();
21029
+ init_constants4();
21030
+ init_constants4();
21031
+ init_constants4();
20978
21032
  exports_external2 = {};
20979
21033
  __export2(exports_external2, {
20980
21034
  void: () => voidType2,
@@ -24532,7 +24586,7 @@ var init_http_exception = () => {};
24532
24586
 
24533
24587
  // ../../node_modules/hono/dist/request/constants.js
24534
24588
  var GET_MATCH_RESULT;
24535
- var init_constants4 = __esm(() => {
24589
+ var init_constants5 = __esm(() => {
24536
24590
  GET_MATCH_RESULT = Symbol();
24537
24591
  });
24538
24592
 
@@ -24796,7 +24850,7 @@ var init_url = __esm(() => {
24796
24850
  var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_), HonoRequest;
24797
24851
  var init_request = __esm(() => {
24798
24852
  init_http_exception();
24799
- init_constants4();
24853
+ init_constants5();
24800
24854
  init_body();
24801
24855
  init_url();
24802
24856
  HonoRequest = class {
@@ -25126,7 +25180,7 @@ var init_router = __esm(() => {
25126
25180
 
25127
25181
  // ../../node_modules/hono/dist/utils/constants.js
25128
25182
  var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
25129
- var init_constants5 = () => {};
25183
+ var init_constants6 = () => {};
25130
25184
 
25131
25185
  // ../../node_modules/hono/dist/hono-base.js
25132
25186
  var notFoundHandler = (c) => {
@@ -25348,7 +25402,7 @@ var init_hono_base = __esm(() => {
25348
25402
  init_compose();
25349
25403
  init_context2();
25350
25404
  init_router();
25351
- init_constants5();
25405
+ init_constants6();
25352
25406
  init_url();
25353
25407
  });
25354
25408
 
@@ -82705,7 +82759,8 @@ var init_schemas3 = __esm(() => {
82705
82759
  });
82706
82760
  SetSecretsRequestSchema = exports_external.record(exports_external.string().min(1), exports_external.string());
82707
82761
  SeedRequestSchema = exports_external.object({
82708
- code: exports_external.string().min(1, "Seed code is required")
82762
+ code: exports_external.string().min(1, "Seed code is required"),
82763
+ secrets: exports_external.record(exports_external.string(), exports_external.string()).optional()
82709
82764
  });
82710
82765
  SchemaInfoSchema = exports_external.object({
82711
82766
  sql: exports_external.string(),
@@ -92876,7 +92931,7 @@ var init_domain_controller = __esm(() => {
92876
92931
  });
92877
92932
 
92878
92933
  // ../api-core/src/controllers/game.controller.ts
92879
- var logger43, list3, getById2, getBySlug, upsertBySlug, remove3, games2;
92934
+ var logger43, list3, getSubjects, getById2, getBySlug, upsertBySlug, remove3, games2;
92880
92935
  var init_game_controller = __esm(() => {
92881
92936
  init_esm();
92882
92937
  init_schemas_index();
@@ -92889,6 +92944,10 @@ var init_game_controller = __esm(() => {
92889
92944
  logger43.debug("Listing games", { userId: ctx.user.id });
92890
92945
  return ctx.services.game.list();
92891
92946
  });
92947
+ getSubjects = requireAuth(async (ctx) => {
92948
+ logger43.debug("Getting game subjects", { userId: ctx.user.id });
92949
+ return ctx.services.game.getSubjects();
92950
+ });
92892
92951
  getById2 = requireAuth(async (ctx) => {
92893
92952
  const gameId = ctx.params.gameId;
92894
92953
  if (!gameId) {
@@ -92941,6 +93000,7 @@ var init_game_controller = __esm(() => {
92941
93000
  });
92942
93001
  games2 = {
92943
93002
  list: list3,
93003
+ getSubjects,
92944
93004
  getById: getById2,
92945
93005
  getBySlug,
92946
93006
  upsertBySlug,
@@ -93324,7 +93384,6 @@ var init_leaderboard_controller = __esm(() => {
93324
93384
  init_esm();
93325
93385
  init_schemas_index();
93326
93386
  init_src2();
93327
- init_src4();
93328
93387
  init_errors();
93329
93388
  init_utils11();
93330
93389
  logger47 = log.scope("LeaderboardController");
@@ -93413,9 +93472,6 @@ var init_leaderboard_controller = __esm(() => {
93413
93472
  if (!gameId || !userId) {
93414
93473
  throw ApiError.badRequest("Game ID and User ID are required");
93415
93474
  }
93416
- if (!isValidUUID(userId)) {
93417
- throw ApiError.unprocessableEntity("userId must be a valid UUID format");
93418
- }
93419
93475
  logger47.debug("Getting user rank", {
93420
93476
  requesterId: ctx.user.id,
93421
93477
  gameId,
@@ -93428,9 +93484,6 @@ var init_leaderboard_controller = __esm(() => {
93428
93484
  if (!userId) {
93429
93485
  throw ApiError.badRequest("User ID is required");
93430
93486
  }
93431
- if (!isValidUUID(userId)) {
93432
- throw ApiError.unprocessableEntity("userId must be a valid UUID format");
93433
- }
93434
93487
  const url = ctx.url;
93435
93488
  const limit = Math.min(Number(url.searchParams.get("limit") || "50"), 100);
93436
93489
  const gameId = url.searchParams.get("gameId") || undefined;
@@ -93447,9 +93500,6 @@ var init_leaderboard_controller = __esm(() => {
93447
93500
  if (!gameId || !userId) {
93448
93501
  throw ApiError.badRequest("Game ID and User ID are required");
93449
93502
  }
93450
- if (!isValidUUID(userId)) {
93451
- throw ApiError.unprocessableEntity("userId must be a valid UUID format");
93452
- }
93453
93503
  const url = ctx.url;
93454
93504
  const limit = Math.min(Number(url.searchParams.get("limit") || "10"), 100);
93455
93505
  logger47.debug("Getting user scores", {
@@ -93875,8 +93925,13 @@ var init_seed_controller = __esm(() => {
93875
93925
  }
93876
93926
  throw ApiError.badRequest("Invalid JSON body");
93877
93927
  }
93878
- logger55.debug("Seeding database", { userId: ctx.user.id, slug: slug2, codeLength: body2.code.length });
93879
- return ctx.services.seed.seed(slug2, body2.code, ctx.user);
93928
+ logger55.debug("Seeding database", {
93929
+ userId: ctx.user.id,
93930
+ slug: slug2,
93931
+ codeLength: body2.code.length,
93932
+ secretCount: body2.secrets ? Object.keys(body2.secrets).length : 0
93933
+ });
93934
+ return ctx.services.seed.seed(slug2, body2.code, ctx.user, body2.secrets);
93880
93935
  });
93881
93936
  });
93882
93937
 
package/dist/constants.js CHANGED
@@ -197,11 +197,15 @@ var init_overworld = __esm(() => {
197
197
  var PLATFORM_TIMEZONE = "America/New_York";
198
198
 
199
199
  // ../constants/src/timeback.ts
200
- var TIMEBACK_ORG_SOURCED_ID = "PLAYCADEMY";
201
- var init_timeback = () => {};
200
+ var TIMEBACK_ROUTES, TIMEBACK_ORG_SOURCED_ID = "PLAYCADEMY";
201
+ var init_timeback = __esm(() => {
202
+ TIMEBACK_ROUTES = {
203
+ END_ACTIVITY: "/integrations/timeback/end-activity"
204
+ };
205
+ });
202
206
 
203
207
  // ../constants/src/workers.ts
204
- var WORKER_NAMING;
208
+ var WORKER_NAMING, SECRETS_PREFIX = "secrets_";
205
209
  var init_workers = __esm(() => {
206
210
  WORKER_NAMING = {
207
211
  STAGING_PREFIX: "staging-",
package/dist/server.js CHANGED
@@ -350,11 +350,15 @@ var init_overworld = __esm(() => {
350
350
  var PLATFORM_TIMEZONE = "America/New_York";
351
351
 
352
352
  // ../constants/src/timeback.ts
353
- var TIMEBACK_ORG_SOURCED_ID = "PLAYCADEMY";
354
- var init_timeback2 = () => {};
353
+ var TIMEBACK_ROUTES, TIMEBACK_ORG_SOURCED_ID = "PLAYCADEMY";
354
+ var init_timeback2 = __esm(() => {
355
+ TIMEBACK_ROUTES = {
356
+ END_ACTIVITY: "/integrations/timeback/end-activity"
357
+ };
358
+ });
355
359
 
356
360
  // ../constants/src/workers.ts
357
- var WORKER_NAMING;
361
+ var WORKER_NAMING, SECRETS_PREFIX = "secrets_";
358
362
  var init_workers = __esm(() => {
359
363
  WORKER_NAMING = {
360
364
  STAGING_PREFIX: "staging-",
@@ -1224,7 +1228,7 @@ var package_default;
1224
1228
  var init_package = __esm(() => {
1225
1229
  package_default = {
1226
1230
  name: "@playcademy/sandbox",
1227
- version: "0.3.11",
1231
+ version: "0.3.13",
1228
1232
  description: "Local development server for Playcademy game development",
1229
1233
  type: "module",
1230
1234
  exports: {
@@ -1675,7 +1679,7 @@ function createHandle(buildContext) {
1675
1679
  try {
1676
1680
  const ctx = await buildContext(c);
1677
1681
  const result = await controller(ctx);
1678
- if (options?.status === 204 || result === undefined || result === null) {
1682
+ if (options?.status === 204 || result === undefined) {
1679
1683
  return new Response(null, { status: options?.status ?? 204 });
1680
1684
  }
1681
1685
  return new Response(JSON.stringify(result), {
@@ -13914,6 +13918,20 @@ class GameService {
13914
13918
  orderBy: [desc(games.createdAt)]
13915
13919
  });
13916
13920
  }
13921
+ async getSubjects() {
13922
+ const db2 = this.ctx.db;
13923
+ const integrations = await db2.query.gameTimebackIntegrations.findMany({
13924
+ columns: { gameId: true, subject: true },
13925
+ orderBy: [asc(gameTimebackIntegrations.createdAt)]
13926
+ });
13927
+ const subjectMap = {};
13928
+ for (const integration of integrations) {
13929
+ if (!(integration.gameId in subjectMap)) {
13930
+ subjectMap[integration.gameId] = integration.subject;
13931
+ }
13932
+ }
13933
+ return subjectMap;
13934
+ }
13917
13935
  async getById(gameId) {
13918
13936
  const db2 = this.ctx.db;
13919
13937
  const game = await db2.query.games.findFirst({
@@ -14908,13 +14926,13 @@ class LevelService {
14908
14926
  throw new BadRequestError("Level must be at least 1");
14909
14927
  }
14910
14928
  if (levelConfigCache?.has(level)) {
14911
- return levelConfigCache.get(level) || null;
14929
+ return levelConfigCache.get(level) ?? null;
14912
14930
  }
14913
14931
  const [config2] = await this.ctx.db.select().from(levelConfigs).where(eq(levelConfigs.level, level)).limit(1);
14914
14932
  if (levelConfigCache && config2) {
14915
14933
  levelConfigCache.set(level, config2);
14916
14934
  }
14917
- return config2 || null;
14935
+ return config2 ?? null;
14918
14936
  }
14919
14937
  async listConfigs() {
14920
14938
  return this.ctx.db.select().from(levelConfigs).orderBy(levelConfigs.level);
@@ -15801,8 +15819,9 @@ class SecretsService {
15801
15819
  }
15802
15820
  }
15803
15821
  }
15804
- var logger21, SECRETS_PREFIX = "secrets_", INTERNAL_SECRET_KEYS;
15822
+ var logger21, INTERNAL_SECRET_KEYS;
15805
15823
  var init_secrets_service = __esm(() => {
15824
+ init_src();
15806
15825
  init_src2();
15807
15826
  init_config2();
15808
15827
  init_errors();
@@ -15811,6 +15830,32 @@ var init_secrets_service = __esm(() => {
15811
15830
  INTERNAL_SECRET_KEYS = ["PLAYCADEMY_API_KEY", "GAME_ID", "PLAYCADEMY_BASE_URL"];
15812
15831
  });
15813
15832
 
15833
+ // ../edge-play/src/constants.ts
15834
+ var ROUTES;
15835
+ var init_constants2 = __esm(() => {
15836
+ init_src();
15837
+ ROUTES = {
15838
+ INDEX: "/api",
15839
+ HEALTH: "/api/health",
15840
+ TIMEBACK: {
15841
+ END_ACTIVITY: `/api${TIMEBACK_ROUTES.END_ACTIVITY}`
15842
+ }
15843
+ };
15844
+ });
15845
+
15846
+ // ../edge-play/src/entry/setup.ts
15847
+ function prefixSecrets(secrets) {
15848
+ const prefixed = {};
15849
+ for (const [key, value] of Object.entries(secrets)) {
15850
+ prefixed[SECRETS_PREFIX + key] = value;
15851
+ }
15852
+ return prefixed;
15853
+ }
15854
+ var init_setup = __esm(() => {
15855
+ init_src();
15856
+ init_constants2();
15857
+ });
15858
+
15814
15859
  // ../api-core/src/services/seed.service.ts
15815
15860
  class SeedService {
15816
15861
  ctx;
@@ -15825,7 +15870,7 @@ class SeedService {
15825
15870
  }
15826
15871
  return cf;
15827
15872
  }
15828
- async seed(slug2, code, user) {
15873
+ async seed(slug2, code, user, secrets) {
15829
15874
  const cf = this.getCloudflare();
15830
15875
  const game = await this.ctx.services.game.validateDeveloperAccessBySlug(user, slug2);
15831
15876
  const isProd = isProduction2(this.ctx.config);
@@ -15837,10 +15882,11 @@ class SeedService {
15837
15882
  gameId: game.id,
15838
15883
  slug: slug2,
15839
15884
  deploymentId,
15840
- codeLength: code.length
15885
+ codeLength: code.length,
15886
+ secretCount: secrets ? Object.keys(secrets).length : 0
15841
15887
  });
15842
15888
  try {
15843
- const workerResponse = await this.deployAndExecuteSeedWorker(cf, seedDeploymentId, game.id, deploymentId, code);
15889
+ const workerResponse = await this.deployAndExecuteSeedWorker(cf, seedDeploymentId, game.id, deploymentId, code, secrets);
15844
15890
  logger22.info("Seed completed", {
15845
15891
  gameId: game.id,
15846
15892
  slug: slug2,
@@ -15912,7 +15958,7 @@ class SeedService {
15912
15958
  });
15913
15959
  }
15914
15960
  }
15915
- async deployAndExecuteSeedWorker(cf, seedDeploymentId, gameId, deploymentId, workerCode) {
15961
+ async deployAndExecuteSeedWorker(cf, seedDeploymentId, gameId, deploymentId, workerCode, secrets) {
15916
15962
  try {
15917
15963
  const result = await cf.deploy(seedDeploymentId, workerCode, {
15918
15964
  GAME_ID: gameId,
@@ -15922,6 +15968,13 @@ class SeedService {
15922
15968
  keepAssets: false
15923
15969
  });
15924
15970
  logger22.info("Worker deployed", { seedDeploymentId, url: result.url });
15971
+ if (secrets && Object.keys(secrets).length > 0) {
15972
+ await cf.setSecrets(seedDeploymentId, prefixSecrets(secrets));
15973
+ logger22.info("Secrets bound to worker", {
15974
+ seedDeploymentId,
15975
+ count: Object.keys(secrets).length
15976
+ });
15977
+ }
15925
15978
  return await this.executeSeedWorker(result.url, seedDeploymentId);
15926
15979
  } finally {
15927
15980
  await this.cleanupSeedWorker(cf, seedDeploymentId);
@@ -16037,6 +16090,7 @@ class SeedService {
16037
16090
  }
16038
16091
  var logger22;
16039
16092
  var init_seed_service = __esm(() => {
16093
+ init_setup();
16040
16094
  init_src2();
16041
16095
  init_config2();
16042
16096
  init_errors();
@@ -16504,7 +16558,7 @@ function isTimebackSubject(value) {
16504
16558
  function isTimebackGrade(value) {
16505
16559
  return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES.includes(value);
16506
16560
  }
16507
- var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), ACHIEVEMENT_IDS2, ACHIEVEMENT_DEFINITIONS2, init_achievements2, init_auth2 = () => {}, TSC_PACKAGE2 = "@typescript/native-preview", USE_NATIVE_TSC2, init_typescript2, init_character2 = () => {}, PLAYCADEMY_BASE_URLS, init_domains2, init_env_vars2 = () => {}, ITEM_SLUGS2, CURRENCIES2, BADGES2, init_overworld2, TIMEBACK_CALIPER_SENSORS, TIMEBACK_ORG_SOURCED_ID2 = "PLAYCADEMY", TIMEBACK_ORG_NAME = "Playcademy Studios", TIMEBACK_ORG_TYPE = "department", TIMEBACK_COURSE_DEFAULTS, TIMEBACK_RESOURCE_DEFAULTS, TIMEBACK_COMPONENT_DEFAULTS, TIMEBACK_COMPONENT_RESOURCE_DEFAULTS, init_timeback3, init_workers2 = () => {}, init_src5, TIMEBACK_API_URLS, TIMEBACK_AUTH_URLS, CALIPER_API_URLS, ONEROSTER_ENDPOINTS, CALIPER_ENDPOINTS, CALIPER_CONSTANTS, TIMEBACK_EVENT_TYPES, TIMEBACK_ACTIONS, TIMEBACK_TYPES, ACTIVITY_METRIC_TYPES, TIME_METRIC_TYPES, TIMEBACK_SUBJECTS, TIMEBACK_GRADE_LEVELS, TIMEBACK_GRADE_LEVEL_LABELS, CALIPER_SUBJECTS, ONEROSTER_STATUS, SCORE_STATUS, ENV_VARS, HTTP_DEFAULTS, AUTH_DEFAULTS, CACHE_DEFAULTS, CONFIG_DEFAULTS, PLAYCADEMY_DEFAULTS, RESOURCE_DEFAULTS, HTTP_STATUS, ERROR_NAMES, init_constants2, isObject = (value) => typeof value === "object" && value !== null, SUBJECT_VALUES, GRADE_VALUES;
16561
+ var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), ACHIEVEMENT_IDS2, ACHIEVEMENT_DEFINITIONS2, init_achievements2, init_auth2 = () => {}, TSC_PACKAGE2 = "@typescript/native-preview", USE_NATIVE_TSC2, init_typescript2, init_character2 = () => {}, PLAYCADEMY_BASE_URLS, init_domains2, init_env_vars2 = () => {}, ITEM_SLUGS2, CURRENCIES2, BADGES2, init_overworld2, TIMEBACK_CALIPER_SENSORS, TIMEBACK_ORG_SOURCED_ID2 = "PLAYCADEMY", TIMEBACK_ORG_NAME = "Playcademy Studios", TIMEBACK_ORG_TYPE = "department", TIMEBACK_COURSE_DEFAULTS, TIMEBACK_RESOURCE_DEFAULTS, TIMEBACK_COMPONENT_DEFAULTS, TIMEBACK_COMPONENT_RESOURCE_DEFAULTS, init_timeback3, init_workers2 = () => {}, init_src5, TIMEBACK_API_URLS, TIMEBACK_AUTH_URLS, CALIPER_API_URLS, ONEROSTER_ENDPOINTS, CALIPER_ENDPOINTS, CALIPER_CONSTANTS, TIMEBACK_EVENT_TYPES, TIMEBACK_ACTIONS, TIMEBACK_TYPES, ACTIVITY_METRIC_TYPES, TIME_METRIC_TYPES, TIMEBACK_SUBJECTS, TIMEBACK_GRADE_LEVELS, TIMEBACK_GRADE_LEVEL_LABELS, CALIPER_SUBJECTS, ONEROSTER_STATUS, SCORE_STATUS, ENV_VARS, HTTP_DEFAULTS, AUTH_DEFAULTS, CACHE_DEFAULTS, CONFIG_DEFAULTS, PLAYCADEMY_DEFAULTS, RESOURCE_DEFAULTS, HTTP_STATUS, ERROR_NAMES, init_constants3, isObject = (value) => typeof value === "object" && value !== null, SUBJECT_VALUES, GRADE_VALUES;
16508
16562
  var init_types7 = __esm(() => {
16509
16563
  init_achievements2 = __esm2(() => {
16510
16564
  ACHIEVEMENT_IDS2 = {
@@ -16681,7 +16735,7 @@ var init_types7 = __esm(() => {
16681
16735
  init_timeback3();
16682
16736
  init_workers2();
16683
16737
  });
16684
- init_constants2 = __esm2(() => {
16738
+ init_constants3 = __esm2(() => {
16685
16739
  init_src5();
16686
16740
  TIMEBACK_API_URLS = {
16687
16741
  production: "https://api.alpha-1edtech.ai",
@@ -16856,7 +16910,7 @@ var init_types7 = __esm(() => {
16856
16910
  timebackSdk: "TimebackSDKError"
16857
16911
  };
16858
16912
  });
16859
- init_constants2();
16913
+ init_constants3();
16860
16914
  SUBJECT_VALUES = TIMEBACK_SUBJECTS;
16861
16915
  GRADE_VALUES = TIMEBACK_GRADE_LEVELS;
16862
16916
  });
@@ -20154,7 +20208,7 @@ var __defProp2, __export2 = (target, all) => {
20154
20208
  course: (courseId) => `${base}${ONEROSTER_ENDPOINTS2.courses}/${courseId}`,
20155
20209
  componentResource: (resourceId) => `${base}${ONEROSTER_ENDPOINTS2.componentResources}/${resourceId}`
20156
20210
  };
20157
- }, CALIPER_CONSTANTS2, TIMEBACK_EVENT_TYPES2, TIMEBACK_ACTIONS2, TIMEBACK_TYPES2, ACTIVITY_METRIC_TYPES2, TIME_METRIC_TYPES2, TIMEBACK_SUBJECTS2, TIMEBACK_GRADE_LEVELS2, TIMEBACK_GRADE_LEVEL_LABELS2, CALIPER_SUBJECTS2, ONEROSTER_STATUS2, SCORE_STATUS2, ENV_VARS2, HTTP_DEFAULTS2, AUTH_DEFAULTS2, CACHE_DEFAULTS2, CONFIG_DEFAULTS2, PLAYCADEMY_DEFAULTS2, RESOURCE_DEFAULTS2, HTTP_STATUS2, ERROR_NAMES2, init_constants3, exports_verify, init_verify, TimebackError, TimebackApiError, TimebackAuthenticationError, StudentNotFoundError, ConfigurationError, ResourceNotFoundError, isObject2 = (value) => typeof value === "object" && value !== null, SUBJECT_VALUES2, GRADE_VALUES2, isBrowser2 = () => {
20211
+ }, CALIPER_CONSTANTS2, TIMEBACK_EVENT_TYPES2, TIMEBACK_ACTIONS2, TIMEBACK_TYPES2, ACTIVITY_METRIC_TYPES2, TIME_METRIC_TYPES2, TIMEBACK_SUBJECTS2, TIMEBACK_GRADE_LEVELS2, TIMEBACK_GRADE_LEVEL_LABELS2, CALIPER_SUBJECTS2, ONEROSTER_STATUS2, SCORE_STATUS2, ENV_VARS2, HTTP_DEFAULTS2, AUTH_DEFAULTS2, CACHE_DEFAULTS2, CONFIG_DEFAULTS2, PLAYCADEMY_DEFAULTS2, RESOURCE_DEFAULTS2, HTTP_STATUS2, ERROR_NAMES2, init_constants4, exports_verify, init_verify, TimebackError, TimebackApiError, TimebackAuthenticationError, StudentNotFoundError, ConfigurationError, ResourceNotFoundError, isObject2 = (value) => typeof value === "object" && value !== null, SUBJECT_VALUES2, GRADE_VALUES2, isBrowser2 = () => {
20158
20212
  const g = globalThis;
20159
20213
  return typeof g.window !== "undefined" && typeof g.document !== "undefined";
20160
20214
  }, isProduction3 = () => {
@@ -20693,7 +20747,7 @@ var init_dist3 = __esm(() => {
20693
20747
  init_timeback4();
20694
20748
  init_workers3();
20695
20749
  });
20696
- init_constants3 = __esm3(() => {
20750
+ init_constants4 = __esm3(() => {
20697
20751
  init_src6();
20698
20752
  TIMEBACK_API_URLS2 = {
20699
20753
  production: "https://api.alpha-1edtech.ai",
@@ -20874,9 +20928,9 @@ var init_dist3 = __esm(() => {
20874
20928
  fetchTimebackConfig: () => fetchTimebackConfig
20875
20929
  });
20876
20930
  init_verify = __esm3(() => {
20877
- init_constants3();
20931
+ init_constants4();
20878
20932
  });
20879
- init_constants3();
20933
+ init_constants4();
20880
20934
  TimebackError = class TimebackError extends Error {
20881
20935
  constructor(message) {
20882
20936
  super(message);
@@ -20933,7 +20987,7 @@ var init_dist3 = __esm(() => {
20933
20987
  Object.setPrototypeOf(this, ResourceNotFoundError.prototype);
20934
20988
  }
20935
20989
  };
20936
- init_constants3();
20990
+ init_constants4();
20937
20991
  SUBJECT_VALUES2 = TIMEBACK_SUBJECTS2;
20938
20992
  GRADE_VALUES2 = TIMEBACK_GRADE_LEVELS2;
20939
20993
  colors3 = {
@@ -20954,8 +21008,8 @@ var init_dist3 = __esm(() => {
20954
21008
  };
20955
21009
  log3 = createLogger2();
20956
21010
  init_verify();
20957
- init_constants3();
20958
- init_constants3();
21011
+ init_constants4();
21012
+ init_constants4();
20959
21013
  if (process.env.DEBUG === "true") {
20960
21014
  process.env.TERM = "dumb";
20961
21015
  }
@@ -20967,13 +21021,13 @@ var init_dist3 = __esm(() => {
20967
21021
  this.name = ERROR_NAMES2.timebackAuth;
20968
21022
  }
20969
21023
  };
20970
- init_constants3();
20971
- init_constants3();
20972
- init_constants3();
20973
- init_constants3();
20974
- init_constants3();
20975
- init_constants3();
20976
- init_constants3();
21024
+ init_constants4();
21025
+ init_constants4();
21026
+ init_constants4();
21027
+ init_constants4();
21028
+ init_constants4();
21029
+ init_constants4();
21030
+ init_constants4();
20977
21031
  exports_external2 = {};
20978
21032
  __export2(exports_external2, {
20979
21033
  void: () => voidType2,
@@ -24531,7 +24585,7 @@ var init_http_exception = () => {};
24531
24585
 
24532
24586
  // ../../node_modules/hono/dist/request/constants.js
24533
24587
  var GET_MATCH_RESULT;
24534
- var init_constants4 = __esm(() => {
24588
+ var init_constants5 = __esm(() => {
24535
24589
  GET_MATCH_RESULT = Symbol();
24536
24590
  });
24537
24591
 
@@ -24795,7 +24849,7 @@ var init_url = __esm(() => {
24795
24849
  var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_), HonoRequest;
24796
24850
  var init_request = __esm(() => {
24797
24851
  init_http_exception();
24798
- init_constants4();
24852
+ init_constants5();
24799
24853
  init_body();
24800
24854
  init_url();
24801
24855
  HonoRequest = class {
@@ -25125,7 +25179,7 @@ var init_router = __esm(() => {
25125
25179
 
25126
25180
  // ../../node_modules/hono/dist/utils/constants.js
25127
25181
  var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
25128
- var init_constants5 = () => {};
25182
+ var init_constants6 = () => {};
25129
25183
 
25130
25184
  // ../../node_modules/hono/dist/hono-base.js
25131
25185
  var notFoundHandler = (c) => {
@@ -25347,7 +25401,7 @@ var init_hono_base = __esm(() => {
25347
25401
  init_compose();
25348
25402
  init_context2();
25349
25403
  init_router();
25350
- init_constants5();
25404
+ init_constants6();
25351
25405
  init_url();
25352
25406
  });
25353
25407
 
@@ -82704,7 +82758,8 @@ var init_schemas3 = __esm(() => {
82704
82758
  });
82705
82759
  SetSecretsRequestSchema = exports_external.record(exports_external.string().min(1), exports_external.string());
82706
82760
  SeedRequestSchema = exports_external.object({
82707
- code: exports_external.string().min(1, "Seed code is required")
82761
+ code: exports_external.string().min(1, "Seed code is required"),
82762
+ secrets: exports_external.record(exports_external.string(), exports_external.string()).optional()
82708
82763
  });
82709
82764
  SchemaInfoSchema = exports_external.object({
82710
82765
  sql: exports_external.string(),
@@ -92875,7 +92930,7 @@ var init_domain_controller = __esm(() => {
92875
92930
  });
92876
92931
 
92877
92932
  // ../api-core/src/controllers/game.controller.ts
92878
- var logger43, list3, getById2, getBySlug, upsertBySlug, remove3, games2;
92933
+ var logger43, list3, getSubjects, getById2, getBySlug, upsertBySlug, remove3, games2;
92879
92934
  var init_game_controller = __esm(() => {
92880
92935
  init_esm();
92881
92936
  init_schemas_index();
@@ -92888,6 +92943,10 @@ var init_game_controller = __esm(() => {
92888
92943
  logger43.debug("Listing games", { userId: ctx.user.id });
92889
92944
  return ctx.services.game.list();
92890
92945
  });
92946
+ getSubjects = requireAuth(async (ctx) => {
92947
+ logger43.debug("Getting game subjects", { userId: ctx.user.id });
92948
+ return ctx.services.game.getSubjects();
92949
+ });
92891
92950
  getById2 = requireAuth(async (ctx) => {
92892
92951
  const gameId = ctx.params.gameId;
92893
92952
  if (!gameId) {
@@ -92940,6 +92999,7 @@ var init_game_controller = __esm(() => {
92940
92999
  });
92941
93000
  games2 = {
92942
93001
  list: list3,
93002
+ getSubjects,
92943
93003
  getById: getById2,
92944
93004
  getBySlug,
92945
93005
  upsertBySlug,
@@ -93323,7 +93383,6 @@ var init_leaderboard_controller = __esm(() => {
93323
93383
  init_esm();
93324
93384
  init_schemas_index();
93325
93385
  init_src2();
93326
- init_src4();
93327
93386
  init_errors();
93328
93387
  init_utils11();
93329
93388
  logger47 = log.scope("LeaderboardController");
@@ -93412,9 +93471,6 @@ var init_leaderboard_controller = __esm(() => {
93412
93471
  if (!gameId || !userId) {
93413
93472
  throw ApiError.badRequest("Game ID and User ID are required");
93414
93473
  }
93415
- if (!isValidUUID(userId)) {
93416
- throw ApiError.unprocessableEntity("userId must be a valid UUID format");
93417
- }
93418
93474
  logger47.debug("Getting user rank", {
93419
93475
  requesterId: ctx.user.id,
93420
93476
  gameId,
@@ -93427,9 +93483,6 @@ var init_leaderboard_controller = __esm(() => {
93427
93483
  if (!userId) {
93428
93484
  throw ApiError.badRequest("User ID is required");
93429
93485
  }
93430
- if (!isValidUUID(userId)) {
93431
- throw ApiError.unprocessableEntity("userId must be a valid UUID format");
93432
- }
93433
93486
  const url = ctx.url;
93434
93487
  const limit = Math.min(Number(url.searchParams.get("limit") || "50"), 100);
93435
93488
  const gameId = url.searchParams.get("gameId") || undefined;
@@ -93446,9 +93499,6 @@ var init_leaderboard_controller = __esm(() => {
93446
93499
  if (!gameId || !userId) {
93447
93500
  throw ApiError.badRequest("Game ID and User ID are required");
93448
93501
  }
93449
- if (!isValidUUID(userId)) {
93450
- throw ApiError.unprocessableEntity("userId must be a valid UUID format");
93451
- }
93452
93502
  const url = ctx.url;
93453
93503
  const limit = Math.min(Number(url.searchParams.get("limit") || "10"), 100);
93454
93504
  logger47.debug("Getting user scores", {
@@ -93874,8 +93924,13 @@ var init_seed_controller = __esm(() => {
93874
93924
  }
93875
93925
  throw ApiError.badRequest("Invalid JSON body");
93876
93926
  }
93877
- logger55.debug("Seeding database", { userId: ctx.user.id, slug: slug2, codeLength: body2.code.length });
93878
- return ctx.services.seed.seed(slug2, body2.code, ctx.user);
93927
+ logger55.debug("Seeding database", {
93928
+ userId: ctx.user.id,
93929
+ slug: slug2,
93930
+ codeLength: body2.code.length,
93931
+ secretCount: body2.secrets ? Object.keys(body2.secrets).length : 0
93932
+ });
93933
+ return ctx.services.seed.seed(slug2, body2.code, ctx.user, body2.secrets);
93879
93934
  });
93880
93935
  });
93881
93936
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/sandbox",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
4
4
  "description": "Local development server for Playcademy game development",
5
5
  "type": "module",
6
6
  "exports": {