@playcademy/vite-plugin 1.2.1-beta.25 → 1.2.1-beta.26

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 +505 -467
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -24315,7 +24315,7 @@ import path2 from "node:path";
24315
24315
  // package.json
24316
24316
  var package_default = {
24317
24317
  name: "@playcademy/vite-plugin",
24318
- version: "1.2.1-beta.25",
24318
+ version: "1.2.1-beta.26",
24319
24319
  type: "module",
24320
24320
  exports: {
24321
24321
  ".": {
@@ -24767,6 +24767,7 @@ import { stdout } from "process";
24767
24767
  import { createHash } from "node:crypto";
24768
24768
  import { createHash as createHash2 } from "node:crypto";
24769
24769
  import crypto3 from "node:crypto";
24770
+ import * as crypto4 from "node:crypto";
24770
24771
  import * as s3 from "fs";
24771
24772
  import * as o3 from "path";
24772
24773
  import fs22 from "node:fs";
@@ -24774,10 +24775,9 @@ import { dirname, isAbsolute, join as join4 } from "node:path";
24774
24775
  import process22 from "process";
24775
24776
  import os2 from "os";
24776
24777
  import tty from "tty";
24777
- import { randomUUID } from "crypto";
24778
+ import { randomUUID as randomUUID2 } from "crypto";
24778
24779
  import fs3 from "node:fs";
24779
24780
  import fs4 from "node:fs";
24780
- import * as crypto4 from "node:crypto";
24781
24781
  import { randomUUID as randomUUID3 } from "node:crypto";
24782
24782
  var __create2 = Object.create;
24783
24783
  var __getProtoOf2 = Object.getPrototypeOf;
@@ -25921,7 +25921,7 @@ var package_default2;
25921
25921
  var init_package = __esm(() => {
25922
25922
  package_default2 = {
25923
25923
  name: "@playcademy/sandbox",
25924
- version: "0.7.1-beta.23",
25924
+ version: "0.7.1-beta.24",
25925
25925
  description: "Local development server for Playcademy game development",
25926
25926
  type: "module",
25927
25927
  exports: {
@@ -63054,67 +63054,6 @@ var init_infra2 = __esm(() => {
63054
63054
  init_alerts_service();
63055
63055
  init_kv_backup_service();
63056
63056
  });
63057
- function createInMemoryDatabaseLock() {
63058
- const tails = new Map;
63059
- return async (db2, key, operation) => {
63060
- const previous = tails.get(key) ?? Promise.resolve();
63061
- let release;
63062
- const gate = new Promise((resolve2) => {
63063
- release = resolve2;
63064
- });
63065
- const tail = previous.then(() => gate);
63066
- tails.set(key, tail);
63067
- await previous;
63068
- try {
63069
- return await operation(db2);
63070
- } finally {
63071
- release();
63072
- if (tails.get(key) === tail) {
63073
- tails.delete(key);
63074
- }
63075
- }
63076
- };
63077
- }
63078
- var LockContentionError;
63079
- var init_locks = __esm(() => {
63080
- init_src6();
63081
- LockContentionError = class LockContentionError2 extends Error {
63082
- constructor(key) {
63083
- super(`Lock is already held: ${key}`);
63084
- this.name = "LockContentionError";
63085
- }
63086
- };
63087
- });
63088
- function assessmentRuntimeStartLockKey(input) {
63089
- return JSON.stringify([
63090
- ASSESSMENT_RUNTIME_LOCK_NAMESPACE,
63091
- "start",
63092
- input.studentId,
63093
- input.activityId,
63094
- input.purpose,
63095
- input.courseId
63096
- ]);
63097
- }
63098
- function assessmentRuntimeAttemptLockKey(attemptId) {
63099
- return JSON.stringify([ASSESSMENT_RUNTIME_LOCK_NAMESPACE, "attempt", attemptId]);
63100
- }
63101
- function createAssessmentRuntimeLock(lock) {
63102
- return async (db2, key, operation) => {
63103
- try {
63104
- return await lock(db2, key, operation);
63105
- } catch (error) {
63106
- if (error instanceof LockContentionError) {
63107
- throw new ServiceUnavailableError("Another assessment operation is in progress. Try again shortly.", { retryable: true });
63108
- }
63109
- throw error;
63110
- }
63111
- };
63112
- }
63113
- var ASSESSMENT_RUNTIME_LOCK_NAMESPACE = "playcademy-assessment-runtime-v1";
63114
- var init_assessment_runtime_lock_util = __esm(() => {
63115
- init_locks();
63116
- init_errors2();
63117
- });
63118
63057
  function hasPagingOptions(options) {
63119
63058
  return options.cursor !== undefined || options.limit !== undefined || options.delimiter !== undefined;
63120
63059
  }
@@ -117910,6 +117849,109 @@ var init_timeback_admin_service = __esm(async () => {
117910
117849
  init_timeback_mastery_completion_util()
117911
117850
  ]);
117912
117851
  });
117852
+ function createInMemoryDatabaseLock() {
117853
+ const tails = new Map;
117854
+ return async (db2, key, operation) => {
117855
+ const previous = tails.get(key) ?? Promise.resolve();
117856
+ let release;
117857
+ const gate = new Promise((resolve2) => {
117858
+ release = resolve2;
117859
+ });
117860
+ const tail = previous.then(() => gate);
117861
+ tails.set(key, tail);
117862
+ await previous;
117863
+ try {
117864
+ return await operation(db2);
117865
+ } finally {
117866
+ release();
117867
+ if (tails.get(key) === tail) {
117868
+ tails.delete(key);
117869
+ }
117870
+ }
117871
+ };
117872
+ }
117873
+ var LockContentionError;
117874
+ var init_locks = __esm(() => {
117875
+ LockContentionError = class LockContentionError2 extends Error {
117876
+ constructor(key) {
117877
+ super(`Lock is already held: ${key}`);
117878
+ this.name = "LockContentionError";
117879
+ }
117880
+ };
117881
+ });
117882
+ function normalizeKeys(keys) {
117883
+ return [...new Set(keys)].toSorted();
117884
+ }
117885
+ function errorCode(error88) {
117886
+ if (typeof error88 !== "object" || error88 === null || !("code" in error88)) {
117887
+ return;
117888
+ }
117889
+ return typeof error88.code === "string" ? error88.code : undefined;
117890
+ }
117891
+ function translateAssessmentRuntimeLockError(error88) {
117892
+ if (error88 instanceof LockContentionError) {
117893
+ throw new ServiceUnavailableError("Another assessment operation is in progress. Try again shortly.", { retryable: true });
117894
+ }
117895
+ if (error88 instanceof AssessmentRuntimeLockTimeoutError) {
117896
+ throw new ServiceUnavailableError("The assessment operation took too long. Try again shortly.", { retryable: true, reason: "LOCK_TIMEOUT" });
117897
+ }
117898
+ const code = errorCode(error88);
117899
+ if (code && POSTGRES_TIMEOUT_ERROR_CODES.has(code)) {
117900
+ throw new ServiceUnavailableError("The assessment operation took too long. Try again shortly.", { retryable: true, reason: "LOCK_TIMEOUT" });
117901
+ }
117902
+ if (code && POSTGRES_CONNECTION_ERROR_CODES.has(code)) {
117903
+ throw new ServiceUnavailableError("The assessment lock connection was interrupted. Try again shortly.", { retryable: true, reason: "LOCK_CONNECTION_LOST" });
117904
+ }
117905
+ throw error88;
117906
+ }
117907
+ function createInMemoryAssessmentRuntimeLock() {
117908
+ const lock = createInMemoryDatabaseLock();
117909
+ return async (db2, keys, operation) => {
117910
+ const ordered = normalizeKeys(keys);
117911
+ function acquire(index2, operationDb) {
117912
+ const key = ordered[index2];
117913
+ return key ? lock(operationDb, key, (nested) => acquire(index2 + 1, nested)) : operation(operationDb);
117914
+ }
117915
+ try {
117916
+ return await acquire(0, db2);
117917
+ } catch (error88) {
117918
+ return translateAssessmentRuntimeLockError(error88);
117919
+ }
117920
+ };
117921
+ }
117922
+ function assessmentRuntimeStartLockKey(input) {
117923
+ return JSON.stringify([
117924
+ ASSESSMENT_RUNTIME_LOCK_NAMESPACE,
117925
+ "start",
117926
+ input.studentId,
117927
+ input.activityId,
117928
+ input.purpose,
117929
+ input.courseId
117930
+ ]);
117931
+ }
117932
+ function assessmentRuntimeAttemptLockKey(attemptId) {
117933
+ return JSON.stringify([ASSESSMENT_RUNTIME_LOCK_NAMESPACE, "attempt", attemptId]);
117934
+ }
117935
+ var ASSESSMENT_RUNTIME_LOCK_NAMESPACE = "playcademy-assessment-runtime-v1";
117936
+ var POSTGRES_TIMEOUT_ERROR_CODES;
117937
+ var POSTGRES_CONNECTION_ERROR_CODES;
117938
+ var AssessmentRuntimeLockTimeoutError;
117939
+ var init_assessment_runtime_lock_util = __esm(() => {
117940
+ init_locks();
117941
+ init_errors2();
117942
+ POSTGRES_TIMEOUT_ERROR_CODES = new Set(["25P03", "57014"]);
117943
+ POSTGRES_CONNECTION_ERROR_CODES = new Set([
117944
+ "CONNECTION_CLOSED",
117945
+ "CONNECTION_DESTROYED",
117946
+ "CONNECTION_ENDED"
117947
+ ]);
117948
+ AssessmentRuntimeLockTimeoutError = class AssessmentRuntimeLockTimeoutError2 extends Error {
117949
+ constructor(timeoutMs) {
117950
+ super(`Assessment operation exceeded its ${timeoutMs}ms lock deadline`);
117951
+ this.name = "AssessmentRuntimeLockTimeoutError";
117952
+ }
117953
+ };
117954
+ });
117913
117955
  function validateAssessmentStatusTransition(current, next) {
117914
117956
  if (current === next) {
117915
117957
  return;
@@ -118733,8 +118775,8 @@ class TimebackAssessmentRuntimeService {
118733
118775
  activityId: input.activityId,
118734
118776
  purpose: input.purpose,
118735
118777
  courseId: row.courseId
118736
- })).toSorted();
118737
- return this.withStartLocks(lockKeys, async (db2) => {
118778
+ }));
118779
+ return this.deps.assessmentRuntimeLock(this.deps.db, lockKeys, async (db2) => {
118738
118780
  const context2 = await this.selectIntegration(candidates, studentId, input);
118739
118781
  const attemptScope = {
118740
118782
  studentId,
@@ -118751,7 +118793,7 @@ class TimebackAssessmentRuntimeService {
118751
118793
  const attempts = listing.attempts;
118752
118794
  const initialResolution = await this.resumeAvailableAttempt(tests, attempts, requestFingerprint, pendingSupersessions, (resumeDecision) => this.resumeSnapshot(resumeDecision, attempts, context2.integration));
118753
118795
  if (initialResolution.kind === "resumed") {
118754
- await this.persistPendingSupersessionsBestEffort(pendingSupersessions);
118796
+ await this.persistPendingSupersessionsBestEffort(db2, pendingSupersessions);
118755
118797
  return initialResolution.snapshot;
118756
118798
  }
118757
118799
  let decision = this.requireDecision(initialResolution.decision, input.purpose);
@@ -118760,7 +118802,7 @@ class TimebackAssessmentRuntimeService {
118760
118802
  const refreshed = refreshedListing.attempts;
118761
118803
  const refreshedResolution = await this.resumeAvailableAttempt(tests, refreshed, requestFingerprint, pendingSupersessions, (resumeDecision) => this.resumeSnapshot(resumeDecision, refreshed, context2.integration));
118762
118804
  if (refreshedResolution.kind === "resumed") {
118763
- await this.persistPendingSupersessionsBestEffort(pendingSupersessions);
118805
+ await this.persistPendingSupersessionsBestEffort(db2, pendingSupersessions);
118764
118806
  return refreshedResolution.snapshot;
118765
118807
  }
118766
118808
  decision = this.requireDecision(refreshedResolution.decision, input.purpose);
@@ -118821,7 +118863,7 @@ class TimebackAssessmentRuntimeService {
118821
118863
  grade: context2.integration.grade
118822
118864
  })
118823
118865
  });
118824
- await this.persistPendingSupersessionsBestEffort(pendingSupersessions);
118866
+ await this.persistPendingSupersessionsBestEffort(db2, pendingSupersessions);
118825
118867
  return this.snapshot(result, metadata2, assessment, context2.integration);
118826
118868
  });
118827
118869
  }
@@ -118838,8 +118880,8 @@ class TimebackAssessmentRuntimeService {
118838
118880
  activityId: input.activityId,
118839
118881
  purpose: input.purpose,
118840
118882
  courseId: row.courseId
118841
- })).toSorted();
118842
- return this.withStartLocks(lockKeys, async (db2) => {
118883
+ }));
118884
+ return this.deps.assessmentRuntimeLock(this.deps.db, lockKeys, async (db2) => {
118843
118885
  const context2 = await this.selectIntegration(candidates, studentId, input);
118844
118886
  const attemptScope = {
118845
118887
  studentId,
@@ -118855,7 +118897,7 @@ class TimebackAssessmentRuntimeService {
118855
118897
  ]);
118856
118898
  const initialResolution = await this.resumeAvailableAttempt(tests, listing.attempts, requestFingerprint, pendingSupersessions, (resumeDecision) => this.resumeDiagnosticSnapshot(resumeDecision, listing.attempts, context2.integration, db2));
118857
118899
  if (initialResolution.kind === "resumed") {
118858
- await this.persistPendingSupersessionsBestEffort(pendingSupersessions);
118900
+ await this.persistPendingSupersessionsBestEffort(db2, pendingSupersessions);
118859
118901
  return initialResolution.snapshot;
118860
118902
  }
118861
118903
  let decision = this.requireDecision(initialResolution.decision, input.purpose);
@@ -118866,7 +118908,7 @@ class TimebackAssessmentRuntimeService {
118866
118908
  const refreshed = refreshedListing.attempts;
118867
118909
  const refreshedResolution = await this.resumeAvailableAttempt(tests, refreshed, requestFingerprint, pendingSupersessions, (resumeDecision) => this.resumeDiagnosticSnapshot(resumeDecision, refreshed, context2.integration, db2));
118868
118910
  if (refreshedResolution.kind === "resumed") {
118869
- await this.persistPendingSupersessionsBestEffort(pendingSupersessions);
118911
+ await this.persistPendingSupersessionsBestEffort(db2, pendingSupersessions);
118870
118912
  return refreshedResolution.snapshot;
118871
118913
  }
118872
118914
  decision = this.requireDecision(refreshedResolution.decision, input.purpose);
@@ -118938,7 +118980,7 @@ class TimebackAssessmentRuntimeService {
118938
118980
  grade: context2.integration.grade
118939
118981
  })
118940
118982
  });
118941
- await this.persistPendingSupersessionsBestEffort(pendingSupersessions);
118983
+ await this.persistPendingSupersessionsBestEffort(db2, pendingSupersessions);
118942
118984
  return this.diagnosticSnapshot(result, metadata2, assessment, context2.integration, routing.state);
118943
118985
  });
118944
118986
  }
@@ -118957,8 +118999,8 @@ class TimebackAssessmentRuntimeService {
118957
118999
  activityId: input.activityId,
118958
119000
  purpose: input.purpose,
118959
119001
  courseId: row.courseId
118960
- })).toSorted();
118961
- return this.withStartLocks(lockKeys, async (db2) => {
119002
+ }));
119003
+ return this.deps.assessmentRuntimeLock(this.deps.db, lockKeys, async (db2) => {
118962
119004
  const context2 = await this.selectIntegration(candidates, studentId, input);
118963
119005
  const attemptScope = {
118964
119006
  studentId,
@@ -118975,7 +119017,7 @@ class TimebackAssessmentRuntimeService {
118975
119017
  const attempts = listing.attempts;
118976
119018
  const initialResolution = await this.resumeAvailableAttempt(tests, attempts, requestFingerprint, pendingSupersessions, (resumeDecision) => this.resumeReviewSnapshot(resumeDecision, attempts, listing.reviewChildren, context2));
118977
119019
  if (initialResolution.kind === "resumed") {
118978
- await this.persistPendingSupersessionsBestEffort(pendingSupersessions);
119020
+ await this.persistPendingSupersessionsBestEffort(db2, pendingSupersessions);
118979
119021
  return initialResolution.snapshot;
118980
119022
  }
118981
119023
  let decision = initialResolution.decision;
@@ -118994,7 +119036,7 @@ class TimebackAssessmentRuntimeService {
118994
119036
  const refreshed = refreshedListing.attempts;
118995
119037
  const refreshedResolution = await this.resumeAvailableAttempt(tests, refreshed, requestFingerprint, pendingSupersessions, (resumeDecision) => this.resumeReviewSnapshot(resumeDecision, refreshed, refreshedListing.reviewChildren, context2));
118996
119038
  if (refreshedResolution.kind === "resumed") {
118997
- await this.persistPendingSupersessionsBestEffort(pendingSupersessions);
119039
+ await this.persistPendingSupersessionsBestEffort(db2, pendingSupersessions);
118998
119040
  return refreshedResolution.snapshot;
118999
119041
  }
119000
119042
  const refreshedDecision = refreshedResolution.decision;
@@ -119088,7 +119130,7 @@ class TimebackAssessmentRuntimeService {
119088
119130
  existingChildResults: refreshedListing.reviewChildren,
119089
119131
  lookupMissingResults: false
119090
119132
  });
119091
- await this.persistPendingSupersessionsBestEffort(pendingSupersessions);
119133
+ await this.persistPendingSupersessionsBestEffort(db2, pendingSupersessions);
119092
119134
  this.recordReviewPreparationPhase("provisioning", provisioningStartedAt);
119093
119135
  this.recordReviewPreparationPhase("total", preparationStartedAt, {
119094
119136
  candidateCount: catalog.bank.items.length,
@@ -119176,7 +119218,7 @@ class TimebackAssessmentRuntimeService {
119176
119218
  "app.error.message": errorMessage2(error88)
119177
119219
  });
119178
119220
  }
119179
- return this.deps.assessmentRuntimeLock(this.deps.db, assessmentRuntimeAttemptLockKey(params.attemptId), async (db2) => {
119221
+ return this.deps.assessmentRuntimeLock(this.deps.db, [assessmentRuntimeAttemptLockKey(params.attemptId)], async (db2) => {
119180
119222
  const attempt = await this.authorizeAttempt(params, {
119181
119223
  db: db2,
119182
119224
  developerAccessValidated: true
@@ -119224,7 +119266,7 @@ class TimebackAssessmentRuntimeService {
119224
119266
  let preview = await this.prepareItemSubmission(params, input);
119225
119267
  let preparationAttempts = 1;
119226
119268
  while (true) {
119227
- const committed = await this.deps.assessmentRuntimeLock(this.deps.db, assessmentRuntimeAttemptLockKey(params.attemptId), async (db2) => {
119269
+ const committed = await this.deps.assessmentRuntimeLock(this.deps.db, [assessmentRuntimeAttemptLockKey(params.attemptId)], async (db2) => {
119228
119270
  const attempt = await this.authorizeAttempt(params, {
119229
119271
  db: db2,
119230
119272
  developerAccessValidated: true
@@ -119320,7 +119362,7 @@ class TimebackAssessmentRuntimeService {
119320
119362
  let preview = await this.prepareDiagnosticItemSubmission(params, input);
119321
119363
  let preparationAttempts = 1;
119322
119364
  while (true) {
119323
- const committed = await this.deps.assessmentRuntimeLock(this.deps.db, assessmentRuntimeAttemptLockKey(params.attemptId), async (db2) => {
119365
+ const committed = await this.deps.assessmentRuntimeLock(this.deps.db, [assessmentRuntimeAttemptLockKey(params.attemptId)], async (db2) => {
119324
119366
  const attempt = await this.authorizeAttempt(params, {
119325
119367
  db: db2,
119326
119368
  developerAccessValidated: true
@@ -119654,7 +119696,7 @@ class TimebackAssessmentRuntimeService {
119654
119696
  }) {
119655
119697
  await this.deps.validateDeveloperAccess(params.user, params.gameId);
119656
119698
  const preview = await this.prepareSubmission(params, input);
119657
- const submission = await this.deps.assessmentRuntimeLock(this.deps.db, assessmentRuntimeAttemptLockKey(params.attemptId), async (db2) => {
119699
+ const submission = await this.deps.assessmentRuntimeLock(this.deps.db, [assessmentRuntimeAttemptLockKey(params.attemptId)], async (db2) => {
119658
119700
  const attempt = await this.authorizeAttempt(params, {
119659
119701
  db: db2,
119660
119702
  developerAccessValidated: true
@@ -119977,10 +120019,6 @@ class TimebackAssessmentRuntimeService {
119977
120019
  enrollment: enrollmentByCourse.get(selection.selected.courseId)
119978
120020
  };
119979
120021
  }
119980
- async withStartLocks(keys, operation) {
119981
- const acquire = (index2, db2) => index2 === keys.length ? operation(db2) : this.deps.assessmentRuntimeLock(db2, keys[index2], (nested) => acquire(index2 + 1, nested));
119982
- return acquire(0, this.deps.db);
119983
- }
119984
120022
  async liveTests(integrationId, purpose, db2 = this.deps.db, requestedStandard, requestedDiagnosticKey) {
119985
120023
  const matchesMasteryStandard = requestedStandard ? masteryStandardMatcher(requestedStandard) : undefined;
119986
120024
  const rows = await db2.query.gameTimebackAssessmentTests.findMany({
@@ -120154,9 +120192,9 @@ class TimebackAssessmentRuntimeService {
120154
120192
  return null;
120155
120193
  }
120156
120194
  }
120157
- async persistPendingSupersessions(attemptIds) {
120195
+ async persistPendingSupersessions(db2, attemptIds) {
120158
120196
  for (const attemptId of [...attemptIds].toSorted()) {
120159
- await this.deps.assessmentRuntimeLock(this.deps.db, assessmentRuntimeAttemptLockKey(attemptId), async () => {
120197
+ await this.deps.assessmentRuntimeLock(db2, [assessmentRuntimeAttemptLockKey(attemptId)], async () => {
120160
120198
  let result;
120161
120199
  try {
120162
120200
  result = await this.requireClient().api.oneroster.assessmentResults.get(attemptId);
@@ -120178,12 +120216,12 @@ class TimebackAssessmentRuntimeService {
120178
120216
  });
120179
120217
  }
120180
120218
  }
120181
- async persistPendingSupersessionsBestEffort(attemptIds) {
120219
+ async persistPendingSupersessionsBestEffort(db2, attemptIds) {
120182
120220
  if (attemptIds.size === 0) {
120183
120221
  return;
120184
120222
  }
120185
120223
  try {
120186
- await this.persistPendingSupersessions(attemptIds);
120224
+ await this.persistPendingSupersessions(db2, attemptIds);
120187
120225
  } catch (error88) {
120188
120226
  addEvent("assessment.attempt_supersession_persist_failed", {
120189
120227
  "app.assessment.attempt_ids": [...attemptIds].toSorted().join(","),
@@ -120809,7 +120847,7 @@ class TimebackAssessmentRuntimeService {
120809
120847
  async crossAttemptLockBarrier(attemptId) {
120810
120848
  for (let attempt = 1;attempt <= TimebackAssessmentRuntimeService.PROJECTION_BARRIER_MAX_ATTEMPTS; attempt += 1) {
120811
120849
  try {
120812
- await this.deps.assessmentRuntimeLock(this.deps.db, assessmentRuntimeAttemptLockKey(attemptId), async () => {
120850
+ await this.deps.assessmentRuntimeLock(this.deps.db, [assessmentRuntimeAttemptLockKey(attemptId)], async () => {
120813
120851
  return;
120814
120852
  });
120815
120853
  return;
@@ -125298,7 +125336,7 @@ var init_upload_service = __esm(() => {
125298
125336
  function createPlatformServices(deps) {
125299
125337
  const {
125300
125338
  db: db2,
125301
- databaseLock,
125339
+ assessmentRuntimeLock,
125302
125340
  config: config5,
125303
125341
  cloudflare: cloudflare2,
125304
125342
  corsKvs,
@@ -125367,7 +125405,7 @@ function createPlatformServices(deps) {
125367
125405
  db: db2,
125368
125406
  timeback: timebackClient,
125369
125407
  validateDeveloperAccess,
125370
- assessmentRuntimeLock: createAssessmentRuntimeLock(databaseLock)
125408
+ assessmentRuntimeLock
125371
125409
  });
125372
125410
  return {
125373
125411
  bucket,
@@ -125385,7 +125423,6 @@ function createPlatformServices(deps) {
125385
125423
  };
125386
125424
  }
125387
125425
  var init_platform2 = __esm(async () => {
125388
- init_assessment_runtime_lock_util();
125389
125426
  init_bucket_service();
125390
125427
  init_database_service();
125391
125428
  init_deployment_state_service();
@@ -126065,7 +126102,7 @@ var init_standalone = __esm(() => {
126065
126102
  init_verify_service();
126066
126103
  });
126067
126104
  function createServices(ctx) {
126068
- const { db: db2, databaseLock, config: config5, providers, cloudflare: cloudflare2, timeback: timeback2, discord, corsKvs } = ctx;
126105
+ const { db: db2, assessmentRuntimeLock, config: config5, providers, cloudflare: cloudflare2, timeback: timeback2, discord, corsKvs } = ctx;
126069
126106
  const { auth: auth2, storage, r2Storage, cache } = providers;
126070
126107
  const infra2 = createInfraServices({
126071
126108
  db: db2,
@@ -126087,7 +126124,7 @@ function createServices(ctx) {
126087
126124
  });
126088
126125
  const platform2 = createPlatformServices({
126089
126126
  db: db2,
126090
- databaseLock,
126127
+ assessmentRuntimeLock,
126091
126128
  config: config5,
126092
126129
  cloudflare: cloudflare2,
126093
126130
  corsKvs,
@@ -126114,6 +126151,324 @@ var init_factory = __esm(async () => {
126114
126151
  init_standalone();
126115
126152
  await init_platform2();
126116
126153
  });
126154
+ function isAuthenticated(ctx) {
126155
+ return ctx.user != null;
126156
+ }
126157
+ var init_types5 = () => {};
126158
+ function hasGameManagementAccess(user) {
126159
+ return user.role === "admin" || user.role === "teacher" || user.role === "developer" && user.developerStatus === "approved";
126160
+ }
126161
+ function isDashboardWorkerKey(key) {
126162
+ return Boolean(key?.permissions?.[DASHBOARD_PERMISSION_NAMESPACE]);
126163
+ }
126164
+ function workerKeyGrantsGameRead(key, slug2) {
126165
+ if (!isDashboardWorkerKey(key) && !isGameWorkerKey(key)) {
126166
+ return false;
126167
+ }
126168
+ const games2 = key?.permissions?.games;
126169
+ return Boolean(games2?.includes(`read:${slug2}`) || games2?.includes(`write:${slug2}`));
126170
+ }
126171
+ function isGameWorkerKey(key) {
126172
+ return Boolean(key?.name?.startsWith(GAME_WORKER_KEY_PREFIX));
126173
+ }
126174
+ function deniedWorkerKeyRequest(key, method, pathname) {
126175
+ if (isDashboardWorkerKey(key) && !isAllowedDashboardWorkerRequest(method, pathname, key.permissions)) {
126176
+ return DASHBOARD_WORKER_KEY_RESTRICTED;
126177
+ }
126178
+ return null;
126179
+ }
126180
+ function rejectDashboardWorkerKey(ctx) {
126181
+ if (isDashboardWorkerKey(ctx.apiKey)) {
126182
+ throw ApiError.forbidden(DASHBOARD_WORKER_KEY_RESTRICTED);
126183
+ }
126184
+ }
126185
+ function assertAuthenticatedRequest(ctx) {
126186
+ if (!isAuthenticated(ctx)) {
126187
+ throw ApiError.unauthorized("Valid session or bearer token required");
126188
+ }
126189
+ if (ctx.apiKey) {
126190
+ const denied = deniedWorkerKeyRequest(ctx.apiKey, ctx.request.method, ctx.url.pathname);
126191
+ if (denied) {
126192
+ throw ApiError.forbidden(denied);
126193
+ }
126194
+ }
126195
+ }
126196
+ function requireAuth(handler) {
126197
+ return async (ctx) => {
126198
+ assertAuthenticatedRequest(ctx);
126199
+ return handler(ctx);
126200
+ };
126201
+ }
126202
+ function requireNonAnonymous(handler) {
126203
+ return async (ctx) => {
126204
+ assertAuthenticatedRequest(ctx);
126205
+ if (ctx.user.isAnonymous) {
126206
+ throw ApiError.forbidden("This operation is not available for demo/anonymous users");
126207
+ }
126208
+ return handler(ctx);
126209
+ };
126210
+ }
126211
+ function requireAnonymous(handler) {
126212
+ return async (ctx) => {
126213
+ assertAuthenticatedRequest(ctx);
126214
+ if (!ctx.user.isAnonymous) {
126215
+ throw ApiError.forbidden("This operation is only available for demo/anonymous users");
126216
+ }
126217
+ return handler(ctx);
126218
+ };
126219
+ }
126220
+ function requireDeveloper(handler) {
126221
+ return async (ctx) => {
126222
+ assertAuthenticatedRequest(ctx);
126223
+ rejectDashboardWorkerKey(ctx);
126224
+ const isAdmin = ctx.user.role === "admin";
126225
+ const isApprovedDev = ctx.user.role === "developer" && ctx.user.developerStatus === "approved";
126226
+ if (!isAdmin && !isApprovedDev) {
126227
+ throw ApiError.forbidden("Must be an approved developer");
126228
+ }
126229
+ return handler(ctx);
126230
+ };
126231
+ }
126232
+ function requireHumanDeveloper(handler) {
126233
+ return requireDeveloper(async (ctx) => {
126234
+ if (isDashboardWorkerKey(ctx.apiKey) || isGameWorkerKey(ctx.apiKey)) {
126235
+ throw ApiError.forbidden(WORKER_KEY_HUMAN_ONLY);
126236
+ }
126237
+ return handler(ctx);
126238
+ });
126239
+ }
126240
+ function requireGameManagementAccess(handler) {
126241
+ return async (ctx) => {
126242
+ assertAuthenticatedRequest(ctx);
126243
+ rejectDashboardWorkerKey(ctx);
126244
+ if (!hasGameManagementAccess(ctx.user)) {
126245
+ throw ApiError.forbidden("Game management access required");
126246
+ }
126247
+ return handler(ctx);
126248
+ };
126249
+ }
126250
+ var WORKER_KEY_HUMAN_ONLY = "This operation requires your own credential — platform worker keys are refused";
126251
+ var init_auth_util = __esm(() => {
126252
+ init_errors2();
126253
+ init_types5();
126254
+ init_dashboard_util();
126255
+ init_deployment_util();
126256
+ });
126257
+ function defineControllerNames(namespace, handlers) {
126258
+ for (const [key, handler] of Object.entries(handlers)) {
126259
+ Object.defineProperty(handler, "name", {
126260
+ value: `${namespace}.${key}`,
126261
+ configurable: true
126262
+ });
126263
+ }
126264
+ return handlers;
126265
+ }
126266
+ function generateUsername(email5) {
126267
+ const baseUsername = (email5.split("@")[0] || "user").toLowerCase();
126268
+ const cleanUsername = baseUsername.replace(/[^a-z0-9]/g, "");
126269
+ const randomSuffix = Math.random().toString(36).substring(2, 7);
126270
+ return `${cleanUsername}_${randomSuffix}`;
126271
+ }
126272
+ function extractRedirectPath(targetUri, currentHost) {
126273
+ try {
126274
+ const targetUrl = new URL(targetUri);
126275
+ if (targetUrl.hostname === currentHost) {
126276
+ return targetUrl.pathname + targetUrl.search;
126277
+ }
126278
+ } catch {}
126279
+ return "/";
126280
+ }
126281
+ function validateLtiClaims(claims) {
126282
+ const messageType = claims["https://purl.imsglobal.org/spec/lti/claim/message_type"];
126283
+ const version4 = claims["https://purl.imsglobal.org/spec/lti/claim/version"];
126284
+ if (messageType !== "LtiResourceLinkRequest") {
126285
+ return `Invalid LTI message type: ${messageType}`;
126286
+ }
126287
+ if (version4 !== "1.3.0") {
126288
+ return `Unsupported LTI version: ${version4}`;
126289
+ }
126290
+ return null;
126291
+ }
126292
+ var init_lti_util = () => {};
126293
+ async function provisionLtiUser(db2, claims) {
126294
+ const database = db2;
126295
+ const email5 = claims.email;
126296
+ const ltiTimebackId = claims.sub;
126297
+ const providerId = AUTH_PROVIDER_IDS.TIMEBACK_LTI;
126298
+ if (!email5) {
126299
+ throw new ValidationError("Email is required in LTI claims");
126300
+ }
126301
+ const existingAccount = await database.query.accounts.findFirst({
126302
+ where: and(eq(accounts.accountId, ltiTimebackId), eq(accounts.providerId, providerId))
126303
+ });
126304
+ if (existingAccount) {
126305
+ const user = await database.query.users.findFirst({
126306
+ where: eq(users.id, existingAccount.userId)
126307
+ });
126308
+ if (user) {
126309
+ setAttribute("app.lti.provision", "existing_account");
126310
+ return user;
126311
+ }
126312
+ }
126313
+ const existingUser = await database.query.users.findFirst({
126314
+ where: eq(users.email, email5)
126315
+ });
126316
+ if (existingUser) {
126317
+ await database.transaction(async (tx) => {
126318
+ const existingLtiAccount = await tx.query.accounts.findFirst({
126319
+ where: and(eq(accounts.userId, existingUser.id), eq(accounts.providerId, providerId))
126320
+ });
126321
+ if (!existingLtiAccount) {
126322
+ const [account] = await tx.insert(accounts).values({
126323
+ id: crypto4.randomUUID(),
126324
+ userId: existingUser.id,
126325
+ accountId: ltiTimebackId,
126326
+ providerId,
126327
+ accessToken: null,
126328
+ refreshToken: null,
126329
+ accessTokenExpiresAt: null,
126330
+ refreshTokenExpiresAt: null,
126331
+ createdAt: new Date,
126332
+ updatedAt: new Date
126333
+ }).returning({ id: accounts.id });
126334
+ if (!account) {
126335
+ throw new InternalError("Failed to link LTI account");
126336
+ }
126337
+ }
126338
+ });
126339
+ setAttribute("app.lti.provision", "linked_account");
126340
+ return existingUser;
126341
+ }
126342
+ const newUserId = crypto4.randomUUID();
126343
+ const createdUser = await database.transaction(async (tx) => {
126344
+ const [insertedUser] = await tx.insert(users).values({
126345
+ id: newUserId,
126346
+ email: email5,
126347
+ emailVerified: true,
126348
+ username: generateUsername(email5),
126349
+ name: claims.name || claims.given_name || email5.split("@")[0] || "Timeback User",
126350
+ createdAt: new Date,
126351
+ updatedAt: new Date
126352
+ }).returning();
126353
+ if (!insertedUser) {
126354
+ throw new InternalError("Failed to create user");
126355
+ }
126356
+ await tx.insert(accounts).values({
126357
+ id: crypto4.randomUUID(),
126358
+ userId: newUserId,
126359
+ accountId: ltiTimebackId,
126360
+ providerId,
126361
+ accessToken: null,
126362
+ refreshToken: null,
126363
+ accessTokenExpiresAt: null,
126364
+ refreshTokenExpiresAt: null,
126365
+ createdAt: new Date,
126366
+ updatedAt: new Date
126367
+ });
126368
+ setAttribute("app.lti.provision", "created_user");
126369
+ return insertedUser;
126370
+ });
126371
+ return createdUser;
126372
+ }
126373
+ var init_lti_provisioning = __esm(() => {
126374
+ init_drizzle_orm();
126375
+ init_src();
126376
+ init_tables_index();
126377
+ init_spans();
126378
+ init_errors2();
126379
+ init_lti_util();
126380
+ });
126381
+ function requireGameId(gameId) {
126382
+ if (!gameId) {
126383
+ throw ApiError.badRequest("Missing game ID");
126384
+ }
126385
+ if (!isValidUUID(gameId)) {
126386
+ throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
126387
+ }
126388
+ return gameId;
126389
+ }
126390
+ function requireSlug(slug2) {
126391
+ if (!slug2) {
126392
+ throw ApiError.badRequest("Missing game slug");
126393
+ }
126394
+ return slug2;
126395
+ }
126396
+ function requireUserId(userId) {
126397
+ if (!userId) {
126398
+ throw ApiError.badRequest("Missing user ID");
126399
+ }
126400
+ if (!isValidUUID(userId)) {
126401
+ throw ApiError.unprocessableEntity("userId must be a valid UUID format");
126402
+ }
126403
+ return userId;
126404
+ }
126405
+ function parseLimitParam(url4, max) {
126406
+ const raw = url4.searchParams.get("limit");
126407
+ if (raw === null) {
126408
+ return;
126409
+ }
126410
+ const limit = Number(raw);
126411
+ if (!Number.isInteger(limit) || limit < 1 || limit > max) {
126412
+ throw ApiError.badRequest(`limit must be an integer between 1 and ${max}`);
126413
+ }
126414
+ return limit;
126415
+ }
126416
+ var init_params_util = __esm(() => {
126417
+ init_src9();
126418
+ init_errors2();
126419
+ });
126420
+ function formatZodError(error88) {
126421
+ const flat = error88.flatten();
126422
+ const result = {};
126423
+ if (Object.keys(flat.fieldErrors).length > 0) {
126424
+ result.fields = {};
126425
+ for (const [field, messages] of Object.entries(flat.fieldErrors)) {
126426
+ if (messages && messages.length > 0) {
126427
+ result.fields[field] = messages[0];
126428
+ }
126429
+ }
126430
+ }
126431
+ if (flat.formErrors.length > 0) {
126432
+ result.errors = flat.formErrors;
126433
+ }
126434
+ return result;
126435
+ }
126436
+ function recordValidationFailure(details) {
126437
+ setAttribute("app.request.outcome", "validation_failed");
126438
+ addEvent("request.validation_failed", {
126439
+ "app.validation.error": JSON.stringify(details)
126440
+ });
126441
+ }
126442
+ async function parseRequestBody(request, schema2) {
126443
+ try {
126444
+ return schema2.parse(await request.json());
126445
+ } catch (error88) {
126446
+ if (error88 instanceof exports_external.ZodError) {
126447
+ const details = formatZodError(error88);
126448
+ recordValidationFailure(details);
126449
+ throw ApiError.unprocessableEntity("Validation failed", details);
126450
+ }
126451
+ throw ApiError.invalidJsonBody();
126452
+ }
126453
+ }
126454
+ var init_validation_util = __esm(() => {
126455
+ init_esm();
126456
+ init_spans();
126457
+ init_errors2();
126458
+ });
126459
+ var init_utils7 = __esm(() => {
126460
+ init_auth_util();
126461
+ init_assessment_runtime_lock_util();
126462
+ init_dashboard_util();
126463
+ init_deployment_util();
126464
+ init_leaderboard_util();
126465
+ init_lti_util();
126466
+ init_lti_provisioning();
126467
+ init_params_util();
126468
+ init_secrets_util();
126469
+ init_timeback_util();
126470
+ init_validation_util();
126471
+ });
126117
126472
  function buildTimebackClient() {
126118
126473
  if (!hasTimebackCredentials()) {
126119
126474
  return;
@@ -126486,7 +126841,7 @@ function createSandboxContext(options) {
126486
126841
  const services = {};
126487
126842
  const ctx = {
126488
126843
  db: options.db,
126489
- databaseLock: createInMemoryDatabaseLock(),
126844
+ assessmentRuntimeLock: createInMemoryAssessmentRuntimeLock(),
126490
126845
  config: config5,
126491
126846
  providers,
126492
126847
  services,
@@ -126515,7 +126870,7 @@ var cachedServiceContext = null;
126515
126870
  var cachedDb = null;
126516
126871
  var init_context = __esm(async () => {
126517
126872
  init_config2();
126518
- init_locks();
126873
+ init_utils7();
126519
126874
  init_src6();
126520
126875
  init_providers();
126521
126876
  await __promiseAll([
@@ -143824,7 +144179,7 @@ var nullableType2;
143824
144179
  var preprocessType2;
143825
144180
  var pipelineType2;
143826
144181
  var coerce2;
143827
- var init_types5;
144182
+ var init_types6;
143828
144183
  var init_external4;
143829
144184
  var init_v32;
143830
144185
  var init_esm2;
@@ -144010,7 +144365,7 @@ var prepareMigrationMeta;
144010
144365
  var schemaRenameKey;
144011
144366
  var tableRenameKey;
144012
144367
  var columnRenameKey;
144013
- var init_utils7;
144368
+ var init_utils8;
144014
144369
  var import_hanji;
144015
144370
  var warning;
144016
144371
  var error88;
@@ -145549,7 +145904,7 @@ var PrimaryKey3;
145549
145904
  var init_primary_keys3;
145550
145905
  var MySqlViewConfig;
145551
145906
  var init_view_common32;
145552
- var init_utils8;
145907
+ var init_utils82;
145553
145908
  var _a3222;
145554
145909
  var _b239;
145555
145910
  var MySqlDeleteBase;
@@ -146297,7 +146652,7 @@ var sqlitePushIntrospect = async (db2, filters) => {
146297
146652
  };
146298
146653
  var generateDrizzleJson = (imports, prevId, schemaFilters, casing2) => {
146299
146654
  const prepared = prepareFromExports(imports);
146300
- const id = randomUUID();
146655
+ const id = randomUUID2();
146301
146656
  const snapshot = generatePgSnapshot(prepared.tables, prepared.enums, prepared.schemas, prepared.sequences, prepared.roles, prepared.policies, prepared.views, prepared.matViews, casing2, schemaFilters);
146302
146657
  return fillPgSnapshot({
146303
146658
  serialized: snapshot,
@@ -146346,7 +146701,7 @@ var pushSchema = async (imports, drizzleInstance, schemaFilters, tablesFilter, e
146346
146701
  var generateSQLiteDrizzleJson = async (imports, prevId, casing2) => {
146347
146702
  const { prepareFromExports: prepareFromExports5 } = await Promise.resolve().then(() => (init_sqliteImports(), sqliteImports_exports));
146348
146703
  const prepared = prepareFromExports5(imports);
146349
- const id = randomUUID();
146704
+ const id = randomUUID2();
146350
146705
  const snapshot = generateSqliteSnapshot(prepared.tables, prepared.views, casing2);
146351
146706
  return {
146352
146707
  ...snapshot,
@@ -146397,7 +146752,7 @@ var pushSQLiteSchema = async (imports, drizzleInstance) => {
146397
146752
  var generateMySQLDrizzleJson = async (imports, prevId, casing2) => {
146398
146753
  const { prepareFromExports: prepareFromExports5 } = await Promise.resolve().then(() => (init_mysqlImports(), mysqlImports_exports));
146399
146754
  const prepared = prepareFromExports5(imports);
146400
- const id = randomUUID();
146755
+ const id = randomUUID2();
146401
146756
  const snapshot = generateMySqlSnapshot(prepared.tables, prepared.views, casing2);
146402
146757
  return {
146403
146758
  ...snapshot,
@@ -146447,7 +146802,7 @@ var pushMySQLSchema = async (imports, drizzleInstance, databaseName) => {
146447
146802
  var generateSingleStoreDrizzleJson = async (imports, prevId, casing2) => {
146448
146803
  const { prepareFromExports: prepareFromExports5 } = await Promise.resolve().then(() => (init_singlestoreImports(), singlestoreImports_exports));
146449
146804
  const prepared = prepareFromExports5(imports);
146450
- const id = randomUUID();
146805
+ const id = randomUUID2();
146451
146806
  const snapshot = generateSingleStoreSnapshot(prepared.tables, casing2);
146452
146807
  return {
146453
146808
  ...snapshot,
@@ -150062,7 +150417,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
150062
150417
  })(errorUtil2 || (errorUtil2 = {}));
150063
150418
  }
150064
150419
  });
150065
- init_types5 = __esm2({
150420
+ init_types6 = __esm2({
150066
150421
  "../node_modules/.pnpm/zod@3.25.42/node_modules/zod/dist/esm/v3/types.js"() {
150067
150422
  init_ZodError2();
150068
150423
  init_errors9();
@@ -153227,7 +153582,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
153227
153582
  init_parseUtil2();
153228
153583
  init_typeAliases2();
153229
153584
  init_util5();
153230
- init_types5();
153585
+ init_types6();
153231
153586
  init_ZodError2();
153232
153587
  }
153233
153588
  });
@@ -154960,7 +155315,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
154960
155315
  backwardCompatibleSqliteSchema = unionType2([sqliteSchemaV5, schema3]);
154961
155316
  }
154962
155317
  });
154963
- init_utils7 = __esm2({
155318
+ init_utils8 = __esm2({
154964
155319
  "src/utils.ts"() {
154965
155320
  init_views();
154966
155321
  init_global2();
@@ -155012,7 +155367,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
155012
155367
  "src/cli/views.ts"() {
155013
155368
  init_source();
155014
155369
  import_hanji = __toESM5(require_hanji());
155015
- init_utils7();
155370
+ init_utils8();
155016
155371
  warning = (msg) => {
155017
155372
  (0, import_hanji.render)(`[${source_default.yellow("Warning")}] ${msg}`);
155018
155373
  };
@@ -157720,7 +158075,7 @@ Is ${source_default.bold.blue(this.base.name)} schema created or renamed from an
157720
158075
  init_pgSchema();
157721
158076
  init_singlestoreSchema();
157722
158077
  init_sqliteSchema();
157723
- init_utils7();
158078
+ init_utils8();
157724
158079
  parseType = (schemaPrefix, type) => {
157725
158080
  const pgNativeTypes = [
157726
158081
  "uuid",
@@ -160216,7 +160571,7 @@ ${BREAKPOINT}ALTER TABLE ${tableNameWithSchema} ADD CONSTRAINT "${statement.newC
160216
160571
  init_source();
160217
160572
  init_sqliteSchema();
160218
160573
  init_sqlgenerator();
160219
- init_utils7();
160574
+ init_utils8();
160220
160575
  _moveDataStatements = (tableName, json42, dataLoss = false) => {
160221
160576
  const statements = [];
160222
160577
  const newTableName = `__new_${tableName}`;
@@ -162374,7 +162729,7 @@ ${BREAKPOINT}ALTER TABLE ${tableNameWithSchema} ADD CONSTRAINT "${statement.newC
162374
162729
  init_singlestoreSchema();
162375
162730
  init_sqliteSchema();
162376
162731
  init_statementCombiner();
162377
- init_utils7();
162732
+ init_utils8();
162378
162733
  makeChanged = (schema5) => {
162379
162734
  return objectType2({
162380
162735
  type: enumType2(["changed"]),
@@ -164599,7 +164954,7 @@ ${BREAKPOINT}ALTER TABLE ${tableNameWithSchema} ADD CONSTRAINT "${statement.newC
164599
164954
  init_pgSchema();
164600
164955
  init_sqliteSchema();
164601
164956
  init_snapshotsDiffer();
164602
- init_utils7();
164957
+ init_utils8();
164603
164958
  init_words();
164604
164959
  init_outputs();
164605
164960
  init_views();
@@ -171159,7 +171514,7 @@ params: ${params}`);
171159
171514
  init_pg_core2();
171160
171515
  init_vector32();
171161
171516
  init_outputs();
171162
- init_utils7();
171517
+ init_utils8();
171163
171518
  init_utils62();
171164
171519
  indexName = (tableName, columns2) => {
171165
171520
  return `${tableName}_${columns2.join("_")}_index`;
@@ -175168,7 +175523,7 @@ ORDER BY
175168
175523
  init_dist9();
175169
175524
  init_sqlite_core();
175170
175525
  init_outputs();
175171
- init_utils7();
175526
+ init_utils8();
175172
175527
  init_utils62();
175173
175528
  generateSqliteSnapshot = (tables, views, casing2) => {
175174
175529
  const dialect6 = new SQLiteSyncDialect({ casing: casing2 });
@@ -177121,7 +177476,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
177121
177476
  MySqlViewConfig = Symbol.for("drizzle:MySqlViewConfig");
177122
177477
  }
177123
177478
  });
177124
- init_utils8 = __esm2({
177479
+ init_utils82 = __esm2({
177125
177480
  "../drizzle-orm/dist/mysql-core/utils.js"() {
177126
177481
  init_entity2();
177127
177482
  init_dist9();
@@ -177143,7 +177498,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
177143
177498
  init_query_promise2();
177144
177499
  init_selection_proxy2();
177145
177500
  init_table8();
177146
- init_utils8();
177501
+ init_utils82();
177147
177502
  MySqlDeleteBase = class extends (_b239 = QueryPromise2, _a3222 = entityKind2, _b239) {
177148
177503
  constructor(table62, session3, dialect6, withList) {
177149
177504
  super();
@@ -177991,7 +178346,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
177991
178346
  init_table8();
177992
178347
  init_utils22();
177993
178348
  init_view_common3();
177994
- init_utils8();
178349
+ init_utils82();
177995
178350
  init_view_base3();
177996
178351
  _a325 = entityKind2;
177997
178352
  MySqlSelectBuilder = class {
@@ -178390,7 +178745,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
178390
178745
  init_sql5();
178391
178746
  init_table8();
178392
178747
  init_utils22();
178393
- init_utils8();
178748
+ init_utils82();
178394
178749
  init_query_builder4();
178395
178750
  _a329 = entityKind2;
178396
178751
  MySqlInsertBuilder = class {
@@ -178494,7 +178849,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
178494
178849
  init_selection_proxy2();
178495
178850
  init_table8();
178496
178851
  init_utils22();
178497
- init_utils8();
178852
+ init_utils82();
178498
178853
  _a331 = entityKind2;
178499
178854
  MySqlUpdateBuilder = class {
178500
178855
  constructor(table62, session3, dialect6, withList) {
@@ -179030,7 +179385,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
179030
179385
  init_subquery4();
179031
179386
  init_table42();
179032
179387
  init_unique_constraint3();
179033
- init_utils8();
179388
+ init_utils82();
179034
179389
  init_view_common32();
179035
179390
  init_view3();
179036
179391
  }
@@ -179041,7 +179396,7 @@ ${withStyle.errorWarning(`We've found duplicated view name across ${source_defau
179041
179396
  init_dist9();
179042
179397
  init_mysql_core();
179043
179398
  init_outputs();
179044
- init_utils7();
179399
+ init_utils8();
179045
179400
  init_utils62();
179046
179401
  handleEnumType = (type) => {
179047
179402
  let str = type.split("(")[1];
@@ -183475,7 +183830,7 @@ The unique index ${source_default.underline.blue(name22)} on the ${source_defaul
183475
183830
  import_hanji10 = __toESM5(require_hanji());
183476
183831
  init_sqlgenerator();
183477
183832
  init_singlestoreSchema();
183478
- init_utils7();
183833
+ init_utils8();
183479
183834
  init_selector_ui();
183480
183835
  init_outputs();
183481
183836
  filterStatements2 = (statements, currentSchema, prevSchema) => {
@@ -183738,7 +184093,7 @@ The unique index ${source_default.underline.blue(name22)} on the ${source_defaul
183738
184093
  init_sqlgenerator();
183739
184094
  init_selector_ui();
183740
184095
  init_pgSchema();
183741
- init_utils7();
184096
+ init_utils8();
183742
184097
  import_hanji6 = __toESM5(require_hanji());
183743
184098
  init_mjs();
183744
184099
  init_global2();
@@ -184601,323 +184956,6 @@ var init_manifest = __esm(async () => {
184601
184956
  });
184602
184957
  });
184603
184958
  });
184604
- function isAuthenticated(ctx) {
184605
- return ctx.user != null;
184606
- }
184607
- var init_types6 = () => {};
184608
- function hasGameManagementAccess(user) {
184609
- return user.role === "admin" || user.role === "teacher" || user.role === "developer" && user.developerStatus === "approved";
184610
- }
184611
- function isDashboardWorkerKey(key) {
184612
- return Boolean(key?.permissions?.[DASHBOARD_PERMISSION_NAMESPACE]);
184613
- }
184614
- function workerKeyGrantsGameRead(key, slug2) {
184615
- if (!isDashboardWorkerKey(key) && !isGameWorkerKey(key)) {
184616
- return false;
184617
- }
184618
- const games2 = key?.permissions?.games;
184619
- return Boolean(games2?.includes(`read:${slug2}`) || games2?.includes(`write:${slug2}`));
184620
- }
184621
- function isGameWorkerKey(key) {
184622
- return Boolean(key?.name?.startsWith(GAME_WORKER_KEY_PREFIX));
184623
- }
184624
- function deniedWorkerKeyRequest(key, method, pathname) {
184625
- if (isDashboardWorkerKey(key) && !isAllowedDashboardWorkerRequest(method, pathname, key.permissions)) {
184626
- return DASHBOARD_WORKER_KEY_RESTRICTED;
184627
- }
184628
- return null;
184629
- }
184630
- function rejectDashboardWorkerKey(ctx) {
184631
- if (isDashboardWorkerKey(ctx.apiKey)) {
184632
- throw ApiError.forbidden(DASHBOARD_WORKER_KEY_RESTRICTED);
184633
- }
184634
- }
184635
- function assertAuthenticatedRequest(ctx) {
184636
- if (!isAuthenticated(ctx)) {
184637
- throw ApiError.unauthorized("Valid session or bearer token required");
184638
- }
184639
- if (ctx.apiKey) {
184640
- const denied = deniedWorkerKeyRequest(ctx.apiKey, ctx.request.method, ctx.url.pathname);
184641
- if (denied) {
184642
- throw ApiError.forbidden(denied);
184643
- }
184644
- }
184645
- }
184646
- function requireAuth(handler) {
184647
- return async (ctx) => {
184648
- assertAuthenticatedRequest(ctx);
184649
- return handler(ctx);
184650
- };
184651
- }
184652
- function requireNonAnonymous(handler) {
184653
- return async (ctx) => {
184654
- assertAuthenticatedRequest(ctx);
184655
- if (ctx.user.isAnonymous) {
184656
- throw ApiError.forbidden("This operation is not available for demo/anonymous users");
184657
- }
184658
- return handler(ctx);
184659
- };
184660
- }
184661
- function requireAnonymous(handler) {
184662
- return async (ctx) => {
184663
- assertAuthenticatedRequest(ctx);
184664
- if (!ctx.user.isAnonymous) {
184665
- throw ApiError.forbidden("This operation is only available for demo/anonymous users");
184666
- }
184667
- return handler(ctx);
184668
- };
184669
- }
184670
- function requireDeveloper(handler) {
184671
- return async (ctx) => {
184672
- assertAuthenticatedRequest(ctx);
184673
- rejectDashboardWorkerKey(ctx);
184674
- const isAdmin = ctx.user.role === "admin";
184675
- const isApprovedDev = ctx.user.role === "developer" && ctx.user.developerStatus === "approved";
184676
- if (!isAdmin && !isApprovedDev) {
184677
- throw ApiError.forbidden("Must be an approved developer");
184678
- }
184679
- return handler(ctx);
184680
- };
184681
- }
184682
- function requireHumanDeveloper(handler) {
184683
- return requireDeveloper(async (ctx) => {
184684
- if (isDashboardWorkerKey(ctx.apiKey) || isGameWorkerKey(ctx.apiKey)) {
184685
- throw ApiError.forbidden(WORKER_KEY_HUMAN_ONLY);
184686
- }
184687
- return handler(ctx);
184688
- });
184689
- }
184690
- function requireGameManagementAccess(handler) {
184691
- return async (ctx) => {
184692
- assertAuthenticatedRequest(ctx);
184693
- rejectDashboardWorkerKey(ctx);
184694
- if (!hasGameManagementAccess(ctx.user)) {
184695
- throw ApiError.forbidden("Game management access required");
184696
- }
184697
- return handler(ctx);
184698
- };
184699
- }
184700
- var WORKER_KEY_HUMAN_ONLY = "This operation requires your own credential — platform worker keys are refused";
184701
- var init_auth_util = __esm(() => {
184702
- init_errors2();
184703
- init_types6();
184704
- init_dashboard_util();
184705
- init_deployment_util();
184706
- });
184707
- function defineControllerNames(namespace, handlers) {
184708
- for (const [key, handler] of Object.entries(handlers)) {
184709
- Object.defineProperty(handler, "name", {
184710
- value: `${namespace}.${key}`,
184711
- configurable: true
184712
- });
184713
- }
184714
- return handlers;
184715
- }
184716
- function generateUsername(email5) {
184717
- const baseUsername = (email5.split("@")[0] || "user").toLowerCase();
184718
- const cleanUsername = baseUsername.replace(/[^a-z0-9]/g, "");
184719
- const randomSuffix = Math.random().toString(36).substring(2, 7);
184720
- return `${cleanUsername}_${randomSuffix}`;
184721
- }
184722
- function extractRedirectPath(targetUri, currentHost) {
184723
- try {
184724
- const targetUrl = new URL(targetUri);
184725
- if (targetUrl.hostname === currentHost) {
184726
- return targetUrl.pathname + targetUrl.search;
184727
- }
184728
- } catch {}
184729
- return "/";
184730
- }
184731
- function validateLtiClaims(claims) {
184732
- const messageType = claims["https://purl.imsglobal.org/spec/lti/claim/message_type"];
184733
- const version6 = claims["https://purl.imsglobal.org/spec/lti/claim/version"];
184734
- if (messageType !== "LtiResourceLinkRequest") {
184735
- return `Invalid LTI message type: ${messageType}`;
184736
- }
184737
- if (version6 !== "1.3.0") {
184738
- return `Unsupported LTI version: ${version6}`;
184739
- }
184740
- return null;
184741
- }
184742
- var init_lti_util = () => {};
184743
- async function provisionLtiUser(db2, claims) {
184744
- const database = db2;
184745
- const email5 = claims.email;
184746
- const ltiTimebackId = claims.sub;
184747
- const providerId = AUTH_PROVIDER_IDS.TIMEBACK_LTI;
184748
- if (!email5) {
184749
- throw new ValidationError("Email is required in LTI claims");
184750
- }
184751
- const existingAccount = await database.query.accounts.findFirst({
184752
- where: and(eq(accounts.accountId, ltiTimebackId), eq(accounts.providerId, providerId))
184753
- });
184754
- if (existingAccount) {
184755
- const user = await database.query.users.findFirst({
184756
- where: eq(users.id, existingAccount.userId)
184757
- });
184758
- if (user) {
184759
- setAttribute("app.lti.provision", "existing_account");
184760
- return user;
184761
- }
184762
- }
184763
- const existingUser = await database.query.users.findFirst({
184764
- where: eq(users.email, email5)
184765
- });
184766
- if (existingUser) {
184767
- await database.transaction(async (tx) => {
184768
- const existingLtiAccount = await tx.query.accounts.findFirst({
184769
- where: and(eq(accounts.userId, existingUser.id), eq(accounts.providerId, providerId))
184770
- });
184771
- if (!existingLtiAccount) {
184772
- const [account] = await tx.insert(accounts).values({
184773
- id: crypto4.randomUUID(),
184774
- userId: existingUser.id,
184775
- accountId: ltiTimebackId,
184776
- providerId,
184777
- accessToken: null,
184778
- refreshToken: null,
184779
- accessTokenExpiresAt: null,
184780
- refreshTokenExpiresAt: null,
184781
- createdAt: new Date,
184782
- updatedAt: new Date
184783
- }).returning({ id: accounts.id });
184784
- if (!account) {
184785
- throw new InternalError("Failed to link LTI account");
184786
- }
184787
- }
184788
- });
184789
- setAttribute("app.lti.provision", "linked_account");
184790
- return existingUser;
184791
- }
184792
- const newUserId = crypto4.randomUUID();
184793
- const createdUser = await database.transaction(async (tx) => {
184794
- const [insertedUser] = await tx.insert(users).values({
184795
- id: newUserId,
184796
- email: email5,
184797
- emailVerified: true,
184798
- username: generateUsername(email5),
184799
- name: claims.name || claims.given_name || email5.split("@")[0] || "Timeback User",
184800
- createdAt: new Date,
184801
- updatedAt: new Date
184802
- }).returning();
184803
- if (!insertedUser) {
184804
- throw new InternalError("Failed to create user");
184805
- }
184806
- await tx.insert(accounts).values({
184807
- id: crypto4.randomUUID(),
184808
- userId: newUserId,
184809
- accountId: ltiTimebackId,
184810
- providerId,
184811
- accessToken: null,
184812
- refreshToken: null,
184813
- accessTokenExpiresAt: null,
184814
- refreshTokenExpiresAt: null,
184815
- createdAt: new Date,
184816
- updatedAt: new Date
184817
- });
184818
- setAttribute("app.lti.provision", "created_user");
184819
- return insertedUser;
184820
- });
184821
- return createdUser;
184822
- }
184823
- var init_lti_provisioning = __esm(() => {
184824
- init_drizzle_orm();
184825
- init_src();
184826
- init_tables_index();
184827
- init_spans();
184828
- init_errors2();
184829
- init_lti_util();
184830
- });
184831
- function requireGameId(gameId) {
184832
- if (!gameId) {
184833
- throw ApiError.badRequest("Missing game ID");
184834
- }
184835
- if (!isValidUUID(gameId)) {
184836
- throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
184837
- }
184838
- return gameId;
184839
- }
184840
- function requireSlug(slug2) {
184841
- if (!slug2) {
184842
- throw ApiError.badRequest("Missing game slug");
184843
- }
184844
- return slug2;
184845
- }
184846
- function requireUserId(userId) {
184847
- if (!userId) {
184848
- throw ApiError.badRequest("Missing user ID");
184849
- }
184850
- if (!isValidUUID(userId)) {
184851
- throw ApiError.unprocessableEntity("userId must be a valid UUID format");
184852
- }
184853
- return userId;
184854
- }
184855
- function parseLimitParam(url4, max2) {
184856
- const raw2 = url4.searchParams.get("limit");
184857
- if (raw2 === null) {
184858
- return;
184859
- }
184860
- const limit = Number(raw2);
184861
- if (!Number.isInteger(limit) || limit < 1 || limit > max2) {
184862
- throw ApiError.badRequest(`limit must be an integer between 1 and ${max2}`);
184863
- }
184864
- return limit;
184865
- }
184866
- var init_params_util = __esm(() => {
184867
- init_src9();
184868
- init_errors2();
184869
- });
184870
- function formatZodError(error89) {
184871
- const flat = error89.flatten();
184872
- const result = {};
184873
- if (Object.keys(flat.fieldErrors).length > 0) {
184874
- result.fields = {};
184875
- for (const [field, messages] of Object.entries(flat.fieldErrors)) {
184876
- if (messages && messages.length > 0) {
184877
- result.fields[field] = messages[0];
184878
- }
184879
- }
184880
- }
184881
- if (flat.formErrors.length > 0) {
184882
- result.errors = flat.formErrors;
184883
- }
184884
- return result;
184885
- }
184886
- function recordValidationFailure(details) {
184887
- setAttribute("app.request.outcome", "validation_failed");
184888
- addEvent("request.validation_failed", {
184889
- "app.validation.error": JSON.stringify(details)
184890
- });
184891
- }
184892
- async function parseRequestBody(request, schema4) {
184893
- try {
184894
- return schema4.parse(await request.json());
184895
- } catch (error89) {
184896
- if (error89 instanceof exports_external.ZodError) {
184897
- const details = formatZodError(error89);
184898
- recordValidationFailure(details);
184899
- throw ApiError.unprocessableEntity("Validation failed", details);
184900
- }
184901
- throw ApiError.invalidJsonBody();
184902
- }
184903
- }
184904
- var init_validation_util = __esm(() => {
184905
- init_esm();
184906
- init_spans();
184907
- init_errors2();
184908
- });
184909
- var init_utils11 = __esm(() => {
184910
- init_auth_util();
184911
- init_dashboard_util();
184912
- init_deployment_util();
184913
- init_leaderboard_util();
184914
- init_lti_util();
184915
- init_lti_provisioning();
184916
- init_params_util();
184917
- init_secrets_util();
184918
- init_timeback_util();
184919
- init_validation_util();
184920
- });
184921
184959
  var listFiles;
184922
184960
  var getFile;
184923
184961
  var putFile;
@@ -184926,7 +184964,7 @@ var initiateUpload;
184926
184964
  var bucket;
184927
184965
  var init_bucket_controller = __esm(() => {
184928
184966
  init_errors2();
184929
- init_utils11();
184967
+ init_utils7();
184930
184968
  listFiles = requireDeveloper(async (ctx) => {
184931
184969
  const slug2 = ctx.params.slug;
184932
184970
  if (!slug2) {
@@ -185025,7 +185063,7 @@ var dashboard2;
185025
185063
  var init_dashboard_controller = __esm(() => {
185026
185064
  init_schemas_index();
185027
185065
  init_errors2();
185028
- init_utils11();
185066
+ init_utils7();
185029
185067
  listUsers = requireHumanDeveloper(async (ctx) => {
185030
185068
  const slug2 = requireSlug(ctx.params.slug);
185031
185069
  const users2 = await ctx.services.dashboard.listUsers(slug2, ctx.user);
@@ -185096,7 +185134,7 @@ var init_database_controller = __esm(() => {
185096
185134
  init_esm();
185097
185135
  init_schemas_index();
185098
185136
  init_errors2();
185099
- init_utils11();
185137
+ init_utils7();
185100
185138
  reset = requireDeveloper(async (ctx) => {
185101
185139
  const slug2 = ctx.params.slug;
185102
185140
  if (!slug2) {
@@ -185157,7 +185195,7 @@ var init_deploy_controller = __esm(() => {
185157
185195
  init_esm();
185158
185196
  init_schemas_index();
185159
185197
  init_errors2();
185160
- init_utils11();
185198
+ init_utils7();
185161
185199
  deploy = defineControllerNames("deploy", {
185162
185200
  createJob: requireDeveloper(createJob),
185163
185201
  getJob: requireDeveloper(getJob)
@@ -185175,7 +185213,7 @@ var deploymentState;
185175
185213
  var init_deployment_state_controller = __esm(() => {
185176
185214
  init_schemas_index();
185177
185215
  init_errors2();
185178
- init_utils11();
185216
+ init_utils7();
185179
185217
  get = requireDeveloper(async (ctx) => {
185180
185218
  const slug2 = requireSlug(ctx.params.slug);
185181
185219
  const include = ctx.url.searchParams.getAll("include").flatMap((value) => value.split(",")).filter(Boolean);
@@ -185245,7 +185283,7 @@ var apply;
185245
185283
  var getStatus;
185246
185284
  var developer;
185247
185285
  var init_developer_controller = __esm(() => {
185248
- init_utils11();
185286
+ init_utils7();
185249
185287
  apply = requireNonAnonymous(async (ctx) => {
185250
185288
  await ctx.services.developer.apply(ctx.user);
185251
185289
  });
@@ -185268,7 +185306,7 @@ var init_domain_controller = __esm(() => {
185268
185306
  init_schemas_index();
185269
185307
  init_config2();
185270
185308
  init_errors2();
185271
- init_utils11();
185309
+ init_utils7();
185272
185310
  add = requireDeveloper(async (ctx) => {
185273
185311
  const slug2 = ctx.params.slug;
185274
185312
  if (!slug2) {
@@ -185345,7 +185383,7 @@ var gameMembers2;
185345
185383
  var init_game_member_controller = __esm(() => {
185346
185384
  init_schemas_index();
185347
185385
  init_errors2();
185348
- init_utils11();
185386
+ init_utils7();
185349
185387
  listMembers = requireNonAnonymous(async (ctx) => {
185350
185388
  const gameId = requireGameId(ctx.params.gameId);
185351
185389
  return ctx.services.gameMember.list(gameId, ctx.user);
@@ -185394,7 +185432,7 @@ var init_game_controller = __esm(() => {
185394
185432
  init_esm();
185395
185433
  init_schemas_index();
185396
185434
  init_errors2();
185397
- init_utils11();
185435
+ init_utils7();
185398
185436
  init_auth_util();
185399
185437
  list2 = requireNonAnonymous(async (ctx) => ctx.services.game.list(ctx.user));
185400
185438
  listAccessible = requireNonAnonymous(async (ctx) => ctx.services.game.listAccessible(ctx.user));
@@ -185471,7 +185509,7 @@ var init_kv_controller = __esm(() => {
185471
185509
  init_esm();
185472
185510
  init_schemas_index();
185473
185511
  init_errors2();
185474
- init_utils11();
185512
+ init_utils7();
185475
185513
  listKeys = requireDeveloper(async (ctx) => {
185476
185514
  const slug2 = ctx.params.slug;
185477
185515
  if (!slug2) {
@@ -185579,7 +185617,7 @@ var init_leaderboard_controller = __esm(() => {
185579
185617
  init_esm();
185580
185618
  init_schemas_index();
185581
185619
  init_errors2();
185582
- init_utils11();
185620
+ init_utils7();
185583
185621
  submitScore = requireAuth(async (ctx) => {
185584
185622
  const gameId = ctx.params.gameId;
185585
185623
  if (!gameId) {
@@ -185687,7 +185725,7 @@ var generateToken;
185687
185725
  var logs;
185688
185726
  var init_logs_controller = __esm(() => {
185689
185727
  init_errors2();
185690
- init_utils11();
185728
+ init_utils7();
185691
185729
  generateToken = requireDeveloper(async (ctx) => {
185692
185730
  const slug2 = ctx.params.slug;
185693
185731
  if (!slug2) {
@@ -185721,7 +185759,7 @@ var init_logs_controller = __esm(() => {
185721
185759
  var getStatus3;
185722
185760
  var lti;
185723
185761
  var init_lti_controller = __esm(() => {
185724
- init_utils11();
185762
+ init_utils7();
185725
185763
  getStatus3 = requireNonAnonymous(async (ctx) => ctx.services.lti.getStatus(ctx.user));
185726
185764
  lti = defineControllerNames("lti", {
185727
185765
  getStatus: getStatus3
@@ -185736,7 +185774,7 @@ var init_secrets_controller = __esm(() => {
185736
185774
  init_esm();
185737
185775
  init_schemas_index();
185738
185776
  init_errors2();
185739
- init_utils11();
185777
+ init_utils7();
185740
185778
  listKeys2 = requireDeveloper(async (ctx) => {
185741
185779
  const slug2 = ctx.params.slug;
185742
185780
  if (!slug2) {
@@ -185798,7 +185836,7 @@ var init_seed_controller = __esm(() => {
185798
185836
  init_esm();
185799
185837
  init_schemas_index();
185800
185838
  init_errors2();
185801
- init_utils11();
185839
+ init_utils7();
185802
185840
  seed2 = requireDeveloper(async (ctx) => {
185803
185841
  const slug2 = ctx.params.slug;
185804
185842
  if (!slug2) {
@@ -185830,7 +185868,7 @@ var init_session_controller = __esm(() => {
185830
185868
  init_spans();
185831
185869
  init_tunnel();
185832
185870
  init_errors2();
185833
- init_utils11();
185871
+ init_utils7();
185834
185872
  MintTokenBody = exports_external.object({
185835
185873
  reason: exports_external.enum(["initial", "refresh_scheduled", "refresh_stale"]).optional()
185836
185874
  });
@@ -185947,7 +185985,7 @@ var init_timeback_controller = __esm(() => {
185947
185985
  init_src9();
185948
185986
  init_timeback3();
185949
185987
  init_errors2();
185950
- init_utils11();
185988
+ init_utils7();
185951
185989
  populateStudent = requireNonAnonymous(async (ctx) => {
185952
185990
  let providedNames;
185953
185991
  try {
@@ -186781,7 +186819,7 @@ var init_upload_controller = __esm(() => {
186781
186819
  init_esm();
186782
186820
  init_schemas_index();
186783
186821
  init_errors2();
186784
- init_utils11();
186822
+ init_utils7();
186785
186823
  initiate = requireDeveloper(async (ctx) => {
186786
186824
  let body2;
186787
186825
  try {
@@ -186808,7 +186846,7 @@ var users2;
186808
186846
  var init_user_controller = __esm(() => {
186809
186847
  init_src();
186810
186848
  init_schemas_index();
186811
- init_utils11();
186849
+ init_utils7();
186812
186850
  getMe = requireNonAnonymous(async (ctx) => ctx.services.user.getMe(ctx.user, ctx.gameId, ctx.request.headers.get(PLAYCADEMY_BROWSER_TIME_ZONE_HEADER)));
186813
186851
  getDemoProfile = requireAnonymous(async (ctx) => ctx.services.user.getDemoProfile(ctx.user.id));
186814
186852
  updateDemoProfile = requireAnonymous(async (ctx) => {
@@ -186841,7 +186879,7 @@ var init_verify_controller = __esm(() => {
186841
186879
  init_esm();
186842
186880
  init_schemas_index();
186843
186881
  init_errors2();
186844
- init_utils11();
186882
+ init_utils7();
186845
186883
  verify = defineControllerNames("verify", {
186846
186884
  verifyToken
186847
186885
  });
@@ -187022,7 +187060,7 @@ async function buildMockUserResponse(db2, user, gameId, observedTimeZone) {
187022
187060
  var LEARNING_TIME_ZONE_REFRESH_INTERVAL_MS2;
187023
187061
  var init_timeback7 = __esm(() => {
187024
187062
  init_drizzle_orm();
187025
- init_utils11();
187063
+ init_utils7();
187026
187064
  init_src();
187027
187065
  init_tables_index();
187028
187066
  init_src6();
@@ -187433,7 +187471,7 @@ var init_seed2 = __esm(async () => {
187433
187471
  init_dist7();
187434
187472
  init_esm();
187435
187473
  init_errors2();
187436
- init_utils11();
187474
+ init_utils7();
187437
187475
  init_schemas_index();
187438
187476
  await init_api3();
187439
187477
  gameSeedRouter = new Hono2;
@@ -187663,7 +187701,7 @@ var init_timeback8 = __esm(async () => {
187663
187701
  init_dist7();
187664
187702
  init_controllers();
187665
187703
  init_errors2();
187666
- init_utils11();
187704
+ init_utils7();
187667
187705
  init_src();
187668
187706
  init_schemas_index();
187669
187707
  init_timeback3();
@@ -187902,7 +187940,7 @@ var init_lti = __esm(async () => {
187902
187940
  init_drizzle_orm();
187903
187941
  init_dist7();
187904
187942
  init_controllers();
187905
- init_utils11();
187943
+ init_utils7();
187906
187944
  init_tables_index();
187907
187945
  init_src6();
187908
187946
  init_constants();