@playcademy/vite-plugin 0.2.34-beta.2 → 0.2.35-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +853 -502
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -25353,7 +25353,7 @@ var package_default;
|
|
|
25353
25353
|
var init_package = __esm(() => {
|
|
25354
25354
|
package_default = {
|
|
25355
25355
|
name: "@playcademy/sandbox",
|
|
25356
|
-
version: "0.3.
|
|
25356
|
+
version: "0.3.19-beta.1",
|
|
25357
25357
|
description: "Local development server for Playcademy game development",
|
|
25358
25358
|
type: "module",
|
|
25359
25359
|
exports: {
|
|
@@ -54361,6 +54361,22 @@ var init_pure = __esm(() => {
|
|
|
54361
54361
|
var init_src4 = __esm(() => {
|
|
54362
54362
|
init_pure();
|
|
54363
54363
|
});
|
|
54364
|
+
function formatGradeLabel(grade) {
|
|
54365
|
+
switch (grade) {
|
|
54366
|
+
case -1: {
|
|
54367
|
+
return "Pre-K";
|
|
54368
|
+
}
|
|
54369
|
+
case 0: {
|
|
54370
|
+
return "Kindergarten";
|
|
54371
|
+
}
|
|
54372
|
+
case 13: {
|
|
54373
|
+
return "AP";
|
|
54374
|
+
}
|
|
54375
|
+
default: {
|
|
54376
|
+
return `Grade ${grade}`;
|
|
54377
|
+
}
|
|
54378
|
+
}
|
|
54379
|
+
}
|
|
54364
54380
|
function isColumnType(column2, columnTypes) {
|
|
54365
54381
|
return columnTypes.includes(column2.columnType);
|
|
54366
54382
|
}
|
|
@@ -55109,6 +55125,8 @@ var TIMEBACK_SUBJECTS4;
|
|
|
55109
55125
|
var TimebackGradeSchema;
|
|
55110
55126
|
var TimebackSubjectSchema;
|
|
55111
55127
|
var UpdateTimebackXpRequestSchema;
|
|
55128
|
+
var CourseGoalsSchema;
|
|
55129
|
+
var UpdateGameTimebackIntegrationRequestSchema;
|
|
55112
55130
|
var TimebackActivityDataSchema;
|
|
55113
55131
|
var EndActivityRequestSchema;
|
|
55114
55132
|
var GameActivityMetricsSchema;
|
|
@@ -55122,9 +55140,13 @@ var TimebackBaseConfigSchema;
|
|
|
55122
55140
|
var PlatformTimebackSetupRequestSchema;
|
|
55123
55141
|
var AdminTimebackMutationBaseSchema;
|
|
55124
55142
|
var AdminAttributionDateSchema;
|
|
55143
|
+
var ADMIN_GRANT_XP_MIN = -1e5;
|
|
55144
|
+
var ADMIN_GRANT_XP_MAX = 1e5;
|
|
55145
|
+
var ADMIN_GRANT_XP_AMOUNT_RANGE_MESSAGE;
|
|
55125
55146
|
var GrantTimebackXpRequestSchema;
|
|
55126
55147
|
var AdjustTimebackTimeRequestSchema;
|
|
55127
55148
|
var AdjustTimebackMasteryRequestSchema;
|
|
55149
|
+
var ReconcileMasteryForConfigChangeSchema;
|
|
55128
55150
|
var EnrollStudentRequestSchema;
|
|
55129
55151
|
var UnenrollStudentRequestSchema;
|
|
55130
55152
|
var ReactivateEnrollmentRequestSchema;
|
|
@@ -55156,6 +55178,24 @@ var init_schemas11 = __esm(() => {
|
|
|
55156
55178
|
xp: exports_external.number().min(0, "XP must be a non-negative number"),
|
|
55157
55179
|
userTimestamp: exports_external.string().datetime().optional()
|
|
55158
55180
|
});
|
|
55181
|
+
CourseGoalsSchema = exports_external.object({
|
|
55182
|
+
dailyXp: exports_external.number().int().nonnegative().nullable().optional(),
|
|
55183
|
+
dailyLessons: exports_external.number().int().nonnegative().nullable().optional(),
|
|
55184
|
+
dailyActiveMinutes: exports_external.number().int().nonnegative().nullable().optional(),
|
|
55185
|
+
dailyAccuracy: exports_external.number().int().min(0).max(100).nullable().optional(),
|
|
55186
|
+
dailyMasteredUnits: exports_external.number().int().nonnegative().nullable().optional()
|
|
55187
|
+
});
|
|
55188
|
+
UpdateGameTimebackIntegrationRequestSchema = exports_external.object({
|
|
55189
|
+
title: exports_external.string().trim().min(1).optional(),
|
|
55190
|
+
courseCode: exports_external.string().trim().min(1).optional(),
|
|
55191
|
+
subject: TimebackSubjectSchema.optional(),
|
|
55192
|
+
totalXp: exports_external.number().int().nonnegative().nullable().optional(),
|
|
55193
|
+
masterableUnits: exports_external.number().int().nonnegative().nullable().optional(),
|
|
55194
|
+
goals: CourseGoalsSchema.optional(),
|
|
55195
|
+
publishStatus: exports_external.enum(["draft", "testing", "published", "deactivated"]).nullable().optional(),
|
|
55196
|
+
isSupplemental: exports_external.boolean().optional(),
|
|
55197
|
+
timebackVisible: exports_external.boolean().nullable().optional()
|
|
55198
|
+
});
|
|
55159
55199
|
TimebackActivityDataSchema = exports_external.object({
|
|
55160
55200
|
activityId: exports_external.string().min(1),
|
|
55161
55201
|
activityName: exports_external.string().optional(),
|
|
@@ -55309,8 +55349,9 @@ var init_schemas11 = __esm(() => {
|
|
|
55309
55349
|
});
|
|
55310
55350
|
}
|
|
55311
55351
|
});
|
|
55352
|
+
ADMIN_GRANT_XP_AMOUNT_RANGE_MESSAGE = `Amount must be between ${ADMIN_GRANT_XP_MIN} and ${ADMIN_GRANT_XP_MAX}`;
|
|
55312
55353
|
GrantTimebackXpRequestSchema = AdminTimebackMutationBaseSchema.extend({
|
|
55313
|
-
xp: exports_external.number().min(
|
|
55354
|
+
xp: exports_external.number().min(ADMIN_GRANT_XP_MIN, ADMIN_GRANT_XP_AMOUNT_RANGE_MESSAGE).max(ADMIN_GRANT_XP_MAX, ADMIN_GRANT_XP_AMOUNT_RANGE_MESSAGE).refine((value) => value !== 0, { message: "Amount cannot be 0" }),
|
|
55314
55355
|
date: AdminAttributionDateSchema.optional(),
|
|
55315
55356
|
useCurrentTime: exports_external.boolean().optional()
|
|
55316
55357
|
});
|
|
@@ -55324,6 +55365,13 @@ var init_schemas11 = __esm(() => {
|
|
|
55324
55365
|
date: AdminAttributionDateSchema.optional(),
|
|
55325
55366
|
useCurrentTime: exports_external.boolean().optional()
|
|
55326
55367
|
});
|
|
55368
|
+
ReconcileMasteryForConfigChangeSchema = exports_external.object({
|
|
55369
|
+
gameId: exports_external.string().uuid(),
|
|
55370
|
+
courseId: exports_external.string().min(1),
|
|
55371
|
+
oldMasterableUnits: exports_external.number().int().positive(),
|
|
55372
|
+
newMasterableUnits: exports_external.number().int().positive(),
|
|
55373
|
+
affectedStudentIds: exports_external.array(exports_external.string().min(1)).min(1).max(500)
|
|
55374
|
+
});
|
|
55327
55375
|
EnrollStudentRequestSchema = exports_external.object({
|
|
55328
55376
|
gameId: exports_external.string().uuid(),
|
|
55329
55377
|
courseId: exports_external.string().min(1),
|
|
@@ -55472,6 +55520,63 @@ function compareEnrollmentsByRecency(a, b) {
|
|
|
55472
55520
|
var init_timeback_admin_util = __esm(() => {
|
|
55473
55521
|
init_errors();
|
|
55474
55522
|
});
|
|
55523
|
+
async function upsertMasteryCompletionEntry(params) {
|
|
55524
|
+
const { client, courseId, studentId, appName, action } = params;
|
|
55525
|
+
const ids = deriveSourcedIds(courseId);
|
|
55526
|
+
const lineItemId = `${ids.course}-mastery-completion-assessment`;
|
|
55527
|
+
const resultId = `${lineItemId}:${studentId}:completion`;
|
|
55528
|
+
if (action === "complete") {
|
|
55529
|
+
await client.oneroster.assessmentLineItems.findOrCreate(lineItemId, {
|
|
55530
|
+
sourcedId: lineItemId,
|
|
55531
|
+
title: "Mastery Completion",
|
|
55532
|
+
status: ONEROSTER_STATUS.active,
|
|
55533
|
+
course: { sourcedId: ids.course },
|
|
55534
|
+
...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
|
|
55535
|
+
});
|
|
55536
|
+
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
55537
|
+
sourcedId: resultId,
|
|
55538
|
+
status: ONEROSTER_STATUS.active,
|
|
55539
|
+
assessmentLineItem: { sourcedId: lineItemId },
|
|
55540
|
+
student: { sourcedId: studentId },
|
|
55541
|
+
score: 100,
|
|
55542
|
+
scoreDate: new Date().toISOString(),
|
|
55543
|
+
scoreStatus: SCORE_STATUS.fullyGraded,
|
|
55544
|
+
inProgress: "false",
|
|
55545
|
+
metadata: {
|
|
55546
|
+
isMasteryCompletion: true,
|
|
55547
|
+
adminAction: true,
|
|
55548
|
+
appName
|
|
55549
|
+
}
|
|
55550
|
+
});
|
|
55551
|
+
} else {
|
|
55552
|
+
try {
|
|
55553
|
+
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
55554
|
+
sourcedId: resultId,
|
|
55555
|
+
status: ONEROSTER_STATUS.active,
|
|
55556
|
+
assessmentLineItem: { sourcedId: lineItemId },
|
|
55557
|
+
student: { sourcedId: studentId },
|
|
55558
|
+
score: 0,
|
|
55559
|
+
scoreDate: new Date().toISOString(),
|
|
55560
|
+
scoreStatus: SCORE_STATUS.notSubmitted,
|
|
55561
|
+
inProgress: "true",
|
|
55562
|
+
metadata: {
|
|
55563
|
+
isMasteryCompletion: true,
|
|
55564
|
+
adminAction: true,
|
|
55565
|
+
appName
|
|
55566
|
+
}
|
|
55567
|
+
});
|
|
55568
|
+
} catch {
|
|
55569
|
+
logger17.debug("No completion entry to revoke", { studentId, courseId });
|
|
55570
|
+
}
|
|
55571
|
+
}
|
|
55572
|
+
}
|
|
55573
|
+
var logger17;
|
|
55574
|
+
var init_timeback_mastery_completion_util = __esm(() => {
|
|
55575
|
+
init_src2();
|
|
55576
|
+
init_constants4();
|
|
55577
|
+
init_utils6();
|
|
55578
|
+
logger17 = log.scope("timeback-mastery-completion");
|
|
55579
|
+
});
|
|
55475
55580
|
function isRecord2(value) {
|
|
55476
55581
|
return typeof value === "object" && value !== null;
|
|
55477
55582
|
}
|
|
@@ -55827,7 +55932,7 @@ class TimebackAdminService {
|
|
|
55827
55932
|
}
|
|
55828
55933
|
requireClient() {
|
|
55829
55934
|
if (!this.deps.timeback) {
|
|
55830
|
-
|
|
55935
|
+
logger18.error("Timeback client not available in context");
|
|
55831
55936
|
throw new ValidationError("Timeback integration not available in this environment");
|
|
55832
55937
|
}
|
|
55833
55938
|
return this.deps.timeback;
|
|
@@ -56047,7 +56152,7 @@ class TimebackAdminService {
|
|
|
56047
56152
|
});
|
|
56048
56153
|
return [enrollmentId, this.summarizeAnalyticsFacts(analytics.facts)];
|
|
56049
56154
|
} catch (error) {
|
|
56050
|
-
|
|
56155
|
+
logger18.warn("Failed to load enrollment analytics summary", {
|
|
56051
56156
|
enrollmentId,
|
|
56052
56157
|
error: error instanceof Error ? error.message : String(error)
|
|
56053
56158
|
});
|
|
@@ -56077,7 +56182,7 @@ class TimebackAdminService {
|
|
|
56077
56182
|
const events = await this.fetchCaliperEventsForStudent(client, studentId, source, eventLimit);
|
|
56078
56183
|
return TimebackAdminService.mapRecentActivityItems(events, relevantCourseIds).slice(0, maxResults);
|
|
56079
56184
|
} catch (error) {
|
|
56080
|
-
|
|
56185
|
+
logger18.warn("Failed to load recent Caliper activity", {
|
|
56081
56186
|
studentId,
|
|
56082
56187
|
gameId: source.gameId,
|
|
56083
56188
|
sourceMode: source.sourceMode,
|
|
@@ -56256,7 +56361,7 @@ class TimebackAdminService {
|
|
|
56256
56361
|
}) : undefined;
|
|
56257
56362
|
return {
|
|
56258
56363
|
courseId: integration.courseId,
|
|
56259
|
-
title: enrollment?.course.title || `${integration.subject}
|
|
56364
|
+
title: enrollment?.course.title || `${integration.subject} ${formatGradeLabel(integration.grade)}`,
|
|
56260
56365
|
grade: integration.grade,
|
|
56261
56366
|
subject: integration.subject,
|
|
56262
56367
|
enrollmentId: enrollment?.id || null,
|
|
@@ -56403,60 +56508,44 @@ class TimebackAdminService {
|
|
|
56403
56508
|
const wasMastered = currentMastered >= masterableUnits;
|
|
56404
56509
|
const willBeMastered = currentMastered + data.units >= masterableUnits;
|
|
56405
56510
|
if (wasMastered !== willBeMastered) {
|
|
56406
|
-
|
|
56407
|
-
|
|
56408
|
-
|
|
56409
|
-
|
|
56410
|
-
|
|
56411
|
-
|
|
56412
|
-
|
|
56413
|
-
status: ONEROSTER_STATUS.active,
|
|
56414
|
-
course: { sourcedId: ids.course },
|
|
56415
|
-
...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
|
|
56416
|
-
});
|
|
56417
|
-
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
56418
|
-
sourcedId: resultId,
|
|
56419
|
-
status: ONEROSTER_STATUS.active,
|
|
56420
|
-
assessmentLineItem: { sourcedId: lineItemId },
|
|
56421
|
-
student: { sourcedId: data.studentId },
|
|
56422
|
-
score: 100,
|
|
56423
|
-
scoreDate: new Date().toISOString(),
|
|
56424
|
-
scoreStatus: SCORE_STATUS.fullyGraded,
|
|
56425
|
-
inProgress: "false",
|
|
56426
|
-
metadata: {
|
|
56427
|
-
isMasteryCompletion: true,
|
|
56428
|
-
adminAction: true,
|
|
56429
|
-
appName
|
|
56430
|
-
}
|
|
56431
|
-
});
|
|
56432
|
-
} else {
|
|
56433
|
-
try {
|
|
56434
|
-
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
56435
|
-
sourcedId: resultId,
|
|
56436
|
-
status: ONEROSTER_STATUS.active,
|
|
56437
|
-
assessmentLineItem: { sourcedId: lineItemId },
|
|
56438
|
-
student: { sourcedId: data.studentId },
|
|
56439
|
-
score: 0,
|
|
56440
|
-
scoreDate: new Date().toISOString(),
|
|
56441
|
-
scoreStatus: SCORE_STATUS.notSubmitted,
|
|
56442
|
-
inProgress: "true",
|
|
56443
|
-
metadata: {
|
|
56444
|
-
isMasteryCompletion: true,
|
|
56445
|
-
adminAction: true,
|
|
56446
|
-
appName
|
|
56447
|
-
}
|
|
56448
|
-
});
|
|
56449
|
-
} catch {
|
|
56450
|
-
logger17.debug("No completion entry to revoke", {
|
|
56451
|
-
studentId: data.studentId,
|
|
56452
|
-
courseId: data.courseId
|
|
56453
|
-
});
|
|
56454
|
-
}
|
|
56455
|
-
}
|
|
56511
|
+
await upsertMasteryCompletionEntry({
|
|
56512
|
+
client,
|
|
56513
|
+
courseId: data.courseId,
|
|
56514
|
+
studentId: data.studentId,
|
|
56515
|
+
appName,
|
|
56516
|
+
action: willBeMastered ? "complete" : "revoke"
|
|
56517
|
+
});
|
|
56456
56518
|
}
|
|
56457
56519
|
}
|
|
56458
56520
|
return { status: "ok" };
|
|
56459
56521
|
}
|
|
56522
|
+
async reconcileMasteryForConfigChange(gameId, courseId, user, context) {
|
|
56523
|
+
const { client, appName } = await this.resolveAdminMutationContext(gameId, courseId, user);
|
|
56524
|
+
const action = context.newMasterableUnits < context.oldMasterableUnits ? "complete" : "revoke";
|
|
56525
|
+
const failed = [];
|
|
56526
|
+
let processed = 0;
|
|
56527
|
+
await TimebackAdminService.runWithConcurrency(context.affectedStudentIds, 8, async (studentId) => {
|
|
56528
|
+
try {
|
|
56529
|
+
await upsertMasteryCompletionEntry({
|
|
56530
|
+
client,
|
|
56531
|
+
courseId,
|
|
56532
|
+
studentId,
|
|
56533
|
+
appName,
|
|
56534
|
+
action
|
|
56535
|
+
});
|
|
56536
|
+
processed++;
|
|
56537
|
+
} catch (error) {
|
|
56538
|
+
logger18.warn("Failed to reconcile mastery completion for student", {
|
|
56539
|
+
studentId,
|
|
56540
|
+
courseId,
|
|
56541
|
+
action,
|
|
56542
|
+
error: error instanceof Error ? error.message : String(error)
|
|
56543
|
+
});
|
|
56544
|
+
failed.push(studentId);
|
|
56545
|
+
}
|
|
56546
|
+
});
|
|
56547
|
+
return { processed, failed };
|
|
56548
|
+
}
|
|
56460
56549
|
async searchStudentsForEnrollment(gameId, courseId, query, user) {
|
|
56461
56550
|
const client = this.requireClient();
|
|
56462
56551
|
await this.deps.validateGameManagementAccess(user, gameId);
|
|
@@ -56483,7 +56572,7 @@ class TimebackAdminService {
|
|
|
56483
56572
|
const response = await client["request"](endpoint, "GET");
|
|
56484
56573
|
allUsers = response.users || [];
|
|
56485
56574
|
} catch (error) {
|
|
56486
|
-
|
|
56575
|
+
logger18.warn("Failed to search OneRoster users", {
|
|
56487
56576
|
query: trimmedQuery,
|
|
56488
56577
|
error: error instanceof Error ? error.message : String(error)
|
|
56489
56578
|
});
|
|
@@ -56628,7 +56717,7 @@ class TimebackAdminService {
|
|
|
56628
56717
|
return results;
|
|
56629
56718
|
}
|
|
56630
56719
|
}
|
|
56631
|
-
var
|
|
56720
|
+
var logger18;
|
|
56632
56721
|
var init_timeback_admin_service = __esm(() => {
|
|
56633
56722
|
init_drizzle_orm();
|
|
56634
56723
|
init_src();
|
|
@@ -56641,8 +56730,9 @@ var init_timeback_admin_service = __esm(() => {
|
|
|
56641
56730
|
init_errors();
|
|
56642
56731
|
init_timeback_admin_metrics_util();
|
|
56643
56732
|
init_timeback_admin_util();
|
|
56733
|
+
init_timeback_mastery_completion_util();
|
|
56644
56734
|
init_timeback_util();
|
|
56645
|
-
|
|
56735
|
+
logger18 = log.scope("TimebackAdminService");
|
|
56646
56736
|
});
|
|
56647
56737
|
var __esm5 = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
56648
56738
|
var TIMEBACK_API_URLS4;
|
|
@@ -56915,7 +57005,7 @@ class TimebackAssessmentsService {
|
|
|
56915
57005
|
isActive: row.bankActive
|
|
56916
57006
|
};
|
|
56917
57007
|
} catch {
|
|
56918
|
-
|
|
57008
|
+
logger19.warn("Failed to fetch QTI test metadata", {
|
|
56919
57009
|
identifier: row.qtiTestIdentifier
|
|
56920
57010
|
});
|
|
56921
57011
|
return {
|
|
@@ -56969,7 +57059,7 @@ class TimebackAssessmentsService {
|
|
|
56969
57059
|
});
|
|
56970
57060
|
} catch (error) {
|
|
56971
57061
|
if (error instanceof TimebackApiError && error.status === 409) {
|
|
56972
|
-
|
|
57062
|
+
logger19.info("QTI test already exists (idempotent retry)", {
|
|
56973
57063
|
qtiTestIdentifier: input.qtiTestIdentifier
|
|
56974
57064
|
});
|
|
56975
57065
|
} else {
|
|
@@ -56982,7 +57072,7 @@ class TimebackAssessmentsService {
|
|
|
56982
57072
|
qtiTestIdentifier: input.qtiTestIdentifier,
|
|
56983
57073
|
sortOrder: maxSortOrder + 1
|
|
56984
57074
|
}).returning();
|
|
56985
|
-
|
|
57075
|
+
logger19.info("Assessment created", {
|
|
56986
57076
|
integrationId,
|
|
56987
57077
|
qtiTestIdentifier: input.qtiTestIdentifier
|
|
56988
57078
|
});
|
|
@@ -57004,13 +57094,13 @@ class TimebackAssessmentsService {
|
|
|
57004
57094
|
}
|
|
57005
57095
|
await client.qti.tests.delete(qtiTestIdentifier);
|
|
57006
57096
|
} catch (error) {
|
|
57007
|
-
|
|
57097
|
+
logger19.warn("Partial QTI cleanup during assessment deletion", {
|
|
57008
57098
|
qtiTestIdentifier,
|
|
57009
57099
|
error: error instanceof Error ? error.message : String(error)
|
|
57010
57100
|
});
|
|
57011
57101
|
}
|
|
57012
57102
|
await this.deps.db.delete(gameTimebackAssessmentTests).where(eq(gameTimebackAssessmentTests.id, row.id));
|
|
57013
|
-
|
|
57103
|
+
logger19.info("Assessment deleted", { integrationId, qtiTestIdentifier });
|
|
57014
57104
|
}
|
|
57015
57105
|
async reorderAssessments(integrationId, identifiers) {
|
|
57016
57106
|
await this.requireIntegration(integrationId);
|
|
@@ -57055,7 +57145,7 @@ class TimebackAssessmentsService {
|
|
|
57055
57145
|
return client.qti.tests.reorderItems(qtiTestIdentifier, partId, sectionId, items2);
|
|
57056
57146
|
}
|
|
57057
57147
|
async activateAssessment(integrationId, qtiTestIdentifier) {
|
|
57058
|
-
|
|
57148
|
+
logger19.debug("Activating assessment", { integrationId, qtiTestIdentifier });
|
|
57059
57149
|
const client = this.requireClient();
|
|
57060
57150
|
const integration = await this.requireIntegration(integrationId);
|
|
57061
57151
|
const row = await this.requireAssessmentRow(integrationId, qtiTestIdentifier);
|
|
@@ -57093,7 +57183,7 @@ class TimebackAssessmentsService {
|
|
|
57093
57183
|
});
|
|
57094
57184
|
}
|
|
57095
57185
|
} catch {
|
|
57096
|
-
|
|
57186
|
+
logger19.warn("Failed to reactivate existing child resource, will create new", {
|
|
57097
57187
|
childResourceId
|
|
57098
57188
|
});
|
|
57099
57189
|
childResourceId = null;
|
|
@@ -57106,7 +57196,7 @@ class TimebackAssessmentsService {
|
|
|
57106
57196
|
const resourceUrl = resource.metadata?.url;
|
|
57107
57197
|
if (resourceUrl === qtiTestUrl) {
|
|
57108
57198
|
childResourceId = resourceId;
|
|
57109
|
-
|
|
57199
|
+
logger19.info("Found existing child Resource for QTI test (idempotent retry)", {
|
|
57110
57200
|
qtiTestIdentifier,
|
|
57111
57201
|
childResourceId
|
|
57112
57202
|
});
|
|
@@ -57115,7 +57205,7 @@ class TimebackAssessmentsService {
|
|
|
57115
57205
|
} catch {}
|
|
57116
57206
|
}
|
|
57117
57207
|
if (!childResourceId) {
|
|
57118
|
-
|
|
57208
|
+
logger19.debug("Creating child resource", { qtiTestIdentifier, qtiTestUrl });
|
|
57119
57209
|
const childResult = await client.oneroster.resources.create({
|
|
57120
57210
|
resource: {
|
|
57121
57211
|
status: "active",
|
|
@@ -57143,10 +57233,10 @@ class TimebackAssessmentsService {
|
|
|
57143
57233
|
}
|
|
57144
57234
|
}
|
|
57145
57235
|
await this.deps.db.update(gameTimebackAssessmentTests).set({ bankResourceId: childResourceId, bankActive: true }).where(eq(gameTimebackAssessmentTests.id, row.id));
|
|
57146
|
-
|
|
57236
|
+
logger19.info("Assessment activated", { integrationId, qtiTestIdentifier, childResourceId });
|
|
57147
57237
|
}
|
|
57148
57238
|
async deactivateAssessment(integrationId, qtiTestIdentifier) {
|
|
57149
|
-
|
|
57239
|
+
logger19.debug("Deactivating assessment", { integrationId, qtiTestIdentifier });
|
|
57150
57240
|
const client = this.requireClient();
|
|
57151
57241
|
const integration = await this.requireIntegration(integrationId);
|
|
57152
57242
|
const row = await this.requireAssessmentRow(integrationId, qtiTestIdentifier);
|
|
@@ -57159,7 +57249,7 @@ class TimebackAssessmentsService {
|
|
|
57159
57249
|
const childResourceId = row.bankResourceId;
|
|
57160
57250
|
const bankIds = deriveAssessmentBankIds(integration.courseId);
|
|
57161
57251
|
try {
|
|
57162
|
-
|
|
57252
|
+
logger19.debug("Reading parent resource for deactivation", {
|
|
57163
57253
|
resourceId: bankIds.resource
|
|
57164
57254
|
});
|
|
57165
57255
|
const parentResource = await client.oneroster.resources.get(bankIds.resource);
|
|
@@ -57178,22 +57268,22 @@ class TimebackAssessmentsService {
|
|
|
57178
57268
|
});
|
|
57179
57269
|
}
|
|
57180
57270
|
} catch (error) {
|
|
57181
|
-
|
|
57271
|
+
logger19.warn("Failed to update parent resource during deactivation", {
|
|
57182
57272
|
bankResourceId: bankIds.resource,
|
|
57183
57273
|
error: error instanceof Error ? error.message : String(error)
|
|
57184
57274
|
});
|
|
57185
57275
|
}
|
|
57186
57276
|
try {
|
|
57187
|
-
|
|
57277
|
+
logger19.debug("Deleting child resource", { childResourceId });
|
|
57188
57278
|
await client.oneroster.resources.delete(childResourceId);
|
|
57189
57279
|
} catch (error) {
|
|
57190
|
-
|
|
57280
|
+
logger19.warn("Failed to delete child resource (may already be deleted)", {
|
|
57191
57281
|
childResourceId,
|
|
57192
57282
|
error: error instanceof Error ? error.message : String(error)
|
|
57193
57283
|
});
|
|
57194
57284
|
}
|
|
57195
57285
|
await this.deps.db.update(gameTimebackAssessmentTests).set({ bankActive: false }).where(eq(gameTimebackAssessmentTests.id, row.id));
|
|
57196
|
-
|
|
57286
|
+
logger19.info("Assessment deactivated", { integrationId, qtiTestIdentifier });
|
|
57197
57287
|
}
|
|
57198
57288
|
isAssessmentActive(row) {
|
|
57199
57289
|
return row.bankActive;
|
|
@@ -57224,14 +57314,14 @@ class TimebackAssessmentsService {
|
|
|
57224
57314
|
status: "tobedeleted"
|
|
57225
57315
|
});
|
|
57226
57316
|
} catch (error) {
|
|
57227
|
-
|
|
57317
|
+
logger19.warn("Failed to delete component resource", { error });
|
|
57228
57318
|
}
|
|
57229
57319
|
for (const row of activeRows) {
|
|
57230
57320
|
if (row.bankResourceId) {
|
|
57231
57321
|
try {
|
|
57232
57322
|
await client.oneroster.resources.delete(row.bankResourceId);
|
|
57233
57323
|
} catch (error) {
|
|
57234
|
-
|
|
57324
|
+
logger19.warn("Failed to delete child resource", {
|
|
57235
57325
|
childResourceId: row.bankResourceId,
|
|
57236
57326
|
error
|
|
57237
57327
|
});
|
|
@@ -57241,17 +57331,17 @@ class TimebackAssessmentsService {
|
|
|
57241
57331
|
try {
|
|
57242
57332
|
await client.oneroster.resources.delete(bankIds.resource);
|
|
57243
57333
|
} catch (error) {
|
|
57244
|
-
|
|
57334
|
+
logger19.warn("Failed to delete parent resource", { error });
|
|
57245
57335
|
}
|
|
57246
57336
|
try {
|
|
57247
57337
|
await client.oneroster.courseComponents.update(bankIds.component, {
|
|
57248
57338
|
status: "tobedeleted"
|
|
57249
57339
|
});
|
|
57250
57340
|
} catch (error) {
|
|
57251
|
-
|
|
57341
|
+
logger19.warn("Failed to delete course component", { error });
|
|
57252
57342
|
}
|
|
57253
57343
|
await this.deps.db.update(gameTimebackAssessmentTests).set({ bankResourceId: null, bankActive: false }).where(eq(gameTimebackAssessmentTests.integrationId, integrationId));
|
|
57254
|
-
|
|
57344
|
+
logger19.info("Bank destroyed", { integrationId });
|
|
57255
57345
|
}
|
|
57256
57346
|
requireClient() {
|
|
57257
57347
|
if (!this.deps.timeback) {
|
|
@@ -57280,7 +57370,7 @@ class TimebackAssessmentsService {
|
|
|
57280
57370
|
async ensureBank(integration) {
|
|
57281
57371
|
const client = this.requireClient();
|
|
57282
57372
|
const bankIds = deriveAssessmentBankIds(integration.courseId);
|
|
57283
|
-
|
|
57373
|
+
logger19.debug("Ensuring assessment bank hierarchy", {
|
|
57284
57374
|
courseId: integration.courseId,
|
|
57285
57375
|
bankIds
|
|
57286
57376
|
});
|
|
@@ -57297,7 +57387,7 @@ class TimebackAssessmentsService {
|
|
|
57297
57387
|
});
|
|
57298
57388
|
} catch (error) {
|
|
57299
57389
|
if (error instanceof TimebackApiError && error.status === 409) {
|
|
57300
|
-
|
|
57390
|
+
logger19.debug("Course component already exists", { sourcedId: bankIds.component });
|
|
57301
57391
|
} else {
|
|
57302
57392
|
throw error;
|
|
57303
57393
|
}
|
|
@@ -57321,7 +57411,7 @@ class TimebackAssessmentsService {
|
|
|
57321
57411
|
});
|
|
57322
57412
|
} catch (error) {
|
|
57323
57413
|
if (error instanceof TimebackApiError && error.status === 409) {
|
|
57324
|
-
|
|
57414
|
+
logger19.debug("Parent resource already exists", { sourcedId: bankIds.resource });
|
|
57325
57415
|
} else {
|
|
57326
57416
|
throw error;
|
|
57327
57417
|
}
|
|
@@ -57341,14 +57431,14 @@ class TimebackAssessmentsService {
|
|
|
57341
57431
|
});
|
|
57342
57432
|
} catch (error) {
|
|
57343
57433
|
if (error instanceof TimebackApiError && error.status === 409) {
|
|
57344
|
-
|
|
57434
|
+
logger19.debug("Component resource already exists", {
|
|
57345
57435
|
sourcedId: bankIds.componentResource
|
|
57346
57436
|
});
|
|
57347
57437
|
} else {
|
|
57348
57438
|
throw error;
|
|
57349
57439
|
}
|
|
57350
57440
|
}
|
|
57351
|
-
|
|
57441
|
+
logger19.info("Assessment bank hierarchy created", {
|
|
57352
57442
|
courseId: integration.courseId
|
|
57353
57443
|
});
|
|
57354
57444
|
}
|
|
@@ -57363,7 +57453,7 @@ class TimebackAssessmentsService {
|
|
|
57363
57453
|
return Math.max(...rows.map((r) => r.sortOrder));
|
|
57364
57454
|
}
|
|
57365
57455
|
}
|
|
57366
|
-
var
|
|
57456
|
+
var logger19;
|
|
57367
57457
|
var init_timeback_assessments_service = __esm(() => {
|
|
57368
57458
|
init_drizzle_orm();
|
|
57369
57459
|
init_tables_index();
|
|
@@ -57372,7 +57462,7 @@ var init_timeback_assessments_service = __esm(() => {
|
|
|
57372
57462
|
init_errors4();
|
|
57373
57463
|
init_utils6();
|
|
57374
57464
|
init_errors();
|
|
57375
|
-
|
|
57465
|
+
logger19 = log.scope("TimebackAssessmentsService");
|
|
57376
57466
|
});
|
|
57377
57467
|
async function promoteCompletedCourse({
|
|
57378
57468
|
db: db2,
|
|
@@ -57386,7 +57476,7 @@ async function promoteCompletedCourse({
|
|
|
57386
57476
|
});
|
|
57387
57477
|
const nextIntegration = subjectIntegrations.filter((integration) => integration.grade > currentIntegration.grade).toSorted((left, right) => left.grade - right.grade)[0];
|
|
57388
57478
|
if (!nextIntegration) {
|
|
57389
|
-
|
|
57479
|
+
logger20.debug("Skipping promotion because no next course is configured", {
|
|
57390
57480
|
gameId: currentIntegration.gameId,
|
|
57391
57481
|
studentId,
|
|
57392
57482
|
grade: currentIntegration.grade,
|
|
@@ -57403,7 +57493,7 @@ async function promoteCompletedCourse({
|
|
|
57403
57493
|
const nextEnrollment = enrollments.find((enrollment) => enrollment.course.id === nextIntegration.courseId);
|
|
57404
57494
|
if (!currentEnrollment) {
|
|
57405
57495
|
if (nextEnrollment) {
|
|
57406
|
-
|
|
57496
|
+
logger20.debug("Skipping promotion because student is already on the next course", {
|
|
57407
57497
|
gameId: currentIntegration.gameId,
|
|
57408
57498
|
studentId,
|
|
57409
57499
|
grade: currentIntegration.grade,
|
|
@@ -57417,7 +57507,7 @@ async function promoteCompletedCourse({
|
|
|
57417
57507
|
nextCourseId: nextIntegration.courseId
|
|
57418
57508
|
};
|
|
57419
57509
|
}
|
|
57420
|
-
|
|
57510
|
+
logger20.debug("Skipping promotion because student is not enrolled in the current course", {
|
|
57421
57511
|
gameId: currentIntegration.gameId,
|
|
57422
57512
|
studentId,
|
|
57423
57513
|
grade: currentIntegration.grade,
|
|
@@ -57448,7 +57538,7 @@ async function promoteCompletedCourse({
|
|
|
57448
57538
|
client.invalidateEnrollments(studentId);
|
|
57449
57539
|
}
|
|
57450
57540
|
}
|
|
57451
|
-
|
|
57541
|
+
logger20.info("Promoted student to next course", {
|
|
57452
57542
|
gameId: currentIntegration.gameId,
|
|
57453
57543
|
studentId,
|
|
57454
57544
|
subject: currentIntegration.subject,
|
|
@@ -57463,14 +57553,14 @@ async function promoteCompletedCourse({
|
|
|
57463
57553
|
nextCourseId: nextIntegration.courseId
|
|
57464
57554
|
};
|
|
57465
57555
|
}
|
|
57466
|
-
var
|
|
57556
|
+
var logger20;
|
|
57467
57557
|
var init_timeback_promotion_util = __esm(() => {
|
|
57468
57558
|
init_drizzle_orm();
|
|
57469
57559
|
init_tables_index();
|
|
57470
57560
|
init_src2();
|
|
57471
|
-
|
|
57561
|
+
logger20 = log.scope("TimebackPromotion");
|
|
57472
57562
|
});
|
|
57473
|
-
var
|
|
57563
|
+
var logger21;
|
|
57474
57564
|
var TimebackService;
|
|
57475
57565
|
var init_timeback_service = __esm(() => {
|
|
57476
57566
|
init_drizzle_orm();
|
|
@@ -57482,7 +57572,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57482
57572
|
init_errors();
|
|
57483
57573
|
init_timeback_promotion_util();
|
|
57484
57574
|
init_timeback_util();
|
|
57485
|
-
|
|
57575
|
+
logger21 = log.scope("TimebackService");
|
|
57486
57576
|
TimebackService = class TimebackService2 {
|
|
57487
57577
|
static HEARTBEAT_DEDUPE_TTL_MS = 300000;
|
|
57488
57578
|
static processedHeartbeatWindows = new Map;
|
|
@@ -57528,7 +57618,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57528
57618
|
}
|
|
57529
57619
|
requireClient() {
|
|
57530
57620
|
if (!this.deps.timeback) {
|
|
57531
|
-
|
|
57621
|
+
logger21.error("Timeback client not available in context");
|
|
57532
57622
|
throw new ValidationError("Timeback integration not available in this environment");
|
|
57533
57623
|
}
|
|
57534
57624
|
return this.deps.timeback;
|
|
@@ -57581,7 +57671,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57581
57671
|
set: { xp: sql`excluded.xp`, updatedAt: new Date }
|
|
57582
57672
|
}).returning({ xp: timebackDailyXp.xp, date: timebackDailyXp.date });
|
|
57583
57673
|
if (!result) {
|
|
57584
|
-
|
|
57674
|
+
logger21.error("Daily XP upsert returned no rows", { userId, date: targetDate });
|
|
57585
57675
|
throw new InternalError("Failed to update daily XP record");
|
|
57586
57676
|
}
|
|
57587
57677
|
return { xp: result.xp, date: result.date.toISOString() };
|
|
@@ -57612,7 +57702,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57612
57702
|
columns: { id: true, timebackId: true }
|
|
57613
57703
|
});
|
|
57614
57704
|
if (dbUser?.timebackId) {
|
|
57615
|
-
|
|
57705
|
+
logger21.info("Student already onboarded", { userId: user.id });
|
|
57616
57706
|
return { status: "already_populated" };
|
|
57617
57707
|
}
|
|
57618
57708
|
let timebackId;
|
|
@@ -57621,7 +57711,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57621
57711
|
const existingUser = await client.oneroster.users.findByEmail(user.email);
|
|
57622
57712
|
timebackId = existingUser.sourcedId;
|
|
57623
57713
|
name3 = `${existingUser.givenName} ${existingUser.familyName}`;
|
|
57624
|
-
|
|
57714
|
+
logger21.info("Found existing student in OneRoster", {
|
|
57625
57715
|
userId: user.id,
|
|
57626
57716
|
timebackId
|
|
57627
57717
|
});
|
|
@@ -57650,7 +57740,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57650
57740
|
}
|
|
57651
57741
|
timebackId = response.sourcedIdPairs.allocatedSourcedId;
|
|
57652
57742
|
name3 = `${providedNames.firstName} ${providedNames.lastName}`;
|
|
57653
|
-
|
|
57743
|
+
logger21.info("Created student in OneRoster", { userId: user.id, timebackId });
|
|
57654
57744
|
}
|
|
57655
57745
|
const assessments = await this.fetchAssessments(timebackId);
|
|
57656
57746
|
await db2.transaction(async (tx) => {
|
|
@@ -57684,7 +57774,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57684
57774
|
}
|
|
57685
57775
|
const [updated] = await tx.update(users).set({ timebackId, name: name3 }).where(eq(users.id, user.id)).returning({ id: users.id });
|
|
57686
57776
|
if (!updated) {
|
|
57687
|
-
|
|
57777
|
+
logger21.error("User Timeback ID update returned no rows", {
|
|
57688
57778
|
userId: user.id,
|
|
57689
57779
|
timebackId
|
|
57690
57780
|
});
|
|
@@ -57708,13 +57798,13 @@ var init_timeback_service = __esm(() => {
|
|
|
57708
57798
|
}
|
|
57709
57799
|
offset += limit;
|
|
57710
57800
|
}
|
|
57711
|
-
|
|
57801
|
+
logger21.debug("Fetched assessments", {
|
|
57712
57802
|
studentSourcedId,
|
|
57713
57803
|
totalCount: allAssessments.length
|
|
57714
57804
|
});
|
|
57715
57805
|
return allAssessments;
|
|
57716
57806
|
} catch (error) {
|
|
57717
|
-
|
|
57807
|
+
logger21.warn("Failed to fetch assessments", { studentSourcedId, error });
|
|
57718
57808
|
return [];
|
|
57719
57809
|
}
|
|
57720
57810
|
}
|
|
@@ -57827,7 +57917,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57827
57917
|
masterableUnits: derivedMasterableUnits
|
|
57828
57918
|
} = courseConfig;
|
|
57829
57919
|
if (!isTimebackSubject(subjectInput)) {
|
|
57830
|
-
|
|
57920
|
+
logger21.warn("Invalid Timeback subject in course config", {
|
|
57831
57921
|
subject: subjectInput,
|
|
57832
57922
|
courseCode,
|
|
57833
57923
|
title
|
|
@@ -57835,7 +57925,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57835
57925
|
throw new ValidationError(`Invalid subject "${subjectInput}"`);
|
|
57836
57926
|
}
|
|
57837
57927
|
if (!isTimebackGrade(grade)) {
|
|
57838
|
-
|
|
57928
|
+
logger21.warn("Invalid Timeback grade in course config", {
|
|
57839
57929
|
grade,
|
|
57840
57930
|
courseCode,
|
|
57841
57931
|
title
|
|
@@ -57847,7 +57937,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57847
57937
|
const totalXp = derivedTotalXp ?? courseMetadata?.metrics?.totalXp;
|
|
57848
57938
|
const masterableUnits = derivedMasterableUnits ?? (isPlaycademyResourceMetadata(courseMetadata?.playcademy) ? courseMetadata?.playcademy?.mastery?.masterableUnits : undefined);
|
|
57849
57939
|
if (typeof totalXp !== "number") {
|
|
57850
|
-
|
|
57940
|
+
logger21.warn("Course missing totalXp in Timeback config", {
|
|
57851
57941
|
courseCode,
|
|
57852
57942
|
title
|
|
57853
57943
|
});
|
|
@@ -57863,7 +57953,9 @@ var init_timeback_service = __esm(() => {
|
|
|
57863
57953
|
courseCode,
|
|
57864
57954
|
level,
|
|
57865
57955
|
gradingScheme: "STANDARD",
|
|
57866
|
-
metadata: metadata2
|
|
57956
|
+
metadata: TimebackService2.patchCourseMetadata(metadata2, totalXp, {
|
|
57957
|
+
masterableUnits: masterableUnits ?? null
|
|
57958
|
+
})
|
|
57867
57959
|
},
|
|
57868
57960
|
component: {
|
|
57869
57961
|
...baseConfig.component,
|
|
@@ -57888,7 +57980,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57888
57980
|
const existingIntegration = existing.find((i2) => i2.grade === grade && i2.subject === subject);
|
|
57889
57981
|
if (existingIntegration) {
|
|
57890
57982
|
await client.update(existingIntegration.courseId, fullConfig);
|
|
57891
|
-
const [updated] = await db2.update(gameTimebackIntegrations).set({ totalXp, updatedAt: new Date }).where(eq(gameTimebackIntegrations.id, existingIntegration.id)).returning();
|
|
57983
|
+
const [updated] = await db2.update(gameTimebackIntegrations).set({ subject, totalXp, updatedAt: new Date }).where(eq(gameTimebackIntegrations.id, existingIntegration.id)).returning();
|
|
57892
57984
|
if (updated) {
|
|
57893
57985
|
integrations.push(this.toGameTimebackIntegration(updated));
|
|
57894
57986
|
}
|
|
@@ -57913,6 +58005,60 @@ var init_timeback_service = __esm(() => {
|
|
|
57913
58005
|
});
|
|
57914
58006
|
return rows.map((row) => this.toGameTimebackIntegration(row));
|
|
57915
58007
|
}
|
|
58008
|
+
async getIntegrationConfig(gameId, courseId, user) {
|
|
58009
|
+
const client = this.requireClient();
|
|
58010
|
+
await this.deps.validateGameManagementAccess(user, gameId);
|
|
58011
|
+
const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
|
|
58012
|
+
where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
|
|
58013
|
+
});
|
|
58014
|
+
if (!integration) {
|
|
58015
|
+
throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
|
|
58016
|
+
}
|
|
58017
|
+
const config2 = await client.getConfig(courseId);
|
|
58018
|
+
return this.toGameTimebackIntegrationConfig(integration, config2);
|
|
58019
|
+
}
|
|
58020
|
+
async updateIntegration(gameId, courseId, user, patch) {
|
|
58021
|
+
const client = this.requireClient();
|
|
58022
|
+
await this.deps.validateDeveloperAccess(user, gameId);
|
|
58023
|
+
const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
|
|
58024
|
+
where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
|
|
58025
|
+
});
|
|
58026
|
+
if (!integration) {
|
|
58027
|
+
throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
|
|
58028
|
+
}
|
|
58029
|
+
const timebackConfig = await client.getConfig(courseId);
|
|
58030
|
+
const liveSubject = timebackConfig.course.subjects[0];
|
|
58031
|
+
const subject = patch.subject ?? (isTimebackSubject(liveSubject) ? liveSubject : integration.subject);
|
|
58032
|
+
if (!isTimebackSubject(subject)) {
|
|
58033
|
+
throw new ValidationError(`Invalid subject "${subject}"`);
|
|
58034
|
+
}
|
|
58035
|
+
if (subject !== integration.subject) {
|
|
58036
|
+
const subjectConflict = await this.deps.db.query.gameTimebackIntegrations.findFirst({
|
|
58037
|
+
where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, integration.grade), eq(gameTimebackIntegrations.subject, subject))
|
|
58038
|
+
});
|
|
58039
|
+
if (subjectConflict && subjectConflict.id !== integration.id) {
|
|
58040
|
+
throw new ValidationError(`A TimeBack integration already exists for ${subject} Grade ${integration.grade}`);
|
|
58041
|
+
}
|
|
58042
|
+
}
|
|
58043
|
+
const totalXp = "totalXp" in patch ? patch.totalXp ?? null : TimebackService2.getTotalXpFromConfig(timebackConfig) ?? integration.totalXp ?? null;
|
|
58044
|
+
const masterableUnits = "masterableUnits" in patch ? patch.masterableUnits ?? null : TimebackService2.getMasterableUnitsFromConfig(timebackConfig);
|
|
58045
|
+
await client.update(courseId, TimebackService2.patchTimebackConfig(timebackConfig, {
|
|
58046
|
+
...patch,
|
|
58047
|
+
subject,
|
|
58048
|
+
totalXp,
|
|
58049
|
+
masterableUnits,
|
|
58050
|
+
grade: integration.grade
|
|
58051
|
+
}));
|
|
58052
|
+
const [updated] = await this.deps.db.update(gameTimebackIntegrations).set({
|
|
58053
|
+
subject,
|
|
58054
|
+
totalXp,
|
|
58055
|
+
updatedAt: new Date
|
|
58056
|
+
}).where(eq(gameTimebackIntegrations.id, integration.id)).returning();
|
|
58057
|
+
if (!updated) {
|
|
58058
|
+
throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
|
|
58059
|
+
}
|
|
58060
|
+
return this.toGameTimebackIntegration(updated);
|
|
58061
|
+
}
|
|
57916
58062
|
async verifyIntegration(gameId, user) {
|
|
57917
58063
|
const client = this.requireClient();
|
|
57918
58064
|
const db2 = this.deps.db;
|
|
@@ -57970,6 +58116,146 @@ var init_timeback_service = __esm(() => {
|
|
|
57970
58116
|
}
|
|
57971
58117
|
await db2.delete(gameTimebackIntegrations).where(eq(gameTimebackIntegrations.gameId, gameId));
|
|
57972
58118
|
}
|
|
58119
|
+
static getMasterableUnitsFromConfig(config2) {
|
|
58120
|
+
const playcademyMetadata = config2.resource.metadata?.playcademy;
|
|
58121
|
+
if (!isPlaycademyResourceMetadata(playcademyMetadata)) {
|
|
58122
|
+
return null;
|
|
58123
|
+
}
|
|
58124
|
+
return playcademyMetadata?.mastery?.masterableUnits ?? null;
|
|
58125
|
+
}
|
|
58126
|
+
static getTotalXpFromConfig(config2) {
|
|
58127
|
+
const courseMetadata = isCourseMetadata(config2.course.metadata) ? config2.course.metadata : undefined;
|
|
58128
|
+
if (typeof courseMetadata?.metrics?.totalXp === "number") {
|
|
58129
|
+
return courseMetadata.metrics.totalXp;
|
|
58130
|
+
}
|
|
58131
|
+
const resourceMetadata = config2.resource.metadata;
|
|
58132
|
+
if (isRecord2(resourceMetadata) && typeof resourceMetadata.xp === "number") {
|
|
58133
|
+
return resourceMetadata.xp;
|
|
58134
|
+
}
|
|
58135
|
+
return null;
|
|
58136
|
+
}
|
|
58137
|
+
static patchCourseMetadata(metadata2, totalXp, options) {
|
|
58138
|
+
const nextMetadata = isRecord2(metadata2) ? { ...metadata2 } : {};
|
|
58139
|
+
const currentMetrics = isRecord2(nextMetadata.metrics) ? nextMetadata.metrics : {};
|
|
58140
|
+
const metrics = { ...currentMetrics };
|
|
58141
|
+
if (totalXp === null) {
|
|
58142
|
+
delete metrics.totalXp;
|
|
58143
|
+
} else {
|
|
58144
|
+
metrics.totalXp = totalXp;
|
|
58145
|
+
}
|
|
58146
|
+
if (options?.masterableUnits !== undefined) {
|
|
58147
|
+
if (options.masterableUnits === null) {
|
|
58148
|
+
delete metrics.totalLessons;
|
|
58149
|
+
} else {
|
|
58150
|
+
metrics.totalLessons = options.masterableUnits;
|
|
58151
|
+
}
|
|
58152
|
+
}
|
|
58153
|
+
metrics.totalGrades = 1;
|
|
58154
|
+
if (Object.keys(metrics).length > 0) {
|
|
58155
|
+
nextMetadata.metrics = metrics;
|
|
58156
|
+
} else {
|
|
58157
|
+
delete nextMetadata.metrics;
|
|
58158
|
+
}
|
|
58159
|
+
const goals = options?.goals;
|
|
58160
|
+
if (goals !== undefined) {
|
|
58161
|
+
if (goals === null) {
|
|
58162
|
+
delete nextMetadata.goals;
|
|
58163
|
+
} else {
|
|
58164
|
+
const currentGoals = isRecord2(nextMetadata.goals) ? nextMetadata.goals : {};
|
|
58165
|
+
const nextGoals = { ...currentGoals };
|
|
58166
|
+
for (const [key, value] of Object.entries(goals)) {
|
|
58167
|
+
if (value === null) {
|
|
58168
|
+
delete nextGoals[key];
|
|
58169
|
+
} else if (value !== undefined) {
|
|
58170
|
+
nextGoals[key] = value;
|
|
58171
|
+
}
|
|
58172
|
+
}
|
|
58173
|
+
if (Object.keys(nextGoals).length > 0) {
|
|
58174
|
+
nextMetadata.goals = nextGoals;
|
|
58175
|
+
} else {
|
|
58176
|
+
delete nextMetadata.goals;
|
|
58177
|
+
}
|
|
58178
|
+
}
|
|
58179
|
+
}
|
|
58180
|
+
if (options?.publishStatus !== undefined) {
|
|
58181
|
+
if (options.publishStatus === null) {
|
|
58182
|
+
delete nextMetadata.publishStatus;
|
|
58183
|
+
const alphaLearn = isRecord2(nextMetadata.AlphaLearn) ? { ...nextMetadata.AlphaLearn } : {};
|
|
58184
|
+
delete alphaLearn.publishStatus;
|
|
58185
|
+
if (Object.keys(alphaLearn).length > 0) {
|
|
58186
|
+
nextMetadata.AlphaLearn = alphaLearn;
|
|
58187
|
+
} else {
|
|
58188
|
+
delete nextMetadata.AlphaLearn;
|
|
58189
|
+
}
|
|
58190
|
+
} else {
|
|
58191
|
+
nextMetadata.publishStatus = options.publishStatus;
|
|
58192
|
+
const alphaLearn = isRecord2(nextMetadata.AlphaLearn) ? { ...nextMetadata.AlphaLearn } : {};
|
|
58193
|
+
alphaLearn.publishStatus = options.publishStatus === "published" ? "active" : options.publishStatus;
|
|
58194
|
+
nextMetadata.AlphaLearn = alphaLearn;
|
|
58195
|
+
}
|
|
58196
|
+
}
|
|
58197
|
+
if (options?.isSupplemental !== undefined) {
|
|
58198
|
+
nextMetadata.isSupplemental = options.isSupplemental;
|
|
58199
|
+
}
|
|
58200
|
+
if (options?.timebackVisible !== undefined) {
|
|
58201
|
+
if (options.timebackVisible === null) {
|
|
58202
|
+
delete nextMetadata.timebackVisible;
|
|
58203
|
+
} else {
|
|
58204
|
+
nextMetadata.timebackVisible = options.timebackVisible;
|
|
58205
|
+
}
|
|
58206
|
+
}
|
|
58207
|
+
return Object.keys(nextMetadata).length > 0 ? nextMetadata : undefined;
|
|
58208
|
+
}
|
|
58209
|
+
static patchResourceMetadata(metadata2, options) {
|
|
58210
|
+
const nextMetadata = isRecord2(metadata2) ? { ...metadata2 } : {};
|
|
58211
|
+
const playcademyMetadata = isRecord2(nextMetadata.playcademy) ? { ...nextMetadata.playcademy } : {};
|
|
58212
|
+
const masteryMetadata = isRecord2(playcademyMetadata.mastery) ? { ...playcademyMetadata.mastery } : {};
|
|
58213
|
+
nextMetadata.subject = options.subject;
|
|
58214
|
+
nextMetadata.grades = [options.grade];
|
|
58215
|
+
if (options.totalXp === null) {
|
|
58216
|
+
delete nextMetadata.xp;
|
|
58217
|
+
} else {
|
|
58218
|
+
nextMetadata.xp = options.totalXp;
|
|
58219
|
+
}
|
|
58220
|
+
if (options.masterableUnits === null) {
|
|
58221
|
+
delete masteryMetadata.masterableUnits;
|
|
58222
|
+
} else {
|
|
58223
|
+
masteryMetadata.masterableUnits = options.masterableUnits;
|
|
58224
|
+
}
|
|
58225
|
+
if (Object.keys(masteryMetadata).length > 0) {
|
|
58226
|
+
playcademyMetadata.mastery = masteryMetadata;
|
|
58227
|
+
} else {
|
|
58228
|
+
delete playcademyMetadata.mastery;
|
|
58229
|
+
}
|
|
58230
|
+
if (Object.keys(playcademyMetadata).length > 0) {
|
|
58231
|
+
nextMetadata.playcademy = playcademyMetadata;
|
|
58232
|
+
} else {
|
|
58233
|
+
delete nextMetadata.playcademy;
|
|
58234
|
+
}
|
|
58235
|
+
return nextMetadata;
|
|
58236
|
+
}
|
|
58237
|
+
static patchTimebackConfig(config2, patch) {
|
|
58238
|
+
return {
|
|
58239
|
+
...config2,
|
|
58240
|
+
course: {
|
|
58241
|
+
...config2.course,
|
|
58242
|
+
title: patch.title ?? config2.course.title,
|
|
58243
|
+
courseCode: patch.courseCode ?? config2.course.courseCode,
|
|
58244
|
+
subjects: [patch.subject],
|
|
58245
|
+
metadata: TimebackService2.patchCourseMetadata(config2.course.metadata, patch.totalXp, {
|
|
58246
|
+
masterableUnits: patch.masterableUnits,
|
|
58247
|
+
goals: patch.goals,
|
|
58248
|
+
publishStatus: patch.publishStatus,
|
|
58249
|
+
isSupplemental: patch.isSupplemental,
|
|
58250
|
+
timebackVisible: patch.timebackVisible
|
|
58251
|
+
})
|
|
58252
|
+
},
|
|
58253
|
+
resource: {
|
|
58254
|
+
...config2.resource,
|
|
58255
|
+
metadata: TimebackService2.patchResourceMetadata(config2.resource.metadata, patch)
|
|
58256
|
+
}
|
|
58257
|
+
};
|
|
58258
|
+
}
|
|
57973
58259
|
toGameTimebackIntegration(integration) {
|
|
57974
58260
|
return {
|
|
57975
58261
|
id: integration.id,
|
|
@@ -57983,6 +58269,21 @@ var init_timeback_service = __esm(() => {
|
|
|
57983
58269
|
lastVerifiedAt: integration.lastVerifiedAt ?? null
|
|
57984
58270
|
};
|
|
57985
58271
|
}
|
|
58272
|
+
toGameTimebackIntegrationConfig(integration, config2) {
|
|
58273
|
+
const subject = config2.course.subjects[0] ?? integration.subject;
|
|
58274
|
+
if (!isTimebackSubject(subject)) {
|
|
58275
|
+
throw new ValidationError(`Invalid subject "${subject}"`);
|
|
58276
|
+
}
|
|
58277
|
+
return {
|
|
58278
|
+
integration: this.toGameTimebackIntegration(integration),
|
|
58279
|
+
title: config2.course.title,
|
|
58280
|
+
courseCode: config2.course.courseCode,
|
|
58281
|
+
subject,
|
|
58282
|
+
totalXp: TimebackService2.getTotalXpFromConfig(config2) ?? integration.totalXp ?? null,
|
|
58283
|
+
masterableUnits: TimebackService2.getMasterableUnitsFromConfig(config2),
|
|
58284
|
+
metadata: isCourseMetadata(config2.course.metadata) ? config2.course.metadata : null
|
|
58285
|
+
};
|
|
58286
|
+
}
|
|
57986
58287
|
async endActivity({
|
|
57987
58288
|
gameId,
|
|
57988
58289
|
studentId,
|
|
@@ -58048,7 +58349,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58048
58349
|
...runId ? { runId } : {}
|
|
58049
58350
|
});
|
|
58050
58351
|
}
|
|
58051
|
-
|
|
58352
|
+
logger21.info("Recorded activity completion", {
|
|
58052
58353
|
gameId,
|
|
58053
58354
|
courseId: integration.courseId,
|
|
58054
58355
|
studentId,
|
|
@@ -58102,7 +58403,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58102
58403
|
masteredUnits: masteryStatus.masteredUnits,
|
|
58103
58404
|
masterableUnits: masteryStatus.masterableUnits
|
|
58104
58405
|
};
|
|
58105
|
-
|
|
58406
|
+
logger21.debug("Skipping course advancement because mastery is incomplete", {
|
|
58106
58407
|
gameId,
|
|
58107
58408
|
studentId,
|
|
58108
58409
|
subject: currentIntegration.subject,
|
|
@@ -58120,7 +58421,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58120
58421
|
studentId,
|
|
58121
58422
|
enrollments
|
|
58122
58423
|
});
|
|
58123
|
-
|
|
58424
|
+
logger21.info("Manually advanced student", {
|
|
58124
58425
|
gameId,
|
|
58125
58426
|
studentId,
|
|
58126
58427
|
subject: currentIntegration.subject,
|
|
@@ -58153,7 +58454,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58153
58454
|
const heartbeatWindowKey = hasWindowStartedAtMs ? `${runId}:t:${windowStartedAtMs}` : `${runId}:s:${windowSequence}`;
|
|
58154
58455
|
const effectiveResumeId = resumeId ?? runId;
|
|
58155
58456
|
if (TimebackService2.isDuplicateHeartbeatWindow(heartbeatWindowKey)) {
|
|
58156
|
-
|
|
58457
|
+
logger21.debug("Skipping duplicate heartbeat window", {
|
|
58157
58458
|
gameId,
|
|
58158
58459
|
studentId,
|
|
58159
58460
|
runId,
|
|
@@ -58166,7 +58467,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58166
58467
|
await this.deps.validateDeveloperAccess(user, gameId);
|
|
58167
58468
|
const inFlightHeartbeat = TimebackService2.getInFlightHeartbeatWindow(heartbeatWindowKey);
|
|
58168
58469
|
if (inFlightHeartbeat) {
|
|
58169
|
-
|
|
58470
|
+
logger21.debug("Joining in-flight heartbeat window", {
|
|
58170
58471
|
gameId,
|
|
58171
58472
|
studentId,
|
|
58172
58473
|
runId,
|
|
@@ -58203,7 +58504,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58203
58504
|
});
|
|
58204
58505
|
}
|
|
58205
58506
|
TimebackService2.markHeartbeatWindowProcessed(heartbeatWindowKey);
|
|
58206
|
-
|
|
58507
|
+
logger21.debug("Recorded heartbeat", {
|
|
58207
58508
|
gameId,
|
|
58208
58509
|
courseId: integration.courseId,
|
|
58209
58510
|
studentId,
|
|
@@ -58238,7 +58539,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58238
58539
|
});
|
|
58239
58540
|
courseIds = integrations.map((i2) => i2.courseId);
|
|
58240
58541
|
if (courseIds.length === 0) {
|
|
58241
|
-
|
|
58542
|
+
logger21.debug("No integrations found for game, returning 0 XP", {
|
|
58242
58543
|
timebackId,
|
|
58243
58544
|
gameId: options.gameId,
|
|
58244
58545
|
grade: options.grade,
|
|
@@ -58255,7 +58556,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58255
58556
|
courseIds: courseIds.length > 0 ? courseIds : undefined,
|
|
58256
58557
|
include: options?.include
|
|
58257
58558
|
});
|
|
58258
|
-
|
|
58559
|
+
logger21.debug("Retrieved student XP", {
|
|
58259
58560
|
timebackId,
|
|
58260
58561
|
gameId: options?.gameId,
|
|
58261
58562
|
grade: options?.grade,
|
|
@@ -58283,15 +58584,15 @@ class UploadService {
|
|
|
58283
58584
|
const { fileName, gameId } = request;
|
|
58284
58585
|
const bucketName = this.deps.uploadBucket;
|
|
58285
58586
|
if (!bucketName) {
|
|
58286
|
-
|
|
58587
|
+
logger22.error("Upload bucket not configured in environment");
|
|
58287
58588
|
throw new ValidationError("Upload bucket not configured");
|
|
58288
58589
|
}
|
|
58289
58590
|
await this.deps.validateDeveloperAccess(user, gameId);
|
|
58290
58591
|
const version2 = ulid();
|
|
58291
58592
|
const tempS3Key = `uploads-temp/${gameId}/${version2}/${fileName}`;
|
|
58292
|
-
|
|
58593
|
+
logger22.debug("Initiating upload", { userId: user.id, gameId, fileName, version: version2 });
|
|
58293
58594
|
const presignedUrl = await this.deps.generatePresignedPutUrl(bucketName, tempS3Key, UploadService.getContentType(fileName));
|
|
58294
|
-
|
|
58595
|
+
logger22.info("Presigned URL generated", {
|
|
58295
58596
|
userId: user.id,
|
|
58296
58597
|
gameId,
|
|
58297
58598
|
version: version2
|
|
@@ -58304,12 +58605,12 @@ class UploadService {
|
|
|
58304
58605
|
};
|
|
58305
58606
|
}
|
|
58306
58607
|
}
|
|
58307
|
-
var
|
|
58608
|
+
var logger22;
|
|
58308
58609
|
var init_upload_service = __esm(() => {
|
|
58309
58610
|
init_node();
|
|
58310
58611
|
init_src2();
|
|
58311
58612
|
init_errors();
|
|
58312
|
-
|
|
58613
|
+
logger22 = log.scope("UploadService");
|
|
58313
58614
|
});
|
|
58314
58615
|
function createPlatformServices(deps) {
|
|
58315
58616
|
const {
|
|
@@ -58610,7 +58911,7 @@ class AchievementService {
|
|
|
58610
58911
|
results.push(result);
|
|
58611
58912
|
}
|
|
58612
58913
|
}
|
|
58613
|
-
|
|
58914
|
+
logger23.debug("Listed current achievements", { userId: user.id, count: results.length });
|
|
58614
58915
|
return results;
|
|
58615
58916
|
}
|
|
58616
58917
|
async listHistory(user, limit) {
|
|
@@ -58628,14 +58929,14 @@ class AchievementService {
|
|
|
58628
58929
|
createdAt: c.createdAt,
|
|
58629
58930
|
scopeKey: c.scopeKey
|
|
58630
58931
|
}));
|
|
58631
|
-
|
|
58932
|
+
logger23.debug("Listed achievement history", { userId: user.id, count: results.length });
|
|
58632
58933
|
return results;
|
|
58633
58934
|
}
|
|
58634
58935
|
async submitProgress(achievementId, user) {
|
|
58635
58936
|
const { claim, wasNewClaim } = await this.award(user.id, achievementId, {
|
|
58636
58937
|
broadcast: false
|
|
58637
58938
|
});
|
|
58638
|
-
|
|
58939
|
+
logger23.debug("Submitted progress", {
|
|
58639
58940
|
userId: user.id,
|
|
58640
58941
|
achievementId,
|
|
58641
58942
|
wasNewClaim
|
|
@@ -58667,7 +58968,7 @@ class AchievementService {
|
|
|
58667
58968
|
rewardCredits
|
|
58668
58969
|
}).returning();
|
|
58669
58970
|
if (!newClaim) {
|
|
58670
|
-
|
|
58971
|
+
logger23.error("Achievement claim insert returned no rows", {
|
|
58671
58972
|
userId,
|
|
58672
58973
|
achievementId,
|
|
58673
58974
|
scopeKey
|
|
@@ -58676,7 +58977,7 @@ class AchievementService {
|
|
|
58676
58977
|
}
|
|
58677
58978
|
await this.deps.addCredits(userId, rewardCredits);
|
|
58678
58979
|
await this.deps.createAchievementNotification(userId, achievement, rewardCredits, scopeKey, { broadcast, metadata: metadata2 });
|
|
58679
|
-
|
|
58980
|
+
logger23.info("Awarded achievement", {
|
|
58680
58981
|
userId,
|
|
58681
58982
|
achievementId,
|
|
58682
58983
|
scopeKey,
|
|
@@ -58713,7 +59014,7 @@ class AchievementService {
|
|
|
58713
59014
|
return { title, body: body2 };
|
|
58714
59015
|
}
|
|
58715
59016
|
}
|
|
58716
|
-
var
|
|
59017
|
+
var logger23;
|
|
58717
59018
|
var init_achievement_service = __esm(() => {
|
|
58718
59019
|
init_drizzle_orm();
|
|
58719
59020
|
init_tables_index();
|
|
@@ -58722,7 +59023,7 @@ var init_achievement_service = __esm(() => {
|
|
|
58722
59023
|
init_errors();
|
|
58723
59024
|
init_leaderboard_util();
|
|
58724
59025
|
init_scope_util();
|
|
58725
|
-
|
|
59026
|
+
logger23 = log.scope("AchievementService");
|
|
58726
59027
|
});
|
|
58727
59028
|
|
|
58728
59029
|
class InventoryService {
|
|
@@ -58749,7 +59050,7 @@ class InventoryService {
|
|
|
58749
59050
|
},
|
|
58750
59051
|
updatedAt: inventoryItems.updatedAt
|
|
58751
59052
|
}).from(inventoryItems).where(eq(inventoryItems.userId, user.id)).innerJoin(items, eq(inventoryItems.itemId, items.id));
|
|
58752
|
-
|
|
59053
|
+
logger24.debug("Listed inventory", { userId: user.id, count: inventory.length });
|
|
58753
59054
|
return inventory;
|
|
58754
59055
|
}
|
|
58755
59056
|
async addItem(itemId, quantity, user) {
|
|
@@ -58766,7 +59067,7 @@ class InventoryService {
|
|
|
58766
59067
|
const [inserted] = await tx.insert(inventoryItems).values({ userId: user.id, itemId, quantity }).returning({ quantity: inventoryItems.quantity });
|
|
58767
59068
|
return inserted?.quantity ?? 0;
|
|
58768
59069
|
});
|
|
58769
|
-
|
|
59070
|
+
logger24.debug("Added item", { userId: user.id, itemId, quantity, newTotal });
|
|
58770
59071
|
return { newTotal };
|
|
58771
59072
|
}
|
|
58772
59073
|
async removeItem(itemId, quantity, user) {
|
|
@@ -58777,7 +59078,7 @@ class InventoryService {
|
|
|
58777
59078
|
}
|
|
58778
59079
|
const [currentItem] = await tx.select({ id: inventoryItems.id, quantity: inventoryItems.quantity }).from(inventoryItems).where(and(eq(inventoryItems.userId, user.id), eq(inventoryItems.itemId, itemId), gte(inventoryItems.quantity, quantity))).limit(1);
|
|
58779
59080
|
if (!currentItem) {
|
|
58780
|
-
|
|
59081
|
+
logger24.warn("Insufficient inventory for removal", {
|
|
58781
59082
|
userId: user.id,
|
|
58782
59083
|
itemId,
|
|
58783
59084
|
requestedQuantity: quantity
|
|
@@ -58787,13 +59088,13 @@ class InventoryService {
|
|
|
58787
59088
|
const [updated] = await tx.update(inventoryItems).set({ quantity: sql`${inventoryItems.quantity} - ${quantity}` }).where(eq(inventoryItems.id, currentItem.id)).returning({ quantity: inventoryItems.quantity });
|
|
58788
59089
|
return updated?.quantity ?? 0;
|
|
58789
59090
|
});
|
|
58790
|
-
|
|
59091
|
+
logger24.debug("Removed item", { userId: user.id, itemId, quantity, newTotal });
|
|
58791
59092
|
return { newTotal };
|
|
58792
59093
|
}
|
|
58793
59094
|
async addCredits(userId, amount) {
|
|
58794
59095
|
const [creditsItem] = await this.deps.db.select({ id: items.id }).from(items).where(eq(items.slug, CURRENCIES.PRIMARY)).limit(1);
|
|
58795
59096
|
if (!creditsItem) {
|
|
58796
|
-
|
|
59097
|
+
logger24.error("Primary currency not found", {
|
|
58797
59098
|
userId,
|
|
58798
59099
|
amount
|
|
58799
59100
|
});
|
|
@@ -58806,17 +59107,17 @@ class InventoryService {
|
|
|
58806
59107
|
updatedAt: new Date
|
|
58807
59108
|
}
|
|
58808
59109
|
});
|
|
58809
|
-
|
|
59110
|
+
logger24.debug("Added credits", { userId, amount });
|
|
58810
59111
|
}
|
|
58811
59112
|
}
|
|
58812
|
-
var
|
|
59113
|
+
var logger24;
|
|
58813
59114
|
var init_inventory_service = __esm(() => {
|
|
58814
59115
|
init_drizzle_orm();
|
|
58815
59116
|
init_src();
|
|
58816
59117
|
init_tables_index();
|
|
58817
59118
|
init_src2();
|
|
58818
59119
|
init_errors();
|
|
58819
|
-
|
|
59120
|
+
logger24 = log.scope("InventoryService");
|
|
58820
59121
|
});
|
|
58821
59122
|
|
|
58822
59123
|
class LeaderboardService {
|
|
@@ -58847,7 +59148,7 @@ class LeaderboardService {
|
|
|
58847
59148
|
sessionId
|
|
58848
59149
|
}).returning();
|
|
58849
59150
|
if (!newScore) {
|
|
58850
|
-
|
|
59151
|
+
logger25.error("Score insert returned no rows", { userId, gameId, score: input.score });
|
|
58851
59152
|
throw new InternalError("Failed to insert score");
|
|
58852
59153
|
}
|
|
58853
59154
|
const bestScoreRows = await db2.select({ score: sql`MAX(${gameScores.score})` }).from(gameScores).where(and(eq(gameScores.gameId, gameId), eq(gameScores.userId, userId)));
|
|
@@ -58875,7 +59176,7 @@ class LeaderboardService {
|
|
|
58875
59176
|
movedUpWithinTop3
|
|
58876
59177
|
});
|
|
58877
59178
|
}
|
|
58878
|
-
|
|
59179
|
+
logger25.info("Score submitted", {
|
|
58879
59180
|
gameId,
|
|
58880
59181
|
userId,
|
|
58881
59182
|
isAnonymousUser,
|
|
@@ -58952,7 +59253,7 @@ class LeaderboardService {
|
|
|
58952
59253
|
});
|
|
58953
59254
|
}
|
|
58954
59255
|
} catch (error) {
|
|
58955
|
-
|
|
59256
|
+
logger25.warn("Failed to publish notification", { error });
|
|
58956
59257
|
}
|
|
58957
59258
|
}
|
|
58958
59259
|
async getLeaderboard(gameId, query, isAnonymousUser) {
|
|
@@ -59071,7 +59372,7 @@ class LeaderboardService {
|
|
|
59071
59372
|
return db2.select().from(gameScores).where(and(eq(gameScores.gameId, gameId), eq(gameScores.userId, userId))).orderBy(desc(gameScores.achievedAt)).limit(effectiveLimit);
|
|
59072
59373
|
}
|
|
59073
59374
|
}
|
|
59074
|
-
var
|
|
59375
|
+
var logger25;
|
|
59075
59376
|
var init_leaderboard_service = __esm(() => {
|
|
59076
59377
|
init_drizzle_orm();
|
|
59077
59378
|
init_src();
|
|
@@ -59081,7 +59382,7 @@ var init_leaderboard_service = __esm(() => {
|
|
|
59081
59382
|
init_notification();
|
|
59082
59383
|
init_errors();
|
|
59083
59384
|
init_leaderboard_util();
|
|
59084
|
-
|
|
59385
|
+
logger25 = log.scope("LeaderboardService");
|
|
59085
59386
|
});
|
|
59086
59387
|
|
|
59087
59388
|
class LevelService {
|
|
@@ -59096,9 +59397,9 @@ class LevelService {
|
|
|
59096
59397
|
for (const config2 of configs) {
|
|
59097
59398
|
levelConfigCache.set(config2.level, config2);
|
|
59098
59399
|
}
|
|
59099
|
-
|
|
59400
|
+
logger26.info("Cache pre-warmed", { count: configs.length });
|
|
59100
59401
|
} catch (error) {
|
|
59101
|
-
|
|
59402
|
+
logger26.error("Cache pre-warm failed", { error });
|
|
59102
59403
|
}
|
|
59103
59404
|
}
|
|
59104
59405
|
async getConfig(level) {
|
|
@@ -59132,7 +59433,7 @@ class LevelService {
|
|
|
59132
59433
|
totalXP
|
|
59133
59434
|
}).returning();
|
|
59134
59435
|
if (!newUserLevel) {
|
|
59135
|
-
|
|
59436
|
+
logger26.error("User level insert returned no rows", { userId: user.id });
|
|
59136
59437
|
throw new InternalError("Failed to create user level cache record");
|
|
59137
59438
|
}
|
|
59138
59439
|
userLevel = newUserLevel;
|
|
@@ -59147,7 +59448,7 @@ class LevelService {
|
|
|
59147
59448
|
userLevel = updatedUserLevel;
|
|
59148
59449
|
}
|
|
59149
59450
|
}
|
|
59150
|
-
|
|
59451
|
+
logger26.debug("Retrieved user level", {
|
|
59151
59452
|
userId: user.id,
|
|
59152
59453
|
totalXP,
|
|
59153
59454
|
currentLevel,
|
|
@@ -59158,7 +59459,7 @@ class LevelService {
|
|
|
59158
59459
|
async getProgress(user) {
|
|
59159
59460
|
const userLevel = await this.getByUser(user);
|
|
59160
59461
|
const xpToNextLevel = await this.calculateXPToNextLevel(userLevel.currentLevel, userLevel.currentXp);
|
|
59161
|
-
|
|
59462
|
+
logger26.debug("Retrieved progress", { userId: user.id });
|
|
59162
59463
|
return {
|
|
59163
59464
|
level: userLevel.currentLevel,
|
|
59164
59465
|
currentXp: userLevel.currentXp,
|
|
@@ -59192,7 +59493,7 @@ class LevelService {
|
|
|
59192
59493
|
if (leveledUp && previousUserLevel) {
|
|
59193
59494
|
await this.awardLevelUpCredits(userId, previousUserLevel.currentLevel, currentLevel);
|
|
59194
59495
|
}
|
|
59195
|
-
|
|
59496
|
+
logger26.info("Synced from Timeback", {
|
|
59196
59497
|
userId,
|
|
59197
59498
|
totalXP,
|
|
59198
59499
|
currentLevel,
|
|
@@ -59233,7 +59534,7 @@ class LevelService {
|
|
|
59233
59534
|
}
|
|
59234
59535
|
if (totalCredits > 0) {
|
|
59235
59536
|
await this.deps.addCredits(userId, totalCredits);
|
|
59236
|
-
|
|
59537
|
+
logger26.info("Awarded level-up credits", {
|
|
59237
59538
|
userId,
|
|
59238
59539
|
fromLevel,
|
|
59239
59540
|
toLevel,
|
|
@@ -59271,7 +59572,7 @@ class LevelService {
|
|
|
59271
59572
|
};
|
|
59272
59573
|
}
|
|
59273
59574
|
}
|
|
59274
|
-
var
|
|
59575
|
+
var logger26;
|
|
59275
59576
|
var levelConfigCache = null;
|
|
59276
59577
|
var init_level_service = __esm(() => {
|
|
59277
59578
|
init_drizzle_orm();
|
|
@@ -59279,7 +59580,7 @@ var init_level_service = __esm(() => {
|
|
|
59279
59580
|
init_tables_index();
|
|
59280
59581
|
init_src2();
|
|
59281
59582
|
init_errors();
|
|
59282
|
-
|
|
59583
|
+
logger26 = log.scope("LevelService");
|
|
59283
59584
|
});
|
|
59284
59585
|
var init_events = () => {};
|
|
59285
59586
|
function convertWebSocketUrlToHttp(wsUrl) {
|
|
@@ -59296,13 +59597,13 @@ async function publishToUser(baseUrl, secret, userId, type, payload) {
|
|
|
59296
59597
|
});
|
|
59297
59598
|
if (!res.ok) {
|
|
59298
59599
|
const text3 = await res.text().catch(() => "");
|
|
59299
|
-
|
|
59600
|
+
logger27.warn("Failed to publish to user", {
|
|
59300
59601
|
status: res.status,
|
|
59301
59602
|
body: text3
|
|
59302
59603
|
});
|
|
59303
59604
|
}
|
|
59304
59605
|
} catch (error) {
|
|
59305
|
-
|
|
59606
|
+
logger27.error("Publish to user error", { error });
|
|
59306
59607
|
}
|
|
59307
59608
|
}
|
|
59308
59609
|
|
|
@@ -59324,7 +59625,7 @@ class NotificationService {
|
|
|
59324
59625
|
conditions2.push(eq(notifications.type, type));
|
|
59325
59626
|
}
|
|
59326
59627
|
const results = await this.deps.db.select().from(notifications).where(and(...conditions2)).orderBy(desc(notifications.createdAt)).limit(limit).offset(offset);
|
|
59327
|
-
|
|
59628
|
+
logger27.debug("Listed notifications", { userId: user.id, count: results.length });
|
|
59328
59629
|
return results;
|
|
59329
59630
|
}
|
|
59330
59631
|
async updateStatus(notificationId, status, method) {
|
|
@@ -59343,7 +59644,7 @@ class NotificationService {
|
|
|
59343
59644
|
if (!updated) {
|
|
59344
59645
|
throw new NotFoundError("Notification", notificationId);
|
|
59345
59646
|
}
|
|
59346
|
-
|
|
59647
|
+
logger27.debug("Updated status", { notificationId, status });
|
|
59347
59648
|
return updated;
|
|
59348
59649
|
}
|
|
59349
59650
|
async getStats(user, options) {
|
|
@@ -59369,7 +59670,7 @@ class NotificationService {
|
|
|
59369
59670
|
const clicked = statsMap.clicked || 0;
|
|
59370
59671
|
const dismissed = statsMap.dismissed || 0;
|
|
59371
59672
|
const expired = statsMap.expired || 0;
|
|
59372
|
-
|
|
59673
|
+
logger27.debug("Retrieved stats", { userId: user.id, total });
|
|
59373
59674
|
return {
|
|
59374
59675
|
total,
|
|
59375
59676
|
delivered,
|
|
@@ -59418,7 +59719,7 @@ class NotificationService {
|
|
|
59418
59719
|
options: { data, clickUrl, metadata: metadata2 }
|
|
59419
59720
|
});
|
|
59420
59721
|
}
|
|
59421
|
-
|
|
59722
|
+
logger27.debug("Created notification", {
|
|
59422
59723
|
userId,
|
|
59423
59724
|
type,
|
|
59424
59725
|
id: notificationId,
|
|
@@ -59426,7 +59727,7 @@ class NotificationService {
|
|
|
59426
59727
|
});
|
|
59427
59728
|
return notificationId;
|
|
59428
59729
|
} catch (error) {
|
|
59429
|
-
|
|
59730
|
+
logger27.error("Failed to create notification", { userId, type, error });
|
|
59430
59731
|
return null;
|
|
59431
59732
|
}
|
|
59432
59733
|
}
|
|
@@ -59440,7 +59741,7 @@ class NotificationService {
|
|
|
59440
59741
|
}) {
|
|
59441
59742
|
const realtimeConfig = this.deps.realtime;
|
|
59442
59743
|
if (!realtimeConfig) {
|
|
59443
|
-
|
|
59744
|
+
logger27.warn("No realtime config for publish");
|
|
59444
59745
|
return;
|
|
59445
59746
|
}
|
|
59446
59747
|
const { relayUrl, publishSecret } = realtimeConfig;
|
|
@@ -59482,13 +59783,13 @@ class NotificationService {
|
|
|
59482
59783
|
metadata: data.metadata || {}
|
|
59483
59784
|
}).returning();
|
|
59484
59785
|
if (!notification) {
|
|
59485
|
-
|
|
59786
|
+
logger27.error("Notification insert returned no rows", {
|
|
59486
59787
|
userId: data.userId,
|
|
59487
59788
|
type: data.type
|
|
59488
59789
|
});
|
|
59489
59790
|
throw new InternalError("Failed to create notification");
|
|
59490
59791
|
}
|
|
59491
|
-
|
|
59792
|
+
logger27.info("Inserted notification", {
|
|
59492
59793
|
notificationId: notification.id,
|
|
59493
59794
|
userId: notification.userId,
|
|
59494
59795
|
type: notification.type
|
|
@@ -59498,7 +59799,7 @@ class NotificationService {
|
|
|
59498
59799
|
async deliverPending(userId) {
|
|
59499
59800
|
const realtimeConfig = this.deps.realtime;
|
|
59500
59801
|
if (!realtimeConfig) {
|
|
59501
|
-
|
|
59802
|
+
logger27.warn("No realtime config for delivery");
|
|
59502
59803
|
return;
|
|
59503
59804
|
}
|
|
59504
59805
|
const { relayUrl, publishSecret } = realtimeConfig;
|
|
@@ -59525,13 +59826,13 @@ class NotificationService {
|
|
|
59525
59826
|
metadata: notification.metadata,
|
|
59526
59827
|
clickUrl: notification.clickUrl
|
|
59527
59828
|
});
|
|
59528
|
-
|
|
59829
|
+
logger27.info("Delivered notification", {
|
|
59529
59830
|
notificationId: notification.id,
|
|
59530
59831
|
userId,
|
|
59531
59832
|
type: notification.type
|
|
59532
59833
|
});
|
|
59533
59834
|
} catch (error) {
|
|
59534
|
-
|
|
59835
|
+
logger27.warn("Failed to deliver", {
|
|
59535
59836
|
notificationId: notification.id,
|
|
59536
59837
|
error
|
|
59537
59838
|
});
|
|
@@ -59539,7 +59840,7 @@ class NotificationService {
|
|
|
59539
59840
|
}
|
|
59540
59841
|
}
|
|
59541
59842
|
}
|
|
59542
|
-
var
|
|
59843
|
+
var logger27;
|
|
59543
59844
|
var init_notification_service = __esm(() => {
|
|
59544
59845
|
init_drizzle_orm();
|
|
59545
59846
|
init_src();
|
|
@@ -59548,7 +59849,7 @@ var init_notification_service = __esm(() => {
|
|
|
59548
59849
|
init_events();
|
|
59549
59850
|
init_notification();
|
|
59550
59851
|
init_errors();
|
|
59551
|
-
|
|
59852
|
+
logger27 = log.scope("NotificationService");
|
|
59552
59853
|
});
|
|
59553
59854
|
function createPlayerServices(deps) {
|
|
59554
59855
|
const { db: db2, realtime } = deps;
|
|
@@ -59667,7 +59968,7 @@ class CharacterService {
|
|
|
59667
59968
|
createdAt: characterComponents.createdAt,
|
|
59668
59969
|
updatedAt: characterComponents.updatedAt
|
|
59669
59970
|
}).from(characterComponents).innerJoin(spriteSheets, eq(characterComponents.spriteSheetId, spriteSheets.id)).where(lte(characterComponents.unlockLevel, level)).orderBy(characterComponents.componentType, characterComponents.variant);
|
|
59670
|
-
|
|
59971
|
+
logger28.debug("Listed available components", {
|
|
59671
59972
|
level,
|
|
59672
59973
|
count: components.length
|
|
59673
59974
|
});
|
|
@@ -59685,7 +59986,7 @@ class CharacterService {
|
|
|
59685
59986
|
}
|
|
59686
59987
|
}
|
|
59687
59988
|
});
|
|
59688
|
-
|
|
59989
|
+
logger28.debug("Retrieved character", { userId: user.id, found: Boolean(pc3) });
|
|
59689
59990
|
return pc3 ?? null;
|
|
59690
59991
|
}
|
|
59691
59992
|
async getByUserId(userId) {
|
|
@@ -59700,7 +60001,7 @@ class CharacterService {
|
|
|
59700
60001
|
}
|
|
59701
60002
|
}
|
|
59702
60003
|
});
|
|
59703
|
-
|
|
60004
|
+
logger28.debug("Retrieved character by ID", { userId, found: Boolean(pc3) });
|
|
59704
60005
|
return pc3 ?? null;
|
|
59705
60006
|
}
|
|
59706
60007
|
async create(input, user) {
|
|
@@ -59715,13 +60016,13 @@ class CharacterService {
|
|
|
59715
60016
|
}
|
|
59716
60017
|
const [characterRow] = await tx.insert(playerCharacters).values({ ...input, userId: user.id }).returning();
|
|
59717
60018
|
if (!characterRow) {
|
|
59718
|
-
|
|
60019
|
+
logger28.error("Character insert returned no rows", { userId: user.id });
|
|
59719
60020
|
throw new InternalError("Failed to create character in database");
|
|
59720
60021
|
}
|
|
59721
60022
|
await tx.update(users).set({ characterCreated: true }).where(eq(users.id, user.id));
|
|
59722
60023
|
return characterRow;
|
|
59723
60024
|
});
|
|
59724
|
-
|
|
60025
|
+
logger28.info("Created character", { userId: user.id, characterId: result.id });
|
|
59725
60026
|
return result;
|
|
59726
60027
|
}
|
|
59727
60028
|
async update(input, user) {
|
|
@@ -59733,7 +60034,7 @@ class CharacterService {
|
|
|
59733
60034
|
if (!row) {
|
|
59734
60035
|
throw new NotFoundError("Player character");
|
|
59735
60036
|
}
|
|
59736
|
-
|
|
60037
|
+
logger28.info("Updated character", {
|
|
59737
60038
|
userId: user.id,
|
|
59738
60039
|
characterId: row.id,
|
|
59739
60040
|
updatedFields: Object.keys(input)
|
|
@@ -59755,7 +60056,7 @@ class CharacterService {
|
|
|
59755
60056
|
const availableComponents = await db2.select().from(characterComponents).where(lte(characterComponents.unlockLevel, playerLevel));
|
|
59756
60057
|
const validation = validateAccessorySlot(accessoryComponentId, slot, playerLevel, availableComponents);
|
|
59757
60058
|
if (!validation.isValid) {
|
|
59758
|
-
|
|
60059
|
+
logger28.warn("Accessory validation failed", {
|
|
59759
60060
|
userId: user.id,
|
|
59760
60061
|
slot,
|
|
59761
60062
|
accessoryComponentId,
|
|
@@ -59771,14 +60072,14 @@ class CharacterService {
|
|
|
59771
60072
|
slot
|
|
59772
60073
|
}).returning();
|
|
59773
60074
|
if (!result) {
|
|
59774
|
-
|
|
60075
|
+
logger28.error("Accessory insert returned no rows", {
|
|
59775
60076
|
userId: user.id,
|
|
59776
60077
|
slot,
|
|
59777
60078
|
accessoryComponentId
|
|
59778
60079
|
});
|
|
59779
60080
|
throw new InternalError("Failed to equip accessory");
|
|
59780
60081
|
}
|
|
59781
|
-
|
|
60082
|
+
logger28.info("Equipped accessory", {
|
|
59782
60083
|
userId: user.id,
|
|
59783
60084
|
slot,
|
|
59784
60085
|
accessoryComponentId
|
|
@@ -59799,7 +60100,7 @@ class CharacterService {
|
|
|
59799
60100
|
const playerLevel = userLevel?.currentLevel ?? 1;
|
|
59800
60101
|
const validation = validateAccessoryRemoval(slot, playerLevel);
|
|
59801
60102
|
if (!validation.isValid) {
|
|
59802
|
-
|
|
60103
|
+
logger28.warn("Accessory removal validation failed", {
|
|
59803
60104
|
userId: user.id,
|
|
59804
60105
|
slot,
|
|
59805
60106
|
playerLevel,
|
|
@@ -59808,17 +60109,17 @@ class CharacterService {
|
|
|
59808
60109
|
throw new ValidationError(validation.error ?? "Invalid accessory removal");
|
|
59809
60110
|
}
|
|
59810
60111
|
await db2.delete(playerCharacterAccessories).where(and(eq(playerCharacterAccessories.playerCharacterId, playerCharacter.id), eq(playerCharacterAccessories.slot, slot)));
|
|
59811
|
-
|
|
60112
|
+
logger28.info("Removed accessory", { userId: user.id, slot });
|
|
59812
60113
|
}
|
|
59813
60114
|
}
|
|
59814
|
-
var
|
|
60115
|
+
var logger28;
|
|
59815
60116
|
var init_character_service = __esm(() => {
|
|
59816
60117
|
init_drizzle_orm();
|
|
59817
60118
|
init_tables_index();
|
|
59818
60119
|
init_src2();
|
|
59819
60120
|
init_errors();
|
|
59820
60121
|
init_accessory_util();
|
|
59821
|
-
|
|
60122
|
+
logger28 = log.scope("CharacterService");
|
|
59822
60123
|
});
|
|
59823
60124
|
|
|
59824
60125
|
class CurrencyService {
|
|
@@ -59829,7 +60130,7 @@ class CurrencyService {
|
|
|
59829
60130
|
async list() {
|
|
59830
60131
|
const db2 = this.deps.db;
|
|
59831
60132
|
const allCurrencies = await db2.query.currencies.findMany();
|
|
59832
|
-
|
|
60133
|
+
logger29.debug("Listed currencies", { count: allCurrencies.length });
|
|
59833
60134
|
return allCurrencies;
|
|
59834
60135
|
}
|
|
59835
60136
|
async getById(currencyId) {
|
|
@@ -59840,7 +60141,7 @@ class CurrencyService {
|
|
|
59840
60141
|
if (!currency) {
|
|
59841
60142
|
throw new NotFoundError("Currency", currencyId);
|
|
59842
60143
|
}
|
|
59843
|
-
|
|
60144
|
+
logger29.debug("Retrieved currency", { currencyId });
|
|
59844
60145
|
return currency;
|
|
59845
60146
|
}
|
|
59846
60147
|
async create(data) {
|
|
@@ -59848,13 +60149,13 @@ class CurrencyService {
|
|
|
59848
60149
|
try {
|
|
59849
60150
|
const [newCurrency] = await db2.insert(currencies).values(data).returning();
|
|
59850
60151
|
if (!newCurrency) {
|
|
59851
|
-
|
|
60152
|
+
logger29.error("Currency insert returned no rows", {
|
|
59852
60153
|
itemId: data.itemId,
|
|
59853
60154
|
symbol: data.symbol
|
|
59854
60155
|
});
|
|
59855
60156
|
throw new InternalError("Failed to create currency");
|
|
59856
60157
|
}
|
|
59857
|
-
|
|
60158
|
+
logger29.info("Created currency", {
|
|
59858
60159
|
currencyId: newCurrency.id,
|
|
59859
60160
|
itemId: newCurrency.itemId,
|
|
59860
60161
|
symbol: newCurrency.symbol,
|
|
@@ -59883,7 +60184,7 @@ class CurrencyService {
|
|
|
59883
60184
|
if (!updatedCurrency) {
|
|
59884
60185
|
throw new NotFoundError("Currency", currencyId);
|
|
59885
60186
|
}
|
|
59886
|
-
|
|
60187
|
+
logger29.info("Updated currency", {
|
|
59887
60188
|
currencyId: updatedCurrency.id,
|
|
59888
60189
|
updatedFields: Object.keys(data)
|
|
59889
60190
|
});
|
|
@@ -59909,16 +60210,16 @@ class CurrencyService {
|
|
|
59909
60210
|
if (result.length === 0) {
|
|
59910
60211
|
throw new NotFoundError("Currency", currencyId);
|
|
59911
60212
|
}
|
|
59912
|
-
|
|
60213
|
+
logger29.info("Deleted currency", { currencyId });
|
|
59913
60214
|
}
|
|
59914
60215
|
}
|
|
59915
|
-
var
|
|
60216
|
+
var logger29;
|
|
59916
60217
|
var init_currency_service = __esm(() => {
|
|
59917
60218
|
init_drizzle_orm();
|
|
59918
60219
|
init_tables_index();
|
|
59919
60220
|
init_src2();
|
|
59920
60221
|
init_errors();
|
|
59921
|
-
|
|
60222
|
+
logger29 = log.scope("CurrencyService");
|
|
59922
60223
|
});
|
|
59923
60224
|
|
|
59924
60225
|
class LogsService {
|
|
@@ -59936,11 +60237,11 @@ class LogsService {
|
|
|
59936
60237
|
if (!game) {
|
|
59937
60238
|
throw new NotFoundError("Game", slug2);
|
|
59938
60239
|
}
|
|
59939
|
-
|
|
60240
|
+
logger30.info("Admin accessing game logs", { adminId: user.id, slug: slug2, sstStage });
|
|
59940
60241
|
} else {
|
|
59941
60242
|
const isApprovedDev = user.developerStatus === "approved";
|
|
59942
60243
|
if (!isApprovedDev) {
|
|
59943
|
-
|
|
60244
|
+
logger30.warn("Unapproved developer attempted log access", { userId: user.id, slug: slug2 });
|
|
59944
60245
|
throw new AccessDeniedError("Must be an approved developer");
|
|
59945
60246
|
}
|
|
59946
60247
|
const game = await db2.query.games.findFirst({
|
|
@@ -59955,7 +60256,7 @@ class LogsService {
|
|
|
59955
60256
|
columns: { id: true }
|
|
59956
60257
|
});
|
|
59957
60258
|
if (!membership) {
|
|
59958
|
-
|
|
60259
|
+
logger30.warn("Developer attempted access to unowned game logs", {
|
|
59959
60260
|
userId: user.id,
|
|
59960
60261
|
slug: slug2
|
|
59961
60262
|
});
|
|
@@ -59964,7 +60265,7 @@ class LogsService {
|
|
|
59964
60265
|
}
|
|
59965
60266
|
const workerId = getDeploymentId(slug2, sstStage);
|
|
59966
60267
|
const token = await this.deps.mintLogStreamToken(user.id, workerId);
|
|
59967
|
-
|
|
60268
|
+
logger30.debug("Generated log stream token", {
|
|
59968
60269
|
userId: user.id,
|
|
59969
60270
|
slug: slug2,
|
|
59970
60271
|
workerId
|
|
@@ -59972,14 +60273,14 @@ class LogsService {
|
|
|
59972
60273
|
return { token, workerId };
|
|
59973
60274
|
}
|
|
59974
60275
|
}
|
|
59975
|
-
var
|
|
60276
|
+
var logger30;
|
|
59976
60277
|
var init_logs_service = __esm(() => {
|
|
59977
60278
|
init_drizzle_orm();
|
|
59978
60279
|
init_tables_index();
|
|
59979
60280
|
init_src2();
|
|
59980
60281
|
init_errors();
|
|
59981
60282
|
init_deployment_util();
|
|
59982
|
-
|
|
60283
|
+
logger30 = log.scope("LogsService");
|
|
59983
60284
|
});
|
|
59984
60285
|
|
|
59985
60286
|
class LtiService {
|
|
@@ -60030,7 +60331,7 @@ class MapService {
|
|
|
60030
60331
|
if (!mapDetails) {
|
|
60031
60332
|
throw new NotFoundError("Map", identifier);
|
|
60032
60333
|
}
|
|
60033
|
-
|
|
60334
|
+
logger31.debug("Retrieved map", { identifier });
|
|
60034
60335
|
return mapDetails;
|
|
60035
60336
|
}
|
|
60036
60337
|
async getElements(mapId) {
|
|
@@ -60046,7 +60347,7 @@ class MapService {
|
|
|
60046
60347
|
}
|
|
60047
60348
|
}
|
|
60048
60349
|
});
|
|
60049
|
-
|
|
60350
|
+
logger31.debug("Retrieved elements", { mapId, count: elements.length });
|
|
60050
60351
|
return elements;
|
|
60051
60352
|
}
|
|
60052
60353
|
async getObjects(mapId, userId) {
|
|
@@ -60067,7 +60368,7 @@ class MapService {
|
|
|
60067
60368
|
}
|
|
60068
60369
|
}
|
|
60069
60370
|
});
|
|
60070
|
-
|
|
60371
|
+
logger31.debug("Retrieved objects", { mapId, userId, count: objects.length });
|
|
60071
60372
|
return objects.map((object) => this.formatMapObjectWithItem(object));
|
|
60072
60373
|
}
|
|
60073
60374
|
async createObject(mapId, data, user) {
|
|
@@ -60094,7 +60395,7 @@ class MapService {
|
|
|
60094
60395
|
throw new NotFoundError("Item", data.itemId);
|
|
60095
60396
|
}
|
|
60096
60397
|
if (!item.isPlaceable) {
|
|
60097
|
-
|
|
60398
|
+
logger31.warn("Attempted to place non-placeable item", {
|
|
60098
60399
|
userId: user.id,
|
|
60099
60400
|
itemId: data.itemId,
|
|
60100
60401
|
mapId
|
|
@@ -60108,7 +60409,7 @@ class MapService {
|
|
|
60108
60409
|
};
|
|
60109
60410
|
const [createdObject] = await db2.insert(mapObjects).values(objectData).returning();
|
|
60110
60411
|
if (!createdObject) {
|
|
60111
|
-
|
|
60412
|
+
logger31.error("Map object insert returned no rows", {
|
|
60112
60413
|
userId: user.id,
|
|
60113
60414
|
mapId,
|
|
60114
60415
|
itemId: data.itemId
|
|
@@ -60132,12 +60433,12 @@ class MapService {
|
|
|
60132
60433
|
}
|
|
60133
60434
|
});
|
|
60134
60435
|
if (!objectWithItem) {
|
|
60135
|
-
|
|
60436
|
+
logger31.error("Map object query after insert returned no rows", {
|
|
60136
60437
|
objectId: createdObject.id
|
|
60137
60438
|
});
|
|
60138
60439
|
throw new InternalError("Failed to retrieve created object");
|
|
60139
60440
|
}
|
|
60140
|
-
|
|
60441
|
+
logger31.info("Created object", {
|
|
60141
60442
|
userId: user.id,
|
|
60142
60443
|
mapId,
|
|
60143
60444
|
objectId: createdObject.id,
|
|
@@ -60161,7 +60462,7 @@ class MapService {
|
|
|
60161
60462
|
if (result.length === 0) {
|
|
60162
60463
|
throw new NotFoundError("MapObject", objectId);
|
|
60163
60464
|
}
|
|
60164
|
-
|
|
60465
|
+
logger31.info("Deleted object", {
|
|
60165
60466
|
userId: user.id,
|
|
60166
60467
|
mapId,
|
|
60167
60468
|
objectId
|
|
@@ -60190,13 +60491,13 @@ class MapService {
|
|
|
60190
60491
|
};
|
|
60191
60492
|
}
|
|
60192
60493
|
}
|
|
60193
|
-
var
|
|
60494
|
+
var logger31;
|
|
60194
60495
|
var init_map_service = __esm(() => {
|
|
60195
60496
|
init_drizzle_orm();
|
|
60196
60497
|
init_tables_index();
|
|
60197
60498
|
init_src2();
|
|
60198
60499
|
init_errors();
|
|
60199
|
-
|
|
60500
|
+
logger31 = log.scope("MapService");
|
|
60200
60501
|
});
|
|
60201
60502
|
|
|
60202
60503
|
class RealtimeService {
|
|
@@ -60230,20 +60531,20 @@ class RealtimeService {
|
|
|
60230
60531
|
}
|
|
60231
60532
|
const displayName = user.username || (user.name ? user.name.split(" ")[0] : undefined) || undefined;
|
|
60232
60533
|
const token = await this.deps.mintRealtimeToken(user.id, resolvedGameId, displayName, user.role);
|
|
60233
|
-
|
|
60534
|
+
logger32.info("Generated token", {
|
|
60234
60535
|
userId: user.id,
|
|
60235
60536
|
gameId: resolvedGameId || "global"
|
|
60236
60537
|
});
|
|
60237
60538
|
return { token };
|
|
60238
60539
|
}
|
|
60239
60540
|
}
|
|
60240
|
-
var
|
|
60541
|
+
var logger32;
|
|
60241
60542
|
var init_realtime_service = __esm(() => {
|
|
60242
60543
|
init_drizzle_orm();
|
|
60243
60544
|
init_tables_index();
|
|
60244
60545
|
init_src2();
|
|
60245
60546
|
init_errors();
|
|
60246
|
-
|
|
60547
|
+
logger32 = log.scope("RealtimeService");
|
|
60247
60548
|
});
|
|
60248
60549
|
|
|
60249
60550
|
class SessionService {
|
|
@@ -60277,10 +60578,10 @@ class SessionService {
|
|
|
60277
60578
|
};
|
|
60278
60579
|
const [newSession] = await db2.insert(gameSessions).values(sessionToInsert).returning({ sessionId: gameSessions.id });
|
|
60279
60580
|
if (!newSession?.sessionId) {
|
|
60280
|
-
|
|
60581
|
+
logger33.error("Game session insert returned no rows", { userId, gameId });
|
|
60281
60582
|
throw new InternalError("Failed to create game session");
|
|
60282
60583
|
}
|
|
60283
|
-
|
|
60584
|
+
logger33.info("Started new session", {
|
|
60284
60585
|
sessionId: newSession.sessionId,
|
|
60285
60586
|
gameId,
|
|
60286
60587
|
userId
|
|
@@ -60301,23 +60602,23 @@ class SessionService {
|
|
|
60301
60602
|
return { success: true, message: "Session already ended" };
|
|
60302
60603
|
}
|
|
60303
60604
|
await db2.update(gameSessions).set({ endedAt: new Date }).where(eq(gameSessions.id, sessionId));
|
|
60304
|
-
|
|
60605
|
+
logger33.info("Ended session", { sessionId, gameId, userId });
|
|
60305
60606
|
return { success: true };
|
|
60306
60607
|
}
|
|
60307
60608
|
async mintToken(gameIdOrSlug, userId) {
|
|
60308
60609
|
const gameId = await this.resolveGameId(gameIdOrSlug);
|
|
60309
60610
|
const result = await this.deps.mintGameToken(gameId, userId);
|
|
60310
|
-
|
|
60611
|
+
logger33.debug("Minted game token", { gameId, userId });
|
|
60311
60612
|
return result;
|
|
60312
60613
|
}
|
|
60313
60614
|
}
|
|
60314
|
-
var
|
|
60615
|
+
var logger33;
|
|
60315
60616
|
var init_session_service = __esm(() => {
|
|
60316
60617
|
init_drizzle_orm();
|
|
60317
60618
|
init_tables_index();
|
|
60318
60619
|
init_src2();
|
|
60319
60620
|
init_errors();
|
|
60320
|
-
|
|
60621
|
+
logger33 = log.scope("SessionService");
|
|
60321
60622
|
});
|
|
60322
60623
|
|
|
60323
60624
|
class ShopService {
|
|
@@ -60362,7 +60663,7 @@ class ShopService {
|
|
|
60362
60663
|
const shopItems = [];
|
|
60363
60664
|
for (const listing of listingsWithRelations) {
|
|
60364
60665
|
if (!listing.item || !listing.currency) {
|
|
60365
|
-
|
|
60666
|
+
logger34.warn("Listing missing item or currency, skipping", {
|
|
60366
60667
|
listingId: listing.id
|
|
60367
60668
|
});
|
|
60368
60669
|
} else {
|
|
@@ -60379,7 +60680,7 @@ class ShopService {
|
|
|
60379
60680
|
});
|
|
60380
60681
|
}
|
|
60381
60682
|
}
|
|
60382
|
-
|
|
60683
|
+
logger34.debug("Retrieved shop view", {
|
|
60383
60684
|
userId: user.id,
|
|
60384
60685
|
itemCount: shopItems.length,
|
|
60385
60686
|
currencyCount: shopCurrencies.length
|
|
@@ -60390,12 +60691,12 @@ class ShopService {
|
|
|
60390
60691
|
};
|
|
60391
60692
|
}
|
|
60392
60693
|
}
|
|
60393
|
-
var
|
|
60694
|
+
var logger34;
|
|
60394
60695
|
var init_shop_service = __esm(() => {
|
|
60395
60696
|
init_drizzle_orm();
|
|
60396
60697
|
init_tables_index();
|
|
60397
60698
|
init_src2();
|
|
60398
|
-
|
|
60699
|
+
logger34 = log.scope("ShopService");
|
|
60399
60700
|
});
|
|
60400
60701
|
|
|
60401
60702
|
class SpriteService {
|
|
@@ -60411,17 +60712,17 @@ class SpriteService {
|
|
|
60411
60712
|
if (!template) {
|
|
60412
60713
|
throw new NotFoundError("SpriteTemplate", slug2);
|
|
60413
60714
|
}
|
|
60414
|
-
|
|
60715
|
+
logger35.debug("Retrieved sprite", { slug: slug2 });
|
|
60415
60716
|
return template;
|
|
60416
60717
|
}
|
|
60417
60718
|
}
|
|
60418
|
-
var
|
|
60719
|
+
var logger35;
|
|
60419
60720
|
var init_sprite_service = __esm(() => {
|
|
60420
60721
|
init_drizzle_orm();
|
|
60421
60722
|
init_tables_index();
|
|
60422
60723
|
init_src2();
|
|
60423
60724
|
init_errors();
|
|
60424
|
-
|
|
60725
|
+
logger35 = log.scope("SpriteService");
|
|
60425
60726
|
});
|
|
60426
60727
|
|
|
60427
60728
|
class UserService {
|
|
@@ -60435,12 +60736,12 @@ class UserService {
|
|
|
60435
60736
|
where: eq(users.id, user.id)
|
|
60436
60737
|
});
|
|
60437
60738
|
if (!userData) {
|
|
60438
|
-
|
|
60739
|
+
logger36.error("User not found", { userId: user.id });
|
|
60439
60740
|
throw new NotFoundError("User", user.id);
|
|
60440
60741
|
}
|
|
60441
60742
|
const timeback2 = userData.timebackId ? await this.fetchTimebackData(userData.timebackId, gameId) : undefined;
|
|
60442
60743
|
if (gameId) {
|
|
60443
|
-
|
|
60744
|
+
logger36.debug("Fetched user profile (game context)", { userId: user.id, gameId });
|
|
60444
60745
|
return {
|
|
60445
60746
|
id: userData.id,
|
|
60446
60747
|
name: userData.name,
|
|
@@ -60453,7 +60754,7 @@ class UserService {
|
|
|
60453
60754
|
const timebackAccount = await db2.query.accounts.findFirst({
|
|
60454
60755
|
where: and(eq(accounts.userId, user.id), eq(accounts.providerId, "timeback"))
|
|
60455
60756
|
});
|
|
60456
|
-
|
|
60757
|
+
logger36.debug("Fetched user profile (platform context)", { userId: user.id });
|
|
60457
60758
|
return {
|
|
60458
60759
|
id: userData.id,
|
|
60459
60760
|
name: userData.name,
|
|
@@ -60476,7 +60777,7 @@ class UserService {
|
|
|
60476
60777
|
columns: { name: true }
|
|
60477
60778
|
});
|
|
60478
60779
|
if (!userData) {
|
|
60479
|
-
|
|
60780
|
+
logger36.error("Demo user not found", { userId });
|
|
60480
60781
|
throw new NotFoundError("User", userId);
|
|
60481
60782
|
}
|
|
60482
60783
|
return {
|
|
@@ -60490,10 +60791,10 @@ class UserService {
|
|
|
60490
60791
|
updatedAt: new Date
|
|
60491
60792
|
}).where(eq(users.id, userId)).returning({ name: users.name });
|
|
60492
60793
|
if (!updatedUser) {
|
|
60493
|
-
|
|
60794
|
+
logger36.error("Demo user not found for profile update", { userId });
|
|
60494
60795
|
throw new NotFoundError("User", userId);
|
|
60495
60796
|
}
|
|
60496
|
-
|
|
60797
|
+
logger36.debug("Updated demo profile", { userId, displayName });
|
|
60497
60798
|
return {
|
|
60498
60799
|
displayName: updatedUser.name,
|
|
60499
60800
|
isDefault: updatedUser.name === DEMO_DISPLAY_NAME_PLACEHOLDER
|
|
@@ -60506,7 +60807,7 @@ class UserService {
|
|
|
60506
60807
|
]);
|
|
60507
60808
|
const enrollments = gameId ? this.filterEnrollmentsByGame(allEnrollments, gameId) : allEnrollments;
|
|
60508
60809
|
const organizations = gameId ? this.filterOrganizationsByEnrollments(allOrganizations, enrollments) : allOrganizations;
|
|
60509
|
-
|
|
60810
|
+
logger36.debug("Fetched Timeback data", {
|
|
60510
60811
|
timebackId,
|
|
60511
60812
|
role,
|
|
60512
60813
|
enrollmentCount: enrollments.length,
|
|
@@ -60515,9 +60816,9 @@ class UserService {
|
|
|
60515
60816
|
return { id: timebackId, role, enrollments, organizations };
|
|
60516
60817
|
}
|
|
60517
60818
|
async fetchStudentProfile(timebackId) {
|
|
60518
|
-
|
|
60819
|
+
logger36.debug("Fetching student profile", { timebackId });
|
|
60519
60820
|
if (!this.deps.timeback) {
|
|
60520
|
-
|
|
60821
|
+
logger36.warn("Timeback client not available");
|
|
60521
60822
|
return { role: "student", organizations: [] };
|
|
60522
60823
|
}
|
|
60523
60824
|
try {
|
|
@@ -60545,14 +60846,14 @@ class UserService {
|
|
|
60545
60846
|
}
|
|
60546
60847
|
return { role, organizations: [...orgMap.values()] };
|
|
60547
60848
|
} catch (error) {
|
|
60548
|
-
|
|
60849
|
+
logger36.warn("Failed to fetch student profile", { error, timebackId });
|
|
60549
60850
|
return { role: "student", organizations: [] };
|
|
60550
60851
|
}
|
|
60551
60852
|
}
|
|
60552
60853
|
async fetchEnrollments(timebackId) {
|
|
60553
|
-
|
|
60854
|
+
logger36.debug("Fetching enrollments", { timebackId });
|
|
60554
60855
|
if (!this.deps.timeback) {
|
|
60555
|
-
|
|
60856
|
+
logger36.warn("Timeback client not available");
|
|
60556
60857
|
return [];
|
|
60557
60858
|
}
|
|
60558
60859
|
try {
|
|
@@ -60573,7 +60874,7 @@ class UserService {
|
|
|
60573
60874
|
orgId: courseToSchool.get(i2.courseId)
|
|
60574
60875
|
}));
|
|
60575
60876
|
} catch (error) {
|
|
60576
|
-
|
|
60877
|
+
logger36.warn("Failed to fetch enrollments", { error, timebackId });
|
|
60577
60878
|
return [];
|
|
60578
60879
|
}
|
|
60579
60880
|
}
|
|
@@ -60588,14 +60889,14 @@ class UserService {
|
|
|
60588
60889
|
return organizations.filter((o) => enrollmentOrgIds.has(o.id));
|
|
60589
60890
|
}
|
|
60590
60891
|
}
|
|
60591
|
-
var
|
|
60892
|
+
var logger36;
|
|
60592
60893
|
var init_user_service = __esm(() => {
|
|
60593
60894
|
init_drizzle_orm();
|
|
60594
60895
|
init_src();
|
|
60595
60896
|
init_tables_index();
|
|
60596
60897
|
init_src2();
|
|
60597
60898
|
init_errors();
|
|
60598
|
-
|
|
60899
|
+
logger36 = log.scope("UserService");
|
|
60599
60900
|
});
|
|
60600
60901
|
|
|
60601
60902
|
class VerifyService {
|
|
@@ -60604,16 +60905,16 @@ class VerifyService {
|
|
|
60604
60905
|
this.deps = deps;
|
|
60605
60906
|
}
|
|
60606
60907
|
async verifyGameToken(token) {
|
|
60607
|
-
|
|
60908
|
+
logger37.debug("Verifying game token");
|
|
60608
60909
|
const payload = await this.deps.validateGameToken(token);
|
|
60609
60910
|
if (!payload) {
|
|
60610
|
-
|
|
60911
|
+
logger37.warn("Invalid or expired game token presented");
|
|
60611
60912
|
throw new ValidationError("Invalid or expired token");
|
|
60612
60913
|
}
|
|
60613
60914
|
const gameId = payload.sub;
|
|
60614
60915
|
const userId = payload.uid;
|
|
60615
60916
|
if (typeof gameId !== "string" || typeof userId !== "string") {
|
|
60616
|
-
|
|
60917
|
+
logger37.warn("Game token missing required claims", {
|
|
60617
60918
|
hasGameId: typeof gameId === "string",
|
|
60618
60919
|
hasUserId: typeof userId === "string"
|
|
60619
60920
|
});
|
|
@@ -60624,7 +60925,7 @@ class VerifyService {
|
|
|
60624
60925
|
where: eq(users.id, userId)
|
|
60625
60926
|
});
|
|
60626
60927
|
if (!userData) {
|
|
60627
|
-
|
|
60928
|
+
logger37.error("User not found for valid token", {
|
|
60628
60929
|
userId
|
|
60629
60930
|
});
|
|
60630
60931
|
throw new NotFoundError("User", userId);
|
|
@@ -60638,7 +60939,7 @@ class VerifyService {
|
|
|
60638
60939
|
family_name: undefined,
|
|
60639
60940
|
timeback_id: userData.timebackId || undefined
|
|
60640
60941
|
};
|
|
60641
|
-
|
|
60942
|
+
logger37.info("Token verified", { gameId, userId });
|
|
60642
60943
|
return {
|
|
60643
60944
|
claims: payload,
|
|
60644
60945
|
gameId,
|
|
@@ -60646,13 +60947,13 @@ class VerifyService {
|
|
|
60646
60947
|
};
|
|
60647
60948
|
}
|
|
60648
60949
|
}
|
|
60649
|
-
var
|
|
60950
|
+
var logger37;
|
|
60650
60951
|
var init_verify_service = __esm(() => {
|
|
60651
60952
|
init_drizzle_orm();
|
|
60652
60953
|
init_tables_index();
|
|
60653
60954
|
init_src2();
|
|
60654
60955
|
init_errors();
|
|
60655
|
-
|
|
60956
|
+
logger37 = log.scope("VerifyService");
|
|
60656
60957
|
});
|
|
60657
60958
|
function createStandaloneServices(deps) {
|
|
60658
60959
|
const { db: db2, auth: auth2, timeback: timeback2 } = deps;
|
|
@@ -65784,7 +66085,7 @@ var colorStatus = async (status) => {
|
|
|
65784
66085
|
}
|
|
65785
66086
|
return `${status}`;
|
|
65786
66087
|
};
|
|
65787
|
-
var
|
|
66088
|
+
var logger38 = (fn = console.log) => {
|
|
65788
66089
|
return async function logger2(c, next) {
|
|
65789
66090
|
const { method, url: url2 } = c.req;
|
|
65790
66091
|
const path2 = url2.slice(url2.indexOf("/", 8));
|
|
@@ -65961,7 +66262,7 @@ function createApp(db2, options) {
|
|
|
65961
66262
|
const app = new Hono2;
|
|
65962
66263
|
app.use("*", cors({ origin: "*", credentials: true }));
|
|
65963
66264
|
if (options.verbose && !options.quiet) {
|
|
65964
|
-
app.use("*",
|
|
66265
|
+
app.use("*", logger38());
|
|
65965
66266
|
}
|
|
65966
66267
|
app.use("/api/*", async (c, next) => {
|
|
65967
66268
|
c.set("db", db2);
|
|
@@ -72663,12 +72964,12 @@ var init_session2 = __esm(() => {
|
|
|
72663
72964
|
init_utils();
|
|
72664
72965
|
init_dist5();
|
|
72665
72966
|
PglitePreparedQuery = class PglitePreparedQuery2 extends PgPreparedQuery {
|
|
72666
|
-
constructor(client, queryString, params,
|
|
72967
|
+
constructor(client, queryString, params, logger39, fields, name3, _isResponseInArrayMode, customResultMapper) {
|
|
72667
72968
|
super({ sql: queryString, params });
|
|
72668
72969
|
this.client = client;
|
|
72669
72970
|
this.queryString = queryString;
|
|
72670
72971
|
this.params = params;
|
|
72671
|
-
this.logger =
|
|
72972
|
+
this.logger = logger39;
|
|
72672
72973
|
this.fields = fields;
|
|
72673
72974
|
this._isResponseInArrayMode = _isResponseInArrayMode;
|
|
72674
72975
|
this.customResultMapper = customResultMapper;
|
|
@@ -72770,11 +73071,11 @@ var init_session2 = __esm(() => {
|
|
|
72770
73071
|
});
|
|
72771
73072
|
function construct(client, config2 = {}) {
|
|
72772
73073
|
const dialect2 = new PgDialect({ casing: config2.casing });
|
|
72773
|
-
let
|
|
73074
|
+
let logger39;
|
|
72774
73075
|
if (config2.logger === true) {
|
|
72775
|
-
|
|
73076
|
+
logger39 = new DefaultLogger;
|
|
72776
73077
|
} else if (config2.logger !== false) {
|
|
72777
|
-
|
|
73078
|
+
logger39 = config2.logger;
|
|
72778
73079
|
}
|
|
72779
73080
|
let schema2;
|
|
72780
73081
|
if (config2.schema) {
|
|
@@ -72785,7 +73086,7 @@ function construct(client, config2 = {}) {
|
|
|
72785
73086
|
tableNamesMap: tablesConfig.tableNamesMap
|
|
72786
73087
|
};
|
|
72787
73088
|
}
|
|
72788
|
-
const driver = new PgliteDriver(client, dialect2, { logger:
|
|
73089
|
+
const driver = new PgliteDriver(client, dialect2, { logger: logger39 });
|
|
72789
73090
|
const session2 = driver.createSession(schema2);
|
|
72790
73091
|
const db2 = new PgliteDatabase(dialect2, session2, schema2);
|
|
72791
73092
|
db2.$client = client;
|
|
@@ -121390,8 +121691,8 @@ var init_currencies = __esm(() => {
|
|
|
121390
121691
|
init_tables_index();
|
|
121391
121692
|
init_constants();
|
|
121392
121693
|
});
|
|
121393
|
-
function setLogger(
|
|
121394
|
-
customLogger =
|
|
121694
|
+
function setLogger(logger39) {
|
|
121695
|
+
customLogger = logger39;
|
|
121395
121696
|
}
|
|
121396
121697
|
function getLogger() {
|
|
121397
121698
|
if (customLogger) {
|
|
@@ -121404,10 +121705,10 @@ function getLogger() {
|
|
|
121404
121705
|
};
|
|
121405
121706
|
}
|
|
121406
121707
|
var customLogger;
|
|
121407
|
-
var
|
|
121708
|
+
var logger39;
|
|
121408
121709
|
var init_adapter = __esm(() => {
|
|
121409
121710
|
init_config();
|
|
121410
|
-
|
|
121711
|
+
logger39 = {
|
|
121411
121712
|
info: (msg) => {
|
|
121412
121713
|
if (customLogger || !config.embedded) {
|
|
121413
121714
|
getLogger().info(msg);
|
|
@@ -121491,7 +121792,7 @@ async function seedCoreGames(db2) {
|
|
|
121491
121792
|
role: "owner"
|
|
121492
121793
|
}).onConflictDoNothing();
|
|
121493
121794
|
} catch (error2) {
|
|
121494
|
-
|
|
121795
|
+
logger39.error(`Error seeding core game '${gameData.slug}': ${error2}`);
|
|
121495
121796
|
}
|
|
121496
121797
|
}
|
|
121497
121798
|
}
|
|
@@ -121541,7 +121842,7 @@ async function seedCurrentProjectGame(db2, project) {
|
|
|
121541
121842
|
}
|
|
121542
121843
|
return newGame;
|
|
121543
121844
|
} catch (error2) {
|
|
121544
|
-
|
|
121845
|
+
logger39.error(`❌ Error seeding project game: ${error2}`);
|
|
121545
121846
|
throw error2;
|
|
121546
121847
|
}
|
|
121547
121848
|
}
|
|
@@ -122304,7 +122605,7 @@ async function provisionLtiUser(db2, claims) {
|
|
|
122304
122605
|
where: eq(users.id, existingAccount.userId)
|
|
122305
122606
|
});
|
|
122306
122607
|
if (user) {
|
|
122307
|
-
|
|
122608
|
+
logger40.info("Found user by LTI account", {
|
|
122308
122609
|
userId: user.id,
|
|
122309
122610
|
ltiTimebackId
|
|
122310
122611
|
});
|
|
@@ -122333,13 +122634,13 @@ async function provisionLtiUser(db2, claims) {
|
|
|
122333
122634
|
updatedAt: new Date
|
|
122334
122635
|
}).returning({ id: accounts.id });
|
|
122335
122636
|
if (!account) {
|
|
122336
|
-
|
|
122637
|
+
logger40.error("LTI account link insert returned no rows", {
|
|
122337
122638
|
userId: existingUser.id,
|
|
122338
122639
|
ltiTimebackId
|
|
122339
122640
|
});
|
|
122340
122641
|
throw new InternalError("Failed to link LTI account");
|
|
122341
122642
|
}
|
|
122342
|
-
|
|
122643
|
+
logger40.info("Linked LTI account to existing user", {
|
|
122343
122644
|
userId: existingUser.id,
|
|
122344
122645
|
ltiTimebackId
|
|
122345
122646
|
});
|
|
@@ -122359,7 +122660,7 @@ async function provisionLtiUser(db2, claims) {
|
|
|
122359
122660
|
updatedAt: new Date
|
|
122360
122661
|
}).returning();
|
|
122361
122662
|
if (!insertedUser) {
|
|
122362
|
-
|
|
122663
|
+
logger40.error("LTI user insert returned no rows", { email, ltiTimebackId });
|
|
122363
122664
|
throw new InternalError("Failed to create user");
|
|
122364
122665
|
}
|
|
122365
122666
|
await tx.insert(accounts).values({
|
|
@@ -122374,7 +122675,7 @@ async function provisionLtiUser(db2, claims) {
|
|
|
122374
122675
|
createdAt: new Date,
|
|
122375
122676
|
updatedAt: new Date
|
|
122376
122677
|
});
|
|
122377
|
-
|
|
122678
|
+
logger40.info("Provisioned new user from LTI", {
|
|
122378
122679
|
userId: insertedUser.id,
|
|
122379
122680
|
ltiTimebackId
|
|
122380
122681
|
});
|
|
@@ -122382,7 +122683,7 @@ async function provisionLtiUser(db2, claims) {
|
|
|
122382
122683
|
});
|
|
122383
122684
|
return createdUser;
|
|
122384
122685
|
}
|
|
122385
|
-
var
|
|
122686
|
+
var logger40;
|
|
122386
122687
|
var init_lti_provisioning = __esm(() => {
|
|
122387
122688
|
init_drizzle_orm();
|
|
122388
122689
|
init_src();
|
|
@@ -122390,7 +122691,7 @@ var init_lti_provisioning = __esm(() => {
|
|
|
122390
122691
|
init_src2();
|
|
122391
122692
|
init_errors();
|
|
122392
122693
|
init_lti_util();
|
|
122393
|
-
|
|
122694
|
+
logger40 = log.scope("LtiProvisioning");
|
|
122394
122695
|
});
|
|
122395
122696
|
function formatZodError(error2) {
|
|
122396
122697
|
const flat = error2.flatten();
|
|
@@ -122433,7 +122734,7 @@ var init_utils11 = __esm(() => {
|
|
|
122433
122734
|
init_timeback_util();
|
|
122434
122735
|
init_validation_util();
|
|
122435
122736
|
});
|
|
122436
|
-
var
|
|
122737
|
+
var logger41;
|
|
122437
122738
|
var listCurrent;
|
|
122438
122739
|
var listHistory;
|
|
122439
122740
|
var postProgress;
|
|
@@ -122444,14 +122745,14 @@ var init_achievement_controller = __esm(() => {
|
|
|
122444
122745
|
init_src2();
|
|
122445
122746
|
init_errors();
|
|
122446
122747
|
init_utils11();
|
|
122447
|
-
|
|
122748
|
+
logger41 = log.scope("AchievementController");
|
|
122448
122749
|
listCurrent = requireNonAnonymous(async (ctx) => {
|
|
122449
|
-
|
|
122750
|
+
logger41.debug("Listing current achievements", { userId: ctx.user.id, gameId: ctx.gameId });
|
|
122450
122751
|
return ctx.services.achievement.listCurrent(ctx.user, ctx.gameId);
|
|
122451
122752
|
});
|
|
122452
122753
|
listHistory = requireNonAnonymous(async (ctx) => {
|
|
122453
122754
|
const limit = Math.max(1, Math.min(100, Number(ctx.url.searchParams.get("limit")) || 20));
|
|
122454
|
-
|
|
122755
|
+
logger41.debug("Listing achievement history", { userId: ctx.user.id, limit });
|
|
122455
122756
|
return ctx.services.achievement.listHistory(ctx.user, limit);
|
|
122456
122757
|
});
|
|
122457
122758
|
postProgress = requireNonAnonymous(async (ctx) => {
|
|
@@ -122462,12 +122763,12 @@ var init_achievement_controller = __esm(() => {
|
|
|
122462
122763
|
} catch (error2) {
|
|
122463
122764
|
if (error2 instanceof exports_external.ZodError) {
|
|
122464
122765
|
const details = formatZodError(error2);
|
|
122465
|
-
|
|
122766
|
+
logger41.warn("Submit achievement progress validation failed", { details });
|
|
122466
122767
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
122467
122768
|
}
|
|
122468
122769
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122469
122770
|
}
|
|
122470
|
-
|
|
122771
|
+
logger41.debug("Submitting progress", {
|
|
122471
122772
|
userId: ctx.user.id,
|
|
122472
122773
|
achievementId: body2.achievementId
|
|
122473
122774
|
});
|
|
@@ -122479,15 +122780,15 @@ var init_achievement_controller = __esm(() => {
|
|
|
122479
122780
|
postProgress
|
|
122480
122781
|
};
|
|
122481
122782
|
});
|
|
122482
|
-
var
|
|
122783
|
+
var logger42;
|
|
122483
122784
|
var getAllowedOrigins;
|
|
122484
122785
|
var init_admin_controller = __esm(() => {
|
|
122485
122786
|
init_src2();
|
|
122486
122787
|
init_utils11();
|
|
122487
|
-
|
|
122788
|
+
logger42 = log.scope("AdminController");
|
|
122488
122789
|
getAllowedOrigins = requireAdmin(async (ctx) => {
|
|
122489
122790
|
const shouldRefresh = ctx.url.searchParams.get("refresh") === "true";
|
|
122490
|
-
|
|
122791
|
+
logger42.debug("Getting allowed origins", { userId: ctx.user.id, refresh: shouldRefresh });
|
|
122491
122792
|
if (shouldRefresh) {
|
|
122492
122793
|
await ctx.providers.cache.refreshGameOrigins();
|
|
122493
122794
|
}
|
|
@@ -122500,7 +122801,7 @@ var init_admin_controller = __esm(() => {
|
|
|
122500
122801
|
};
|
|
122501
122802
|
});
|
|
122502
122803
|
});
|
|
122503
|
-
var
|
|
122804
|
+
var logger43;
|
|
122504
122805
|
var listFiles;
|
|
122505
122806
|
var getFile;
|
|
122506
122807
|
var putFile;
|
|
@@ -122512,7 +122813,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
122512
122813
|
init_src2();
|
|
122513
122814
|
init_errors();
|
|
122514
122815
|
init_utils11();
|
|
122515
|
-
|
|
122816
|
+
logger43 = log.scope("BucketController");
|
|
122516
122817
|
listFiles = requireDeveloper(async (ctx) => {
|
|
122517
122818
|
const slug2 = ctx.params.slug;
|
|
122518
122819
|
if (!slug2) {
|
|
@@ -122520,7 +122821,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
122520
122821
|
}
|
|
122521
122822
|
const url2 = ctx.url;
|
|
122522
122823
|
const prefix2 = url2.searchParams.get("prefix") || undefined;
|
|
122523
|
-
|
|
122824
|
+
logger43.debug("Listing files", { userId: ctx.user.id, slug: slug2, prefix: prefix2 });
|
|
122524
122825
|
const files = await ctx.services.bucket.listFiles(slug2, ctx.user, prefix2);
|
|
122525
122826
|
return { files };
|
|
122526
122827
|
});
|
|
@@ -122530,7 +122831,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
122530
122831
|
if (!slug2 || !key) {
|
|
122531
122832
|
throw ApiError.badRequest("Missing game slug or file key");
|
|
122532
122833
|
}
|
|
122533
|
-
|
|
122834
|
+
logger43.debug("Getting file", { userId: ctx.user.id, slug: slug2, key });
|
|
122534
122835
|
const object = await ctx.services.bucket.getFile(slug2, key, ctx.user);
|
|
122535
122836
|
return new Response(Buffer.from(object.body), {
|
|
122536
122837
|
status: 200,
|
|
@@ -122549,7 +122850,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
122549
122850
|
const arrayBuffer = await ctx.request.arrayBuffer();
|
|
122550
122851
|
const body2 = new Uint8Array(arrayBuffer);
|
|
122551
122852
|
const contentType = ctx.request.headers.get("content-type") || undefined;
|
|
122552
|
-
|
|
122853
|
+
logger43.debug("Uploading file", {
|
|
122553
122854
|
userId: ctx.user.id,
|
|
122554
122855
|
slug: slug2,
|
|
122555
122856
|
key,
|
|
@@ -122565,7 +122866,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
122565
122866
|
if (!slug2 || !key) {
|
|
122566
122867
|
throw ApiError.badRequest("Missing game slug or file key");
|
|
122567
122868
|
}
|
|
122568
|
-
|
|
122869
|
+
logger43.debug("Deleting file", { userId: ctx.user.id, slug: slug2, key });
|
|
122569
122870
|
await ctx.services.bucket.deleteFile(slug2, key, ctx.user);
|
|
122570
122871
|
return { success: true, key };
|
|
122571
122872
|
});
|
|
@@ -122577,12 +122878,12 @@ var init_bucket_controller = __esm(() => {
|
|
|
122577
122878
|
} catch (error2) {
|
|
122578
122879
|
if (error2 instanceof exports_external.ZodError) {
|
|
122579
122880
|
const details = formatZodError(error2);
|
|
122580
|
-
|
|
122881
|
+
logger43.warn("Initiate upload validation failed", { details });
|
|
122581
122882
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
122582
122883
|
}
|
|
122583
122884
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122584
122885
|
}
|
|
122585
|
-
|
|
122886
|
+
logger43.debug("Initiating multipart upload", {
|
|
122586
122887
|
userId: ctx.user.id,
|
|
122587
122888
|
gameId: body2.gameId,
|
|
122588
122889
|
fileName: body2.fileName
|
|
@@ -122597,10 +122898,10 @@ async function listComponents(ctx) {
|
|
|
122597
122898
|
if (!isNaN(parsed) && isFinite(parsed)) {
|
|
122598
122899
|
level = Math.floor(Math.max(0, parsed));
|
|
122599
122900
|
}
|
|
122600
|
-
|
|
122901
|
+
logger44.debug("Listing components", { level });
|
|
122601
122902
|
return ctx.services.character.listAvailableComponents(level);
|
|
122602
122903
|
}
|
|
122603
|
-
var
|
|
122904
|
+
var logger44;
|
|
122604
122905
|
var get;
|
|
122605
122906
|
var getByUserId;
|
|
122606
122907
|
var create;
|
|
@@ -122614,9 +122915,9 @@ var init_character_controller = __esm(() => {
|
|
|
122614
122915
|
init_src2();
|
|
122615
122916
|
init_errors();
|
|
122616
122917
|
init_utils11();
|
|
122617
|
-
|
|
122918
|
+
logger44 = log.scope("CharacterController");
|
|
122618
122919
|
get = requireNonAnonymous(async (ctx) => {
|
|
122619
|
-
|
|
122920
|
+
logger44.debug("Getting character", { userId: ctx.user.id });
|
|
122620
122921
|
return ctx.services.character.getByUser(ctx.user);
|
|
122621
122922
|
});
|
|
122622
122923
|
getByUserId = requireNonAnonymous(async (ctx) => {
|
|
@@ -122624,7 +122925,7 @@ var init_character_controller = __esm(() => {
|
|
|
122624
122925
|
if (!userId) {
|
|
122625
122926
|
throw ApiError.badRequest("User ID is required in the URL path");
|
|
122626
122927
|
}
|
|
122627
|
-
|
|
122928
|
+
logger44.debug("Getting character by user ID", { requestedUserId: userId });
|
|
122628
122929
|
return ctx.services.character.getByUserId(userId);
|
|
122629
122930
|
});
|
|
122630
122931
|
create = requireNonAnonymous(async (ctx) => {
|
|
@@ -122635,12 +122936,12 @@ var init_character_controller = __esm(() => {
|
|
|
122635
122936
|
} catch (error2) {
|
|
122636
122937
|
if (error2 instanceof exports_external.ZodError) {
|
|
122637
122938
|
const details = formatZodError(error2);
|
|
122638
|
-
|
|
122939
|
+
logger44.warn("Create character validation failed", { details });
|
|
122639
122940
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
122640
122941
|
}
|
|
122641
122942
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122642
122943
|
}
|
|
122643
|
-
|
|
122944
|
+
logger44.debug("Creating character", {
|
|
122644
122945
|
userId: ctx.user.id,
|
|
122645
122946
|
bodyComponentId: body2.bodyComponentId,
|
|
122646
122947
|
hairstyleComponentId: body2.hairstyleComponentId
|
|
@@ -122655,12 +122956,12 @@ var init_character_controller = __esm(() => {
|
|
|
122655
122956
|
} catch (error2) {
|
|
122656
122957
|
if (error2 instanceof exports_external.ZodError) {
|
|
122657
122958
|
const details = formatZodError(error2);
|
|
122658
|
-
|
|
122959
|
+
logger44.warn("Update character validation failed", { details });
|
|
122659
122960
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
122660
122961
|
}
|
|
122661
122962
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122662
122963
|
}
|
|
122663
|
-
|
|
122964
|
+
logger44.debug("Updating character", {
|
|
122664
122965
|
userId: ctx.user.id,
|
|
122665
122966
|
bodyComponentId: body2.bodyComponentId,
|
|
122666
122967
|
hairstyleComponentId: body2.hairstyleComponentId,
|
|
@@ -122676,12 +122977,12 @@ var init_character_controller = __esm(() => {
|
|
|
122676
122977
|
} catch (error2) {
|
|
122677
122978
|
if (error2 instanceof exports_external.ZodError) {
|
|
122678
122979
|
const details = formatZodError(error2);
|
|
122679
|
-
|
|
122980
|
+
logger44.warn("Equip accessory validation failed", { details });
|
|
122680
122981
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
122681
122982
|
}
|
|
122682
122983
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122683
122984
|
}
|
|
122684
|
-
|
|
122985
|
+
logger44.debug("Equipping accessory", {
|
|
122685
122986
|
userId: ctx.user.id,
|
|
122686
122987
|
slot: body2.slot,
|
|
122687
122988
|
accessoryComponentId: body2.accessoryComponentId
|
|
@@ -122693,7 +122994,7 @@ var init_character_controller = __esm(() => {
|
|
|
122693
122994
|
if (!slot) {
|
|
122694
122995
|
throw ApiError.badRequest("Slot is required in the URL path");
|
|
122695
122996
|
}
|
|
122696
|
-
|
|
122997
|
+
logger44.debug("Removing accessory", { userId: ctx.user.id, slot });
|
|
122697
122998
|
await ctx.services.character.removeAccessory(slot, ctx.user);
|
|
122698
122999
|
return { success: true };
|
|
122699
123000
|
});
|
|
@@ -122707,7 +123008,7 @@ var init_character_controller = __esm(() => {
|
|
|
122707
123008
|
removeAccessory
|
|
122708
123009
|
};
|
|
122709
123010
|
});
|
|
122710
|
-
var
|
|
123011
|
+
var logger45;
|
|
122711
123012
|
var list;
|
|
122712
123013
|
var getById;
|
|
122713
123014
|
var create2;
|
|
@@ -122721,9 +123022,9 @@ var init_currency_controller = __esm(() => {
|
|
|
122721
123022
|
init_src4();
|
|
122722
123023
|
init_errors();
|
|
122723
123024
|
init_utils11();
|
|
122724
|
-
|
|
123025
|
+
logger45 = log.scope("CurrencyController");
|
|
122725
123026
|
list = requireNonAnonymous(async (ctx) => {
|
|
122726
|
-
|
|
123027
|
+
logger45.debug("Listing currencies", { userId: ctx.user.id });
|
|
122727
123028
|
return ctx.services.currency.list();
|
|
122728
123029
|
});
|
|
122729
123030
|
getById = requireNonAnonymous(async (ctx) => {
|
|
@@ -122734,7 +123035,7 @@ var init_currency_controller = __esm(() => {
|
|
|
122734
123035
|
if (!isValidUUID(currencyId)) {
|
|
122735
123036
|
throw ApiError.unprocessableEntity("currencyId must be a valid UUID format");
|
|
122736
123037
|
}
|
|
122737
|
-
|
|
123038
|
+
logger45.debug("Getting currency", { userId: ctx.user.id, currencyId });
|
|
122738
123039
|
return ctx.services.currency.getById(currencyId);
|
|
122739
123040
|
});
|
|
122740
123041
|
create2 = requireAdmin(async (ctx) => {
|
|
@@ -122745,12 +123046,12 @@ var init_currency_controller = __esm(() => {
|
|
|
122745
123046
|
} catch (error2) {
|
|
122746
123047
|
if (error2 instanceof exports_external.ZodError) {
|
|
122747
123048
|
const details = formatZodError(error2);
|
|
122748
|
-
|
|
123049
|
+
logger45.warn("Create currency validation failed", { details });
|
|
122749
123050
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
122750
123051
|
}
|
|
122751
123052
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122752
123053
|
}
|
|
122753
|
-
|
|
123054
|
+
logger45.debug("Creating currency", {
|
|
122754
123055
|
userId: ctx.user.id,
|
|
122755
123056
|
symbol: body2.symbol,
|
|
122756
123057
|
itemId: body2.itemId,
|
|
@@ -122773,12 +123074,12 @@ var init_currency_controller = __esm(() => {
|
|
|
122773
123074
|
} catch (error2) {
|
|
122774
123075
|
if (error2 instanceof exports_external.ZodError) {
|
|
122775
123076
|
const details = formatZodError(error2);
|
|
122776
|
-
|
|
123077
|
+
logger45.warn("Update currency validation failed", { details });
|
|
122777
123078
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
122778
123079
|
}
|
|
122779
123080
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122780
123081
|
}
|
|
122781
|
-
|
|
123082
|
+
logger45.debug("Updating currency", {
|
|
122782
123083
|
userId: ctx.user.id,
|
|
122783
123084
|
currencyId,
|
|
122784
123085
|
symbol: body2.symbol,
|
|
@@ -122795,7 +123096,7 @@ var init_currency_controller = __esm(() => {
|
|
|
122795
123096
|
if (!isValidUUID(currencyId)) {
|
|
122796
123097
|
throw ApiError.unprocessableEntity("currencyId must be a valid UUID format");
|
|
122797
123098
|
}
|
|
122798
|
-
|
|
123099
|
+
logger45.debug("Deleting currency", { userId: ctx.user.id, currencyId });
|
|
122799
123100
|
await ctx.services.currency.delete(currencyId);
|
|
122800
123101
|
});
|
|
122801
123102
|
currencyController = {
|
|
@@ -122806,7 +123107,7 @@ var init_currency_controller = __esm(() => {
|
|
|
122806
123107
|
remove
|
|
122807
123108
|
};
|
|
122808
123109
|
});
|
|
122809
|
-
var
|
|
123110
|
+
var logger46;
|
|
122810
123111
|
var reset;
|
|
122811
123112
|
var init_database_controller = __esm(() => {
|
|
122812
123113
|
init_esm();
|
|
@@ -122814,7 +123115,7 @@ var init_database_controller = __esm(() => {
|
|
|
122814
123115
|
init_src2();
|
|
122815
123116
|
init_errors();
|
|
122816
123117
|
init_utils11();
|
|
122817
|
-
|
|
123118
|
+
logger46 = log.scope("DatabaseController");
|
|
122818
123119
|
reset = requireDeveloper(async (ctx) => {
|
|
122819
123120
|
const slug2 = ctx.params.slug;
|
|
122820
123121
|
if (!slug2) {
|
|
@@ -122827,11 +123128,11 @@ var init_database_controller = __esm(() => {
|
|
|
122827
123128
|
} catch (error2) {
|
|
122828
123129
|
if (error2 instanceof exports_external.ZodError) {
|
|
122829
123130
|
const details = formatZodError(error2);
|
|
122830
|
-
|
|
123131
|
+
logger46.warn("Database reset validation failed", { details });
|
|
122831
123132
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
122832
123133
|
}
|
|
122833
123134
|
}
|
|
122834
|
-
|
|
123135
|
+
logger46.debug("Resetting database", {
|
|
122835
123136
|
userId: ctx.user.id,
|
|
122836
123137
|
slug: slug2,
|
|
122837
123138
|
hasSchema: Boolean(body2.schema)
|
|
@@ -122847,7 +123148,7 @@ async function createJob(ctx) {
|
|
|
122847
123148
|
let body2;
|
|
122848
123149
|
try {
|
|
122849
123150
|
const json4 = await ctx.request.json();
|
|
122850
|
-
|
|
123151
|
+
logger47.debug("Deploy request body", {
|
|
122851
123152
|
keys: Object.keys(json4 || {}),
|
|
122852
123153
|
hasUploadToken: Boolean(json4?.uploadToken),
|
|
122853
123154
|
hasCode: Boolean(json4?.code),
|
|
@@ -122857,7 +123158,7 @@ async function createJob(ctx) {
|
|
|
122857
123158
|
} catch (error2) {
|
|
122858
123159
|
if (error2 instanceof exports_external.ZodError) {
|
|
122859
123160
|
const details = formatZodError(error2);
|
|
122860
|
-
|
|
123161
|
+
logger47.warn("Deploy validation failed", { details });
|
|
122861
123162
|
throw ApiError.unprocessableEntity("Invalid deploy request", details);
|
|
122862
123163
|
}
|
|
122863
123164
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -122878,7 +123179,7 @@ async function getJob(ctx) {
|
|
|
122878
123179
|
}
|
|
122879
123180
|
return ctx.services.deployJobs.get(jobId, slug2, ctx.user);
|
|
122880
123181
|
}
|
|
122881
|
-
var
|
|
123182
|
+
var logger47;
|
|
122882
123183
|
var deploy;
|
|
122883
123184
|
var init_deploy_controller = __esm(() => {
|
|
122884
123185
|
init_esm();
|
|
@@ -122886,26 +123187,26 @@ var init_deploy_controller = __esm(() => {
|
|
|
122886
123187
|
init_src2();
|
|
122887
123188
|
init_errors();
|
|
122888
123189
|
init_utils11();
|
|
122889
|
-
|
|
123190
|
+
logger47 = log.scope("DeployController");
|
|
122890
123191
|
deploy = {
|
|
122891
123192
|
createJob: requireDeveloper(createJob),
|
|
122892
123193
|
getJob: requireDeveloper(getJob)
|
|
122893
123194
|
};
|
|
122894
123195
|
});
|
|
122895
|
-
var
|
|
123196
|
+
var logger48;
|
|
122896
123197
|
var apply;
|
|
122897
123198
|
var getStatus;
|
|
122898
123199
|
var developer;
|
|
122899
123200
|
var init_developer_controller = __esm(() => {
|
|
122900
123201
|
init_src2();
|
|
122901
123202
|
init_utils11();
|
|
122902
|
-
|
|
123203
|
+
logger48 = log.scope("DeveloperController");
|
|
122903
123204
|
apply = requireNonAnonymous(async (ctx) => {
|
|
122904
|
-
|
|
123205
|
+
logger48.debug("Applying for developer status", { userId: ctx.user.id });
|
|
122905
123206
|
await ctx.services.developer.apply(ctx.user);
|
|
122906
123207
|
});
|
|
122907
123208
|
getStatus = requireNonAnonymous(async (ctx) => {
|
|
122908
|
-
|
|
123209
|
+
logger48.debug("Getting developer status", { userId: ctx.user.id });
|
|
122909
123210
|
const status = await ctx.services.developer.getStatus(ctx.user.id);
|
|
122910
123211
|
return { status };
|
|
122911
123212
|
});
|
|
@@ -122914,7 +123215,7 @@ var init_developer_controller = __esm(() => {
|
|
|
122914
123215
|
getStatus
|
|
122915
123216
|
};
|
|
122916
123217
|
});
|
|
122917
|
-
var
|
|
123218
|
+
var logger49;
|
|
122918
123219
|
var add;
|
|
122919
123220
|
var list2;
|
|
122920
123221
|
var getStatus2;
|
|
@@ -122927,7 +123228,7 @@ var init_domain_controller = __esm(() => {
|
|
|
122927
123228
|
init_config2();
|
|
122928
123229
|
init_errors();
|
|
122929
123230
|
init_utils11();
|
|
122930
|
-
|
|
123231
|
+
logger49 = log.scope("DomainController");
|
|
122931
123232
|
add = requireDeveloper(async (ctx) => {
|
|
122932
123233
|
const slug2 = ctx.params.slug;
|
|
122933
123234
|
if (!slug2) {
|
|
@@ -122940,13 +123241,13 @@ var init_domain_controller = __esm(() => {
|
|
|
122940
123241
|
} catch (error2) {
|
|
122941
123242
|
if (error2 instanceof exports_external.ZodError) {
|
|
122942
123243
|
const details = formatZodError(error2);
|
|
122943
|
-
|
|
123244
|
+
logger49.warn("Add domain validation failed", { details });
|
|
122944
123245
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
122945
123246
|
}
|
|
122946
123247
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122947
123248
|
}
|
|
122948
123249
|
const environment = getPlatformEnvironment(ctx.config);
|
|
122949
|
-
|
|
123250
|
+
logger49.debug("Adding domain", {
|
|
122950
123251
|
userId: ctx.user.id,
|
|
122951
123252
|
slug: slug2,
|
|
122952
123253
|
hostname: body2.hostname,
|
|
@@ -122960,7 +123261,7 @@ var init_domain_controller = __esm(() => {
|
|
|
122960
123261
|
throw ApiError.badRequest("Missing game slug");
|
|
122961
123262
|
}
|
|
122962
123263
|
const environment = getPlatformEnvironment(ctx.config);
|
|
122963
|
-
|
|
123264
|
+
logger49.debug("Listing domains", { userId: ctx.user.id, slug: slug2, environment });
|
|
122964
123265
|
const domains22 = await ctx.services.domain.list(slug2, environment, ctx.user);
|
|
122965
123266
|
return { domains: domains22 };
|
|
122966
123267
|
});
|
|
@@ -122975,7 +123276,7 @@ var init_domain_controller = __esm(() => {
|
|
|
122975
123276
|
}
|
|
122976
123277
|
const refresh = ctx.url.searchParams.get("refresh") === "true";
|
|
122977
123278
|
const environment = getPlatformEnvironment(ctx.config);
|
|
122978
|
-
|
|
123279
|
+
logger49.debug("Getting domain status", { userId: ctx.user.id, slug: slug2, hostname, refresh });
|
|
122979
123280
|
return ctx.services.domain.getStatus(slug2, hostname, environment, ctx.user, refresh);
|
|
122980
123281
|
});
|
|
122981
123282
|
remove2 = requireDeveloper(async (ctx) => {
|
|
@@ -122988,7 +123289,7 @@ var init_domain_controller = __esm(() => {
|
|
|
122988
123289
|
throw ApiError.badRequest("Missing hostname");
|
|
122989
123290
|
}
|
|
122990
123291
|
const environment = getPlatformEnvironment(ctx.config);
|
|
122991
|
-
|
|
123292
|
+
logger49.debug("Removing domain", { userId: ctx.user.id, slug: slug2, hostname, environment });
|
|
122992
123293
|
await ctx.services.domain.delete(slug2, hostname, environment, ctx.user);
|
|
122993
123294
|
});
|
|
122994
123295
|
domains2 = {
|
|
@@ -122998,7 +123299,7 @@ var init_domain_controller = __esm(() => {
|
|
|
122998
123299
|
remove: remove2
|
|
122999
123300
|
};
|
|
123000
123301
|
});
|
|
123001
|
-
var
|
|
123302
|
+
var logger50;
|
|
123002
123303
|
var list3;
|
|
123003
123304
|
var listAccessible;
|
|
123004
123305
|
var getSubjects;
|
|
@@ -123015,17 +123316,17 @@ var init_game_controller = __esm(() => {
|
|
|
123015
123316
|
init_src4();
|
|
123016
123317
|
init_errors();
|
|
123017
123318
|
init_utils11();
|
|
123018
|
-
|
|
123319
|
+
logger50 = log.scope("GameController");
|
|
123019
123320
|
list3 = requireNonAnonymous(async (ctx) => {
|
|
123020
|
-
|
|
123321
|
+
logger50.debug("Listing games", { userId: ctx.user.id });
|
|
123021
123322
|
return ctx.services.game.list(ctx.user);
|
|
123022
123323
|
});
|
|
123023
123324
|
listAccessible = requireNonAnonymous(async (ctx) => {
|
|
123024
|
-
|
|
123325
|
+
logger50.debug("Listing accessible games", { userId: ctx.user.id });
|
|
123025
123326
|
return ctx.services.game.listAccessible(ctx.user);
|
|
123026
123327
|
});
|
|
123027
123328
|
getSubjects = requireNonAnonymous(async (ctx) => {
|
|
123028
|
-
|
|
123329
|
+
logger50.debug("Getting game subjects", { userId: ctx.user.id });
|
|
123029
123330
|
return ctx.services.game.getSubjects();
|
|
123030
123331
|
});
|
|
123031
123332
|
getById2 = requireNonAnonymous(async (ctx) => {
|
|
@@ -123036,7 +123337,7 @@ var init_game_controller = __esm(() => {
|
|
|
123036
123337
|
if (!isValidUUID(gameId)) {
|
|
123037
123338
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
123038
123339
|
}
|
|
123039
|
-
|
|
123340
|
+
logger50.debug("Getting game by ID", { userId: ctx.user.id, gameId, launchId: ctx.launchId });
|
|
123040
123341
|
return ctx.services.game.getById(gameId, ctx.user);
|
|
123041
123342
|
});
|
|
123042
123343
|
getBySlug = requireNonAnonymous(async (ctx) => {
|
|
@@ -123044,7 +123345,7 @@ var init_game_controller = __esm(() => {
|
|
|
123044
123345
|
if (!slug2) {
|
|
123045
123346
|
throw ApiError.badRequest("Missing game slug");
|
|
123046
123347
|
}
|
|
123047
|
-
|
|
123348
|
+
logger50.debug("Getting game by slug", { userId: ctx.user.id, slug: slug2, launchId: ctx.launchId });
|
|
123048
123349
|
return ctx.services.game.getBySlug(slug2, ctx.user);
|
|
123049
123350
|
});
|
|
123050
123351
|
getManifest = requireNonAnonymous(async (ctx) => {
|
|
@@ -123055,7 +123356,7 @@ var init_game_controller = __esm(() => {
|
|
|
123055
123356
|
if (!isValidUUID(gameId)) {
|
|
123056
123357
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
123057
123358
|
}
|
|
123058
|
-
|
|
123359
|
+
logger50.debug("Getting game manifest by ID", {
|
|
123059
123360
|
userId: ctx.user.id,
|
|
123060
123361
|
gameId,
|
|
123061
123362
|
launchId: ctx.launchId
|
|
@@ -123074,12 +123375,12 @@ var init_game_controller = __esm(() => {
|
|
|
123074
123375
|
} catch (error2) {
|
|
123075
123376
|
if (error2 instanceof exports_external.ZodError) {
|
|
123076
123377
|
const details = formatZodError(error2);
|
|
123077
|
-
|
|
123378
|
+
logger50.warn("Upsert game validation failed", { details });
|
|
123078
123379
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123079
123380
|
}
|
|
123080
123381
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123081
123382
|
}
|
|
123082
|
-
|
|
123383
|
+
logger50.debug("Upserting game", { userId: ctx.user.id, slug: slug2, displayName: body2.displayName });
|
|
123083
123384
|
return ctx.services.game.upsertBySlug(slug2, body2, ctx.user);
|
|
123084
123385
|
});
|
|
123085
123386
|
remove3 = requireNonAnonymous(async (ctx) => {
|
|
@@ -123090,7 +123391,7 @@ var init_game_controller = __esm(() => {
|
|
|
123090
123391
|
if (!isValidUUID(gameId)) {
|
|
123091
123392
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
123092
123393
|
}
|
|
123093
|
-
|
|
123394
|
+
logger50.debug("Deleting game", { userId: ctx.user.id, gameId });
|
|
123094
123395
|
await ctx.services.game.delete(gameId, ctx.user);
|
|
123095
123396
|
});
|
|
123096
123397
|
games2 = {
|
|
@@ -123104,7 +123405,7 @@ var init_game_controller = __esm(() => {
|
|
|
123104
123405
|
remove: remove3
|
|
123105
123406
|
};
|
|
123106
123407
|
});
|
|
123107
|
-
var
|
|
123408
|
+
var logger51;
|
|
123108
123409
|
var list4;
|
|
123109
123410
|
var addItem;
|
|
123110
123411
|
var removeItem;
|
|
@@ -123115,9 +123416,9 @@ var init_inventory_controller = __esm(() => {
|
|
|
123115
123416
|
init_src2();
|
|
123116
123417
|
init_errors();
|
|
123117
123418
|
init_utils11();
|
|
123118
|
-
|
|
123419
|
+
logger51 = log.scope("InventoryController");
|
|
123119
123420
|
list4 = requireNonAnonymous(async (ctx) => {
|
|
123120
|
-
|
|
123421
|
+
logger51.debug("Listing inventory", { userId: ctx.user.id });
|
|
123121
123422
|
return ctx.services.inventory.list(ctx.user);
|
|
123122
123423
|
});
|
|
123123
123424
|
addItem = requireNonAnonymous(async (ctx) => {
|
|
@@ -123128,12 +123429,12 @@ var init_inventory_controller = __esm(() => {
|
|
|
123128
123429
|
} catch (error2) {
|
|
123129
123430
|
if (error2 instanceof exports_external.ZodError) {
|
|
123130
123431
|
const details = formatZodError(error2);
|
|
123131
|
-
|
|
123432
|
+
logger51.warn("Add inventory item validation failed", { details });
|
|
123132
123433
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
123133
123434
|
}
|
|
123134
123435
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123135
123436
|
}
|
|
123136
|
-
|
|
123437
|
+
logger51.debug("Adding item", {
|
|
123137
123438
|
userId: ctx.user.id,
|
|
123138
123439
|
itemId: body2.itemId,
|
|
123139
123440
|
qty: body2.qty
|
|
@@ -123148,12 +123449,12 @@ var init_inventory_controller = __esm(() => {
|
|
|
123148
123449
|
} catch (error2) {
|
|
123149
123450
|
if (error2 instanceof exports_external.ZodError) {
|
|
123150
123451
|
const details = formatZodError(error2);
|
|
123151
|
-
|
|
123452
|
+
logger51.warn("Remove inventory item validation failed", { details });
|
|
123152
123453
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
123153
123454
|
}
|
|
123154
123455
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123155
123456
|
}
|
|
123156
|
-
|
|
123457
|
+
logger51.debug("Removing item", {
|
|
123157
123458
|
userId: ctx.user.id,
|
|
123158
123459
|
itemId: body2.itemId,
|
|
123159
123460
|
qty: body2.qty
|
|
@@ -123166,7 +123467,7 @@ var init_inventory_controller = __esm(() => {
|
|
|
123166
123467
|
removeItem
|
|
123167
123468
|
};
|
|
123168
123469
|
});
|
|
123169
|
-
var
|
|
123470
|
+
var logger52;
|
|
123170
123471
|
var list5;
|
|
123171
123472
|
var getById3;
|
|
123172
123473
|
var resolve2;
|
|
@@ -123185,10 +123486,10 @@ var init_item_controller = __esm(() => {
|
|
|
123185
123486
|
init_src4();
|
|
123186
123487
|
init_errors();
|
|
123187
123488
|
init_utils11();
|
|
123188
|
-
|
|
123489
|
+
logger52 = log.scope("ItemController");
|
|
123189
123490
|
list5 = requireNonAnonymous(async (ctx) => {
|
|
123190
123491
|
const gameId = ctx.url.searchParams.get("gameId") || undefined;
|
|
123191
|
-
|
|
123492
|
+
logger52.debug("Listing items", { userId: ctx.user.id, gameId });
|
|
123192
123493
|
return ctx.services.item.list(gameId);
|
|
123193
123494
|
});
|
|
123194
123495
|
getById3 = requireNonAnonymous(async (ctx) => {
|
|
@@ -123199,7 +123500,7 @@ var init_item_controller = __esm(() => {
|
|
|
123199
123500
|
if (!isValidUUID(itemId)) {
|
|
123200
123501
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
123201
123502
|
}
|
|
123202
|
-
|
|
123503
|
+
logger52.debug("Getting item", { userId: ctx.user.id, itemId });
|
|
123203
123504
|
return ctx.services.item.getById(itemId);
|
|
123204
123505
|
});
|
|
123205
123506
|
resolve2 = requireNonAnonymous(async (ctx) => {
|
|
@@ -123211,7 +123512,7 @@ var init_item_controller = __esm(() => {
|
|
|
123211
123512
|
if (gameId && !isValidUUID(gameId)) {
|
|
123212
123513
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
123213
123514
|
}
|
|
123214
|
-
|
|
123515
|
+
logger52.debug("Resolving item", { userId: ctx.user.id, slug: slug2, gameId });
|
|
123215
123516
|
return ctx.services.item.resolveBySlug(slug2, gameId);
|
|
123216
123517
|
});
|
|
123217
123518
|
create3 = requireRole(["admin"], async (ctx) => {
|
|
@@ -123222,12 +123523,12 @@ var init_item_controller = __esm(() => {
|
|
|
123222
123523
|
} catch (error2) {
|
|
123223
123524
|
if (error2 instanceof exports_external.ZodError) {
|
|
123224
123525
|
const details = formatZodError(error2);
|
|
123225
|
-
|
|
123526
|
+
logger52.warn("Create item validation failed", { details });
|
|
123226
123527
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123227
123528
|
}
|
|
123228
123529
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123229
123530
|
}
|
|
123230
|
-
|
|
123531
|
+
logger52.debug("Creating item", {
|
|
123231
123532
|
userId: ctx.user.id,
|
|
123232
123533
|
slug: body2.slug,
|
|
123233
123534
|
displayName: body2.displayName
|
|
@@ -123249,7 +123550,7 @@ var init_item_controller = __esm(() => {
|
|
|
123249
123550
|
} catch (error2) {
|
|
123250
123551
|
if (error2 instanceof exports_external.ZodError) {
|
|
123251
123552
|
const details = formatZodError(error2);
|
|
123252
|
-
|
|
123553
|
+
logger52.warn("Update item validation failed", { details });
|
|
123253
123554
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123254
123555
|
}
|
|
123255
123556
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -123257,7 +123558,7 @@ var init_item_controller = __esm(() => {
|
|
|
123257
123558
|
if (Object.keys(body2).length === 0) {
|
|
123258
123559
|
throw ApiError.badRequest("No update data provided");
|
|
123259
123560
|
}
|
|
123260
|
-
|
|
123561
|
+
logger52.debug("Updating item", {
|
|
123261
123562
|
userId: ctx.user.id,
|
|
123262
123563
|
itemId,
|
|
123263
123564
|
slug: body2.slug,
|
|
@@ -123274,7 +123575,7 @@ var init_item_controller = __esm(() => {
|
|
|
123274
123575
|
if (!isValidUUID(itemId)) {
|
|
123275
123576
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
123276
123577
|
}
|
|
123277
|
-
|
|
123578
|
+
logger52.debug("Deleting item", { userId: ctx.user.id, itemId });
|
|
123278
123579
|
await ctx.services.item.delete(itemId);
|
|
123279
123580
|
});
|
|
123280
123581
|
listByGame = requireNonAnonymous(async (ctx) => {
|
|
@@ -123285,7 +123586,7 @@ var init_item_controller = __esm(() => {
|
|
|
123285
123586
|
if (!isValidUUID(gameId)) {
|
|
123286
123587
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
123287
123588
|
}
|
|
123288
|
-
|
|
123589
|
+
logger52.debug("Listing game items", { userId: ctx.user.id, gameId });
|
|
123289
123590
|
return ctx.services.item.listByGame(gameId);
|
|
123290
123591
|
});
|
|
123291
123592
|
createForGame = requireNonAnonymous(async (ctx) => {
|
|
@@ -123303,12 +123604,12 @@ var init_item_controller = __esm(() => {
|
|
|
123303
123604
|
} catch (error2) {
|
|
123304
123605
|
if (error2 instanceof exports_external.ZodError) {
|
|
123305
123606
|
const details = formatZodError(error2);
|
|
123306
|
-
|
|
123607
|
+
logger52.warn("Create game item validation failed", { details });
|
|
123307
123608
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123308
123609
|
}
|
|
123309
123610
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123310
123611
|
}
|
|
123311
|
-
|
|
123612
|
+
logger52.debug("Creating game item", {
|
|
123312
123613
|
userId: ctx.user.id,
|
|
123313
123614
|
gameId,
|
|
123314
123615
|
slug: body2.slug,
|
|
@@ -123335,7 +123636,7 @@ var init_item_controller = __esm(() => {
|
|
|
123335
123636
|
} catch (error2) {
|
|
123336
123637
|
if (error2 instanceof exports_external.ZodError) {
|
|
123337
123638
|
const details = formatZodError(error2);
|
|
123338
|
-
|
|
123639
|
+
logger52.warn("Update game item validation failed", { details });
|
|
123339
123640
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123340
123641
|
}
|
|
123341
123642
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -123343,7 +123644,7 @@ var init_item_controller = __esm(() => {
|
|
|
123343
123644
|
if (Object.keys(body2).length === 0) {
|
|
123344
123645
|
throw ApiError.badRequest("No update data provided");
|
|
123345
123646
|
}
|
|
123346
|
-
|
|
123647
|
+
logger52.debug("Updating game item", {
|
|
123347
123648
|
userId: ctx.user.id,
|
|
123348
123649
|
gameId,
|
|
123349
123650
|
itemId,
|
|
@@ -123365,7 +123666,7 @@ var init_item_controller = __esm(() => {
|
|
|
123365
123666
|
if (!isValidUUID(itemId)) {
|
|
123366
123667
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
123367
123668
|
}
|
|
123368
|
-
|
|
123669
|
+
logger52.debug("Deleting game item", { userId: ctx.user.id, gameId, itemId });
|
|
123369
123670
|
await ctx.services.item.deleteForGame(gameId, itemId, ctx.user);
|
|
123370
123671
|
});
|
|
123371
123672
|
items2 = {
|
|
@@ -123381,7 +123682,7 @@ var init_item_controller = __esm(() => {
|
|
|
123381
123682
|
deleteForGame
|
|
123382
123683
|
};
|
|
123383
123684
|
});
|
|
123384
|
-
var
|
|
123685
|
+
var logger53;
|
|
123385
123686
|
var listKeys;
|
|
123386
123687
|
var getStats;
|
|
123387
123688
|
var seed;
|
|
@@ -123396,7 +123697,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123396
123697
|
init_src2();
|
|
123397
123698
|
init_errors();
|
|
123398
123699
|
init_utils11();
|
|
123399
|
-
|
|
123700
|
+
logger53 = log.scope("KVController");
|
|
123400
123701
|
listKeys = requireDeveloper(async (ctx) => {
|
|
123401
123702
|
const slug2 = ctx.params.slug;
|
|
123402
123703
|
if (!slug2) {
|
|
@@ -123404,7 +123705,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123404
123705
|
}
|
|
123405
123706
|
const url2 = ctx.url;
|
|
123406
123707
|
const prefix2 = url2.searchParams.get("prefix") || undefined;
|
|
123407
|
-
|
|
123708
|
+
logger53.debug("Listing keys", { userId: ctx.user.id, slug: slug2, prefix: prefix2 });
|
|
123408
123709
|
const keys = await ctx.services.kv.listKeys(slug2, ctx.user, prefix2);
|
|
123409
123710
|
return { keys };
|
|
123410
123711
|
});
|
|
@@ -123413,7 +123714,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123413
123714
|
if (!slug2) {
|
|
123414
123715
|
throw ApiError.badRequest("Missing game slug");
|
|
123415
123716
|
}
|
|
123416
|
-
|
|
123717
|
+
logger53.debug("Getting stats", { userId: ctx.user.id, slug: slug2 });
|
|
123417
123718
|
return ctx.services.kv.getStats(slug2, ctx.user);
|
|
123418
123719
|
});
|
|
123419
123720
|
seed = requireDeveloper(async (ctx) => {
|
|
@@ -123428,12 +123729,12 @@ var init_kv_controller = __esm(() => {
|
|
|
123428
123729
|
} catch (error2) {
|
|
123429
123730
|
if (error2 instanceof exports_external.ZodError) {
|
|
123430
123731
|
const details = formatZodError(error2);
|
|
123431
|
-
|
|
123732
|
+
logger53.warn("Seed validation failed", { details });
|
|
123432
123733
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123433
123734
|
}
|
|
123434
123735
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123435
123736
|
}
|
|
123436
|
-
|
|
123737
|
+
logger53.debug("Seeding values", { userId: ctx.user.id, slug: slug2, count: body2.entries.length });
|
|
123437
123738
|
await ctx.services.kv.seed(slug2, body2.entries, ctx.user);
|
|
123438
123739
|
return { success: true, count: body2.entries.length };
|
|
123439
123740
|
});
|
|
@@ -123443,7 +123744,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123443
123744
|
if (!slug2 || !key) {
|
|
123444
123745
|
throw ApiError.badRequest("Missing game slug or key");
|
|
123445
123746
|
}
|
|
123446
|
-
|
|
123747
|
+
logger53.debug("Getting value", { userId: ctx.user.id, slug: slug2, key });
|
|
123447
123748
|
const value = await ctx.services.kv.getValue(slug2, key, ctx.user);
|
|
123448
123749
|
return { key, value };
|
|
123449
123750
|
});
|
|
@@ -123457,7 +123758,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123457
123758
|
if (!value) {
|
|
123458
123759
|
throw ApiError.badRequest("Missing value in request body");
|
|
123459
123760
|
}
|
|
123460
|
-
|
|
123761
|
+
logger53.debug("Setting value", { userId: ctx.user.id, slug: slug2, key, size: value.length });
|
|
123461
123762
|
await ctx.services.kv.setValue(slug2, key, value, ctx.user);
|
|
123462
123763
|
return { success: true, key };
|
|
123463
123764
|
});
|
|
@@ -123467,7 +123768,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123467
123768
|
if (!slug2 || !key) {
|
|
123468
123769
|
throw ApiError.badRequest("Missing game slug or key");
|
|
123469
123770
|
}
|
|
123470
|
-
|
|
123771
|
+
logger53.debug("Deleting value", { userId: ctx.user.id, slug: slug2, key });
|
|
123471
123772
|
await ctx.services.kv.deleteValue(slug2, key, ctx.user);
|
|
123472
123773
|
return { success: true, key };
|
|
123473
123774
|
});
|
|
@@ -123477,7 +123778,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123477
123778
|
if (!slug2 || !key) {
|
|
123478
123779
|
throw ApiError.badRequest("Missing game slug or key");
|
|
123479
123780
|
}
|
|
123480
|
-
|
|
123781
|
+
logger53.debug("Getting metadata", { userId: ctx.user.id, slug: slug2, key });
|
|
123481
123782
|
const metadata2 = await ctx.services.kv.getMetadata(slug2, key, ctx.user);
|
|
123482
123783
|
return { key, metadata: metadata2 };
|
|
123483
123784
|
});
|
|
@@ -123486,12 +123787,12 @@ var init_kv_controller = __esm(() => {
|
|
|
123486
123787
|
if (!slug2) {
|
|
123487
123788
|
throw ApiError.badRequest("Missing game slug");
|
|
123488
123789
|
}
|
|
123489
|
-
|
|
123790
|
+
logger53.debug("Clearing all keys", { userId: ctx.user.id, slug: slug2 });
|
|
123490
123791
|
const deleted = await ctx.services.kv.clear(slug2, ctx.user);
|
|
123491
123792
|
return { success: true, deleted };
|
|
123492
123793
|
});
|
|
123493
123794
|
});
|
|
123494
|
-
var
|
|
123795
|
+
var logger54;
|
|
123495
123796
|
var submitScore;
|
|
123496
123797
|
var getGlobalLeaderboard;
|
|
123497
123798
|
var getLeaderboard;
|
|
@@ -123505,7 +123806,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123505
123806
|
init_src2();
|
|
123506
123807
|
init_errors();
|
|
123507
123808
|
init_utils11();
|
|
123508
|
-
|
|
123809
|
+
logger54 = log.scope("LeaderboardController");
|
|
123509
123810
|
submitScore = requireAuth(async (ctx) => {
|
|
123510
123811
|
const gameId = ctx.params.gameId;
|
|
123511
123812
|
if (!gameId) {
|
|
@@ -123518,12 +123819,12 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123518
123819
|
} catch (error2) {
|
|
123519
123820
|
if (error2 instanceof exports_external.ZodError) {
|
|
123520
123821
|
const details = formatZodError(error2);
|
|
123521
|
-
|
|
123822
|
+
logger54.warn("Submit score validation failed", { details });
|
|
123522
123823
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123523
123824
|
}
|
|
123524
123825
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123525
123826
|
}
|
|
123526
|
-
|
|
123827
|
+
logger54.debug("Submitting score", {
|
|
123527
123828
|
userId: ctx.user.id,
|
|
123528
123829
|
gameId,
|
|
123529
123830
|
score: body2.score
|
|
@@ -123546,12 +123847,12 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123546
123847
|
} catch (error2) {
|
|
123547
123848
|
if (error2 instanceof exports_external.ZodError) {
|
|
123548
123849
|
const details = formatZodError(error2);
|
|
123549
|
-
|
|
123850
|
+
logger54.warn("Get global leaderboard query validation failed", { details });
|
|
123550
123851
|
throw ApiError.badRequest("Invalid query parameters", details);
|
|
123551
123852
|
}
|
|
123552
123853
|
throw ApiError.badRequest("Invalid query parameters");
|
|
123553
123854
|
}
|
|
123554
|
-
|
|
123855
|
+
logger54.debug("Getting global leaderboard", {
|
|
123555
123856
|
userId: ctx.user.id,
|
|
123556
123857
|
gameId,
|
|
123557
123858
|
...query
|
|
@@ -123574,12 +123875,12 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123574
123875
|
} catch (error2) {
|
|
123575
123876
|
if (error2 instanceof exports_external.ZodError) {
|
|
123576
123877
|
const details = formatZodError(error2);
|
|
123577
|
-
|
|
123878
|
+
logger54.warn("Get leaderboard query validation failed", { details });
|
|
123578
123879
|
throw ApiError.badRequest("Invalid query parameters", details);
|
|
123579
123880
|
}
|
|
123580
123881
|
throw ApiError.badRequest("Invalid query parameters");
|
|
123581
123882
|
}
|
|
123582
|
-
|
|
123883
|
+
logger54.debug("Getting leaderboard", {
|
|
123583
123884
|
userId: ctx.user.id,
|
|
123584
123885
|
gameId,
|
|
123585
123886
|
...query
|
|
@@ -123591,7 +123892,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123591
123892
|
if (!gameId || !userId) {
|
|
123592
123893
|
throw ApiError.badRequest("Game ID and User ID are required");
|
|
123593
123894
|
}
|
|
123594
|
-
|
|
123895
|
+
logger54.debug("Getting user rank", {
|
|
123595
123896
|
requesterId: ctx.user.id,
|
|
123596
123897
|
gameId,
|
|
123597
123898
|
targetUserId: userId
|
|
@@ -123606,7 +123907,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123606
123907
|
const url2 = ctx.url;
|
|
123607
123908
|
const limit = Math.min(Number(url2.searchParams.get("limit") || "50"), 100);
|
|
123608
123909
|
const gameId = url2.searchParams.get("gameId") || undefined;
|
|
123609
|
-
|
|
123910
|
+
logger54.debug("Getting user all scores", {
|
|
123610
123911
|
requesterId: ctx.user.id,
|
|
123611
123912
|
targetUserId: userId,
|
|
123612
123913
|
gameId,
|
|
@@ -123621,7 +123922,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123621
123922
|
}
|
|
123622
123923
|
const url2 = ctx.url;
|
|
123623
123924
|
const limit = Math.min(Number(url2.searchParams.get("limit") || "10"), 100);
|
|
123624
|
-
|
|
123925
|
+
logger54.debug("Getting user scores", {
|
|
123625
123926
|
requesterId: ctx.user.id,
|
|
123626
123927
|
gameId,
|
|
123627
123928
|
targetUserId: userId,
|
|
@@ -123639,7 +123940,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123639
123940
|
};
|
|
123640
123941
|
});
|
|
123641
123942
|
async function listConfigs(ctx) {
|
|
123642
|
-
|
|
123943
|
+
logger55.debug("Listing level configs");
|
|
123643
123944
|
return ctx.services.level.listConfigs();
|
|
123644
123945
|
}
|
|
123645
123946
|
async function getConfig(ctx) {
|
|
@@ -123651,10 +123952,10 @@ async function getConfig(ctx) {
|
|
|
123651
123952
|
if (isNaN(level) || level < 1) {
|
|
123652
123953
|
throw ApiError.badRequest("Level must be a positive integer");
|
|
123653
123954
|
}
|
|
123654
|
-
|
|
123955
|
+
logger55.debug("Getting level config", { level });
|
|
123655
123956
|
return ctx.services.level.getConfig(level);
|
|
123656
123957
|
}
|
|
123657
|
-
var
|
|
123958
|
+
var logger55;
|
|
123658
123959
|
var getByUser;
|
|
123659
123960
|
var getProgress;
|
|
123660
123961
|
var levels;
|
|
@@ -123662,13 +123963,13 @@ var init_level_controller = __esm(() => {
|
|
|
123662
123963
|
init_src2();
|
|
123663
123964
|
init_errors();
|
|
123664
123965
|
init_utils11();
|
|
123665
|
-
|
|
123966
|
+
logger55 = log.scope("LevelController");
|
|
123666
123967
|
getByUser = requireNonAnonymous(async (ctx) => {
|
|
123667
|
-
|
|
123968
|
+
logger55.debug("Getting user level", { userId: ctx.user.id });
|
|
123668
123969
|
return ctx.services.level.getByUser(ctx.user);
|
|
123669
123970
|
});
|
|
123670
123971
|
getProgress = requireNonAnonymous(async (ctx) => {
|
|
123671
|
-
|
|
123972
|
+
logger55.debug("Getting level progress", { userId: ctx.user.id });
|
|
123672
123973
|
return ctx.services.level.getProgress(ctx.user);
|
|
123673
123974
|
});
|
|
123674
123975
|
levels = {
|
|
@@ -123678,14 +123979,14 @@ var init_level_controller = __esm(() => {
|
|
|
123678
123979
|
getProgress
|
|
123679
123980
|
};
|
|
123680
123981
|
});
|
|
123681
|
-
var
|
|
123982
|
+
var logger56;
|
|
123682
123983
|
var generateToken;
|
|
123683
123984
|
var logs;
|
|
123684
123985
|
var init_logs_controller = __esm(() => {
|
|
123685
123986
|
init_src2();
|
|
123686
123987
|
init_errors();
|
|
123687
123988
|
init_utils11();
|
|
123688
|
-
|
|
123989
|
+
logger56 = log.scope("LogsController");
|
|
123689
123990
|
generateToken = requireDeveloper(async (ctx) => {
|
|
123690
123991
|
const slug2 = ctx.params.slug;
|
|
123691
123992
|
if (!slug2) {
|
|
@@ -123704,7 +124005,7 @@ var init_logs_controller = __esm(() => {
|
|
|
123704
124005
|
}
|
|
123705
124006
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123706
124007
|
}
|
|
123707
|
-
|
|
124008
|
+
logger56.debug("Generating log stream token", {
|
|
123708
124009
|
userId: ctx.user.id,
|
|
123709
124010
|
slug: slug2,
|
|
123710
124011
|
environment: body2.environment
|
|
@@ -123721,22 +124022,22 @@ var init_logs_controller = __esm(() => {
|
|
|
123721
124022
|
generateToken
|
|
123722
124023
|
};
|
|
123723
124024
|
});
|
|
123724
|
-
var
|
|
124025
|
+
var logger57;
|
|
123725
124026
|
var getStatus3;
|
|
123726
124027
|
var lti;
|
|
123727
124028
|
var init_lti_controller = __esm(() => {
|
|
123728
124029
|
init_src2();
|
|
123729
124030
|
init_utils11();
|
|
123730
|
-
|
|
124031
|
+
logger57 = log.scope("LtiController");
|
|
123731
124032
|
getStatus3 = requireNonAnonymous(async (ctx) => {
|
|
123732
|
-
|
|
124033
|
+
logger57.debug("Getting status", { userId: ctx.user.id });
|
|
123733
124034
|
return ctx.services.lti.getStatus(ctx.user);
|
|
123734
124035
|
});
|
|
123735
124036
|
lti = {
|
|
123736
124037
|
getStatus: getStatus3
|
|
123737
124038
|
};
|
|
123738
124039
|
});
|
|
123739
|
-
var
|
|
124040
|
+
var logger58;
|
|
123740
124041
|
var getByIdentifier;
|
|
123741
124042
|
var getElements;
|
|
123742
124043
|
var getObjects;
|
|
@@ -123750,13 +124051,13 @@ var init_map_controller = __esm(() => {
|
|
|
123750
124051
|
init_src4();
|
|
123751
124052
|
init_errors();
|
|
123752
124053
|
init_utils11();
|
|
123753
|
-
|
|
124054
|
+
logger58 = log.scope("MapController");
|
|
123754
124055
|
getByIdentifier = requireNonAnonymous(async (ctx) => {
|
|
123755
124056
|
const identifier = ctx.params.identifier;
|
|
123756
124057
|
if (!identifier) {
|
|
123757
124058
|
throw ApiError.badRequest("Missing map identifier");
|
|
123758
124059
|
}
|
|
123759
|
-
|
|
124060
|
+
logger58.debug("Getting map", { userId: ctx.user.id, identifier });
|
|
123760
124061
|
return ctx.services.map.getByIdentifier(identifier);
|
|
123761
124062
|
});
|
|
123762
124063
|
getElements = requireNonAnonymous(async (ctx) => {
|
|
@@ -123767,7 +124068,7 @@ var init_map_controller = __esm(() => {
|
|
|
123767
124068
|
if (!isValidUUID(mapId)) {
|
|
123768
124069
|
throw ApiError.unprocessableEntity("mapId must be a valid UUID format");
|
|
123769
124070
|
}
|
|
123770
|
-
|
|
124071
|
+
logger58.debug("Getting map elements", { userId: ctx.user.id, mapId });
|
|
123771
124072
|
return ctx.services.map.getElements(mapId);
|
|
123772
124073
|
});
|
|
123773
124074
|
getObjects = requireNonAnonymous(async (ctx) => {
|
|
@@ -123778,7 +124079,7 @@ var init_map_controller = __esm(() => {
|
|
|
123778
124079
|
if (!isValidUUID(mapId)) {
|
|
123779
124080
|
throw ApiError.unprocessableEntity("mapId must be a valid UUID format");
|
|
123780
124081
|
}
|
|
123781
|
-
|
|
124082
|
+
logger58.debug("Getting map objects", { userId: ctx.user.id, mapId });
|
|
123782
124083
|
return ctx.services.map.getObjects(mapId, ctx.user.id);
|
|
123783
124084
|
});
|
|
123784
124085
|
createObject = requireNonAnonymous(async (ctx) => {
|
|
@@ -123800,12 +124101,12 @@ var init_map_controller = __esm(() => {
|
|
|
123800
124101
|
} catch (error2) {
|
|
123801
124102
|
if (error2 instanceof exports_external.ZodError) {
|
|
123802
124103
|
const details = formatZodError(error2);
|
|
123803
|
-
|
|
124104
|
+
logger58.warn("Create map object validation failed", { details });
|
|
123804
124105
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123805
124106
|
}
|
|
123806
124107
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123807
124108
|
}
|
|
123808
|
-
|
|
124109
|
+
logger58.debug("Creating map object", {
|
|
123809
124110
|
userId: ctx.user.id,
|
|
123810
124111
|
mapId,
|
|
123811
124112
|
itemId: body2.itemId,
|
|
@@ -123829,7 +124130,7 @@ var init_map_controller = __esm(() => {
|
|
|
123829
124130
|
if (!isValidUUID(objectId)) {
|
|
123830
124131
|
throw ApiError.unprocessableEntity("objectId must be a valid UUID format");
|
|
123831
124132
|
}
|
|
123832
|
-
|
|
124133
|
+
logger58.debug("Deleting map object", { userId: ctx.user.id, mapId, objectId });
|
|
123833
124134
|
await ctx.services.map.deleteObject(mapId, objectId, ctx.user);
|
|
123834
124135
|
});
|
|
123835
124136
|
maps2 = {
|
|
@@ -123840,7 +124141,7 @@ var init_map_controller = __esm(() => {
|
|
|
123840
124141
|
deleteObject
|
|
123841
124142
|
};
|
|
123842
124143
|
});
|
|
123843
|
-
var
|
|
124144
|
+
var logger59;
|
|
123844
124145
|
var list6;
|
|
123845
124146
|
var updateStatus;
|
|
123846
124147
|
var getStats2;
|
|
@@ -123853,7 +124154,7 @@ var init_notification_controller = __esm(() => {
|
|
|
123853
124154
|
init_src2();
|
|
123854
124155
|
init_errors();
|
|
123855
124156
|
init_utils11();
|
|
123856
|
-
|
|
124157
|
+
logger59 = log.scope("NotificationController");
|
|
123857
124158
|
list6 = requireNonAnonymous(async (ctx) => {
|
|
123858
124159
|
const query = {
|
|
123859
124160
|
status: ctx.url.searchParams.get("status") || undefined,
|
|
@@ -123864,10 +124165,10 @@ var init_notification_controller = __esm(() => {
|
|
|
123864
124165
|
const result = NotificationListQuerySchema.omit({ userId: true }).safeParse(query);
|
|
123865
124166
|
if (!result.success) {
|
|
123866
124167
|
const details = formatZodError(result.error);
|
|
123867
|
-
|
|
124168
|
+
logger59.warn("List notifications query validation failed", { details });
|
|
123868
124169
|
throw ApiError.badRequest("Invalid query parameters", details);
|
|
123869
124170
|
}
|
|
123870
|
-
|
|
124171
|
+
logger59.debug("Listing notifications", { userId: ctx.user.id, ...result.data });
|
|
123871
124172
|
return ctx.services.notification.list(ctx.user, result.data);
|
|
123872
124173
|
});
|
|
123873
124174
|
updateStatus = requireNonAnonymous(async (ctx) => {
|
|
@@ -123882,12 +124183,12 @@ var init_notification_controller = __esm(() => {
|
|
|
123882
124183
|
} catch (error2) {
|
|
123883
124184
|
if (error2 instanceof exports_external.ZodError) {
|
|
123884
124185
|
const details = formatZodError(error2);
|
|
123885
|
-
|
|
124186
|
+
logger59.warn("Update notification status validation failed", { details });
|
|
123886
124187
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
123887
124188
|
}
|
|
123888
124189
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123889
124190
|
}
|
|
123890
|
-
|
|
124191
|
+
logger59.debug("Updating status", {
|
|
123891
124192
|
userId: ctx.user.id,
|
|
123892
124193
|
notificationId,
|
|
123893
124194
|
status: body2.status
|
|
@@ -123897,7 +124198,7 @@ var init_notification_controller = __esm(() => {
|
|
|
123897
124198
|
getStats2 = requireNonAnonymous(async (ctx) => {
|
|
123898
124199
|
const startDate = ctx.url.searchParams.get("startDate");
|
|
123899
124200
|
const endDate = ctx.url.searchParams.get("endDate");
|
|
123900
|
-
|
|
124201
|
+
logger59.debug("Getting stats", { userId: ctx.user.id, startDate, endDate });
|
|
123901
124202
|
return ctx.services.notification.getStats(ctx.user, {
|
|
123902
124203
|
startDate: startDate ? new Date(startDate) : undefined,
|
|
123903
124204
|
endDate: endDate ? new Date(endDate) : undefined
|
|
@@ -123911,12 +124212,12 @@ var init_notification_controller = __esm(() => {
|
|
|
123911
124212
|
} catch (error2) {
|
|
123912
124213
|
if (error2 instanceof exports_external.ZodError) {
|
|
123913
124214
|
const details = formatZodError(error2);
|
|
123914
|
-
|
|
124215
|
+
logger59.warn("Create notification validation failed", { details });
|
|
123915
124216
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
123916
124217
|
}
|
|
123917
124218
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123918
124219
|
}
|
|
123919
|
-
|
|
124220
|
+
logger59.debug("Creating notification", {
|
|
123920
124221
|
userId: ctx.user.id,
|
|
123921
124222
|
targetUserId: body2.userId,
|
|
123922
124223
|
type: body2.type
|
|
@@ -123934,12 +124235,12 @@ var init_notification_controller = __esm(() => {
|
|
|
123934
124235
|
});
|
|
123935
124236
|
});
|
|
123936
124237
|
deliver = requireNonAnonymous(async (ctx) => {
|
|
123937
|
-
|
|
124238
|
+
logger59.debug("Delivering notifications", { userId: ctx.user.id });
|
|
123938
124239
|
try {
|
|
123939
124240
|
await ctx.services.notification.deliverPending(ctx.user.id);
|
|
123940
124241
|
return { success: true };
|
|
123941
124242
|
} catch (error2) {
|
|
123942
|
-
|
|
124243
|
+
logger59.error("Failed to deliver notifications", { error: error2 });
|
|
123943
124244
|
throw ApiError.internal("Failed to deliver notifications");
|
|
123944
124245
|
}
|
|
123945
124246
|
});
|
|
@@ -123951,16 +124252,16 @@ var init_notification_controller = __esm(() => {
|
|
|
123951
124252
|
deliver
|
|
123952
124253
|
};
|
|
123953
124254
|
});
|
|
123954
|
-
var
|
|
124255
|
+
var logger60;
|
|
123955
124256
|
var generateToken2;
|
|
123956
124257
|
var realtime;
|
|
123957
124258
|
var init_realtime_controller = __esm(() => {
|
|
123958
124259
|
init_src2();
|
|
123959
124260
|
init_utils11();
|
|
123960
|
-
|
|
124261
|
+
logger60 = log.scope("RealtimeController");
|
|
123961
124262
|
generateToken2 = requireNonAnonymous(async (ctx) => {
|
|
123962
124263
|
const gameIdOrSlug = ctx.params.gameId;
|
|
123963
|
-
|
|
124264
|
+
logger60.debug("Generating token", {
|
|
123964
124265
|
userId: ctx.user.id,
|
|
123965
124266
|
gameId: gameIdOrSlug || "global",
|
|
123966
124267
|
launchId: ctx.launchId
|
|
@@ -123971,7 +124272,7 @@ var init_realtime_controller = __esm(() => {
|
|
|
123971
124272
|
generateToken: generateToken2
|
|
123972
124273
|
};
|
|
123973
124274
|
});
|
|
123974
|
-
var
|
|
124275
|
+
var logger61;
|
|
123975
124276
|
var listKeys2;
|
|
123976
124277
|
var setSecrets;
|
|
123977
124278
|
var deleteSecret;
|
|
@@ -123982,13 +124283,13 @@ var init_secrets_controller = __esm(() => {
|
|
|
123982
124283
|
init_src2();
|
|
123983
124284
|
init_errors();
|
|
123984
124285
|
init_utils11();
|
|
123985
|
-
|
|
124286
|
+
logger61 = log.scope("SecretsController");
|
|
123986
124287
|
listKeys2 = requireDeveloper(async (ctx) => {
|
|
123987
124288
|
const slug2 = ctx.params.slug;
|
|
123988
124289
|
if (!slug2) {
|
|
123989
124290
|
throw ApiError.badRequest("Missing game slug");
|
|
123990
124291
|
}
|
|
123991
|
-
|
|
124292
|
+
logger61.debug("Listing secret keys", { userId: ctx.user.id, slug: slug2 });
|
|
123992
124293
|
const keys = await ctx.services.secrets.listKeys(slug2, ctx.user);
|
|
123993
124294
|
return { keys };
|
|
123994
124295
|
});
|
|
@@ -124004,12 +124305,12 @@ var init_secrets_controller = __esm(() => {
|
|
|
124004
124305
|
} catch (error2) {
|
|
124005
124306
|
if (error2 instanceof exports_external.ZodError) {
|
|
124006
124307
|
const details = formatZodError(error2);
|
|
124007
|
-
|
|
124308
|
+
logger61.warn("Set secrets validation failed", { details });
|
|
124008
124309
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124009
124310
|
}
|
|
124010
124311
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124011
124312
|
}
|
|
124012
|
-
|
|
124313
|
+
logger61.debug("Setting secrets", {
|
|
124013
124314
|
userId: ctx.user.id,
|
|
124014
124315
|
slug: slug2,
|
|
124015
124316
|
keyCount: Object.keys(body2).length
|
|
@@ -124026,7 +124327,7 @@ var init_secrets_controller = __esm(() => {
|
|
|
124026
124327
|
if (!key) {
|
|
124027
124328
|
throw ApiError.badRequest("Missing secret key");
|
|
124028
124329
|
}
|
|
124029
|
-
|
|
124330
|
+
logger61.debug("Deleting secret", { userId: ctx.user.id, slug: slug2, key });
|
|
124030
124331
|
await ctx.services.secrets.deleteSecret(slug2, key, ctx.user);
|
|
124031
124332
|
return { success: true };
|
|
124032
124333
|
});
|
|
@@ -124036,7 +124337,7 @@ var init_secrets_controller = __esm(() => {
|
|
|
124036
124337
|
deleteSecret
|
|
124037
124338
|
};
|
|
124038
124339
|
});
|
|
124039
|
-
var
|
|
124340
|
+
var logger62;
|
|
124040
124341
|
var seed2;
|
|
124041
124342
|
var init_seed_controller = __esm(() => {
|
|
124042
124343
|
init_esm();
|
|
@@ -124044,7 +124345,7 @@ var init_seed_controller = __esm(() => {
|
|
|
124044
124345
|
init_src2();
|
|
124045
124346
|
init_errors();
|
|
124046
124347
|
init_utils11();
|
|
124047
|
-
|
|
124348
|
+
logger62 = log.scope("SeedController");
|
|
124048
124349
|
seed2 = requireDeveloper(async (ctx) => {
|
|
124049
124350
|
const slug2 = ctx.params.slug;
|
|
124050
124351
|
if (!slug2) {
|
|
@@ -124057,12 +124358,12 @@ var init_seed_controller = __esm(() => {
|
|
|
124057
124358
|
} catch (error2) {
|
|
124058
124359
|
if (error2 instanceof exports_external.ZodError) {
|
|
124059
124360
|
const details = formatZodError(error2);
|
|
124060
|
-
|
|
124361
|
+
logger62.warn("Seed database validation failed", { details });
|
|
124061
124362
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124062
124363
|
}
|
|
124063
124364
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124064
124365
|
}
|
|
124065
|
-
|
|
124366
|
+
logger62.debug("Seeding database", {
|
|
124066
124367
|
userId: ctx.user.id,
|
|
124067
124368
|
slug: slug2,
|
|
124068
124369
|
codeLength: body2.code.length,
|
|
@@ -124071,7 +124372,7 @@ var init_seed_controller = __esm(() => {
|
|
|
124071
124372
|
return ctx.services.seed.seed(slug2, body2.code, ctx.user, body2.secrets);
|
|
124072
124373
|
});
|
|
124073
124374
|
});
|
|
124074
|
-
var
|
|
124375
|
+
var logger63;
|
|
124075
124376
|
var start2;
|
|
124076
124377
|
var end;
|
|
124077
124378
|
var mintToken;
|
|
@@ -124081,13 +124382,13 @@ var init_session_controller = __esm(() => {
|
|
|
124081
124382
|
init_tunnel();
|
|
124082
124383
|
init_errors();
|
|
124083
124384
|
init_utils11();
|
|
124084
|
-
|
|
124385
|
+
logger63 = log.scope("SessionController");
|
|
124085
124386
|
start2 = requireAuth(async (ctx) => {
|
|
124086
124387
|
const gameIdOrSlug = ctx.params.gameId;
|
|
124087
124388
|
if (!gameIdOrSlug) {
|
|
124088
124389
|
throw ApiError.badRequest("Missing game ID or slug");
|
|
124089
124390
|
}
|
|
124090
|
-
|
|
124391
|
+
logger63.debug("Starting session", { userId: ctx.user.id, gameIdOrSlug, launchId: ctx.launchId });
|
|
124091
124392
|
return ctx.services.session.start(gameIdOrSlug, ctx.user.id);
|
|
124092
124393
|
});
|
|
124093
124394
|
end = requireAuth(async (ctx) => {
|
|
@@ -124099,7 +124400,7 @@ var init_session_controller = __esm(() => {
|
|
|
124099
124400
|
if (!sessionId) {
|
|
124100
124401
|
throw ApiError.badRequest("Missing session ID");
|
|
124101
124402
|
}
|
|
124102
|
-
|
|
124403
|
+
logger63.debug("Ending session", {
|
|
124103
124404
|
userId: ctx.user.id,
|
|
124104
124405
|
gameIdOrSlug,
|
|
124105
124406
|
sessionId,
|
|
@@ -124112,7 +124413,7 @@ var init_session_controller = __esm(() => {
|
|
|
124112
124413
|
if (!gameIdOrSlug) {
|
|
124113
124414
|
throw ApiError.badRequest("Missing game ID or slug");
|
|
124114
124415
|
}
|
|
124115
|
-
|
|
124416
|
+
logger63.debug("Minting token", { userId: ctx.user.id, gameIdOrSlug, launchId: ctx.launchId });
|
|
124116
124417
|
const { token, exp } = await ctx.services.session.mintToken(gameIdOrSlug, ctx.user.id);
|
|
124117
124418
|
let baseUrl;
|
|
124118
124419
|
if (ctx.config.isLocal) {
|
|
@@ -124128,22 +124429,22 @@ var init_session_controller = __esm(() => {
|
|
|
124128
124429
|
mintToken
|
|
124129
124430
|
};
|
|
124130
124431
|
});
|
|
124131
|
-
var
|
|
124432
|
+
var logger64;
|
|
124132
124433
|
var getShopView;
|
|
124133
124434
|
var shop;
|
|
124134
124435
|
var init_shop_controller = __esm(() => {
|
|
124135
124436
|
init_src2();
|
|
124136
124437
|
init_utils11();
|
|
124137
|
-
|
|
124438
|
+
logger64 = log.scope("ShopController");
|
|
124138
124439
|
getShopView = requireNonAnonymous(async (ctx) => {
|
|
124139
|
-
|
|
124440
|
+
logger64.debug("Getting shop view", { userId: ctx.user.id });
|
|
124140
124441
|
return ctx.services.shop.getShopView(ctx.user);
|
|
124141
124442
|
});
|
|
124142
124443
|
shop = {
|
|
124143
124444
|
getShopView
|
|
124144
124445
|
};
|
|
124145
124446
|
});
|
|
124146
|
-
var
|
|
124447
|
+
var logger65;
|
|
124147
124448
|
var list7;
|
|
124148
124449
|
var getById4;
|
|
124149
124450
|
var create5;
|
|
@@ -124162,9 +124463,9 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124162
124463
|
init_src4();
|
|
124163
124464
|
init_errors();
|
|
124164
124465
|
init_utils11();
|
|
124165
|
-
|
|
124466
|
+
logger65 = log.scope("ShopListingController");
|
|
124166
124467
|
list7 = requireAdmin(async (ctx) => {
|
|
124167
|
-
|
|
124468
|
+
logger65.debug("Listing shop listings", { userId: ctx.user.id });
|
|
124168
124469
|
return ctx.services.shopListing.list();
|
|
124169
124470
|
});
|
|
124170
124471
|
getById4 = requireAdmin(async (ctx) => {
|
|
@@ -124175,7 +124476,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124175
124476
|
if (!isValidUUID(listingId)) {
|
|
124176
124477
|
throw ApiError.unprocessableEntity("listingId must be a valid UUID format");
|
|
124177
124478
|
}
|
|
124178
|
-
|
|
124479
|
+
logger65.debug("Getting listing", { userId: ctx.user.id, listingId });
|
|
124179
124480
|
return ctx.services.shopListing.getById(listingId);
|
|
124180
124481
|
});
|
|
124181
124482
|
create5 = requireAdmin(async (ctx) => {
|
|
@@ -124186,12 +124487,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124186
124487
|
} catch (error2) {
|
|
124187
124488
|
if (error2 instanceof exports_external.ZodError) {
|
|
124188
124489
|
const details = formatZodError(error2);
|
|
124189
|
-
|
|
124490
|
+
logger65.warn("Create shop listing validation failed", { details });
|
|
124190
124491
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124191
124492
|
}
|
|
124192
124493
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124193
124494
|
}
|
|
124194
|
-
|
|
124495
|
+
logger65.debug("Creating listing", {
|
|
124195
124496
|
userId: ctx.user.id,
|
|
124196
124497
|
itemId: body2.itemId,
|
|
124197
124498
|
currencyId: body2.currencyId,
|
|
@@ -124214,12 +124515,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124214
124515
|
} catch (error2) {
|
|
124215
124516
|
if (error2 instanceof exports_external.ZodError) {
|
|
124216
124517
|
const details = formatZodError(error2);
|
|
124217
|
-
|
|
124518
|
+
logger65.warn("Update shop listing validation failed", { details });
|
|
124218
124519
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124219
124520
|
}
|
|
124220
124521
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124221
124522
|
}
|
|
124222
|
-
|
|
124523
|
+
logger65.debug("Updating listing", {
|
|
124223
124524
|
userId: ctx.user.id,
|
|
124224
124525
|
listingId,
|
|
124225
124526
|
price: body2.price,
|
|
@@ -124236,7 +124537,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124236
124537
|
if (!isValidUUID(listingId)) {
|
|
124237
124538
|
throw ApiError.unprocessableEntity("listingId must be a valid UUID format");
|
|
124238
124539
|
}
|
|
124239
|
-
|
|
124540
|
+
logger65.debug("Deleting listing", { userId: ctx.user.id, listingId });
|
|
124240
124541
|
await ctx.services.shopListing.delete(listingId);
|
|
124241
124542
|
});
|
|
124242
124543
|
listByGame2 = requireNonAnonymous(async (ctx) => {
|
|
@@ -124247,7 +124548,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124247
124548
|
if (!isValidUUID(gameId)) {
|
|
124248
124549
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
124249
124550
|
}
|
|
124250
|
-
|
|
124551
|
+
logger65.debug("Listing game listings", { userId: ctx.user.id, gameId });
|
|
124251
124552
|
return ctx.services.shopListing.listByGame(gameId, ctx.user);
|
|
124252
124553
|
});
|
|
124253
124554
|
getByGameItem = requireNonAnonymous(async (ctx) => {
|
|
@@ -124262,7 +124563,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124262
124563
|
if (!isValidUUID(itemId)) {
|
|
124263
124564
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
124264
124565
|
}
|
|
124265
|
-
|
|
124566
|
+
logger65.debug("Getting game item listing", { userId: ctx.user.id, gameId, itemId });
|
|
124266
124567
|
return ctx.services.shopListing.getByGameItem(gameId, itemId, ctx.user);
|
|
124267
124568
|
});
|
|
124268
124569
|
createForGameItem = requireNonAnonymous(async (ctx) => {
|
|
@@ -124284,12 +124585,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124284
124585
|
} catch (error2) {
|
|
124285
124586
|
if (error2 instanceof exports_external.ZodError) {
|
|
124286
124587
|
const details = formatZodError(error2);
|
|
124287
|
-
|
|
124588
|
+
logger65.warn("Create game item listing validation failed", { details });
|
|
124288
124589
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124289
124590
|
}
|
|
124290
124591
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124291
124592
|
}
|
|
124292
|
-
|
|
124593
|
+
logger65.debug("Creating game item listing", {
|
|
124293
124594
|
userId: ctx.user.id,
|
|
124294
124595
|
gameId,
|
|
124295
124596
|
itemId,
|
|
@@ -124317,12 +124618,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124317
124618
|
} catch (error2) {
|
|
124318
124619
|
if (error2 instanceof exports_external.ZodError) {
|
|
124319
124620
|
const details = formatZodError(error2);
|
|
124320
|
-
|
|
124621
|
+
logger65.warn("Update game item listing validation failed", { details });
|
|
124321
124622
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124322
124623
|
}
|
|
124323
124624
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124324
124625
|
}
|
|
124325
|
-
|
|
124626
|
+
logger65.debug("Updating game item listing", {
|
|
124326
124627
|
userId: ctx.user.id,
|
|
124327
124628
|
gameId,
|
|
124328
124629
|
itemId,
|
|
@@ -124344,7 +124645,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124344
124645
|
if (!isValidUUID(itemId)) {
|
|
124345
124646
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
124346
124647
|
}
|
|
124347
|
-
|
|
124648
|
+
logger65.debug("Deleting game item listing", {
|
|
124348
124649
|
userId: ctx.user.id,
|
|
124349
124650
|
gameId,
|
|
124350
124651
|
itemId
|
|
@@ -124369,20 +124670,20 @@ async function getBySlug2(ctx) {
|
|
|
124369
124670
|
if (!slug2) {
|
|
124370
124671
|
throw ApiError.badRequest("Template slug is required");
|
|
124371
124672
|
}
|
|
124372
|
-
|
|
124673
|
+
logger66.debug("Getting sprite by slug", { slug: slug2 });
|
|
124373
124674
|
return ctx.services.sprite.getBySlug(slug2);
|
|
124374
124675
|
}
|
|
124375
|
-
var
|
|
124676
|
+
var logger66;
|
|
124376
124677
|
var sprites;
|
|
124377
124678
|
var init_sprite_controller = __esm(() => {
|
|
124378
124679
|
init_src2();
|
|
124379
124680
|
init_errors();
|
|
124380
|
-
|
|
124681
|
+
logger66 = log.scope("SpriteController");
|
|
124381
124682
|
sprites = {
|
|
124382
124683
|
getBySlug: getBySlug2
|
|
124383
124684
|
};
|
|
124384
124685
|
});
|
|
124385
|
-
var
|
|
124686
|
+
var logger67;
|
|
124386
124687
|
var getTodayXp;
|
|
124387
124688
|
var getTotalXp;
|
|
124388
124689
|
var updateTodayXp;
|
|
@@ -124392,6 +124693,8 @@ var getUser;
|
|
|
124392
124693
|
var getUserById;
|
|
124393
124694
|
var setupIntegration;
|
|
124394
124695
|
var getIntegrations;
|
|
124696
|
+
var updateIntegration;
|
|
124697
|
+
var getIntegrationConfig;
|
|
124395
124698
|
var verifyIntegration;
|
|
124396
124699
|
var getConfig2;
|
|
124397
124700
|
var deleteIntegrations;
|
|
@@ -124407,6 +124710,7 @@ var getActivityDetail;
|
|
|
124407
124710
|
var grantXp;
|
|
124408
124711
|
var adjustTime;
|
|
124409
124712
|
var adjustMastery;
|
|
124713
|
+
var reconcileMasteryForConfigChange;
|
|
124410
124714
|
var searchStudents;
|
|
124411
124715
|
var enrollStudent;
|
|
124412
124716
|
var unenrollStudent;
|
|
@@ -124432,15 +124736,15 @@ var init_timeback_controller = __esm(() => {
|
|
|
124432
124736
|
init_src4();
|
|
124433
124737
|
init_errors();
|
|
124434
124738
|
init_utils11();
|
|
124435
|
-
|
|
124739
|
+
logger67 = log.scope("TimebackController");
|
|
124436
124740
|
getTodayXp = requireNonAnonymous(async (ctx) => {
|
|
124437
124741
|
const date4 = ctx.url.searchParams.get("date") || undefined;
|
|
124438
124742
|
const tz = ctx.url.searchParams.get("tz") || undefined;
|
|
124439
|
-
|
|
124743
|
+
logger67.debug("Getting today XP", { userId: ctx.user.id, date: date4, tz });
|
|
124440
124744
|
return ctx.services.timeback.getTodayXp(ctx.user.id, date4, tz);
|
|
124441
124745
|
});
|
|
124442
124746
|
getTotalXp = requireNonAnonymous(async (ctx) => {
|
|
124443
|
-
|
|
124747
|
+
logger67.debug("Getting total XP", { userId: ctx.user.id });
|
|
124444
124748
|
return ctx.services.timeback.getTotalXp(ctx.user.id);
|
|
124445
124749
|
});
|
|
124446
124750
|
updateTodayXp = requireNonAnonymous(async (ctx) => {
|
|
@@ -124451,18 +124755,18 @@ var init_timeback_controller = __esm(() => {
|
|
|
124451
124755
|
} catch (error2) {
|
|
124452
124756
|
if (error2 instanceof exports_external.ZodError) {
|
|
124453
124757
|
const details = formatZodError(error2);
|
|
124454
|
-
|
|
124758
|
+
logger67.warn("Update today XP validation failed", { details });
|
|
124455
124759
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124456
124760
|
}
|
|
124457
124761
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124458
124762
|
}
|
|
124459
|
-
|
|
124763
|
+
logger67.debug("Updating today XP", { userId: ctx.user.id, xp: body2.xp });
|
|
124460
124764
|
return ctx.services.timeback.updateTodayXp(ctx.user.id, body2);
|
|
124461
124765
|
});
|
|
124462
124766
|
getXpHistory = requireNonAnonymous(async (ctx) => {
|
|
124463
124767
|
const startDate = ctx.url.searchParams.get("startDate") || undefined;
|
|
124464
124768
|
const endDate = ctx.url.searchParams.get("endDate") || undefined;
|
|
124465
|
-
|
|
124769
|
+
logger67.debug("Getting XP history", { userId: ctx.user.id, startDate, endDate });
|
|
124466
124770
|
return ctx.services.timeback.getXpHistory(ctx.user.id, startDate, endDate);
|
|
124467
124771
|
});
|
|
124468
124772
|
populateStudent = requireNonAnonymous(async (ctx) => {
|
|
@@ -124473,18 +124777,18 @@ var init_timeback_controller = __esm(() => {
|
|
|
124473
124777
|
} catch (error2) {
|
|
124474
124778
|
if (error2 instanceof exports_external.ZodError) {
|
|
124475
124779
|
const details = formatZodError(error2);
|
|
124476
|
-
|
|
124780
|
+
logger67.warn("Populate student validation failed", { details });
|
|
124477
124781
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124478
124782
|
}
|
|
124479
124783
|
}
|
|
124480
|
-
|
|
124784
|
+
logger67.debug("Populating student", {
|
|
124481
124785
|
userId: ctx.user.id,
|
|
124482
124786
|
hasProvidedNames: Boolean(providedNames)
|
|
124483
124787
|
});
|
|
124484
124788
|
return ctx.services.timeback.populateStudent(ctx.user, providedNames);
|
|
124485
124789
|
});
|
|
124486
124790
|
getUser = requireNonAnonymous(async (ctx) => {
|
|
124487
|
-
|
|
124791
|
+
logger67.debug("Getting user", { userId: ctx.user.id, gameId: ctx.gameId });
|
|
124488
124792
|
return ctx.services.timeback.getUserData(ctx.user.id, ctx.gameId);
|
|
124489
124793
|
});
|
|
124490
124794
|
getUserById = requireNonAnonymous(async (ctx) => {
|
|
@@ -124492,7 +124796,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124492
124796
|
if (!timebackId) {
|
|
124493
124797
|
throw ApiError.badRequest("Missing timebackId parameter");
|
|
124494
124798
|
}
|
|
124495
|
-
|
|
124799
|
+
logger67.debug("Getting user by ID", { requesterId: ctx.user.id, timebackId });
|
|
124496
124800
|
return ctx.services.timeback.getUserDataByTimebackId(timebackId);
|
|
124497
124801
|
});
|
|
124498
124802
|
setupIntegration = requireDeveloper(async (ctx) => {
|
|
@@ -124503,12 +124807,12 @@ var init_timeback_controller = __esm(() => {
|
|
|
124503
124807
|
} catch (error2) {
|
|
124504
124808
|
if (error2 instanceof exports_external.ZodError) {
|
|
124505
124809
|
const details = formatZodError(error2);
|
|
124506
|
-
|
|
124810
|
+
logger67.warn("Setup integration validation failed", { details });
|
|
124507
124811
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124508
124812
|
}
|
|
124509
124813
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124510
124814
|
}
|
|
124511
|
-
|
|
124815
|
+
logger67.debug("Setting up integration", {
|
|
124512
124816
|
userId: ctx.user.id,
|
|
124513
124817
|
gameId: body2.gameId
|
|
124514
124818
|
});
|
|
@@ -124522,9 +124826,37 @@ var init_timeback_controller = __esm(() => {
|
|
|
124522
124826
|
if (!isValidUUID(gameId)) {
|
|
124523
124827
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124524
124828
|
}
|
|
124525
|
-
|
|
124829
|
+
logger67.debug("Getting integrations", { userId: ctx.user.id, gameId });
|
|
124526
124830
|
return ctx.services.timeback.getIntegrations(gameId, ctx.user);
|
|
124527
124831
|
});
|
|
124832
|
+
updateIntegration = requireDeveloper(async (ctx) => {
|
|
124833
|
+
const { gameId, courseId } = ctx.params;
|
|
124834
|
+
if (!gameId || !courseId) {
|
|
124835
|
+
throw ApiError.badRequest("Missing gameId or courseId parameter");
|
|
124836
|
+
}
|
|
124837
|
+
if (!isValidUUID(gameId)) {
|
|
124838
|
+
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124839
|
+
}
|
|
124840
|
+
const body2 = await parseRequestBody(ctx.request, UpdateGameTimebackIntegrationRequestSchema);
|
|
124841
|
+
logger67.debug("Updating integration", {
|
|
124842
|
+
userId: ctx.user.id,
|
|
124843
|
+
gameId,
|
|
124844
|
+
courseId,
|
|
124845
|
+
fields: Object.keys(body2)
|
|
124846
|
+
});
|
|
124847
|
+
return ctx.services.timeback.updateIntegration(gameId, courseId, ctx.user, body2);
|
|
124848
|
+
});
|
|
124849
|
+
getIntegrationConfig = requireGameManagementAccess(async (ctx) => {
|
|
124850
|
+
const { gameId, courseId } = ctx.params;
|
|
124851
|
+
if (!gameId || !courseId) {
|
|
124852
|
+
throw ApiError.badRequest("Missing gameId or courseId parameter");
|
|
124853
|
+
}
|
|
124854
|
+
if (!isValidUUID(gameId)) {
|
|
124855
|
+
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124856
|
+
}
|
|
124857
|
+
logger67.debug("Getting integration config", { userId: ctx.user.id, gameId, courseId });
|
|
124858
|
+
return ctx.services.timeback.getIntegrationConfig(gameId, courseId, ctx.user);
|
|
124859
|
+
});
|
|
124528
124860
|
verifyIntegration = requireDeveloper(async (ctx) => {
|
|
124529
124861
|
const gameId = ctx.params.gameId;
|
|
124530
124862
|
if (!gameId) {
|
|
@@ -124533,7 +124865,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124533
124865
|
if (!isValidUUID(gameId)) {
|
|
124534
124866
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124535
124867
|
}
|
|
124536
|
-
|
|
124868
|
+
logger67.debug("Verifying integration", { userId: ctx.user.id, gameId });
|
|
124537
124869
|
return ctx.services.timeback.verifyIntegration(gameId, ctx.user);
|
|
124538
124870
|
});
|
|
124539
124871
|
getConfig2 = requireDeveloper(async (ctx) => {
|
|
@@ -124544,7 +124876,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124544
124876
|
if (!isValidUUID(gameId)) {
|
|
124545
124877
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124546
124878
|
}
|
|
124547
|
-
|
|
124879
|
+
logger67.debug("Getting config", { userId: ctx.user.id, gameId });
|
|
124548
124880
|
return ctx.services.timeback.getConfig(gameId, ctx.user);
|
|
124549
124881
|
});
|
|
124550
124882
|
deleteIntegrations = requireDeveloper(async (ctx) => {
|
|
@@ -124555,7 +124887,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124555
124887
|
if (!isValidUUID(gameId)) {
|
|
124556
124888
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124557
124889
|
}
|
|
124558
|
-
|
|
124890
|
+
logger67.debug("Deleting integrations", { userId: ctx.user.id, gameId });
|
|
124559
124891
|
await ctx.services.timeback.deleteIntegrations(gameId, ctx.user);
|
|
124560
124892
|
});
|
|
124561
124893
|
endActivity = requireDeveloper(async (ctx) => {
|
|
@@ -124566,7 +124898,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124566
124898
|
} catch (error2) {
|
|
124567
124899
|
if (error2 instanceof exports_external.ZodError) {
|
|
124568
124900
|
const details = formatZodError(error2);
|
|
124569
|
-
|
|
124901
|
+
logger67.warn("End activity validation failed", { details });
|
|
124570
124902
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124571
124903
|
}
|
|
124572
124904
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -124584,7 +124916,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124584
124916
|
masteredUnits,
|
|
124585
124917
|
extensions
|
|
124586
124918
|
} = body2;
|
|
124587
|
-
|
|
124919
|
+
logger67.debug("Ending activity", { userId: ctx.user.id, gameId });
|
|
124588
124920
|
return ctx.services.timeback.endActivity({
|
|
124589
124921
|
gameId,
|
|
124590
124922
|
studentId,
|
|
@@ -124608,7 +124940,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124608
124940
|
} catch (error2) {
|
|
124609
124941
|
if (error2 instanceof exports_external.ZodError) {
|
|
124610
124942
|
const details = formatZodError(error2);
|
|
124611
|
-
|
|
124943
|
+
logger67.warn("Heartbeat validation failed", { details });
|
|
124612
124944
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124613
124945
|
}
|
|
124614
124946
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -124624,7 +124956,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124624
124956
|
windowSequence,
|
|
124625
124957
|
isFinal
|
|
124626
124958
|
} = body2;
|
|
124627
|
-
|
|
124959
|
+
logger67.debug("Recording heartbeat", {
|
|
124628
124960
|
userId: ctx.user.id,
|
|
124629
124961
|
gameId,
|
|
124630
124962
|
runId,
|
|
@@ -124649,7 +124981,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124649
124981
|
});
|
|
124650
124982
|
advanceCourse = requireDeveloper(async (ctx) => {
|
|
124651
124983
|
const body2 = await parseRequestBody(ctx.request, AdvanceCourseRequestSchema);
|
|
124652
|
-
|
|
124984
|
+
logger67.debug("Advancing student manually", {
|
|
124653
124985
|
userId: ctx.user.id,
|
|
124654
124986
|
gameId: body2.gameId,
|
|
124655
124987
|
studentId: body2.studentId,
|
|
@@ -124690,7 +125022,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124690
125022
|
perCourse: includeOptions.includes("percourse"),
|
|
124691
125023
|
today: includeOptions.includes("today")
|
|
124692
125024
|
};
|
|
124693
|
-
|
|
125025
|
+
logger67.debug("Getting student XP", {
|
|
124694
125026
|
requesterId: ctx.user.id,
|
|
124695
125027
|
timebackId,
|
|
124696
125028
|
gameId,
|
|
@@ -124712,7 +125044,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124712
125044
|
if (!gameId || !courseId) {
|
|
124713
125045
|
throw ApiError.badRequest("Missing gameId or courseId parameter");
|
|
124714
125046
|
}
|
|
124715
|
-
|
|
125047
|
+
logger67.debug("Getting course roster", {
|
|
124716
125048
|
requesterId: ctx.user.id,
|
|
124717
125049
|
gameId,
|
|
124718
125050
|
courseId,
|
|
@@ -124729,7 +125061,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124729
125061
|
if (!timebackId || !gameId) {
|
|
124730
125062
|
throw ApiError.badRequest("Missing timebackId parameter or gameId query parameter");
|
|
124731
125063
|
}
|
|
124732
|
-
|
|
125064
|
+
logger67.debug("Getting student overview", {
|
|
124733
125065
|
requesterId: ctx.user.id,
|
|
124734
125066
|
timebackId,
|
|
124735
125067
|
gameId,
|
|
@@ -124743,7 +125075,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124743
125075
|
if (!gameId || !timebackId) {
|
|
124744
125076
|
throw ApiError.badRequest("Missing gameId or timebackId path parameter");
|
|
124745
125077
|
}
|
|
124746
|
-
|
|
125078
|
+
logger67.debug("Getting game metrics", {
|
|
124747
125079
|
requesterId: ctx.user.id,
|
|
124748
125080
|
gameId,
|
|
124749
125081
|
timebackId
|
|
@@ -124761,7 +125093,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124761
125093
|
if (!timebackId || !courseId || !gameId) {
|
|
124762
125094
|
throw ApiError.badRequest("Missing timebackId or courseId path parameter, or gameId query parameter");
|
|
124763
125095
|
}
|
|
124764
|
-
|
|
125096
|
+
logger67.debug("Getting student activity", {
|
|
124765
125097
|
requesterId: ctx.user.id,
|
|
124766
125098
|
timebackId,
|
|
124767
125099
|
courseId,
|
|
@@ -124786,7 +125118,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124786
125118
|
if (!timebackId || !courseId || !activityId || !gameId) {
|
|
124787
125119
|
throw ApiError.badRequest("Missing timebackId, courseId, or activityId path parameter, or gameId query parameter");
|
|
124788
125120
|
}
|
|
124789
|
-
|
|
125121
|
+
logger67.debug("Getting activity detail", {
|
|
124790
125122
|
requesterId: ctx.user.id,
|
|
124791
125123
|
timebackId,
|
|
124792
125124
|
courseId,
|
|
@@ -124804,7 +125136,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124804
125136
|
});
|
|
124805
125137
|
grantXp = requireDeveloper(async (ctx) => {
|
|
124806
125138
|
const body2 = await parseRequestBody(ctx.request, GrantTimebackXpRequestSchema);
|
|
124807
|
-
|
|
125139
|
+
logger67.debug("Granting manual XP", {
|
|
124808
125140
|
requesterId: ctx.user.id,
|
|
124809
125141
|
gameId: body2.gameId,
|
|
124810
125142
|
courseId: body2.courseId,
|
|
@@ -124816,7 +125148,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124816
125148
|
});
|
|
124817
125149
|
adjustTime = requireDeveloper(async (ctx) => {
|
|
124818
125150
|
const body2 = await parseRequestBody(ctx.request, AdjustTimebackTimeRequestSchema);
|
|
124819
|
-
|
|
125151
|
+
logger67.debug("Adjusting time spent", {
|
|
124820
125152
|
requesterId: ctx.user.id,
|
|
124821
125153
|
gameId: body2.gameId,
|
|
124822
125154
|
courseId: body2.courseId,
|
|
@@ -124828,7 +125160,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124828
125160
|
});
|
|
124829
125161
|
adjustMastery = requireDeveloper(async (ctx) => {
|
|
124830
125162
|
const body2 = await parseRequestBody(ctx.request, AdjustTimebackMasteryRequestSchema);
|
|
124831
|
-
|
|
125163
|
+
logger67.debug("Adjusting mastered units", {
|
|
124832
125164
|
requesterId: ctx.user.id,
|
|
124833
125165
|
gameId: body2.gameId,
|
|
124834
125166
|
courseId: body2.courseId,
|
|
@@ -124838,6 +125170,22 @@ var init_timeback_controller = __esm(() => {
|
|
|
124838
125170
|
});
|
|
124839
125171
|
return ctx.services.timebackAdmin.adjustMasteredUnits(body2, ctx.user);
|
|
124840
125172
|
});
|
|
125173
|
+
reconcileMasteryForConfigChange = requireDeveloper(async (ctx) => {
|
|
125174
|
+
const body2 = await parseRequestBody(ctx.request, ReconcileMasteryForConfigChangeSchema);
|
|
125175
|
+
logger67.debug("Reconciling mastery completion for config change", {
|
|
125176
|
+
requesterId: ctx.user.id,
|
|
125177
|
+
gameId: body2.gameId,
|
|
125178
|
+
courseId: body2.courseId,
|
|
125179
|
+
oldMasterableUnits: body2.oldMasterableUnits,
|
|
125180
|
+
newMasterableUnits: body2.newMasterableUnits,
|
|
125181
|
+
affectedCount: body2.affectedStudentIds.length
|
|
125182
|
+
});
|
|
125183
|
+
return ctx.services.timebackAdmin.reconcileMasteryForConfigChange(body2.gameId, body2.courseId, ctx.user, {
|
|
125184
|
+
oldMasterableUnits: body2.oldMasterableUnits,
|
|
125185
|
+
newMasterableUnits: body2.newMasterableUnits,
|
|
125186
|
+
affectedStudentIds: body2.affectedStudentIds
|
|
125187
|
+
});
|
|
125188
|
+
});
|
|
124841
125189
|
searchStudents = requireGameManagementAccess(async (ctx) => {
|
|
124842
125190
|
const gameId = ctx.params.gameId;
|
|
124843
125191
|
const courseId = ctx.params.courseId;
|
|
@@ -124845,7 +125193,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124845
125193
|
if (!gameId || !courseId) {
|
|
124846
125194
|
throw ApiError.badRequest("Missing gameId or courseId parameter");
|
|
124847
125195
|
}
|
|
124848
|
-
|
|
125196
|
+
logger67.debug("Searching students for enrollment", {
|
|
124849
125197
|
requesterId: ctx.user.id,
|
|
124850
125198
|
gameId,
|
|
124851
125199
|
courseId,
|
|
@@ -124855,7 +125203,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124855
125203
|
});
|
|
124856
125204
|
enrollStudent = requireGameManagementAccess(async (ctx) => {
|
|
124857
125205
|
const body2 = await parseRequestBody(ctx.request, EnrollStudentRequestSchema);
|
|
124858
|
-
|
|
125206
|
+
logger67.debug("Enrolling student", {
|
|
124859
125207
|
requesterId: ctx.user.id,
|
|
124860
125208
|
gameId: body2.gameId,
|
|
124861
125209
|
courseId: body2.courseId,
|
|
@@ -124865,7 +125213,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124865
125213
|
});
|
|
124866
125214
|
unenrollStudent = requireGameManagementAccess(async (ctx) => {
|
|
124867
125215
|
const body2 = await parseRequestBody(ctx.request, UnenrollStudentRequestSchema);
|
|
124868
|
-
|
|
125216
|
+
logger67.debug("Unenrolling student", {
|
|
124869
125217
|
requesterId: ctx.user.id,
|
|
124870
125218
|
gameId: body2.gameId,
|
|
124871
125219
|
courseId: body2.courseId,
|
|
@@ -124875,7 +125223,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124875
125223
|
});
|
|
124876
125224
|
reactivateEnrollment = requireGameManagementAccess(async (ctx) => {
|
|
124877
125225
|
const body2 = await parseRequestBody(ctx.request, ReactivateEnrollmentRequestSchema);
|
|
124878
|
-
|
|
125226
|
+
logger67.debug("Reactivating enrollment", {
|
|
124879
125227
|
requesterId: ctx.user.id,
|
|
124880
125228
|
gameId: body2.gameId,
|
|
124881
125229
|
courseId: body2.courseId,
|
|
@@ -125015,6 +125363,8 @@ var init_timeback_controller = __esm(() => {
|
|
|
125015
125363
|
getUserById,
|
|
125016
125364
|
setupIntegration,
|
|
125017
125365
|
getIntegrations,
|
|
125366
|
+
updateIntegration,
|
|
125367
|
+
getIntegrationConfig,
|
|
125018
125368
|
verifyIntegration,
|
|
125019
125369
|
getConfig: getConfig2,
|
|
125020
125370
|
deleteIntegrations,
|
|
@@ -125030,6 +125380,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
125030
125380
|
grantXp,
|
|
125031
125381
|
adjustTime,
|
|
125032
125382
|
adjustMastery,
|
|
125383
|
+
reconcileMasteryForConfigChange,
|
|
125033
125384
|
searchStudents,
|
|
125034
125385
|
enrollStudent,
|
|
125035
125386
|
unenrollStudent,
|
|
@@ -125049,7 +125400,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
125049
125400
|
destroyAssessmentBank
|
|
125050
125401
|
};
|
|
125051
125402
|
});
|
|
125052
|
-
var
|
|
125403
|
+
var logger68;
|
|
125053
125404
|
var initiate;
|
|
125054
125405
|
var init_upload_controller = __esm(() => {
|
|
125055
125406
|
init_esm();
|
|
@@ -125057,7 +125408,7 @@ var init_upload_controller = __esm(() => {
|
|
|
125057
125408
|
init_src2();
|
|
125058
125409
|
init_errors();
|
|
125059
125410
|
init_utils11();
|
|
125060
|
-
|
|
125411
|
+
logger68 = log.scope("UploadController");
|
|
125061
125412
|
initiate = requireDeveloper(async (ctx) => {
|
|
125062
125413
|
let body2;
|
|
125063
125414
|
try {
|
|
@@ -125066,16 +125417,16 @@ var init_upload_controller = __esm(() => {
|
|
|
125066
125417
|
} catch (error2) {
|
|
125067
125418
|
if (error2 instanceof exports_external.ZodError) {
|
|
125068
125419
|
const details = formatZodError(error2);
|
|
125069
|
-
|
|
125420
|
+
logger68.warn("Initiate upload validation failed", { details });
|
|
125070
125421
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
125071
125422
|
}
|
|
125072
125423
|
throw ApiError.badRequest("Invalid JSON body");
|
|
125073
125424
|
}
|
|
125074
|
-
|
|
125425
|
+
logger68.debug("Initiating upload", { userId: ctx.user.id, gameId: body2.gameId });
|
|
125075
125426
|
return ctx.services.upload.initiate(body2, ctx.user);
|
|
125076
125427
|
});
|
|
125077
125428
|
});
|
|
125078
|
-
var
|
|
125429
|
+
var logger69;
|
|
125079
125430
|
var getMe;
|
|
125080
125431
|
var getDemoProfile;
|
|
125081
125432
|
var updateDemoProfile;
|
|
@@ -125084,18 +125435,18 @@ var init_user_controller = __esm(() => {
|
|
|
125084
125435
|
init_schemas_index();
|
|
125085
125436
|
init_src2();
|
|
125086
125437
|
init_utils11();
|
|
125087
|
-
|
|
125438
|
+
logger69 = log.scope("UserController");
|
|
125088
125439
|
getMe = requireNonAnonymous(async (ctx) => {
|
|
125089
|
-
|
|
125440
|
+
logger69.debug("Getting current user", { userId: ctx.user.id, gameId: ctx.gameId });
|
|
125090
125441
|
return ctx.services.user.getMe(ctx.user, ctx.gameId);
|
|
125091
125442
|
});
|
|
125092
125443
|
getDemoProfile = requireAnonymous(async (ctx) => {
|
|
125093
|
-
|
|
125444
|
+
logger69.debug("Getting demo profile", { userId: ctx.user.id });
|
|
125094
125445
|
return ctx.services.user.getDemoProfile(ctx.user.id);
|
|
125095
125446
|
});
|
|
125096
125447
|
updateDemoProfile = requireAnonymous(async (ctx) => {
|
|
125097
125448
|
const body2 = await parseRequestBody(ctx.request, DemoProfileSchema);
|
|
125098
|
-
|
|
125449
|
+
logger69.debug("Updating demo profile", {
|
|
125099
125450
|
userId: ctx.user.id,
|
|
125100
125451
|
displayName: body2.displayName
|
|
125101
125452
|
});
|
|
@@ -125107,13 +125458,13 @@ var init_user_controller = __esm(() => {
|
|
|
125107
125458
|
updateDemoProfile
|
|
125108
125459
|
};
|
|
125109
125460
|
});
|
|
125110
|
-
var
|
|
125461
|
+
var logger70;
|
|
125111
125462
|
var init_verify_controller = __esm(() => {
|
|
125112
125463
|
init_schemas_index();
|
|
125113
125464
|
init_src2();
|
|
125114
125465
|
init_errors();
|
|
125115
125466
|
init_utils11();
|
|
125116
|
-
|
|
125467
|
+
logger70 = log.scope("VerifyController");
|
|
125117
125468
|
});
|
|
125118
125469
|
var init_controllers = __esm(() => {
|
|
125119
125470
|
init_achievement_controller();
|
|
@@ -125411,7 +125762,7 @@ var init_uploads = __esm(() => {
|
|
|
125411
125762
|
gameUploadsRouter.post("/uploads/finalize", finalizeHandler);
|
|
125412
125763
|
gameUploadsRouter.post("/uploads/finalize/", finalizeHandler);
|
|
125413
125764
|
});
|
|
125414
|
-
var
|
|
125765
|
+
var logger71;
|
|
125415
125766
|
var gameDeployRouter;
|
|
125416
125767
|
var init_deploy = __esm(() => {
|
|
125417
125768
|
init_drizzle_orm();
|
|
@@ -125422,7 +125773,7 @@ var init_deploy = __esm(() => {
|
|
|
125422
125773
|
init_src2();
|
|
125423
125774
|
init_api();
|
|
125424
125775
|
init_uploads();
|
|
125425
|
-
|
|
125776
|
+
logger71 = log.scope("SandboxDeploy");
|
|
125426
125777
|
gameDeployRouter = new Hono2;
|
|
125427
125778
|
gameDeployRouter.post("/:slug/deploy", async (c2) => {
|
|
125428
125779
|
const user = c2.get("user");
|
|
@@ -125548,7 +125899,7 @@ var init_deploy = __esm(() => {
|
|
|
125548
125899
|
completedAt: now2
|
|
125549
125900
|
};
|
|
125550
125901
|
const [insertedJob] = await db2.insert(gameDeployJobs).values([jobValues]).returning();
|
|
125551
|
-
|
|
125902
|
+
logger71.info("Mock deploy job completed", { jobId: insertedJob.id, slug: slug2 });
|
|
125552
125903
|
return c2.json({
|
|
125553
125904
|
id: insertedJob.id,
|
|
125554
125905
|
status: "succeeded",
|
|
@@ -126119,7 +126470,7 @@ var init_timeback6 = __esm(() => {
|
|
|
126119
126470
|
return {
|
|
126120
126471
|
grade: e.grade,
|
|
126121
126472
|
subject: e.subject,
|
|
126122
|
-
title: `${e.subject}
|
|
126473
|
+
title: `${e.subject} ${formatGradeLabel(e.grade)}`,
|
|
126123
126474
|
totalXp: totalXp2,
|
|
126124
126475
|
...includeToday && { todayXp: todayXp2 }
|
|
126125
126476
|
};
|
|
@@ -126146,7 +126497,7 @@ function verifyMockToken(idToken) {
|
|
|
126146
126497
|
throw new Error("Invalid LTI token format");
|
|
126147
126498
|
}
|
|
126148
126499
|
}
|
|
126149
|
-
var
|
|
126500
|
+
var logger72;
|
|
126150
126501
|
var ltiRouter;
|
|
126151
126502
|
var init_lti = __esm(() => {
|
|
126152
126503
|
init_drizzle_orm();
|
|
@@ -126157,7 +126508,7 @@ var init_lti = __esm(() => {
|
|
|
126157
126508
|
init_src2();
|
|
126158
126509
|
init_constants();
|
|
126159
126510
|
init_api();
|
|
126160
|
-
|
|
126511
|
+
logger72 = log.scope("SandboxLti");
|
|
126161
126512
|
ltiRouter = new Hono2;
|
|
126162
126513
|
ltiRouter.post("/launch", async (c2) => {
|
|
126163
126514
|
const db2 = c2.get("db");
|
|
@@ -126175,7 +126526,7 @@ var init_lti = __esm(() => {
|
|
|
126175
126526
|
claims = verifyMockToken(idToken);
|
|
126176
126527
|
} catch (error2) {
|
|
126177
126528
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
126178
|
-
|
|
126529
|
+
logger72.error("LTI token verification failed", { error: errorMessage });
|
|
126179
126530
|
return c2.json({
|
|
126180
126531
|
error: "invalid_token",
|
|
126181
126532
|
message: errorMessage
|
|
@@ -126183,7 +126534,7 @@ var init_lti = __esm(() => {
|
|
|
126183
126534
|
}
|
|
126184
126535
|
const validationError = validateLtiClaims(claims);
|
|
126185
126536
|
if (validationError) {
|
|
126186
|
-
|
|
126537
|
+
logger72.warn("LTI claims validation failed", {
|
|
126187
126538
|
error: validationError,
|
|
126188
126539
|
sub: claims.sub
|
|
126189
126540
|
});
|
|
@@ -126203,7 +126554,7 @@ var init_lti = __esm(() => {
|
|
|
126203
126554
|
createdAt: new Date,
|
|
126204
126555
|
updatedAt: new Date
|
|
126205
126556
|
});
|
|
126206
|
-
|
|
126557
|
+
logger72.info("LTI launch successful", { userId: user.id });
|
|
126207
126558
|
const targetUri = claims["https://purl.imsglobal.org/spec/lti/claim/target_link_uri"];
|
|
126208
126559
|
const currentHost = new URL(c2.req.url).hostname;
|
|
126209
126560
|
const redirectPath = extractRedirectPath(targetUri, currentHost);
|
|
@@ -126211,7 +126562,7 @@ var init_lti = __esm(() => {
|
|
|
126211
126562
|
return c2.redirect(redirectPath);
|
|
126212
126563
|
} catch (error2) {
|
|
126213
126564
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
126214
|
-
|
|
126565
|
+
logger72.error("Unexpected error during LTI launch", { error: errorMessage });
|
|
126215
126566
|
return c2.json({
|
|
126216
126567
|
error: "unexpected_error",
|
|
126217
126568
|
message: "An unexpected error occurred during LTI launch"
|
|
@@ -127885,7 +128236,7 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
|
127885
128236
|
// package.json
|
|
127886
128237
|
var package_default2 = {
|
|
127887
128238
|
name: "@playcademy/vite-plugin",
|
|
127888
|
-
version: "0.2.
|
|
128239
|
+
version: "0.2.35-beta.1",
|
|
127889
128240
|
type: "module",
|
|
127890
128241
|
exports: {
|
|
127891
128242
|
".": {
|