@playcademy/vite-plugin 0.2.34 → 0.2.35-beta.2
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 +844 -501
- package/package.json +1 -1
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.2",
|
|
25357
25357
|
description: "Local development server for Playcademy game development",
|
|
25358
25358
|
type: "module",
|
|
25359
25359
|
exports: {
|
|
@@ -30030,7 +30030,8 @@ var init_schema = __esm(() => {
|
|
|
30030
30030
|
ltiTestMode: exports_external.boolean().default(false),
|
|
30031
30031
|
realtime: realtimeConfigSchema.optional(),
|
|
30032
30032
|
platformServiceJwt: platformServiceJwtConfigSchema.optional(),
|
|
30033
|
-
uploadBucket: exports_external.string().optional()
|
|
30033
|
+
uploadBucket: exports_external.string().optional(),
|
|
30034
|
+
queueIngressSecret: exports_external.string().optional()
|
|
30034
30035
|
});
|
|
30035
30036
|
});
|
|
30036
30037
|
var init_config2 = __esm(() => {
|
|
@@ -50287,6 +50288,14 @@ class DeployService {
|
|
|
50287
50288
|
await cf.setSecrets(deploymentId, { PLAYCADEMY_API_KEY: apiKey });
|
|
50288
50289
|
logger3.info("Set API key on worker", { slug, deploymentId });
|
|
50289
50290
|
}
|
|
50291
|
+
async ensureQueueIngressSecretOnWorker(slug, deploymentId) {
|
|
50292
|
+
const secret = this.deps.config.queueIngressSecret;
|
|
50293
|
+
if (!secret) {
|
|
50294
|
+
return;
|
|
50295
|
+
}
|
|
50296
|
+
const cf = this.getCloudflare();
|
|
50297
|
+
await cf.setSecrets(deploymentId, { QUEUE_INGRESS_SECRET: secret });
|
|
50298
|
+
}
|
|
50290
50299
|
async fetchAndExtractFrontendAssets(slug, gameId, uploadToken, uploadDeps, extractZip) {
|
|
50291
50300
|
const frontendZip = await this.timeStep("Fetch temporary files", () => uploadDeps.getObjectAsByteArray(uploadToken), { slug });
|
|
50292
50301
|
if (!frontendZip || frontendZip.length === 0) {
|
|
@@ -50369,7 +50378,10 @@ class DeployService {
|
|
|
50369
50378
|
const codeHash = hasBackend ? await generateDeploymentHash(request.code) : null;
|
|
50370
50379
|
await this.saveDeployment(game.id, result.deploymentId, result.url, codeHash, result.resources);
|
|
50371
50380
|
if (hasBackend) {
|
|
50372
|
-
await this.timeStep("Configure worker secrets", () =>
|
|
50381
|
+
await this.timeStep("Configure worker secrets", async () => {
|
|
50382
|
+
await this.ensureApiKeyOnWorker(user, slug, result.deploymentId);
|
|
50383
|
+
await this.ensureQueueIngressSecretOnWorker(slug, result.deploymentId);
|
|
50384
|
+
}, { slug, deploymentId: result.deploymentId });
|
|
50373
50385
|
}
|
|
50374
50386
|
if (hasMetadata || hasFrontend) {
|
|
50375
50387
|
await this.applyGameMetadata(game.id, request, hasFrontend, hasMetadata, result.url);
|
|
@@ -55125,6 +55137,8 @@ var TIMEBACK_SUBJECTS4;
|
|
|
55125
55137
|
var TimebackGradeSchema;
|
|
55126
55138
|
var TimebackSubjectSchema;
|
|
55127
55139
|
var UpdateTimebackXpRequestSchema;
|
|
55140
|
+
var CourseGoalsSchema;
|
|
55141
|
+
var UpdateGameTimebackIntegrationRequestSchema;
|
|
55128
55142
|
var TimebackActivityDataSchema;
|
|
55129
55143
|
var EndActivityRequestSchema;
|
|
55130
55144
|
var GameActivityMetricsSchema;
|
|
@@ -55144,6 +55158,7 @@ var ADMIN_GRANT_XP_AMOUNT_RANGE_MESSAGE;
|
|
|
55144
55158
|
var GrantTimebackXpRequestSchema;
|
|
55145
55159
|
var AdjustTimebackTimeRequestSchema;
|
|
55146
55160
|
var AdjustTimebackMasteryRequestSchema;
|
|
55161
|
+
var ReconcileMasteryForConfigChangeSchema;
|
|
55147
55162
|
var EnrollStudentRequestSchema;
|
|
55148
55163
|
var UnenrollStudentRequestSchema;
|
|
55149
55164
|
var ReactivateEnrollmentRequestSchema;
|
|
@@ -55175,6 +55190,24 @@ var init_schemas11 = __esm(() => {
|
|
|
55175
55190
|
xp: exports_external.number().min(0, "XP must be a non-negative number"),
|
|
55176
55191
|
userTimestamp: exports_external.string().datetime().optional()
|
|
55177
55192
|
});
|
|
55193
|
+
CourseGoalsSchema = exports_external.object({
|
|
55194
|
+
dailyXp: exports_external.number().int().nonnegative().nullable().optional(),
|
|
55195
|
+
dailyLessons: exports_external.number().int().nonnegative().nullable().optional(),
|
|
55196
|
+
dailyActiveMinutes: exports_external.number().int().nonnegative().nullable().optional(),
|
|
55197
|
+
dailyAccuracy: exports_external.number().int().min(0).max(100).nullable().optional(),
|
|
55198
|
+
dailyMasteredUnits: exports_external.number().int().nonnegative().nullable().optional()
|
|
55199
|
+
});
|
|
55200
|
+
UpdateGameTimebackIntegrationRequestSchema = exports_external.object({
|
|
55201
|
+
title: exports_external.string().trim().min(1).optional(),
|
|
55202
|
+
courseCode: exports_external.string().trim().min(1).optional(),
|
|
55203
|
+
subject: TimebackSubjectSchema.optional(),
|
|
55204
|
+
totalXp: exports_external.number().int().nonnegative().nullable().optional(),
|
|
55205
|
+
masterableUnits: exports_external.number().int().nonnegative().nullable().optional(),
|
|
55206
|
+
goals: CourseGoalsSchema.optional(),
|
|
55207
|
+
publishStatus: exports_external.enum(["draft", "testing", "published", "deactivated"]).nullable().optional(),
|
|
55208
|
+
isSupplemental: exports_external.boolean().optional(),
|
|
55209
|
+
timebackVisible: exports_external.boolean().nullable().optional()
|
|
55210
|
+
});
|
|
55178
55211
|
TimebackActivityDataSchema = exports_external.object({
|
|
55179
55212
|
activityId: exports_external.string().min(1),
|
|
55180
55213
|
activityName: exports_external.string().optional(),
|
|
@@ -55344,6 +55377,13 @@ var init_schemas11 = __esm(() => {
|
|
|
55344
55377
|
date: AdminAttributionDateSchema.optional(),
|
|
55345
55378
|
useCurrentTime: exports_external.boolean().optional()
|
|
55346
55379
|
});
|
|
55380
|
+
ReconcileMasteryForConfigChangeSchema = exports_external.object({
|
|
55381
|
+
gameId: exports_external.string().uuid(),
|
|
55382
|
+
courseId: exports_external.string().min(1),
|
|
55383
|
+
oldMasterableUnits: exports_external.number().int().positive(),
|
|
55384
|
+
newMasterableUnits: exports_external.number().int().positive(),
|
|
55385
|
+
affectedStudentIds: exports_external.array(exports_external.string().min(1)).min(1).max(500)
|
|
55386
|
+
});
|
|
55347
55387
|
EnrollStudentRequestSchema = exports_external.object({
|
|
55348
55388
|
gameId: exports_external.string().uuid(),
|
|
55349
55389
|
courseId: exports_external.string().min(1),
|
|
@@ -55492,6 +55532,63 @@ function compareEnrollmentsByRecency(a, b) {
|
|
|
55492
55532
|
var init_timeback_admin_util = __esm(() => {
|
|
55493
55533
|
init_errors();
|
|
55494
55534
|
});
|
|
55535
|
+
async function upsertMasteryCompletionEntry(params) {
|
|
55536
|
+
const { client, courseId, studentId, appName, action } = params;
|
|
55537
|
+
const ids = deriveSourcedIds(courseId);
|
|
55538
|
+
const lineItemId = `${ids.course}-mastery-completion-assessment`;
|
|
55539
|
+
const resultId = `${lineItemId}:${studentId}:completion`;
|
|
55540
|
+
if (action === "complete") {
|
|
55541
|
+
await client.oneroster.assessmentLineItems.findOrCreate(lineItemId, {
|
|
55542
|
+
sourcedId: lineItemId,
|
|
55543
|
+
title: "Mastery Completion",
|
|
55544
|
+
status: ONEROSTER_STATUS.active,
|
|
55545
|
+
course: { sourcedId: ids.course },
|
|
55546
|
+
...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
|
|
55547
|
+
});
|
|
55548
|
+
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
55549
|
+
sourcedId: resultId,
|
|
55550
|
+
status: ONEROSTER_STATUS.active,
|
|
55551
|
+
assessmentLineItem: { sourcedId: lineItemId },
|
|
55552
|
+
student: { sourcedId: studentId },
|
|
55553
|
+
score: 100,
|
|
55554
|
+
scoreDate: new Date().toISOString(),
|
|
55555
|
+
scoreStatus: SCORE_STATUS.fullyGraded,
|
|
55556
|
+
inProgress: "false",
|
|
55557
|
+
metadata: {
|
|
55558
|
+
isMasteryCompletion: true,
|
|
55559
|
+
adminAction: true,
|
|
55560
|
+
appName
|
|
55561
|
+
}
|
|
55562
|
+
});
|
|
55563
|
+
} else {
|
|
55564
|
+
try {
|
|
55565
|
+
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
55566
|
+
sourcedId: resultId,
|
|
55567
|
+
status: ONEROSTER_STATUS.active,
|
|
55568
|
+
assessmentLineItem: { sourcedId: lineItemId },
|
|
55569
|
+
student: { sourcedId: studentId },
|
|
55570
|
+
score: 0,
|
|
55571
|
+
scoreDate: new Date().toISOString(),
|
|
55572
|
+
scoreStatus: SCORE_STATUS.notSubmitted,
|
|
55573
|
+
inProgress: "true",
|
|
55574
|
+
metadata: {
|
|
55575
|
+
isMasteryCompletion: true,
|
|
55576
|
+
adminAction: true,
|
|
55577
|
+
appName
|
|
55578
|
+
}
|
|
55579
|
+
});
|
|
55580
|
+
} catch {
|
|
55581
|
+
logger17.debug("No completion entry to revoke", { studentId, courseId });
|
|
55582
|
+
}
|
|
55583
|
+
}
|
|
55584
|
+
}
|
|
55585
|
+
var logger17;
|
|
55586
|
+
var init_timeback_mastery_completion_util = __esm(() => {
|
|
55587
|
+
init_src2();
|
|
55588
|
+
init_constants4();
|
|
55589
|
+
init_utils6();
|
|
55590
|
+
logger17 = log.scope("timeback-mastery-completion");
|
|
55591
|
+
});
|
|
55495
55592
|
function isRecord2(value) {
|
|
55496
55593
|
return typeof value === "object" && value !== null;
|
|
55497
55594
|
}
|
|
@@ -55847,7 +55944,7 @@ class TimebackAdminService {
|
|
|
55847
55944
|
}
|
|
55848
55945
|
requireClient() {
|
|
55849
55946
|
if (!this.deps.timeback) {
|
|
55850
|
-
|
|
55947
|
+
logger18.error("Timeback client not available in context");
|
|
55851
55948
|
throw new ValidationError("Timeback integration not available in this environment");
|
|
55852
55949
|
}
|
|
55853
55950
|
return this.deps.timeback;
|
|
@@ -56067,7 +56164,7 @@ class TimebackAdminService {
|
|
|
56067
56164
|
});
|
|
56068
56165
|
return [enrollmentId, this.summarizeAnalyticsFacts(analytics.facts)];
|
|
56069
56166
|
} catch (error) {
|
|
56070
|
-
|
|
56167
|
+
logger18.warn("Failed to load enrollment analytics summary", {
|
|
56071
56168
|
enrollmentId,
|
|
56072
56169
|
error: error instanceof Error ? error.message : String(error)
|
|
56073
56170
|
});
|
|
@@ -56097,7 +56194,7 @@ class TimebackAdminService {
|
|
|
56097
56194
|
const events = await this.fetchCaliperEventsForStudent(client, studentId, source, eventLimit);
|
|
56098
56195
|
return TimebackAdminService.mapRecentActivityItems(events, relevantCourseIds).slice(0, maxResults);
|
|
56099
56196
|
} catch (error) {
|
|
56100
|
-
|
|
56197
|
+
logger18.warn("Failed to load recent Caliper activity", {
|
|
56101
56198
|
studentId,
|
|
56102
56199
|
gameId: source.gameId,
|
|
56103
56200
|
sourceMode: source.sourceMode,
|
|
@@ -56423,60 +56520,44 @@ class TimebackAdminService {
|
|
|
56423
56520
|
const wasMastered = currentMastered >= masterableUnits;
|
|
56424
56521
|
const willBeMastered = currentMastered + data.units >= masterableUnits;
|
|
56425
56522
|
if (wasMastered !== willBeMastered) {
|
|
56426
|
-
|
|
56427
|
-
|
|
56428
|
-
|
|
56429
|
-
|
|
56430
|
-
|
|
56431
|
-
|
|
56432
|
-
|
|
56433
|
-
status: ONEROSTER_STATUS.active,
|
|
56434
|
-
course: { sourcedId: ids.course },
|
|
56435
|
-
...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
|
|
56436
|
-
});
|
|
56437
|
-
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
56438
|
-
sourcedId: resultId,
|
|
56439
|
-
status: ONEROSTER_STATUS.active,
|
|
56440
|
-
assessmentLineItem: { sourcedId: lineItemId },
|
|
56441
|
-
student: { sourcedId: data.studentId },
|
|
56442
|
-
score: 100,
|
|
56443
|
-
scoreDate: new Date().toISOString(),
|
|
56444
|
-
scoreStatus: SCORE_STATUS.fullyGraded,
|
|
56445
|
-
inProgress: "false",
|
|
56446
|
-
metadata: {
|
|
56447
|
-
isMasteryCompletion: true,
|
|
56448
|
-
adminAction: true,
|
|
56449
|
-
appName
|
|
56450
|
-
}
|
|
56451
|
-
});
|
|
56452
|
-
} else {
|
|
56453
|
-
try {
|
|
56454
|
-
await client.oneroster.assessmentResults.upsert(resultId, {
|
|
56455
|
-
sourcedId: resultId,
|
|
56456
|
-
status: ONEROSTER_STATUS.active,
|
|
56457
|
-
assessmentLineItem: { sourcedId: lineItemId },
|
|
56458
|
-
student: { sourcedId: data.studentId },
|
|
56459
|
-
score: 0,
|
|
56460
|
-
scoreDate: new Date().toISOString(),
|
|
56461
|
-
scoreStatus: SCORE_STATUS.notSubmitted,
|
|
56462
|
-
inProgress: "true",
|
|
56463
|
-
metadata: {
|
|
56464
|
-
isMasteryCompletion: true,
|
|
56465
|
-
adminAction: true,
|
|
56466
|
-
appName
|
|
56467
|
-
}
|
|
56468
|
-
});
|
|
56469
|
-
} catch {
|
|
56470
|
-
logger17.debug("No completion entry to revoke", {
|
|
56471
|
-
studentId: data.studentId,
|
|
56472
|
-
courseId: data.courseId
|
|
56473
|
-
});
|
|
56474
|
-
}
|
|
56475
|
-
}
|
|
56523
|
+
await upsertMasteryCompletionEntry({
|
|
56524
|
+
client,
|
|
56525
|
+
courseId: data.courseId,
|
|
56526
|
+
studentId: data.studentId,
|
|
56527
|
+
appName,
|
|
56528
|
+
action: willBeMastered ? "complete" : "revoke"
|
|
56529
|
+
});
|
|
56476
56530
|
}
|
|
56477
56531
|
}
|
|
56478
56532
|
return { status: "ok" };
|
|
56479
56533
|
}
|
|
56534
|
+
async reconcileMasteryForConfigChange(gameId, courseId, user, context) {
|
|
56535
|
+
const { client, appName } = await this.resolveAdminMutationContext(gameId, courseId, user);
|
|
56536
|
+
const action = context.newMasterableUnits < context.oldMasterableUnits ? "complete" : "revoke";
|
|
56537
|
+
const failed = [];
|
|
56538
|
+
let processed = 0;
|
|
56539
|
+
await TimebackAdminService.runWithConcurrency(context.affectedStudentIds, 8, async (studentId) => {
|
|
56540
|
+
try {
|
|
56541
|
+
await upsertMasteryCompletionEntry({
|
|
56542
|
+
client,
|
|
56543
|
+
courseId,
|
|
56544
|
+
studentId,
|
|
56545
|
+
appName,
|
|
56546
|
+
action
|
|
56547
|
+
});
|
|
56548
|
+
processed++;
|
|
56549
|
+
} catch (error) {
|
|
56550
|
+
logger18.warn("Failed to reconcile mastery completion for student", {
|
|
56551
|
+
studentId,
|
|
56552
|
+
courseId,
|
|
56553
|
+
action,
|
|
56554
|
+
error: error instanceof Error ? error.message : String(error)
|
|
56555
|
+
});
|
|
56556
|
+
failed.push(studentId);
|
|
56557
|
+
}
|
|
56558
|
+
});
|
|
56559
|
+
return { processed, failed };
|
|
56560
|
+
}
|
|
56480
56561
|
async searchStudentsForEnrollment(gameId, courseId, query, user) {
|
|
56481
56562
|
const client = this.requireClient();
|
|
56482
56563
|
await this.deps.validateGameManagementAccess(user, gameId);
|
|
@@ -56503,7 +56584,7 @@ class TimebackAdminService {
|
|
|
56503
56584
|
const response = await client["request"](endpoint, "GET");
|
|
56504
56585
|
allUsers = response.users || [];
|
|
56505
56586
|
} catch (error) {
|
|
56506
|
-
|
|
56587
|
+
logger18.warn("Failed to search OneRoster users", {
|
|
56507
56588
|
query: trimmedQuery,
|
|
56508
56589
|
error: error instanceof Error ? error.message : String(error)
|
|
56509
56590
|
});
|
|
@@ -56648,7 +56729,7 @@ class TimebackAdminService {
|
|
|
56648
56729
|
return results;
|
|
56649
56730
|
}
|
|
56650
56731
|
}
|
|
56651
|
-
var
|
|
56732
|
+
var logger18;
|
|
56652
56733
|
var init_timeback_admin_service = __esm(() => {
|
|
56653
56734
|
init_drizzle_orm();
|
|
56654
56735
|
init_src();
|
|
@@ -56661,8 +56742,9 @@ var init_timeback_admin_service = __esm(() => {
|
|
|
56661
56742
|
init_errors();
|
|
56662
56743
|
init_timeback_admin_metrics_util();
|
|
56663
56744
|
init_timeback_admin_util();
|
|
56745
|
+
init_timeback_mastery_completion_util();
|
|
56664
56746
|
init_timeback_util();
|
|
56665
|
-
|
|
56747
|
+
logger18 = log.scope("TimebackAdminService");
|
|
56666
56748
|
});
|
|
56667
56749
|
var __esm5 = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
56668
56750
|
var TIMEBACK_API_URLS4;
|
|
@@ -56935,7 +57017,7 @@ class TimebackAssessmentsService {
|
|
|
56935
57017
|
isActive: row.bankActive
|
|
56936
57018
|
};
|
|
56937
57019
|
} catch {
|
|
56938
|
-
|
|
57020
|
+
logger19.warn("Failed to fetch QTI test metadata", {
|
|
56939
57021
|
identifier: row.qtiTestIdentifier
|
|
56940
57022
|
});
|
|
56941
57023
|
return {
|
|
@@ -56989,7 +57071,7 @@ class TimebackAssessmentsService {
|
|
|
56989
57071
|
});
|
|
56990
57072
|
} catch (error) {
|
|
56991
57073
|
if (error instanceof TimebackApiError && error.status === 409) {
|
|
56992
|
-
|
|
57074
|
+
logger19.info("QTI test already exists (idempotent retry)", {
|
|
56993
57075
|
qtiTestIdentifier: input.qtiTestIdentifier
|
|
56994
57076
|
});
|
|
56995
57077
|
} else {
|
|
@@ -57002,7 +57084,7 @@ class TimebackAssessmentsService {
|
|
|
57002
57084
|
qtiTestIdentifier: input.qtiTestIdentifier,
|
|
57003
57085
|
sortOrder: maxSortOrder + 1
|
|
57004
57086
|
}).returning();
|
|
57005
|
-
|
|
57087
|
+
logger19.info("Assessment created", {
|
|
57006
57088
|
integrationId,
|
|
57007
57089
|
qtiTestIdentifier: input.qtiTestIdentifier
|
|
57008
57090
|
});
|
|
@@ -57024,13 +57106,13 @@ class TimebackAssessmentsService {
|
|
|
57024
57106
|
}
|
|
57025
57107
|
await client.qti.tests.delete(qtiTestIdentifier);
|
|
57026
57108
|
} catch (error) {
|
|
57027
|
-
|
|
57109
|
+
logger19.warn("Partial QTI cleanup during assessment deletion", {
|
|
57028
57110
|
qtiTestIdentifier,
|
|
57029
57111
|
error: error instanceof Error ? error.message : String(error)
|
|
57030
57112
|
});
|
|
57031
57113
|
}
|
|
57032
57114
|
await this.deps.db.delete(gameTimebackAssessmentTests).where(eq(gameTimebackAssessmentTests.id, row.id));
|
|
57033
|
-
|
|
57115
|
+
logger19.info("Assessment deleted", { integrationId, qtiTestIdentifier });
|
|
57034
57116
|
}
|
|
57035
57117
|
async reorderAssessments(integrationId, identifiers) {
|
|
57036
57118
|
await this.requireIntegration(integrationId);
|
|
@@ -57075,7 +57157,7 @@ class TimebackAssessmentsService {
|
|
|
57075
57157
|
return client.qti.tests.reorderItems(qtiTestIdentifier, partId, sectionId, items2);
|
|
57076
57158
|
}
|
|
57077
57159
|
async activateAssessment(integrationId, qtiTestIdentifier) {
|
|
57078
|
-
|
|
57160
|
+
logger19.debug("Activating assessment", { integrationId, qtiTestIdentifier });
|
|
57079
57161
|
const client = this.requireClient();
|
|
57080
57162
|
const integration = await this.requireIntegration(integrationId);
|
|
57081
57163
|
const row = await this.requireAssessmentRow(integrationId, qtiTestIdentifier);
|
|
@@ -57113,7 +57195,7 @@ class TimebackAssessmentsService {
|
|
|
57113
57195
|
});
|
|
57114
57196
|
}
|
|
57115
57197
|
} catch {
|
|
57116
|
-
|
|
57198
|
+
logger19.warn("Failed to reactivate existing child resource, will create new", {
|
|
57117
57199
|
childResourceId
|
|
57118
57200
|
});
|
|
57119
57201
|
childResourceId = null;
|
|
@@ -57126,7 +57208,7 @@ class TimebackAssessmentsService {
|
|
|
57126
57208
|
const resourceUrl = resource.metadata?.url;
|
|
57127
57209
|
if (resourceUrl === qtiTestUrl) {
|
|
57128
57210
|
childResourceId = resourceId;
|
|
57129
|
-
|
|
57211
|
+
logger19.info("Found existing child Resource for QTI test (idempotent retry)", {
|
|
57130
57212
|
qtiTestIdentifier,
|
|
57131
57213
|
childResourceId
|
|
57132
57214
|
});
|
|
@@ -57135,7 +57217,7 @@ class TimebackAssessmentsService {
|
|
|
57135
57217
|
} catch {}
|
|
57136
57218
|
}
|
|
57137
57219
|
if (!childResourceId) {
|
|
57138
|
-
|
|
57220
|
+
logger19.debug("Creating child resource", { qtiTestIdentifier, qtiTestUrl });
|
|
57139
57221
|
const childResult = await client.oneroster.resources.create({
|
|
57140
57222
|
resource: {
|
|
57141
57223
|
status: "active",
|
|
@@ -57163,10 +57245,10 @@ class TimebackAssessmentsService {
|
|
|
57163
57245
|
}
|
|
57164
57246
|
}
|
|
57165
57247
|
await this.deps.db.update(gameTimebackAssessmentTests).set({ bankResourceId: childResourceId, bankActive: true }).where(eq(gameTimebackAssessmentTests.id, row.id));
|
|
57166
|
-
|
|
57248
|
+
logger19.info("Assessment activated", { integrationId, qtiTestIdentifier, childResourceId });
|
|
57167
57249
|
}
|
|
57168
57250
|
async deactivateAssessment(integrationId, qtiTestIdentifier) {
|
|
57169
|
-
|
|
57251
|
+
logger19.debug("Deactivating assessment", { integrationId, qtiTestIdentifier });
|
|
57170
57252
|
const client = this.requireClient();
|
|
57171
57253
|
const integration = await this.requireIntegration(integrationId);
|
|
57172
57254
|
const row = await this.requireAssessmentRow(integrationId, qtiTestIdentifier);
|
|
@@ -57179,7 +57261,7 @@ class TimebackAssessmentsService {
|
|
|
57179
57261
|
const childResourceId = row.bankResourceId;
|
|
57180
57262
|
const bankIds = deriveAssessmentBankIds(integration.courseId);
|
|
57181
57263
|
try {
|
|
57182
|
-
|
|
57264
|
+
logger19.debug("Reading parent resource for deactivation", {
|
|
57183
57265
|
resourceId: bankIds.resource
|
|
57184
57266
|
});
|
|
57185
57267
|
const parentResource = await client.oneroster.resources.get(bankIds.resource);
|
|
@@ -57198,22 +57280,22 @@ class TimebackAssessmentsService {
|
|
|
57198
57280
|
});
|
|
57199
57281
|
}
|
|
57200
57282
|
} catch (error) {
|
|
57201
|
-
|
|
57283
|
+
logger19.warn("Failed to update parent resource during deactivation", {
|
|
57202
57284
|
bankResourceId: bankIds.resource,
|
|
57203
57285
|
error: error instanceof Error ? error.message : String(error)
|
|
57204
57286
|
});
|
|
57205
57287
|
}
|
|
57206
57288
|
try {
|
|
57207
|
-
|
|
57289
|
+
logger19.debug("Deleting child resource", { childResourceId });
|
|
57208
57290
|
await client.oneroster.resources.delete(childResourceId);
|
|
57209
57291
|
} catch (error) {
|
|
57210
|
-
|
|
57292
|
+
logger19.warn("Failed to delete child resource (may already be deleted)", {
|
|
57211
57293
|
childResourceId,
|
|
57212
57294
|
error: error instanceof Error ? error.message : String(error)
|
|
57213
57295
|
});
|
|
57214
57296
|
}
|
|
57215
57297
|
await this.deps.db.update(gameTimebackAssessmentTests).set({ bankActive: false }).where(eq(gameTimebackAssessmentTests.id, row.id));
|
|
57216
|
-
|
|
57298
|
+
logger19.info("Assessment deactivated", { integrationId, qtiTestIdentifier });
|
|
57217
57299
|
}
|
|
57218
57300
|
isAssessmentActive(row) {
|
|
57219
57301
|
return row.bankActive;
|
|
@@ -57244,14 +57326,14 @@ class TimebackAssessmentsService {
|
|
|
57244
57326
|
status: "tobedeleted"
|
|
57245
57327
|
});
|
|
57246
57328
|
} catch (error) {
|
|
57247
|
-
|
|
57329
|
+
logger19.warn("Failed to delete component resource", { error });
|
|
57248
57330
|
}
|
|
57249
57331
|
for (const row of activeRows) {
|
|
57250
57332
|
if (row.bankResourceId) {
|
|
57251
57333
|
try {
|
|
57252
57334
|
await client.oneroster.resources.delete(row.bankResourceId);
|
|
57253
57335
|
} catch (error) {
|
|
57254
|
-
|
|
57336
|
+
logger19.warn("Failed to delete child resource", {
|
|
57255
57337
|
childResourceId: row.bankResourceId,
|
|
57256
57338
|
error
|
|
57257
57339
|
});
|
|
@@ -57261,17 +57343,17 @@ class TimebackAssessmentsService {
|
|
|
57261
57343
|
try {
|
|
57262
57344
|
await client.oneroster.resources.delete(bankIds.resource);
|
|
57263
57345
|
} catch (error) {
|
|
57264
|
-
|
|
57346
|
+
logger19.warn("Failed to delete parent resource", { error });
|
|
57265
57347
|
}
|
|
57266
57348
|
try {
|
|
57267
57349
|
await client.oneroster.courseComponents.update(bankIds.component, {
|
|
57268
57350
|
status: "tobedeleted"
|
|
57269
57351
|
});
|
|
57270
57352
|
} catch (error) {
|
|
57271
|
-
|
|
57353
|
+
logger19.warn("Failed to delete course component", { error });
|
|
57272
57354
|
}
|
|
57273
57355
|
await this.deps.db.update(gameTimebackAssessmentTests).set({ bankResourceId: null, bankActive: false }).where(eq(gameTimebackAssessmentTests.integrationId, integrationId));
|
|
57274
|
-
|
|
57356
|
+
logger19.info("Bank destroyed", { integrationId });
|
|
57275
57357
|
}
|
|
57276
57358
|
requireClient() {
|
|
57277
57359
|
if (!this.deps.timeback) {
|
|
@@ -57300,7 +57382,7 @@ class TimebackAssessmentsService {
|
|
|
57300
57382
|
async ensureBank(integration) {
|
|
57301
57383
|
const client = this.requireClient();
|
|
57302
57384
|
const bankIds = deriveAssessmentBankIds(integration.courseId);
|
|
57303
|
-
|
|
57385
|
+
logger19.debug("Ensuring assessment bank hierarchy", {
|
|
57304
57386
|
courseId: integration.courseId,
|
|
57305
57387
|
bankIds
|
|
57306
57388
|
});
|
|
@@ -57317,7 +57399,7 @@ class TimebackAssessmentsService {
|
|
|
57317
57399
|
});
|
|
57318
57400
|
} catch (error) {
|
|
57319
57401
|
if (error instanceof TimebackApiError && error.status === 409) {
|
|
57320
|
-
|
|
57402
|
+
logger19.debug("Course component already exists", { sourcedId: bankIds.component });
|
|
57321
57403
|
} else {
|
|
57322
57404
|
throw error;
|
|
57323
57405
|
}
|
|
@@ -57341,7 +57423,7 @@ class TimebackAssessmentsService {
|
|
|
57341
57423
|
});
|
|
57342
57424
|
} catch (error) {
|
|
57343
57425
|
if (error instanceof TimebackApiError && error.status === 409) {
|
|
57344
|
-
|
|
57426
|
+
logger19.debug("Parent resource already exists", { sourcedId: bankIds.resource });
|
|
57345
57427
|
} else {
|
|
57346
57428
|
throw error;
|
|
57347
57429
|
}
|
|
@@ -57361,14 +57443,14 @@ class TimebackAssessmentsService {
|
|
|
57361
57443
|
});
|
|
57362
57444
|
} catch (error) {
|
|
57363
57445
|
if (error instanceof TimebackApiError && error.status === 409) {
|
|
57364
|
-
|
|
57446
|
+
logger19.debug("Component resource already exists", {
|
|
57365
57447
|
sourcedId: bankIds.componentResource
|
|
57366
57448
|
});
|
|
57367
57449
|
} else {
|
|
57368
57450
|
throw error;
|
|
57369
57451
|
}
|
|
57370
57452
|
}
|
|
57371
|
-
|
|
57453
|
+
logger19.info("Assessment bank hierarchy created", {
|
|
57372
57454
|
courseId: integration.courseId
|
|
57373
57455
|
});
|
|
57374
57456
|
}
|
|
@@ -57383,7 +57465,7 @@ class TimebackAssessmentsService {
|
|
|
57383
57465
|
return Math.max(...rows.map((r) => r.sortOrder));
|
|
57384
57466
|
}
|
|
57385
57467
|
}
|
|
57386
|
-
var
|
|
57468
|
+
var logger19;
|
|
57387
57469
|
var init_timeback_assessments_service = __esm(() => {
|
|
57388
57470
|
init_drizzle_orm();
|
|
57389
57471
|
init_tables_index();
|
|
@@ -57392,7 +57474,7 @@ var init_timeback_assessments_service = __esm(() => {
|
|
|
57392
57474
|
init_errors4();
|
|
57393
57475
|
init_utils6();
|
|
57394
57476
|
init_errors();
|
|
57395
|
-
|
|
57477
|
+
logger19 = log.scope("TimebackAssessmentsService");
|
|
57396
57478
|
});
|
|
57397
57479
|
async function promoteCompletedCourse({
|
|
57398
57480
|
db: db2,
|
|
@@ -57406,7 +57488,7 @@ async function promoteCompletedCourse({
|
|
|
57406
57488
|
});
|
|
57407
57489
|
const nextIntegration = subjectIntegrations.filter((integration) => integration.grade > currentIntegration.grade).toSorted((left, right) => left.grade - right.grade)[0];
|
|
57408
57490
|
if (!nextIntegration) {
|
|
57409
|
-
|
|
57491
|
+
logger20.debug("Skipping promotion because no next course is configured", {
|
|
57410
57492
|
gameId: currentIntegration.gameId,
|
|
57411
57493
|
studentId,
|
|
57412
57494
|
grade: currentIntegration.grade,
|
|
@@ -57423,7 +57505,7 @@ async function promoteCompletedCourse({
|
|
|
57423
57505
|
const nextEnrollment = enrollments.find((enrollment) => enrollment.course.id === nextIntegration.courseId);
|
|
57424
57506
|
if (!currentEnrollment) {
|
|
57425
57507
|
if (nextEnrollment) {
|
|
57426
|
-
|
|
57508
|
+
logger20.debug("Skipping promotion because student is already on the next course", {
|
|
57427
57509
|
gameId: currentIntegration.gameId,
|
|
57428
57510
|
studentId,
|
|
57429
57511
|
grade: currentIntegration.grade,
|
|
@@ -57437,7 +57519,7 @@ async function promoteCompletedCourse({
|
|
|
57437
57519
|
nextCourseId: nextIntegration.courseId
|
|
57438
57520
|
};
|
|
57439
57521
|
}
|
|
57440
|
-
|
|
57522
|
+
logger20.debug("Skipping promotion because student is not enrolled in the current course", {
|
|
57441
57523
|
gameId: currentIntegration.gameId,
|
|
57442
57524
|
studentId,
|
|
57443
57525
|
grade: currentIntegration.grade,
|
|
@@ -57468,7 +57550,7 @@ async function promoteCompletedCourse({
|
|
|
57468
57550
|
client.invalidateEnrollments(studentId);
|
|
57469
57551
|
}
|
|
57470
57552
|
}
|
|
57471
|
-
|
|
57553
|
+
logger20.info("Promoted student to next course", {
|
|
57472
57554
|
gameId: currentIntegration.gameId,
|
|
57473
57555
|
studentId,
|
|
57474
57556
|
subject: currentIntegration.subject,
|
|
@@ -57483,14 +57565,14 @@ async function promoteCompletedCourse({
|
|
|
57483
57565
|
nextCourseId: nextIntegration.courseId
|
|
57484
57566
|
};
|
|
57485
57567
|
}
|
|
57486
|
-
var
|
|
57568
|
+
var logger20;
|
|
57487
57569
|
var init_timeback_promotion_util = __esm(() => {
|
|
57488
57570
|
init_drizzle_orm();
|
|
57489
57571
|
init_tables_index();
|
|
57490
57572
|
init_src2();
|
|
57491
|
-
|
|
57573
|
+
logger20 = log.scope("TimebackPromotion");
|
|
57492
57574
|
});
|
|
57493
|
-
var
|
|
57575
|
+
var logger21;
|
|
57494
57576
|
var TimebackService;
|
|
57495
57577
|
var init_timeback_service = __esm(() => {
|
|
57496
57578
|
init_drizzle_orm();
|
|
@@ -57502,7 +57584,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57502
57584
|
init_errors();
|
|
57503
57585
|
init_timeback_promotion_util();
|
|
57504
57586
|
init_timeback_util();
|
|
57505
|
-
|
|
57587
|
+
logger21 = log.scope("TimebackService");
|
|
57506
57588
|
TimebackService = class TimebackService2 {
|
|
57507
57589
|
static HEARTBEAT_DEDUPE_TTL_MS = 300000;
|
|
57508
57590
|
static processedHeartbeatWindows = new Map;
|
|
@@ -57548,7 +57630,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57548
57630
|
}
|
|
57549
57631
|
requireClient() {
|
|
57550
57632
|
if (!this.deps.timeback) {
|
|
57551
|
-
|
|
57633
|
+
logger21.error("Timeback client not available in context");
|
|
57552
57634
|
throw new ValidationError("Timeback integration not available in this environment");
|
|
57553
57635
|
}
|
|
57554
57636
|
return this.deps.timeback;
|
|
@@ -57601,7 +57683,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57601
57683
|
set: { xp: sql`excluded.xp`, updatedAt: new Date }
|
|
57602
57684
|
}).returning({ xp: timebackDailyXp.xp, date: timebackDailyXp.date });
|
|
57603
57685
|
if (!result) {
|
|
57604
|
-
|
|
57686
|
+
logger21.error("Daily XP upsert returned no rows", { userId, date: targetDate });
|
|
57605
57687
|
throw new InternalError("Failed to update daily XP record");
|
|
57606
57688
|
}
|
|
57607
57689
|
return { xp: result.xp, date: result.date.toISOString() };
|
|
@@ -57632,7 +57714,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57632
57714
|
columns: { id: true, timebackId: true }
|
|
57633
57715
|
});
|
|
57634
57716
|
if (dbUser?.timebackId) {
|
|
57635
|
-
|
|
57717
|
+
logger21.info("Student already onboarded", { userId: user.id });
|
|
57636
57718
|
return { status: "already_populated" };
|
|
57637
57719
|
}
|
|
57638
57720
|
let timebackId;
|
|
@@ -57641,7 +57723,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57641
57723
|
const existingUser = await client.oneroster.users.findByEmail(user.email);
|
|
57642
57724
|
timebackId = existingUser.sourcedId;
|
|
57643
57725
|
name3 = `${existingUser.givenName} ${existingUser.familyName}`;
|
|
57644
|
-
|
|
57726
|
+
logger21.info("Found existing student in OneRoster", {
|
|
57645
57727
|
userId: user.id,
|
|
57646
57728
|
timebackId
|
|
57647
57729
|
});
|
|
@@ -57670,7 +57752,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57670
57752
|
}
|
|
57671
57753
|
timebackId = response.sourcedIdPairs.allocatedSourcedId;
|
|
57672
57754
|
name3 = `${providedNames.firstName} ${providedNames.lastName}`;
|
|
57673
|
-
|
|
57755
|
+
logger21.info("Created student in OneRoster", { userId: user.id, timebackId });
|
|
57674
57756
|
}
|
|
57675
57757
|
const assessments = await this.fetchAssessments(timebackId);
|
|
57676
57758
|
await db2.transaction(async (tx) => {
|
|
@@ -57704,7 +57786,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57704
57786
|
}
|
|
57705
57787
|
const [updated] = await tx.update(users).set({ timebackId, name: name3 }).where(eq(users.id, user.id)).returning({ id: users.id });
|
|
57706
57788
|
if (!updated) {
|
|
57707
|
-
|
|
57789
|
+
logger21.error("User Timeback ID update returned no rows", {
|
|
57708
57790
|
userId: user.id,
|
|
57709
57791
|
timebackId
|
|
57710
57792
|
});
|
|
@@ -57728,13 +57810,13 @@ var init_timeback_service = __esm(() => {
|
|
|
57728
57810
|
}
|
|
57729
57811
|
offset += limit;
|
|
57730
57812
|
}
|
|
57731
|
-
|
|
57813
|
+
logger21.debug("Fetched assessments", {
|
|
57732
57814
|
studentSourcedId,
|
|
57733
57815
|
totalCount: allAssessments.length
|
|
57734
57816
|
});
|
|
57735
57817
|
return allAssessments;
|
|
57736
57818
|
} catch (error) {
|
|
57737
|
-
|
|
57819
|
+
logger21.warn("Failed to fetch assessments", { studentSourcedId, error });
|
|
57738
57820
|
return [];
|
|
57739
57821
|
}
|
|
57740
57822
|
}
|
|
@@ -57847,7 +57929,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57847
57929
|
masterableUnits: derivedMasterableUnits
|
|
57848
57930
|
} = courseConfig;
|
|
57849
57931
|
if (!isTimebackSubject(subjectInput)) {
|
|
57850
|
-
|
|
57932
|
+
logger21.warn("Invalid Timeback subject in course config", {
|
|
57851
57933
|
subject: subjectInput,
|
|
57852
57934
|
courseCode,
|
|
57853
57935
|
title
|
|
@@ -57855,7 +57937,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57855
57937
|
throw new ValidationError(`Invalid subject "${subjectInput}"`);
|
|
57856
57938
|
}
|
|
57857
57939
|
if (!isTimebackGrade(grade)) {
|
|
57858
|
-
|
|
57940
|
+
logger21.warn("Invalid Timeback grade in course config", {
|
|
57859
57941
|
grade,
|
|
57860
57942
|
courseCode,
|
|
57861
57943
|
title
|
|
@@ -57867,7 +57949,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57867
57949
|
const totalXp = derivedTotalXp ?? courseMetadata?.metrics?.totalXp;
|
|
57868
57950
|
const masterableUnits = derivedMasterableUnits ?? (isPlaycademyResourceMetadata(courseMetadata?.playcademy) ? courseMetadata?.playcademy?.mastery?.masterableUnits : undefined);
|
|
57869
57951
|
if (typeof totalXp !== "number") {
|
|
57870
|
-
|
|
57952
|
+
logger21.warn("Course missing totalXp in Timeback config", {
|
|
57871
57953
|
courseCode,
|
|
57872
57954
|
title
|
|
57873
57955
|
});
|
|
@@ -57883,7 +57965,9 @@ var init_timeback_service = __esm(() => {
|
|
|
57883
57965
|
courseCode,
|
|
57884
57966
|
level,
|
|
57885
57967
|
gradingScheme: "STANDARD",
|
|
57886
|
-
metadata: metadata2
|
|
57968
|
+
metadata: TimebackService2.patchCourseMetadata(metadata2, totalXp, {
|
|
57969
|
+
masterableUnits: masterableUnits ?? null
|
|
57970
|
+
})
|
|
57887
57971
|
},
|
|
57888
57972
|
component: {
|
|
57889
57973
|
...baseConfig.component,
|
|
@@ -57908,7 +57992,7 @@ var init_timeback_service = __esm(() => {
|
|
|
57908
57992
|
const existingIntegration = existing.find((i2) => i2.grade === grade && i2.subject === subject);
|
|
57909
57993
|
if (existingIntegration) {
|
|
57910
57994
|
await client.update(existingIntegration.courseId, fullConfig);
|
|
57911
|
-
const [updated] = await db2.update(gameTimebackIntegrations).set({ totalXp, updatedAt: new Date }).where(eq(gameTimebackIntegrations.id, existingIntegration.id)).returning();
|
|
57995
|
+
const [updated] = await db2.update(gameTimebackIntegrations).set({ subject, totalXp, updatedAt: new Date }).where(eq(gameTimebackIntegrations.id, existingIntegration.id)).returning();
|
|
57912
57996
|
if (updated) {
|
|
57913
57997
|
integrations.push(this.toGameTimebackIntegration(updated));
|
|
57914
57998
|
}
|
|
@@ -57933,6 +58017,60 @@ var init_timeback_service = __esm(() => {
|
|
|
57933
58017
|
});
|
|
57934
58018
|
return rows.map((row) => this.toGameTimebackIntegration(row));
|
|
57935
58019
|
}
|
|
58020
|
+
async getIntegrationConfig(gameId, courseId, user) {
|
|
58021
|
+
const client = this.requireClient();
|
|
58022
|
+
await this.deps.validateGameManagementAccess(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 config2 = await client.getConfig(courseId);
|
|
58030
|
+
return this.toGameTimebackIntegrationConfig(integration, config2);
|
|
58031
|
+
}
|
|
58032
|
+
async updateIntegration(gameId, courseId, user, patch) {
|
|
58033
|
+
const client = this.requireClient();
|
|
58034
|
+
await this.deps.validateDeveloperAccess(user, gameId);
|
|
58035
|
+
const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
|
|
58036
|
+
where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
|
|
58037
|
+
});
|
|
58038
|
+
if (!integration) {
|
|
58039
|
+
throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
|
|
58040
|
+
}
|
|
58041
|
+
const timebackConfig = await client.getConfig(courseId);
|
|
58042
|
+
const liveSubject = timebackConfig.course.subjects[0];
|
|
58043
|
+
const subject = patch.subject ?? (isTimebackSubject(liveSubject) ? liveSubject : integration.subject);
|
|
58044
|
+
if (!isTimebackSubject(subject)) {
|
|
58045
|
+
throw new ValidationError(`Invalid subject "${subject}"`);
|
|
58046
|
+
}
|
|
58047
|
+
if (subject !== integration.subject) {
|
|
58048
|
+
const subjectConflict = await this.deps.db.query.gameTimebackIntegrations.findFirst({
|
|
58049
|
+
where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, integration.grade), eq(gameTimebackIntegrations.subject, subject))
|
|
58050
|
+
});
|
|
58051
|
+
if (subjectConflict && subjectConflict.id !== integration.id) {
|
|
58052
|
+
throw new ValidationError(`A TimeBack integration already exists for ${subject} Grade ${integration.grade}`);
|
|
58053
|
+
}
|
|
58054
|
+
}
|
|
58055
|
+
const totalXp = "totalXp" in patch ? patch.totalXp ?? null : TimebackService2.getTotalXpFromConfig(timebackConfig) ?? integration.totalXp ?? null;
|
|
58056
|
+
const masterableUnits = "masterableUnits" in patch ? patch.masterableUnits ?? null : TimebackService2.getMasterableUnitsFromConfig(timebackConfig);
|
|
58057
|
+
await client.update(courseId, TimebackService2.patchTimebackConfig(timebackConfig, {
|
|
58058
|
+
...patch,
|
|
58059
|
+
subject,
|
|
58060
|
+
totalXp,
|
|
58061
|
+
masterableUnits,
|
|
58062
|
+
grade: integration.grade
|
|
58063
|
+
}));
|
|
58064
|
+
const [updated] = await this.deps.db.update(gameTimebackIntegrations).set({
|
|
58065
|
+
subject,
|
|
58066
|
+
totalXp,
|
|
58067
|
+
updatedAt: new Date
|
|
58068
|
+
}).where(eq(gameTimebackIntegrations.id, integration.id)).returning();
|
|
58069
|
+
if (!updated) {
|
|
58070
|
+
throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
|
|
58071
|
+
}
|
|
58072
|
+
return this.toGameTimebackIntegration(updated);
|
|
58073
|
+
}
|
|
57936
58074
|
async verifyIntegration(gameId, user) {
|
|
57937
58075
|
const client = this.requireClient();
|
|
57938
58076
|
const db2 = this.deps.db;
|
|
@@ -57990,6 +58128,146 @@ var init_timeback_service = __esm(() => {
|
|
|
57990
58128
|
}
|
|
57991
58129
|
await db2.delete(gameTimebackIntegrations).where(eq(gameTimebackIntegrations.gameId, gameId));
|
|
57992
58130
|
}
|
|
58131
|
+
static getMasterableUnitsFromConfig(config2) {
|
|
58132
|
+
const playcademyMetadata = config2.resource.metadata?.playcademy;
|
|
58133
|
+
if (!isPlaycademyResourceMetadata(playcademyMetadata)) {
|
|
58134
|
+
return null;
|
|
58135
|
+
}
|
|
58136
|
+
return playcademyMetadata?.mastery?.masterableUnits ?? null;
|
|
58137
|
+
}
|
|
58138
|
+
static getTotalXpFromConfig(config2) {
|
|
58139
|
+
const courseMetadata = isCourseMetadata(config2.course.metadata) ? config2.course.metadata : undefined;
|
|
58140
|
+
if (typeof courseMetadata?.metrics?.totalXp === "number") {
|
|
58141
|
+
return courseMetadata.metrics.totalXp;
|
|
58142
|
+
}
|
|
58143
|
+
const resourceMetadata = config2.resource.metadata;
|
|
58144
|
+
if (isRecord2(resourceMetadata) && typeof resourceMetadata.xp === "number") {
|
|
58145
|
+
return resourceMetadata.xp;
|
|
58146
|
+
}
|
|
58147
|
+
return null;
|
|
58148
|
+
}
|
|
58149
|
+
static patchCourseMetadata(metadata2, totalXp, options) {
|
|
58150
|
+
const nextMetadata = isRecord2(metadata2) ? { ...metadata2 } : {};
|
|
58151
|
+
const currentMetrics = isRecord2(nextMetadata.metrics) ? nextMetadata.metrics : {};
|
|
58152
|
+
const metrics = { ...currentMetrics };
|
|
58153
|
+
if (totalXp === null) {
|
|
58154
|
+
delete metrics.totalXp;
|
|
58155
|
+
} else {
|
|
58156
|
+
metrics.totalXp = totalXp;
|
|
58157
|
+
}
|
|
58158
|
+
if (options?.masterableUnits !== undefined) {
|
|
58159
|
+
if (options.masterableUnits === null) {
|
|
58160
|
+
delete metrics.totalLessons;
|
|
58161
|
+
} else {
|
|
58162
|
+
metrics.totalLessons = options.masterableUnits;
|
|
58163
|
+
}
|
|
58164
|
+
}
|
|
58165
|
+
metrics.totalGrades = 1;
|
|
58166
|
+
if (Object.keys(metrics).length > 0) {
|
|
58167
|
+
nextMetadata.metrics = metrics;
|
|
58168
|
+
} else {
|
|
58169
|
+
delete nextMetadata.metrics;
|
|
58170
|
+
}
|
|
58171
|
+
const goals = options?.goals;
|
|
58172
|
+
if (goals !== undefined) {
|
|
58173
|
+
if (goals === null) {
|
|
58174
|
+
delete nextMetadata.goals;
|
|
58175
|
+
} else {
|
|
58176
|
+
const currentGoals = isRecord2(nextMetadata.goals) ? nextMetadata.goals : {};
|
|
58177
|
+
const nextGoals = { ...currentGoals };
|
|
58178
|
+
for (const [key, value] of Object.entries(goals)) {
|
|
58179
|
+
if (value === null) {
|
|
58180
|
+
delete nextGoals[key];
|
|
58181
|
+
} else if (value !== undefined) {
|
|
58182
|
+
nextGoals[key] = value;
|
|
58183
|
+
}
|
|
58184
|
+
}
|
|
58185
|
+
if (Object.keys(nextGoals).length > 0) {
|
|
58186
|
+
nextMetadata.goals = nextGoals;
|
|
58187
|
+
} else {
|
|
58188
|
+
delete nextMetadata.goals;
|
|
58189
|
+
}
|
|
58190
|
+
}
|
|
58191
|
+
}
|
|
58192
|
+
if (options?.publishStatus !== undefined) {
|
|
58193
|
+
if (options.publishStatus === null) {
|
|
58194
|
+
delete nextMetadata.publishStatus;
|
|
58195
|
+
const alphaLearn = isRecord2(nextMetadata.AlphaLearn) ? { ...nextMetadata.AlphaLearn } : {};
|
|
58196
|
+
delete alphaLearn.publishStatus;
|
|
58197
|
+
if (Object.keys(alphaLearn).length > 0) {
|
|
58198
|
+
nextMetadata.AlphaLearn = alphaLearn;
|
|
58199
|
+
} else {
|
|
58200
|
+
delete nextMetadata.AlphaLearn;
|
|
58201
|
+
}
|
|
58202
|
+
} else {
|
|
58203
|
+
nextMetadata.publishStatus = options.publishStatus;
|
|
58204
|
+
const alphaLearn = isRecord2(nextMetadata.AlphaLearn) ? { ...nextMetadata.AlphaLearn } : {};
|
|
58205
|
+
alphaLearn.publishStatus = options.publishStatus === "published" ? "active" : options.publishStatus;
|
|
58206
|
+
nextMetadata.AlphaLearn = alphaLearn;
|
|
58207
|
+
}
|
|
58208
|
+
}
|
|
58209
|
+
if (options?.isSupplemental !== undefined) {
|
|
58210
|
+
nextMetadata.isSupplemental = options.isSupplemental;
|
|
58211
|
+
}
|
|
58212
|
+
if (options?.timebackVisible !== undefined) {
|
|
58213
|
+
if (options.timebackVisible === null) {
|
|
58214
|
+
delete nextMetadata.timebackVisible;
|
|
58215
|
+
} else {
|
|
58216
|
+
nextMetadata.timebackVisible = options.timebackVisible;
|
|
58217
|
+
}
|
|
58218
|
+
}
|
|
58219
|
+
return Object.keys(nextMetadata).length > 0 ? nextMetadata : undefined;
|
|
58220
|
+
}
|
|
58221
|
+
static patchResourceMetadata(metadata2, options) {
|
|
58222
|
+
const nextMetadata = isRecord2(metadata2) ? { ...metadata2 } : {};
|
|
58223
|
+
const playcademyMetadata = isRecord2(nextMetadata.playcademy) ? { ...nextMetadata.playcademy } : {};
|
|
58224
|
+
const masteryMetadata = isRecord2(playcademyMetadata.mastery) ? { ...playcademyMetadata.mastery } : {};
|
|
58225
|
+
nextMetadata.subject = options.subject;
|
|
58226
|
+
nextMetadata.grades = [options.grade];
|
|
58227
|
+
if (options.totalXp === null) {
|
|
58228
|
+
delete nextMetadata.xp;
|
|
58229
|
+
} else {
|
|
58230
|
+
nextMetadata.xp = options.totalXp;
|
|
58231
|
+
}
|
|
58232
|
+
if (options.masterableUnits === null) {
|
|
58233
|
+
delete masteryMetadata.masterableUnits;
|
|
58234
|
+
} else {
|
|
58235
|
+
masteryMetadata.masterableUnits = options.masterableUnits;
|
|
58236
|
+
}
|
|
58237
|
+
if (Object.keys(masteryMetadata).length > 0) {
|
|
58238
|
+
playcademyMetadata.mastery = masteryMetadata;
|
|
58239
|
+
} else {
|
|
58240
|
+
delete playcademyMetadata.mastery;
|
|
58241
|
+
}
|
|
58242
|
+
if (Object.keys(playcademyMetadata).length > 0) {
|
|
58243
|
+
nextMetadata.playcademy = playcademyMetadata;
|
|
58244
|
+
} else {
|
|
58245
|
+
delete nextMetadata.playcademy;
|
|
58246
|
+
}
|
|
58247
|
+
return nextMetadata;
|
|
58248
|
+
}
|
|
58249
|
+
static patchTimebackConfig(config2, patch) {
|
|
58250
|
+
return {
|
|
58251
|
+
...config2,
|
|
58252
|
+
course: {
|
|
58253
|
+
...config2.course,
|
|
58254
|
+
title: patch.title ?? config2.course.title,
|
|
58255
|
+
courseCode: patch.courseCode ?? config2.course.courseCode,
|
|
58256
|
+
subjects: [patch.subject],
|
|
58257
|
+
metadata: TimebackService2.patchCourseMetadata(config2.course.metadata, patch.totalXp, {
|
|
58258
|
+
masterableUnits: patch.masterableUnits,
|
|
58259
|
+
goals: patch.goals,
|
|
58260
|
+
publishStatus: patch.publishStatus,
|
|
58261
|
+
isSupplemental: patch.isSupplemental,
|
|
58262
|
+
timebackVisible: patch.timebackVisible
|
|
58263
|
+
})
|
|
58264
|
+
},
|
|
58265
|
+
resource: {
|
|
58266
|
+
...config2.resource,
|
|
58267
|
+
metadata: TimebackService2.patchResourceMetadata(config2.resource.metadata, patch)
|
|
58268
|
+
}
|
|
58269
|
+
};
|
|
58270
|
+
}
|
|
57993
58271
|
toGameTimebackIntegration(integration) {
|
|
57994
58272
|
return {
|
|
57995
58273
|
id: integration.id,
|
|
@@ -58003,6 +58281,21 @@ var init_timeback_service = __esm(() => {
|
|
|
58003
58281
|
lastVerifiedAt: integration.lastVerifiedAt ?? null
|
|
58004
58282
|
};
|
|
58005
58283
|
}
|
|
58284
|
+
toGameTimebackIntegrationConfig(integration, config2) {
|
|
58285
|
+
const subject = config2.course.subjects[0] ?? integration.subject;
|
|
58286
|
+
if (!isTimebackSubject(subject)) {
|
|
58287
|
+
throw new ValidationError(`Invalid subject "${subject}"`);
|
|
58288
|
+
}
|
|
58289
|
+
return {
|
|
58290
|
+
integration: this.toGameTimebackIntegration(integration),
|
|
58291
|
+
title: config2.course.title,
|
|
58292
|
+
courseCode: config2.course.courseCode,
|
|
58293
|
+
subject,
|
|
58294
|
+
totalXp: TimebackService2.getTotalXpFromConfig(config2) ?? integration.totalXp ?? null,
|
|
58295
|
+
masterableUnits: TimebackService2.getMasterableUnitsFromConfig(config2),
|
|
58296
|
+
metadata: isCourseMetadata(config2.course.metadata) ? config2.course.metadata : null
|
|
58297
|
+
};
|
|
58298
|
+
}
|
|
58006
58299
|
async endActivity({
|
|
58007
58300
|
gameId,
|
|
58008
58301
|
studentId,
|
|
@@ -58068,7 +58361,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58068
58361
|
...runId ? { runId } : {}
|
|
58069
58362
|
});
|
|
58070
58363
|
}
|
|
58071
|
-
|
|
58364
|
+
logger21.info("Recorded activity completion", {
|
|
58072
58365
|
gameId,
|
|
58073
58366
|
courseId: integration.courseId,
|
|
58074
58367
|
studentId,
|
|
@@ -58122,7 +58415,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58122
58415
|
masteredUnits: masteryStatus.masteredUnits,
|
|
58123
58416
|
masterableUnits: masteryStatus.masterableUnits
|
|
58124
58417
|
};
|
|
58125
|
-
|
|
58418
|
+
logger21.debug("Skipping course advancement because mastery is incomplete", {
|
|
58126
58419
|
gameId,
|
|
58127
58420
|
studentId,
|
|
58128
58421
|
subject: currentIntegration.subject,
|
|
@@ -58140,7 +58433,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58140
58433
|
studentId,
|
|
58141
58434
|
enrollments
|
|
58142
58435
|
});
|
|
58143
|
-
|
|
58436
|
+
logger21.info("Manually advanced student", {
|
|
58144
58437
|
gameId,
|
|
58145
58438
|
studentId,
|
|
58146
58439
|
subject: currentIntegration.subject,
|
|
@@ -58173,7 +58466,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58173
58466
|
const heartbeatWindowKey = hasWindowStartedAtMs ? `${runId}:t:${windowStartedAtMs}` : `${runId}:s:${windowSequence}`;
|
|
58174
58467
|
const effectiveResumeId = resumeId ?? runId;
|
|
58175
58468
|
if (TimebackService2.isDuplicateHeartbeatWindow(heartbeatWindowKey)) {
|
|
58176
|
-
|
|
58469
|
+
logger21.debug("Skipping duplicate heartbeat window", {
|
|
58177
58470
|
gameId,
|
|
58178
58471
|
studentId,
|
|
58179
58472
|
runId,
|
|
@@ -58186,7 +58479,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58186
58479
|
await this.deps.validateDeveloperAccess(user, gameId);
|
|
58187
58480
|
const inFlightHeartbeat = TimebackService2.getInFlightHeartbeatWindow(heartbeatWindowKey);
|
|
58188
58481
|
if (inFlightHeartbeat) {
|
|
58189
|
-
|
|
58482
|
+
logger21.debug("Joining in-flight heartbeat window", {
|
|
58190
58483
|
gameId,
|
|
58191
58484
|
studentId,
|
|
58192
58485
|
runId,
|
|
@@ -58223,7 +58516,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58223
58516
|
});
|
|
58224
58517
|
}
|
|
58225
58518
|
TimebackService2.markHeartbeatWindowProcessed(heartbeatWindowKey);
|
|
58226
|
-
|
|
58519
|
+
logger21.debug("Recorded heartbeat", {
|
|
58227
58520
|
gameId,
|
|
58228
58521
|
courseId: integration.courseId,
|
|
58229
58522
|
studentId,
|
|
@@ -58258,7 +58551,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58258
58551
|
});
|
|
58259
58552
|
courseIds = integrations.map((i2) => i2.courseId);
|
|
58260
58553
|
if (courseIds.length === 0) {
|
|
58261
|
-
|
|
58554
|
+
logger21.debug("No integrations found for game, returning 0 XP", {
|
|
58262
58555
|
timebackId,
|
|
58263
58556
|
gameId: options.gameId,
|
|
58264
58557
|
grade: options.grade,
|
|
@@ -58275,7 +58568,7 @@ var init_timeback_service = __esm(() => {
|
|
|
58275
58568
|
courseIds: courseIds.length > 0 ? courseIds : undefined,
|
|
58276
58569
|
include: options?.include
|
|
58277
58570
|
});
|
|
58278
|
-
|
|
58571
|
+
logger21.debug("Retrieved student XP", {
|
|
58279
58572
|
timebackId,
|
|
58280
58573
|
gameId: options?.gameId,
|
|
58281
58574
|
grade: options?.grade,
|
|
@@ -58303,15 +58596,15 @@ class UploadService {
|
|
|
58303
58596
|
const { fileName, gameId } = request;
|
|
58304
58597
|
const bucketName = this.deps.uploadBucket;
|
|
58305
58598
|
if (!bucketName) {
|
|
58306
|
-
|
|
58599
|
+
logger22.error("Upload bucket not configured in environment");
|
|
58307
58600
|
throw new ValidationError("Upload bucket not configured");
|
|
58308
58601
|
}
|
|
58309
58602
|
await this.deps.validateDeveloperAccess(user, gameId);
|
|
58310
58603
|
const version2 = ulid();
|
|
58311
58604
|
const tempS3Key = `uploads-temp/${gameId}/${version2}/${fileName}`;
|
|
58312
|
-
|
|
58605
|
+
logger22.debug("Initiating upload", { userId: user.id, gameId, fileName, version: version2 });
|
|
58313
58606
|
const presignedUrl = await this.deps.generatePresignedPutUrl(bucketName, tempS3Key, UploadService.getContentType(fileName));
|
|
58314
|
-
|
|
58607
|
+
logger22.info("Presigned URL generated", {
|
|
58315
58608
|
userId: user.id,
|
|
58316
58609
|
gameId,
|
|
58317
58610
|
version: version2
|
|
@@ -58324,12 +58617,12 @@ class UploadService {
|
|
|
58324
58617
|
};
|
|
58325
58618
|
}
|
|
58326
58619
|
}
|
|
58327
|
-
var
|
|
58620
|
+
var logger22;
|
|
58328
58621
|
var init_upload_service = __esm(() => {
|
|
58329
58622
|
init_node();
|
|
58330
58623
|
init_src2();
|
|
58331
58624
|
init_errors();
|
|
58332
|
-
|
|
58625
|
+
logger22 = log.scope("UploadService");
|
|
58333
58626
|
});
|
|
58334
58627
|
function createPlatformServices(deps) {
|
|
58335
58628
|
const {
|
|
@@ -58630,7 +58923,7 @@ class AchievementService {
|
|
|
58630
58923
|
results.push(result);
|
|
58631
58924
|
}
|
|
58632
58925
|
}
|
|
58633
|
-
|
|
58926
|
+
logger23.debug("Listed current achievements", { userId: user.id, count: results.length });
|
|
58634
58927
|
return results;
|
|
58635
58928
|
}
|
|
58636
58929
|
async listHistory(user, limit) {
|
|
@@ -58648,14 +58941,14 @@ class AchievementService {
|
|
|
58648
58941
|
createdAt: c.createdAt,
|
|
58649
58942
|
scopeKey: c.scopeKey
|
|
58650
58943
|
}));
|
|
58651
|
-
|
|
58944
|
+
logger23.debug("Listed achievement history", { userId: user.id, count: results.length });
|
|
58652
58945
|
return results;
|
|
58653
58946
|
}
|
|
58654
58947
|
async submitProgress(achievementId, user) {
|
|
58655
58948
|
const { claim, wasNewClaim } = await this.award(user.id, achievementId, {
|
|
58656
58949
|
broadcast: false
|
|
58657
58950
|
});
|
|
58658
|
-
|
|
58951
|
+
logger23.debug("Submitted progress", {
|
|
58659
58952
|
userId: user.id,
|
|
58660
58953
|
achievementId,
|
|
58661
58954
|
wasNewClaim
|
|
@@ -58687,7 +58980,7 @@ class AchievementService {
|
|
|
58687
58980
|
rewardCredits
|
|
58688
58981
|
}).returning();
|
|
58689
58982
|
if (!newClaim) {
|
|
58690
|
-
|
|
58983
|
+
logger23.error("Achievement claim insert returned no rows", {
|
|
58691
58984
|
userId,
|
|
58692
58985
|
achievementId,
|
|
58693
58986
|
scopeKey
|
|
@@ -58696,7 +58989,7 @@ class AchievementService {
|
|
|
58696
58989
|
}
|
|
58697
58990
|
await this.deps.addCredits(userId, rewardCredits);
|
|
58698
58991
|
await this.deps.createAchievementNotification(userId, achievement, rewardCredits, scopeKey, { broadcast, metadata: metadata2 });
|
|
58699
|
-
|
|
58992
|
+
logger23.info("Awarded achievement", {
|
|
58700
58993
|
userId,
|
|
58701
58994
|
achievementId,
|
|
58702
58995
|
scopeKey,
|
|
@@ -58733,7 +59026,7 @@ class AchievementService {
|
|
|
58733
59026
|
return { title, body: body2 };
|
|
58734
59027
|
}
|
|
58735
59028
|
}
|
|
58736
|
-
var
|
|
59029
|
+
var logger23;
|
|
58737
59030
|
var init_achievement_service = __esm(() => {
|
|
58738
59031
|
init_drizzle_orm();
|
|
58739
59032
|
init_tables_index();
|
|
@@ -58742,7 +59035,7 @@ var init_achievement_service = __esm(() => {
|
|
|
58742
59035
|
init_errors();
|
|
58743
59036
|
init_leaderboard_util();
|
|
58744
59037
|
init_scope_util();
|
|
58745
|
-
|
|
59038
|
+
logger23 = log.scope("AchievementService");
|
|
58746
59039
|
});
|
|
58747
59040
|
|
|
58748
59041
|
class InventoryService {
|
|
@@ -58769,7 +59062,7 @@ class InventoryService {
|
|
|
58769
59062
|
},
|
|
58770
59063
|
updatedAt: inventoryItems.updatedAt
|
|
58771
59064
|
}).from(inventoryItems).where(eq(inventoryItems.userId, user.id)).innerJoin(items, eq(inventoryItems.itemId, items.id));
|
|
58772
|
-
|
|
59065
|
+
logger24.debug("Listed inventory", { userId: user.id, count: inventory.length });
|
|
58773
59066
|
return inventory;
|
|
58774
59067
|
}
|
|
58775
59068
|
async addItem(itemId, quantity, user) {
|
|
@@ -58786,7 +59079,7 @@ class InventoryService {
|
|
|
58786
59079
|
const [inserted] = await tx.insert(inventoryItems).values({ userId: user.id, itemId, quantity }).returning({ quantity: inventoryItems.quantity });
|
|
58787
59080
|
return inserted?.quantity ?? 0;
|
|
58788
59081
|
});
|
|
58789
|
-
|
|
59082
|
+
logger24.debug("Added item", { userId: user.id, itemId, quantity, newTotal });
|
|
58790
59083
|
return { newTotal };
|
|
58791
59084
|
}
|
|
58792
59085
|
async removeItem(itemId, quantity, user) {
|
|
@@ -58797,7 +59090,7 @@ class InventoryService {
|
|
|
58797
59090
|
}
|
|
58798
59091
|
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);
|
|
58799
59092
|
if (!currentItem) {
|
|
58800
|
-
|
|
59093
|
+
logger24.warn("Insufficient inventory for removal", {
|
|
58801
59094
|
userId: user.id,
|
|
58802
59095
|
itemId,
|
|
58803
59096
|
requestedQuantity: quantity
|
|
@@ -58807,13 +59100,13 @@ class InventoryService {
|
|
|
58807
59100
|
const [updated] = await tx.update(inventoryItems).set({ quantity: sql`${inventoryItems.quantity} - ${quantity}` }).where(eq(inventoryItems.id, currentItem.id)).returning({ quantity: inventoryItems.quantity });
|
|
58808
59101
|
return updated?.quantity ?? 0;
|
|
58809
59102
|
});
|
|
58810
|
-
|
|
59103
|
+
logger24.debug("Removed item", { userId: user.id, itemId, quantity, newTotal });
|
|
58811
59104
|
return { newTotal };
|
|
58812
59105
|
}
|
|
58813
59106
|
async addCredits(userId, amount) {
|
|
58814
59107
|
const [creditsItem] = await this.deps.db.select({ id: items.id }).from(items).where(eq(items.slug, CURRENCIES.PRIMARY)).limit(1);
|
|
58815
59108
|
if (!creditsItem) {
|
|
58816
|
-
|
|
59109
|
+
logger24.error("Primary currency not found", {
|
|
58817
59110
|
userId,
|
|
58818
59111
|
amount
|
|
58819
59112
|
});
|
|
@@ -58826,17 +59119,17 @@ class InventoryService {
|
|
|
58826
59119
|
updatedAt: new Date
|
|
58827
59120
|
}
|
|
58828
59121
|
});
|
|
58829
|
-
|
|
59122
|
+
logger24.debug("Added credits", { userId, amount });
|
|
58830
59123
|
}
|
|
58831
59124
|
}
|
|
58832
|
-
var
|
|
59125
|
+
var logger24;
|
|
58833
59126
|
var init_inventory_service = __esm(() => {
|
|
58834
59127
|
init_drizzle_orm();
|
|
58835
59128
|
init_src();
|
|
58836
59129
|
init_tables_index();
|
|
58837
59130
|
init_src2();
|
|
58838
59131
|
init_errors();
|
|
58839
|
-
|
|
59132
|
+
logger24 = log.scope("InventoryService");
|
|
58840
59133
|
});
|
|
58841
59134
|
|
|
58842
59135
|
class LeaderboardService {
|
|
@@ -58867,7 +59160,7 @@ class LeaderboardService {
|
|
|
58867
59160
|
sessionId
|
|
58868
59161
|
}).returning();
|
|
58869
59162
|
if (!newScore) {
|
|
58870
|
-
|
|
59163
|
+
logger25.error("Score insert returned no rows", { userId, gameId, score: input.score });
|
|
58871
59164
|
throw new InternalError("Failed to insert score");
|
|
58872
59165
|
}
|
|
58873
59166
|
const bestScoreRows = await db2.select({ score: sql`MAX(${gameScores.score})` }).from(gameScores).where(and(eq(gameScores.gameId, gameId), eq(gameScores.userId, userId)));
|
|
@@ -58895,7 +59188,7 @@ class LeaderboardService {
|
|
|
58895
59188
|
movedUpWithinTop3
|
|
58896
59189
|
});
|
|
58897
59190
|
}
|
|
58898
|
-
|
|
59191
|
+
logger25.info("Score submitted", {
|
|
58899
59192
|
gameId,
|
|
58900
59193
|
userId,
|
|
58901
59194
|
isAnonymousUser,
|
|
@@ -58972,7 +59265,7 @@ class LeaderboardService {
|
|
|
58972
59265
|
});
|
|
58973
59266
|
}
|
|
58974
59267
|
} catch (error) {
|
|
58975
|
-
|
|
59268
|
+
logger25.warn("Failed to publish notification", { error });
|
|
58976
59269
|
}
|
|
58977
59270
|
}
|
|
58978
59271
|
async getLeaderboard(gameId, query, isAnonymousUser) {
|
|
@@ -59091,7 +59384,7 @@ class LeaderboardService {
|
|
|
59091
59384
|
return db2.select().from(gameScores).where(and(eq(gameScores.gameId, gameId), eq(gameScores.userId, userId))).orderBy(desc(gameScores.achievedAt)).limit(effectiveLimit);
|
|
59092
59385
|
}
|
|
59093
59386
|
}
|
|
59094
|
-
var
|
|
59387
|
+
var logger25;
|
|
59095
59388
|
var init_leaderboard_service = __esm(() => {
|
|
59096
59389
|
init_drizzle_orm();
|
|
59097
59390
|
init_src();
|
|
@@ -59101,7 +59394,7 @@ var init_leaderboard_service = __esm(() => {
|
|
|
59101
59394
|
init_notification();
|
|
59102
59395
|
init_errors();
|
|
59103
59396
|
init_leaderboard_util();
|
|
59104
|
-
|
|
59397
|
+
logger25 = log.scope("LeaderboardService");
|
|
59105
59398
|
});
|
|
59106
59399
|
|
|
59107
59400
|
class LevelService {
|
|
@@ -59116,9 +59409,9 @@ class LevelService {
|
|
|
59116
59409
|
for (const config2 of configs) {
|
|
59117
59410
|
levelConfigCache.set(config2.level, config2);
|
|
59118
59411
|
}
|
|
59119
|
-
|
|
59412
|
+
logger26.info("Cache pre-warmed", { count: configs.length });
|
|
59120
59413
|
} catch (error) {
|
|
59121
|
-
|
|
59414
|
+
logger26.error("Cache pre-warm failed", { error });
|
|
59122
59415
|
}
|
|
59123
59416
|
}
|
|
59124
59417
|
async getConfig(level) {
|
|
@@ -59152,7 +59445,7 @@ class LevelService {
|
|
|
59152
59445
|
totalXP
|
|
59153
59446
|
}).returning();
|
|
59154
59447
|
if (!newUserLevel) {
|
|
59155
|
-
|
|
59448
|
+
logger26.error("User level insert returned no rows", { userId: user.id });
|
|
59156
59449
|
throw new InternalError("Failed to create user level cache record");
|
|
59157
59450
|
}
|
|
59158
59451
|
userLevel = newUserLevel;
|
|
@@ -59167,7 +59460,7 @@ class LevelService {
|
|
|
59167
59460
|
userLevel = updatedUserLevel;
|
|
59168
59461
|
}
|
|
59169
59462
|
}
|
|
59170
|
-
|
|
59463
|
+
logger26.debug("Retrieved user level", {
|
|
59171
59464
|
userId: user.id,
|
|
59172
59465
|
totalXP,
|
|
59173
59466
|
currentLevel,
|
|
@@ -59178,7 +59471,7 @@ class LevelService {
|
|
|
59178
59471
|
async getProgress(user) {
|
|
59179
59472
|
const userLevel = await this.getByUser(user);
|
|
59180
59473
|
const xpToNextLevel = await this.calculateXPToNextLevel(userLevel.currentLevel, userLevel.currentXp);
|
|
59181
|
-
|
|
59474
|
+
logger26.debug("Retrieved progress", { userId: user.id });
|
|
59182
59475
|
return {
|
|
59183
59476
|
level: userLevel.currentLevel,
|
|
59184
59477
|
currentXp: userLevel.currentXp,
|
|
@@ -59212,7 +59505,7 @@ class LevelService {
|
|
|
59212
59505
|
if (leveledUp && previousUserLevel) {
|
|
59213
59506
|
await this.awardLevelUpCredits(userId, previousUserLevel.currentLevel, currentLevel);
|
|
59214
59507
|
}
|
|
59215
|
-
|
|
59508
|
+
logger26.info("Synced from Timeback", {
|
|
59216
59509
|
userId,
|
|
59217
59510
|
totalXP,
|
|
59218
59511
|
currentLevel,
|
|
@@ -59253,7 +59546,7 @@ class LevelService {
|
|
|
59253
59546
|
}
|
|
59254
59547
|
if (totalCredits > 0) {
|
|
59255
59548
|
await this.deps.addCredits(userId, totalCredits);
|
|
59256
|
-
|
|
59549
|
+
logger26.info("Awarded level-up credits", {
|
|
59257
59550
|
userId,
|
|
59258
59551
|
fromLevel,
|
|
59259
59552
|
toLevel,
|
|
@@ -59291,7 +59584,7 @@ class LevelService {
|
|
|
59291
59584
|
};
|
|
59292
59585
|
}
|
|
59293
59586
|
}
|
|
59294
|
-
var
|
|
59587
|
+
var logger26;
|
|
59295
59588
|
var levelConfigCache = null;
|
|
59296
59589
|
var init_level_service = __esm(() => {
|
|
59297
59590
|
init_drizzle_orm();
|
|
@@ -59299,7 +59592,7 @@ var init_level_service = __esm(() => {
|
|
|
59299
59592
|
init_tables_index();
|
|
59300
59593
|
init_src2();
|
|
59301
59594
|
init_errors();
|
|
59302
|
-
|
|
59595
|
+
logger26 = log.scope("LevelService");
|
|
59303
59596
|
});
|
|
59304
59597
|
var init_events = () => {};
|
|
59305
59598
|
function convertWebSocketUrlToHttp(wsUrl) {
|
|
@@ -59316,13 +59609,13 @@ async function publishToUser(baseUrl, secret, userId, type, payload) {
|
|
|
59316
59609
|
});
|
|
59317
59610
|
if (!res.ok) {
|
|
59318
59611
|
const text3 = await res.text().catch(() => "");
|
|
59319
|
-
|
|
59612
|
+
logger27.warn("Failed to publish to user", {
|
|
59320
59613
|
status: res.status,
|
|
59321
59614
|
body: text3
|
|
59322
59615
|
});
|
|
59323
59616
|
}
|
|
59324
59617
|
} catch (error) {
|
|
59325
|
-
|
|
59618
|
+
logger27.error("Publish to user error", { error });
|
|
59326
59619
|
}
|
|
59327
59620
|
}
|
|
59328
59621
|
|
|
@@ -59344,7 +59637,7 @@ class NotificationService {
|
|
|
59344
59637
|
conditions2.push(eq(notifications.type, type));
|
|
59345
59638
|
}
|
|
59346
59639
|
const results = await this.deps.db.select().from(notifications).where(and(...conditions2)).orderBy(desc(notifications.createdAt)).limit(limit).offset(offset);
|
|
59347
|
-
|
|
59640
|
+
logger27.debug("Listed notifications", { userId: user.id, count: results.length });
|
|
59348
59641
|
return results;
|
|
59349
59642
|
}
|
|
59350
59643
|
async updateStatus(notificationId, status, method) {
|
|
@@ -59363,7 +59656,7 @@ class NotificationService {
|
|
|
59363
59656
|
if (!updated) {
|
|
59364
59657
|
throw new NotFoundError("Notification", notificationId);
|
|
59365
59658
|
}
|
|
59366
|
-
|
|
59659
|
+
logger27.debug("Updated status", { notificationId, status });
|
|
59367
59660
|
return updated;
|
|
59368
59661
|
}
|
|
59369
59662
|
async getStats(user, options) {
|
|
@@ -59389,7 +59682,7 @@ class NotificationService {
|
|
|
59389
59682
|
const clicked = statsMap.clicked || 0;
|
|
59390
59683
|
const dismissed = statsMap.dismissed || 0;
|
|
59391
59684
|
const expired = statsMap.expired || 0;
|
|
59392
|
-
|
|
59685
|
+
logger27.debug("Retrieved stats", { userId: user.id, total });
|
|
59393
59686
|
return {
|
|
59394
59687
|
total,
|
|
59395
59688
|
delivered,
|
|
@@ -59438,7 +59731,7 @@ class NotificationService {
|
|
|
59438
59731
|
options: { data, clickUrl, metadata: metadata2 }
|
|
59439
59732
|
});
|
|
59440
59733
|
}
|
|
59441
|
-
|
|
59734
|
+
logger27.debug("Created notification", {
|
|
59442
59735
|
userId,
|
|
59443
59736
|
type,
|
|
59444
59737
|
id: notificationId,
|
|
@@ -59446,7 +59739,7 @@ class NotificationService {
|
|
|
59446
59739
|
});
|
|
59447
59740
|
return notificationId;
|
|
59448
59741
|
} catch (error) {
|
|
59449
|
-
|
|
59742
|
+
logger27.error("Failed to create notification", { userId, type, error });
|
|
59450
59743
|
return null;
|
|
59451
59744
|
}
|
|
59452
59745
|
}
|
|
@@ -59460,7 +59753,7 @@ class NotificationService {
|
|
|
59460
59753
|
}) {
|
|
59461
59754
|
const realtimeConfig = this.deps.realtime;
|
|
59462
59755
|
if (!realtimeConfig) {
|
|
59463
|
-
|
|
59756
|
+
logger27.warn("No realtime config for publish");
|
|
59464
59757
|
return;
|
|
59465
59758
|
}
|
|
59466
59759
|
const { relayUrl, publishSecret } = realtimeConfig;
|
|
@@ -59502,13 +59795,13 @@ class NotificationService {
|
|
|
59502
59795
|
metadata: data.metadata || {}
|
|
59503
59796
|
}).returning();
|
|
59504
59797
|
if (!notification) {
|
|
59505
|
-
|
|
59798
|
+
logger27.error("Notification insert returned no rows", {
|
|
59506
59799
|
userId: data.userId,
|
|
59507
59800
|
type: data.type
|
|
59508
59801
|
});
|
|
59509
59802
|
throw new InternalError("Failed to create notification");
|
|
59510
59803
|
}
|
|
59511
|
-
|
|
59804
|
+
logger27.info("Inserted notification", {
|
|
59512
59805
|
notificationId: notification.id,
|
|
59513
59806
|
userId: notification.userId,
|
|
59514
59807
|
type: notification.type
|
|
@@ -59518,7 +59811,7 @@ class NotificationService {
|
|
|
59518
59811
|
async deliverPending(userId) {
|
|
59519
59812
|
const realtimeConfig = this.deps.realtime;
|
|
59520
59813
|
if (!realtimeConfig) {
|
|
59521
|
-
|
|
59814
|
+
logger27.warn("No realtime config for delivery");
|
|
59522
59815
|
return;
|
|
59523
59816
|
}
|
|
59524
59817
|
const { relayUrl, publishSecret } = realtimeConfig;
|
|
@@ -59545,13 +59838,13 @@ class NotificationService {
|
|
|
59545
59838
|
metadata: notification.metadata,
|
|
59546
59839
|
clickUrl: notification.clickUrl
|
|
59547
59840
|
});
|
|
59548
|
-
|
|
59841
|
+
logger27.info("Delivered notification", {
|
|
59549
59842
|
notificationId: notification.id,
|
|
59550
59843
|
userId,
|
|
59551
59844
|
type: notification.type
|
|
59552
59845
|
});
|
|
59553
59846
|
} catch (error) {
|
|
59554
|
-
|
|
59847
|
+
logger27.warn("Failed to deliver", {
|
|
59555
59848
|
notificationId: notification.id,
|
|
59556
59849
|
error
|
|
59557
59850
|
});
|
|
@@ -59559,7 +59852,7 @@ class NotificationService {
|
|
|
59559
59852
|
}
|
|
59560
59853
|
}
|
|
59561
59854
|
}
|
|
59562
|
-
var
|
|
59855
|
+
var logger27;
|
|
59563
59856
|
var init_notification_service = __esm(() => {
|
|
59564
59857
|
init_drizzle_orm();
|
|
59565
59858
|
init_src();
|
|
@@ -59568,7 +59861,7 @@ var init_notification_service = __esm(() => {
|
|
|
59568
59861
|
init_events();
|
|
59569
59862
|
init_notification();
|
|
59570
59863
|
init_errors();
|
|
59571
|
-
|
|
59864
|
+
logger27 = log.scope("NotificationService");
|
|
59572
59865
|
});
|
|
59573
59866
|
function createPlayerServices(deps) {
|
|
59574
59867
|
const { db: db2, realtime } = deps;
|
|
@@ -59687,7 +59980,7 @@ class CharacterService {
|
|
|
59687
59980
|
createdAt: characterComponents.createdAt,
|
|
59688
59981
|
updatedAt: characterComponents.updatedAt
|
|
59689
59982
|
}).from(characterComponents).innerJoin(spriteSheets, eq(characterComponents.spriteSheetId, spriteSheets.id)).where(lte(characterComponents.unlockLevel, level)).orderBy(characterComponents.componentType, characterComponents.variant);
|
|
59690
|
-
|
|
59983
|
+
logger28.debug("Listed available components", {
|
|
59691
59984
|
level,
|
|
59692
59985
|
count: components.length
|
|
59693
59986
|
});
|
|
@@ -59705,7 +59998,7 @@ class CharacterService {
|
|
|
59705
59998
|
}
|
|
59706
59999
|
}
|
|
59707
60000
|
});
|
|
59708
|
-
|
|
60001
|
+
logger28.debug("Retrieved character", { userId: user.id, found: Boolean(pc3) });
|
|
59709
60002
|
return pc3 ?? null;
|
|
59710
60003
|
}
|
|
59711
60004
|
async getByUserId(userId) {
|
|
@@ -59720,7 +60013,7 @@ class CharacterService {
|
|
|
59720
60013
|
}
|
|
59721
60014
|
}
|
|
59722
60015
|
});
|
|
59723
|
-
|
|
60016
|
+
logger28.debug("Retrieved character by ID", { userId, found: Boolean(pc3) });
|
|
59724
60017
|
return pc3 ?? null;
|
|
59725
60018
|
}
|
|
59726
60019
|
async create(input, user) {
|
|
@@ -59735,13 +60028,13 @@ class CharacterService {
|
|
|
59735
60028
|
}
|
|
59736
60029
|
const [characterRow] = await tx.insert(playerCharacters).values({ ...input, userId: user.id }).returning();
|
|
59737
60030
|
if (!characterRow) {
|
|
59738
|
-
|
|
60031
|
+
logger28.error("Character insert returned no rows", { userId: user.id });
|
|
59739
60032
|
throw new InternalError("Failed to create character in database");
|
|
59740
60033
|
}
|
|
59741
60034
|
await tx.update(users).set({ characterCreated: true }).where(eq(users.id, user.id));
|
|
59742
60035
|
return characterRow;
|
|
59743
60036
|
});
|
|
59744
|
-
|
|
60037
|
+
logger28.info("Created character", { userId: user.id, characterId: result.id });
|
|
59745
60038
|
return result;
|
|
59746
60039
|
}
|
|
59747
60040
|
async update(input, user) {
|
|
@@ -59753,7 +60046,7 @@ class CharacterService {
|
|
|
59753
60046
|
if (!row) {
|
|
59754
60047
|
throw new NotFoundError("Player character");
|
|
59755
60048
|
}
|
|
59756
|
-
|
|
60049
|
+
logger28.info("Updated character", {
|
|
59757
60050
|
userId: user.id,
|
|
59758
60051
|
characterId: row.id,
|
|
59759
60052
|
updatedFields: Object.keys(input)
|
|
@@ -59775,7 +60068,7 @@ class CharacterService {
|
|
|
59775
60068
|
const availableComponents = await db2.select().from(characterComponents).where(lte(characterComponents.unlockLevel, playerLevel));
|
|
59776
60069
|
const validation = validateAccessorySlot(accessoryComponentId, slot, playerLevel, availableComponents);
|
|
59777
60070
|
if (!validation.isValid) {
|
|
59778
|
-
|
|
60071
|
+
logger28.warn("Accessory validation failed", {
|
|
59779
60072
|
userId: user.id,
|
|
59780
60073
|
slot,
|
|
59781
60074
|
accessoryComponentId,
|
|
@@ -59791,14 +60084,14 @@ class CharacterService {
|
|
|
59791
60084
|
slot
|
|
59792
60085
|
}).returning();
|
|
59793
60086
|
if (!result) {
|
|
59794
|
-
|
|
60087
|
+
logger28.error("Accessory insert returned no rows", {
|
|
59795
60088
|
userId: user.id,
|
|
59796
60089
|
slot,
|
|
59797
60090
|
accessoryComponentId
|
|
59798
60091
|
});
|
|
59799
60092
|
throw new InternalError("Failed to equip accessory");
|
|
59800
60093
|
}
|
|
59801
|
-
|
|
60094
|
+
logger28.info("Equipped accessory", {
|
|
59802
60095
|
userId: user.id,
|
|
59803
60096
|
slot,
|
|
59804
60097
|
accessoryComponentId
|
|
@@ -59819,7 +60112,7 @@ class CharacterService {
|
|
|
59819
60112
|
const playerLevel = userLevel?.currentLevel ?? 1;
|
|
59820
60113
|
const validation = validateAccessoryRemoval(slot, playerLevel);
|
|
59821
60114
|
if (!validation.isValid) {
|
|
59822
|
-
|
|
60115
|
+
logger28.warn("Accessory removal validation failed", {
|
|
59823
60116
|
userId: user.id,
|
|
59824
60117
|
slot,
|
|
59825
60118
|
playerLevel,
|
|
@@ -59828,17 +60121,17 @@ class CharacterService {
|
|
|
59828
60121
|
throw new ValidationError(validation.error ?? "Invalid accessory removal");
|
|
59829
60122
|
}
|
|
59830
60123
|
await db2.delete(playerCharacterAccessories).where(and(eq(playerCharacterAccessories.playerCharacterId, playerCharacter.id), eq(playerCharacterAccessories.slot, slot)));
|
|
59831
|
-
|
|
60124
|
+
logger28.info("Removed accessory", { userId: user.id, slot });
|
|
59832
60125
|
}
|
|
59833
60126
|
}
|
|
59834
|
-
var
|
|
60127
|
+
var logger28;
|
|
59835
60128
|
var init_character_service = __esm(() => {
|
|
59836
60129
|
init_drizzle_orm();
|
|
59837
60130
|
init_tables_index();
|
|
59838
60131
|
init_src2();
|
|
59839
60132
|
init_errors();
|
|
59840
60133
|
init_accessory_util();
|
|
59841
|
-
|
|
60134
|
+
logger28 = log.scope("CharacterService");
|
|
59842
60135
|
});
|
|
59843
60136
|
|
|
59844
60137
|
class CurrencyService {
|
|
@@ -59849,7 +60142,7 @@ class CurrencyService {
|
|
|
59849
60142
|
async list() {
|
|
59850
60143
|
const db2 = this.deps.db;
|
|
59851
60144
|
const allCurrencies = await db2.query.currencies.findMany();
|
|
59852
|
-
|
|
60145
|
+
logger29.debug("Listed currencies", { count: allCurrencies.length });
|
|
59853
60146
|
return allCurrencies;
|
|
59854
60147
|
}
|
|
59855
60148
|
async getById(currencyId) {
|
|
@@ -59860,7 +60153,7 @@ class CurrencyService {
|
|
|
59860
60153
|
if (!currency) {
|
|
59861
60154
|
throw new NotFoundError("Currency", currencyId);
|
|
59862
60155
|
}
|
|
59863
|
-
|
|
60156
|
+
logger29.debug("Retrieved currency", { currencyId });
|
|
59864
60157
|
return currency;
|
|
59865
60158
|
}
|
|
59866
60159
|
async create(data) {
|
|
@@ -59868,13 +60161,13 @@ class CurrencyService {
|
|
|
59868
60161
|
try {
|
|
59869
60162
|
const [newCurrency] = await db2.insert(currencies).values(data).returning();
|
|
59870
60163
|
if (!newCurrency) {
|
|
59871
|
-
|
|
60164
|
+
logger29.error("Currency insert returned no rows", {
|
|
59872
60165
|
itemId: data.itemId,
|
|
59873
60166
|
symbol: data.symbol
|
|
59874
60167
|
});
|
|
59875
60168
|
throw new InternalError("Failed to create currency");
|
|
59876
60169
|
}
|
|
59877
|
-
|
|
60170
|
+
logger29.info("Created currency", {
|
|
59878
60171
|
currencyId: newCurrency.id,
|
|
59879
60172
|
itemId: newCurrency.itemId,
|
|
59880
60173
|
symbol: newCurrency.symbol,
|
|
@@ -59903,7 +60196,7 @@ class CurrencyService {
|
|
|
59903
60196
|
if (!updatedCurrency) {
|
|
59904
60197
|
throw new NotFoundError("Currency", currencyId);
|
|
59905
60198
|
}
|
|
59906
|
-
|
|
60199
|
+
logger29.info("Updated currency", {
|
|
59907
60200
|
currencyId: updatedCurrency.id,
|
|
59908
60201
|
updatedFields: Object.keys(data)
|
|
59909
60202
|
});
|
|
@@ -59929,16 +60222,16 @@ class CurrencyService {
|
|
|
59929
60222
|
if (result.length === 0) {
|
|
59930
60223
|
throw new NotFoundError("Currency", currencyId);
|
|
59931
60224
|
}
|
|
59932
|
-
|
|
60225
|
+
logger29.info("Deleted currency", { currencyId });
|
|
59933
60226
|
}
|
|
59934
60227
|
}
|
|
59935
|
-
var
|
|
60228
|
+
var logger29;
|
|
59936
60229
|
var init_currency_service = __esm(() => {
|
|
59937
60230
|
init_drizzle_orm();
|
|
59938
60231
|
init_tables_index();
|
|
59939
60232
|
init_src2();
|
|
59940
60233
|
init_errors();
|
|
59941
|
-
|
|
60234
|
+
logger29 = log.scope("CurrencyService");
|
|
59942
60235
|
});
|
|
59943
60236
|
|
|
59944
60237
|
class LogsService {
|
|
@@ -59956,11 +60249,11 @@ class LogsService {
|
|
|
59956
60249
|
if (!game) {
|
|
59957
60250
|
throw new NotFoundError("Game", slug2);
|
|
59958
60251
|
}
|
|
59959
|
-
|
|
60252
|
+
logger30.info("Admin accessing game logs", { adminId: user.id, slug: slug2, sstStage });
|
|
59960
60253
|
} else {
|
|
59961
60254
|
const isApprovedDev = user.developerStatus === "approved";
|
|
59962
60255
|
if (!isApprovedDev) {
|
|
59963
|
-
|
|
60256
|
+
logger30.warn("Unapproved developer attempted log access", { userId: user.id, slug: slug2 });
|
|
59964
60257
|
throw new AccessDeniedError("Must be an approved developer");
|
|
59965
60258
|
}
|
|
59966
60259
|
const game = await db2.query.games.findFirst({
|
|
@@ -59975,7 +60268,7 @@ class LogsService {
|
|
|
59975
60268
|
columns: { id: true }
|
|
59976
60269
|
});
|
|
59977
60270
|
if (!membership) {
|
|
59978
|
-
|
|
60271
|
+
logger30.warn("Developer attempted access to unowned game logs", {
|
|
59979
60272
|
userId: user.id,
|
|
59980
60273
|
slug: slug2
|
|
59981
60274
|
});
|
|
@@ -59984,7 +60277,7 @@ class LogsService {
|
|
|
59984
60277
|
}
|
|
59985
60278
|
const workerId = getDeploymentId(slug2, sstStage);
|
|
59986
60279
|
const token = await this.deps.mintLogStreamToken(user.id, workerId);
|
|
59987
|
-
|
|
60280
|
+
logger30.debug("Generated log stream token", {
|
|
59988
60281
|
userId: user.id,
|
|
59989
60282
|
slug: slug2,
|
|
59990
60283
|
workerId
|
|
@@ -59992,14 +60285,14 @@ class LogsService {
|
|
|
59992
60285
|
return { token, workerId };
|
|
59993
60286
|
}
|
|
59994
60287
|
}
|
|
59995
|
-
var
|
|
60288
|
+
var logger30;
|
|
59996
60289
|
var init_logs_service = __esm(() => {
|
|
59997
60290
|
init_drizzle_orm();
|
|
59998
60291
|
init_tables_index();
|
|
59999
60292
|
init_src2();
|
|
60000
60293
|
init_errors();
|
|
60001
60294
|
init_deployment_util();
|
|
60002
|
-
|
|
60295
|
+
logger30 = log.scope("LogsService");
|
|
60003
60296
|
});
|
|
60004
60297
|
|
|
60005
60298
|
class LtiService {
|
|
@@ -60050,7 +60343,7 @@ class MapService {
|
|
|
60050
60343
|
if (!mapDetails) {
|
|
60051
60344
|
throw new NotFoundError("Map", identifier);
|
|
60052
60345
|
}
|
|
60053
|
-
|
|
60346
|
+
logger31.debug("Retrieved map", { identifier });
|
|
60054
60347
|
return mapDetails;
|
|
60055
60348
|
}
|
|
60056
60349
|
async getElements(mapId) {
|
|
@@ -60066,7 +60359,7 @@ class MapService {
|
|
|
60066
60359
|
}
|
|
60067
60360
|
}
|
|
60068
60361
|
});
|
|
60069
|
-
|
|
60362
|
+
logger31.debug("Retrieved elements", { mapId, count: elements.length });
|
|
60070
60363
|
return elements;
|
|
60071
60364
|
}
|
|
60072
60365
|
async getObjects(mapId, userId) {
|
|
@@ -60087,7 +60380,7 @@ class MapService {
|
|
|
60087
60380
|
}
|
|
60088
60381
|
}
|
|
60089
60382
|
});
|
|
60090
|
-
|
|
60383
|
+
logger31.debug("Retrieved objects", { mapId, userId, count: objects.length });
|
|
60091
60384
|
return objects.map((object) => this.formatMapObjectWithItem(object));
|
|
60092
60385
|
}
|
|
60093
60386
|
async createObject(mapId, data, user) {
|
|
@@ -60114,7 +60407,7 @@ class MapService {
|
|
|
60114
60407
|
throw new NotFoundError("Item", data.itemId);
|
|
60115
60408
|
}
|
|
60116
60409
|
if (!item.isPlaceable) {
|
|
60117
|
-
|
|
60410
|
+
logger31.warn("Attempted to place non-placeable item", {
|
|
60118
60411
|
userId: user.id,
|
|
60119
60412
|
itemId: data.itemId,
|
|
60120
60413
|
mapId
|
|
@@ -60128,7 +60421,7 @@ class MapService {
|
|
|
60128
60421
|
};
|
|
60129
60422
|
const [createdObject] = await db2.insert(mapObjects).values(objectData).returning();
|
|
60130
60423
|
if (!createdObject) {
|
|
60131
|
-
|
|
60424
|
+
logger31.error("Map object insert returned no rows", {
|
|
60132
60425
|
userId: user.id,
|
|
60133
60426
|
mapId,
|
|
60134
60427
|
itemId: data.itemId
|
|
@@ -60152,12 +60445,12 @@ class MapService {
|
|
|
60152
60445
|
}
|
|
60153
60446
|
});
|
|
60154
60447
|
if (!objectWithItem) {
|
|
60155
|
-
|
|
60448
|
+
logger31.error("Map object query after insert returned no rows", {
|
|
60156
60449
|
objectId: createdObject.id
|
|
60157
60450
|
});
|
|
60158
60451
|
throw new InternalError("Failed to retrieve created object");
|
|
60159
60452
|
}
|
|
60160
|
-
|
|
60453
|
+
logger31.info("Created object", {
|
|
60161
60454
|
userId: user.id,
|
|
60162
60455
|
mapId,
|
|
60163
60456
|
objectId: createdObject.id,
|
|
@@ -60181,7 +60474,7 @@ class MapService {
|
|
|
60181
60474
|
if (result.length === 0) {
|
|
60182
60475
|
throw new NotFoundError("MapObject", objectId);
|
|
60183
60476
|
}
|
|
60184
|
-
|
|
60477
|
+
logger31.info("Deleted object", {
|
|
60185
60478
|
userId: user.id,
|
|
60186
60479
|
mapId,
|
|
60187
60480
|
objectId
|
|
@@ -60210,13 +60503,13 @@ class MapService {
|
|
|
60210
60503
|
};
|
|
60211
60504
|
}
|
|
60212
60505
|
}
|
|
60213
|
-
var
|
|
60506
|
+
var logger31;
|
|
60214
60507
|
var init_map_service = __esm(() => {
|
|
60215
60508
|
init_drizzle_orm();
|
|
60216
60509
|
init_tables_index();
|
|
60217
60510
|
init_src2();
|
|
60218
60511
|
init_errors();
|
|
60219
|
-
|
|
60512
|
+
logger31 = log.scope("MapService");
|
|
60220
60513
|
});
|
|
60221
60514
|
|
|
60222
60515
|
class RealtimeService {
|
|
@@ -60250,20 +60543,20 @@ class RealtimeService {
|
|
|
60250
60543
|
}
|
|
60251
60544
|
const displayName = user.username || (user.name ? user.name.split(" ")[0] : undefined) || undefined;
|
|
60252
60545
|
const token = await this.deps.mintRealtimeToken(user.id, resolvedGameId, displayName, user.role);
|
|
60253
|
-
|
|
60546
|
+
logger32.info("Generated token", {
|
|
60254
60547
|
userId: user.id,
|
|
60255
60548
|
gameId: resolvedGameId || "global"
|
|
60256
60549
|
});
|
|
60257
60550
|
return { token };
|
|
60258
60551
|
}
|
|
60259
60552
|
}
|
|
60260
|
-
var
|
|
60553
|
+
var logger32;
|
|
60261
60554
|
var init_realtime_service = __esm(() => {
|
|
60262
60555
|
init_drizzle_orm();
|
|
60263
60556
|
init_tables_index();
|
|
60264
60557
|
init_src2();
|
|
60265
60558
|
init_errors();
|
|
60266
|
-
|
|
60559
|
+
logger32 = log.scope("RealtimeService");
|
|
60267
60560
|
});
|
|
60268
60561
|
|
|
60269
60562
|
class SessionService {
|
|
@@ -60297,10 +60590,10 @@ class SessionService {
|
|
|
60297
60590
|
};
|
|
60298
60591
|
const [newSession] = await db2.insert(gameSessions).values(sessionToInsert).returning({ sessionId: gameSessions.id });
|
|
60299
60592
|
if (!newSession?.sessionId) {
|
|
60300
|
-
|
|
60593
|
+
logger33.error("Game session insert returned no rows", { userId, gameId });
|
|
60301
60594
|
throw new InternalError("Failed to create game session");
|
|
60302
60595
|
}
|
|
60303
|
-
|
|
60596
|
+
logger33.info("Started new session", {
|
|
60304
60597
|
sessionId: newSession.sessionId,
|
|
60305
60598
|
gameId,
|
|
60306
60599
|
userId
|
|
@@ -60321,23 +60614,23 @@ class SessionService {
|
|
|
60321
60614
|
return { success: true, message: "Session already ended" };
|
|
60322
60615
|
}
|
|
60323
60616
|
await db2.update(gameSessions).set({ endedAt: new Date }).where(eq(gameSessions.id, sessionId));
|
|
60324
|
-
|
|
60617
|
+
logger33.info("Ended session", { sessionId, gameId, userId });
|
|
60325
60618
|
return { success: true };
|
|
60326
60619
|
}
|
|
60327
60620
|
async mintToken(gameIdOrSlug, userId) {
|
|
60328
60621
|
const gameId = await this.resolveGameId(gameIdOrSlug);
|
|
60329
60622
|
const result = await this.deps.mintGameToken(gameId, userId);
|
|
60330
|
-
|
|
60623
|
+
logger33.debug("Minted game token", { gameId, userId });
|
|
60331
60624
|
return result;
|
|
60332
60625
|
}
|
|
60333
60626
|
}
|
|
60334
|
-
var
|
|
60627
|
+
var logger33;
|
|
60335
60628
|
var init_session_service = __esm(() => {
|
|
60336
60629
|
init_drizzle_orm();
|
|
60337
60630
|
init_tables_index();
|
|
60338
60631
|
init_src2();
|
|
60339
60632
|
init_errors();
|
|
60340
|
-
|
|
60633
|
+
logger33 = log.scope("SessionService");
|
|
60341
60634
|
});
|
|
60342
60635
|
|
|
60343
60636
|
class ShopService {
|
|
@@ -60382,7 +60675,7 @@ class ShopService {
|
|
|
60382
60675
|
const shopItems = [];
|
|
60383
60676
|
for (const listing of listingsWithRelations) {
|
|
60384
60677
|
if (!listing.item || !listing.currency) {
|
|
60385
|
-
|
|
60678
|
+
logger34.warn("Listing missing item or currency, skipping", {
|
|
60386
60679
|
listingId: listing.id
|
|
60387
60680
|
});
|
|
60388
60681
|
} else {
|
|
@@ -60399,7 +60692,7 @@ class ShopService {
|
|
|
60399
60692
|
});
|
|
60400
60693
|
}
|
|
60401
60694
|
}
|
|
60402
|
-
|
|
60695
|
+
logger34.debug("Retrieved shop view", {
|
|
60403
60696
|
userId: user.id,
|
|
60404
60697
|
itemCount: shopItems.length,
|
|
60405
60698
|
currencyCount: shopCurrencies.length
|
|
@@ -60410,12 +60703,12 @@ class ShopService {
|
|
|
60410
60703
|
};
|
|
60411
60704
|
}
|
|
60412
60705
|
}
|
|
60413
|
-
var
|
|
60706
|
+
var logger34;
|
|
60414
60707
|
var init_shop_service = __esm(() => {
|
|
60415
60708
|
init_drizzle_orm();
|
|
60416
60709
|
init_tables_index();
|
|
60417
60710
|
init_src2();
|
|
60418
|
-
|
|
60711
|
+
logger34 = log.scope("ShopService");
|
|
60419
60712
|
});
|
|
60420
60713
|
|
|
60421
60714
|
class SpriteService {
|
|
@@ -60431,17 +60724,17 @@ class SpriteService {
|
|
|
60431
60724
|
if (!template) {
|
|
60432
60725
|
throw new NotFoundError("SpriteTemplate", slug2);
|
|
60433
60726
|
}
|
|
60434
|
-
|
|
60727
|
+
logger35.debug("Retrieved sprite", { slug: slug2 });
|
|
60435
60728
|
return template;
|
|
60436
60729
|
}
|
|
60437
60730
|
}
|
|
60438
|
-
var
|
|
60731
|
+
var logger35;
|
|
60439
60732
|
var init_sprite_service = __esm(() => {
|
|
60440
60733
|
init_drizzle_orm();
|
|
60441
60734
|
init_tables_index();
|
|
60442
60735
|
init_src2();
|
|
60443
60736
|
init_errors();
|
|
60444
|
-
|
|
60737
|
+
logger35 = log.scope("SpriteService");
|
|
60445
60738
|
});
|
|
60446
60739
|
|
|
60447
60740
|
class UserService {
|
|
@@ -60455,12 +60748,12 @@ class UserService {
|
|
|
60455
60748
|
where: eq(users.id, user.id)
|
|
60456
60749
|
});
|
|
60457
60750
|
if (!userData) {
|
|
60458
|
-
|
|
60751
|
+
logger36.error("User not found", { userId: user.id });
|
|
60459
60752
|
throw new NotFoundError("User", user.id);
|
|
60460
60753
|
}
|
|
60461
60754
|
const timeback2 = userData.timebackId ? await this.fetchTimebackData(userData.timebackId, gameId) : undefined;
|
|
60462
60755
|
if (gameId) {
|
|
60463
|
-
|
|
60756
|
+
logger36.debug("Fetched user profile (game context)", { userId: user.id, gameId });
|
|
60464
60757
|
return {
|
|
60465
60758
|
id: userData.id,
|
|
60466
60759
|
name: userData.name,
|
|
@@ -60473,7 +60766,7 @@ class UserService {
|
|
|
60473
60766
|
const timebackAccount = await db2.query.accounts.findFirst({
|
|
60474
60767
|
where: and(eq(accounts.userId, user.id), eq(accounts.providerId, "timeback"))
|
|
60475
60768
|
});
|
|
60476
|
-
|
|
60769
|
+
logger36.debug("Fetched user profile (platform context)", { userId: user.id });
|
|
60477
60770
|
return {
|
|
60478
60771
|
id: userData.id,
|
|
60479
60772
|
name: userData.name,
|
|
@@ -60496,7 +60789,7 @@ class UserService {
|
|
|
60496
60789
|
columns: { name: true }
|
|
60497
60790
|
});
|
|
60498
60791
|
if (!userData) {
|
|
60499
|
-
|
|
60792
|
+
logger36.error("Demo user not found", { userId });
|
|
60500
60793
|
throw new NotFoundError("User", userId);
|
|
60501
60794
|
}
|
|
60502
60795
|
return {
|
|
@@ -60510,10 +60803,10 @@ class UserService {
|
|
|
60510
60803
|
updatedAt: new Date
|
|
60511
60804
|
}).where(eq(users.id, userId)).returning({ name: users.name });
|
|
60512
60805
|
if (!updatedUser) {
|
|
60513
|
-
|
|
60806
|
+
logger36.error("Demo user not found for profile update", { userId });
|
|
60514
60807
|
throw new NotFoundError("User", userId);
|
|
60515
60808
|
}
|
|
60516
|
-
|
|
60809
|
+
logger36.debug("Updated demo profile", { userId, displayName });
|
|
60517
60810
|
return {
|
|
60518
60811
|
displayName: updatedUser.name,
|
|
60519
60812
|
isDefault: updatedUser.name === DEMO_DISPLAY_NAME_PLACEHOLDER
|
|
@@ -60526,7 +60819,7 @@ class UserService {
|
|
|
60526
60819
|
]);
|
|
60527
60820
|
const enrollments = gameId ? this.filterEnrollmentsByGame(allEnrollments, gameId) : allEnrollments;
|
|
60528
60821
|
const organizations = gameId ? this.filterOrganizationsByEnrollments(allOrganizations, enrollments) : allOrganizations;
|
|
60529
|
-
|
|
60822
|
+
logger36.debug("Fetched Timeback data", {
|
|
60530
60823
|
timebackId,
|
|
60531
60824
|
role,
|
|
60532
60825
|
enrollmentCount: enrollments.length,
|
|
@@ -60535,9 +60828,9 @@ class UserService {
|
|
|
60535
60828
|
return { id: timebackId, role, enrollments, organizations };
|
|
60536
60829
|
}
|
|
60537
60830
|
async fetchStudentProfile(timebackId) {
|
|
60538
|
-
|
|
60831
|
+
logger36.debug("Fetching student profile", { timebackId });
|
|
60539
60832
|
if (!this.deps.timeback) {
|
|
60540
|
-
|
|
60833
|
+
logger36.warn("Timeback client not available");
|
|
60541
60834
|
return { role: "student", organizations: [] };
|
|
60542
60835
|
}
|
|
60543
60836
|
try {
|
|
@@ -60565,14 +60858,14 @@ class UserService {
|
|
|
60565
60858
|
}
|
|
60566
60859
|
return { role, organizations: [...orgMap.values()] };
|
|
60567
60860
|
} catch (error) {
|
|
60568
|
-
|
|
60861
|
+
logger36.warn("Failed to fetch student profile", { error, timebackId });
|
|
60569
60862
|
return { role: "student", organizations: [] };
|
|
60570
60863
|
}
|
|
60571
60864
|
}
|
|
60572
60865
|
async fetchEnrollments(timebackId) {
|
|
60573
|
-
|
|
60866
|
+
logger36.debug("Fetching enrollments", { timebackId });
|
|
60574
60867
|
if (!this.deps.timeback) {
|
|
60575
|
-
|
|
60868
|
+
logger36.warn("Timeback client not available");
|
|
60576
60869
|
return [];
|
|
60577
60870
|
}
|
|
60578
60871
|
try {
|
|
@@ -60593,7 +60886,7 @@ class UserService {
|
|
|
60593
60886
|
orgId: courseToSchool.get(i2.courseId)
|
|
60594
60887
|
}));
|
|
60595
60888
|
} catch (error) {
|
|
60596
|
-
|
|
60889
|
+
logger36.warn("Failed to fetch enrollments", { error, timebackId });
|
|
60597
60890
|
return [];
|
|
60598
60891
|
}
|
|
60599
60892
|
}
|
|
@@ -60608,14 +60901,14 @@ class UserService {
|
|
|
60608
60901
|
return organizations.filter((o) => enrollmentOrgIds.has(o.id));
|
|
60609
60902
|
}
|
|
60610
60903
|
}
|
|
60611
|
-
var
|
|
60904
|
+
var logger36;
|
|
60612
60905
|
var init_user_service = __esm(() => {
|
|
60613
60906
|
init_drizzle_orm();
|
|
60614
60907
|
init_src();
|
|
60615
60908
|
init_tables_index();
|
|
60616
60909
|
init_src2();
|
|
60617
60910
|
init_errors();
|
|
60618
|
-
|
|
60911
|
+
logger36 = log.scope("UserService");
|
|
60619
60912
|
});
|
|
60620
60913
|
|
|
60621
60914
|
class VerifyService {
|
|
@@ -60624,16 +60917,16 @@ class VerifyService {
|
|
|
60624
60917
|
this.deps = deps;
|
|
60625
60918
|
}
|
|
60626
60919
|
async verifyGameToken(token) {
|
|
60627
|
-
|
|
60920
|
+
logger37.debug("Verifying game token");
|
|
60628
60921
|
const payload = await this.deps.validateGameToken(token);
|
|
60629
60922
|
if (!payload) {
|
|
60630
|
-
|
|
60923
|
+
logger37.warn("Invalid or expired game token presented");
|
|
60631
60924
|
throw new ValidationError("Invalid or expired token");
|
|
60632
60925
|
}
|
|
60633
60926
|
const gameId = payload.sub;
|
|
60634
60927
|
const userId = payload.uid;
|
|
60635
60928
|
if (typeof gameId !== "string" || typeof userId !== "string") {
|
|
60636
|
-
|
|
60929
|
+
logger37.warn("Game token missing required claims", {
|
|
60637
60930
|
hasGameId: typeof gameId === "string",
|
|
60638
60931
|
hasUserId: typeof userId === "string"
|
|
60639
60932
|
});
|
|
@@ -60644,7 +60937,7 @@ class VerifyService {
|
|
|
60644
60937
|
where: eq(users.id, userId)
|
|
60645
60938
|
});
|
|
60646
60939
|
if (!userData) {
|
|
60647
|
-
|
|
60940
|
+
logger37.error("User not found for valid token", {
|
|
60648
60941
|
userId
|
|
60649
60942
|
});
|
|
60650
60943
|
throw new NotFoundError("User", userId);
|
|
@@ -60658,7 +60951,7 @@ class VerifyService {
|
|
|
60658
60951
|
family_name: undefined,
|
|
60659
60952
|
timeback_id: userData.timebackId || undefined
|
|
60660
60953
|
};
|
|
60661
|
-
|
|
60954
|
+
logger37.info("Token verified", { gameId, userId });
|
|
60662
60955
|
return {
|
|
60663
60956
|
claims: payload,
|
|
60664
60957
|
gameId,
|
|
@@ -60666,13 +60959,13 @@ class VerifyService {
|
|
|
60666
60959
|
};
|
|
60667
60960
|
}
|
|
60668
60961
|
}
|
|
60669
|
-
var
|
|
60962
|
+
var logger37;
|
|
60670
60963
|
var init_verify_service = __esm(() => {
|
|
60671
60964
|
init_drizzle_orm();
|
|
60672
60965
|
init_tables_index();
|
|
60673
60966
|
init_src2();
|
|
60674
60967
|
init_errors();
|
|
60675
|
-
|
|
60968
|
+
logger37 = log.scope("VerifyService");
|
|
60676
60969
|
});
|
|
60677
60970
|
function createStandaloneServices(deps) {
|
|
60678
60971
|
const { db: db2, auth: auth2, timeback: timeback2 } = deps;
|
|
@@ -65804,7 +66097,7 @@ var colorStatus = async (status) => {
|
|
|
65804
66097
|
}
|
|
65805
66098
|
return `${status}`;
|
|
65806
66099
|
};
|
|
65807
|
-
var
|
|
66100
|
+
var logger38 = (fn = console.log) => {
|
|
65808
66101
|
return async function logger2(c, next) {
|
|
65809
66102
|
const { method, url: url2 } = c.req;
|
|
65810
66103
|
const path2 = url2.slice(url2.indexOf("/", 8));
|
|
@@ -65981,7 +66274,7 @@ function createApp(db2, options) {
|
|
|
65981
66274
|
const app = new Hono2;
|
|
65982
66275
|
app.use("*", cors({ origin: "*", credentials: true }));
|
|
65983
66276
|
if (options.verbose && !options.quiet) {
|
|
65984
|
-
app.use("*",
|
|
66277
|
+
app.use("*", logger38());
|
|
65985
66278
|
}
|
|
65986
66279
|
app.use("/api/*", async (c, next) => {
|
|
65987
66280
|
c.set("db", db2);
|
|
@@ -72683,12 +72976,12 @@ var init_session2 = __esm(() => {
|
|
|
72683
72976
|
init_utils();
|
|
72684
72977
|
init_dist5();
|
|
72685
72978
|
PglitePreparedQuery = class PglitePreparedQuery2 extends PgPreparedQuery {
|
|
72686
|
-
constructor(client, queryString, params,
|
|
72979
|
+
constructor(client, queryString, params, logger39, fields, name3, _isResponseInArrayMode, customResultMapper) {
|
|
72687
72980
|
super({ sql: queryString, params });
|
|
72688
72981
|
this.client = client;
|
|
72689
72982
|
this.queryString = queryString;
|
|
72690
72983
|
this.params = params;
|
|
72691
|
-
this.logger =
|
|
72984
|
+
this.logger = logger39;
|
|
72692
72985
|
this.fields = fields;
|
|
72693
72986
|
this._isResponseInArrayMode = _isResponseInArrayMode;
|
|
72694
72987
|
this.customResultMapper = customResultMapper;
|
|
@@ -72790,11 +73083,11 @@ var init_session2 = __esm(() => {
|
|
|
72790
73083
|
});
|
|
72791
73084
|
function construct(client, config2 = {}) {
|
|
72792
73085
|
const dialect2 = new PgDialect({ casing: config2.casing });
|
|
72793
|
-
let
|
|
73086
|
+
let logger39;
|
|
72794
73087
|
if (config2.logger === true) {
|
|
72795
|
-
|
|
73088
|
+
logger39 = new DefaultLogger;
|
|
72796
73089
|
} else if (config2.logger !== false) {
|
|
72797
|
-
|
|
73090
|
+
logger39 = config2.logger;
|
|
72798
73091
|
}
|
|
72799
73092
|
let schema2;
|
|
72800
73093
|
if (config2.schema) {
|
|
@@ -72805,7 +73098,7 @@ function construct(client, config2 = {}) {
|
|
|
72805
73098
|
tableNamesMap: tablesConfig.tableNamesMap
|
|
72806
73099
|
};
|
|
72807
73100
|
}
|
|
72808
|
-
const driver = new PgliteDriver(client, dialect2, { logger:
|
|
73101
|
+
const driver = new PgliteDriver(client, dialect2, { logger: logger39 });
|
|
72809
73102
|
const session2 = driver.createSession(schema2);
|
|
72810
73103
|
const db2 = new PgliteDatabase(dialect2, session2, schema2);
|
|
72811
73104
|
db2.$client = client;
|
|
@@ -121410,8 +121703,8 @@ var init_currencies = __esm(() => {
|
|
|
121410
121703
|
init_tables_index();
|
|
121411
121704
|
init_constants();
|
|
121412
121705
|
});
|
|
121413
|
-
function setLogger(
|
|
121414
|
-
customLogger =
|
|
121706
|
+
function setLogger(logger39) {
|
|
121707
|
+
customLogger = logger39;
|
|
121415
121708
|
}
|
|
121416
121709
|
function getLogger() {
|
|
121417
121710
|
if (customLogger) {
|
|
@@ -121424,10 +121717,10 @@ function getLogger() {
|
|
|
121424
121717
|
};
|
|
121425
121718
|
}
|
|
121426
121719
|
var customLogger;
|
|
121427
|
-
var
|
|
121720
|
+
var logger39;
|
|
121428
121721
|
var init_adapter = __esm(() => {
|
|
121429
121722
|
init_config();
|
|
121430
|
-
|
|
121723
|
+
logger39 = {
|
|
121431
121724
|
info: (msg) => {
|
|
121432
121725
|
if (customLogger || !config.embedded) {
|
|
121433
121726
|
getLogger().info(msg);
|
|
@@ -121511,7 +121804,7 @@ async function seedCoreGames(db2) {
|
|
|
121511
121804
|
role: "owner"
|
|
121512
121805
|
}).onConflictDoNothing();
|
|
121513
121806
|
} catch (error2) {
|
|
121514
|
-
|
|
121807
|
+
logger39.error(`Error seeding core game '${gameData.slug}': ${error2}`);
|
|
121515
121808
|
}
|
|
121516
121809
|
}
|
|
121517
121810
|
}
|
|
@@ -121561,7 +121854,7 @@ async function seedCurrentProjectGame(db2, project) {
|
|
|
121561
121854
|
}
|
|
121562
121855
|
return newGame;
|
|
121563
121856
|
} catch (error2) {
|
|
121564
|
-
|
|
121857
|
+
logger39.error(`❌ Error seeding project game: ${error2}`);
|
|
121565
121858
|
throw error2;
|
|
121566
121859
|
}
|
|
121567
121860
|
}
|
|
@@ -122324,7 +122617,7 @@ async function provisionLtiUser(db2, claims) {
|
|
|
122324
122617
|
where: eq(users.id, existingAccount.userId)
|
|
122325
122618
|
});
|
|
122326
122619
|
if (user) {
|
|
122327
|
-
|
|
122620
|
+
logger40.info("Found user by LTI account", {
|
|
122328
122621
|
userId: user.id,
|
|
122329
122622
|
ltiTimebackId
|
|
122330
122623
|
});
|
|
@@ -122353,13 +122646,13 @@ async function provisionLtiUser(db2, claims) {
|
|
|
122353
122646
|
updatedAt: new Date
|
|
122354
122647
|
}).returning({ id: accounts.id });
|
|
122355
122648
|
if (!account) {
|
|
122356
|
-
|
|
122649
|
+
logger40.error("LTI account link insert returned no rows", {
|
|
122357
122650
|
userId: existingUser.id,
|
|
122358
122651
|
ltiTimebackId
|
|
122359
122652
|
});
|
|
122360
122653
|
throw new InternalError("Failed to link LTI account");
|
|
122361
122654
|
}
|
|
122362
|
-
|
|
122655
|
+
logger40.info("Linked LTI account to existing user", {
|
|
122363
122656
|
userId: existingUser.id,
|
|
122364
122657
|
ltiTimebackId
|
|
122365
122658
|
});
|
|
@@ -122379,7 +122672,7 @@ async function provisionLtiUser(db2, claims) {
|
|
|
122379
122672
|
updatedAt: new Date
|
|
122380
122673
|
}).returning();
|
|
122381
122674
|
if (!insertedUser) {
|
|
122382
|
-
|
|
122675
|
+
logger40.error("LTI user insert returned no rows", { email, ltiTimebackId });
|
|
122383
122676
|
throw new InternalError("Failed to create user");
|
|
122384
122677
|
}
|
|
122385
122678
|
await tx.insert(accounts).values({
|
|
@@ -122394,7 +122687,7 @@ async function provisionLtiUser(db2, claims) {
|
|
|
122394
122687
|
createdAt: new Date,
|
|
122395
122688
|
updatedAt: new Date
|
|
122396
122689
|
});
|
|
122397
|
-
|
|
122690
|
+
logger40.info("Provisioned new user from LTI", {
|
|
122398
122691
|
userId: insertedUser.id,
|
|
122399
122692
|
ltiTimebackId
|
|
122400
122693
|
});
|
|
@@ -122402,7 +122695,7 @@ async function provisionLtiUser(db2, claims) {
|
|
|
122402
122695
|
});
|
|
122403
122696
|
return createdUser;
|
|
122404
122697
|
}
|
|
122405
|
-
var
|
|
122698
|
+
var logger40;
|
|
122406
122699
|
var init_lti_provisioning = __esm(() => {
|
|
122407
122700
|
init_drizzle_orm();
|
|
122408
122701
|
init_src();
|
|
@@ -122410,7 +122703,7 @@ var init_lti_provisioning = __esm(() => {
|
|
|
122410
122703
|
init_src2();
|
|
122411
122704
|
init_errors();
|
|
122412
122705
|
init_lti_util();
|
|
122413
|
-
|
|
122706
|
+
logger40 = log.scope("LtiProvisioning");
|
|
122414
122707
|
});
|
|
122415
122708
|
function formatZodError(error2) {
|
|
122416
122709
|
const flat = error2.flatten();
|
|
@@ -122453,7 +122746,7 @@ var init_utils11 = __esm(() => {
|
|
|
122453
122746
|
init_timeback_util();
|
|
122454
122747
|
init_validation_util();
|
|
122455
122748
|
});
|
|
122456
|
-
var
|
|
122749
|
+
var logger41;
|
|
122457
122750
|
var listCurrent;
|
|
122458
122751
|
var listHistory;
|
|
122459
122752
|
var postProgress;
|
|
@@ -122464,14 +122757,14 @@ var init_achievement_controller = __esm(() => {
|
|
|
122464
122757
|
init_src2();
|
|
122465
122758
|
init_errors();
|
|
122466
122759
|
init_utils11();
|
|
122467
|
-
|
|
122760
|
+
logger41 = log.scope("AchievementController");
|
|
122468
122761
|
listCurrent = requireNonAnonymous(async (ctx) => {
|
|
122469
|
-
|
|
122762
|
+
logger41.debug("Listing current achievements", { userId: ctx.user.id, gameId: ctx.gameId });
|
|
122470
122763
|
return ctx.services.achievement.listCurrent(ctx.user, ctx.gameId);
|
|
122471
122764
|
});
|
|
122472
122765
|
listHistory = requireNonAnonymous(async (ctx) => {
|
|
122473
122766
|
const limit = Math.max(1, Math.min(100, Number(ctx.url.searchParams.get("limit")) || 20));
|
|
122474
|
-
|
|
122767
|
+
logger41.debug("Listing achievement history", { userId: ctx.user.id, limit });
|
|
122475
122768
|
return ctx.services.achievement.listHistory(ctx.user, limit);
|
|
122476
122769
|
});
|
|
122477
122770
|
postProgress = requireNonAnonymous(async (ctx) => {
|
|
@@ -122482,12 +122775,12 @@ var init_achievement_controller = __esm(() => {
|
|
|
122482
122775
|
} catch (error2) {
|
|
122483
122776
|
if (error2 instanceof exports_external.ZodError) {
|
|
122484
122777
|
const details = formatZodError(error2);
|
|
122485
|
-
|
|
122778
|
+
logger41.warn("Submit achievement progress validation failed", { details });
|
|
122486
122779
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
122487
122780
|
}
|
|
122488
122781
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122489
122782
|
}
|
|
122490
|
-
|
|
122783
|
+
logger41.debug("Submitting progress", {
|
|
122491
122784
|
userId: ctx.user.id,
|
|
122492
122785
|
achievementId: body2.achievementId
|
|
122493
122786
|
});
|
|
@@ -122499,15 +122792,15 @@ var init_achievement_controller = __esm(() => {
|
|
|
122499
122792
|
postProgress
|
|
122500
122793
|
};
|
|
122501
122794
|
});
|
|
122502
|
-
var
|
|
122795
|
+
var logger42;
|
|
122503
122796
|
var getAllowedOrigins;
|
|
122504
122797
|
var init_admin_controller = __esm(() => {
|
|
122505
122798
|
init_src2();
|
|
122506
122799
|
init_utils11();
|
|
122507
|
-
|
|
122800
|
+
logger42 = log.scope("AdminController");
|
|
122508
122801
|
getAllowedOrigins = requireAdmin(async (ctx) => {
|
|
122509
122802
|
const shouldRefresh = ctx.url.searchParams.get("refresh") === "true";
|
|
122510
|
-
|
|
122803
|
+
logger42.debug("Getting allowed origins", { userId: ctx.user.id, refresh: shouldRefresh });
|
|
122511
122804
|
if (shouldRefresh) {
|
|
122512
122805
|
await ctx.providers.cache.refreshGameOrigins();
|
|
122513
122806
|
}
|
|
@@ -122520,7 +122813,7 @@ var init_admin_controller = __esm(() => {
|
|
|
122520
122813
|
};
|
|
122521
122814
|
});
|
|
122522
122815
|
});
|
|
122523
|
-
var
|
|
122816
|
+
var logger43;
|
|
122524
122817
|
var listFiles;
|
|
122525
122818
|
var getFile;
|
|
122526
122819
|
var putFile;
|
|
@@ -122532,7 +122825,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
122532
122825
|
init_src2();
|
|
122533
122826
|
init_errors();
|
|
122534
122827
|
init_utils11();
|
|
122535
|
-
|
|
122828
|
+
logger43 = log.scope("BucketController");
|
|
122536
122829
|
listFiles = requireDeveloper(async (ctx) => {
|
|
122537
122830
|
const slug2 = ctx.params.slug;
|
|
122538
122831
|
if (!slug2) {
|
|
@@ -122540,7 +122833,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
122540
122833
|
}
|
|
122541
122834
|
const url2 = ctx.url;
|
|
122542
122835
|
const prefix2 = url2.searchParams.get("prefix") || undefined;
|
|
122543
|
-
|
|
122836
|
+
logger43.debug("Listing files", { userId: ctx.user.id, slug: slug2, prefix: prefix2 });
|
|
122544
122837
|
const files = await ctx.services.bucket.listFiles(slug2, ctx.user, prefix2);
|
|
122545
122838
|
return { files };
|
|
122546
122839
|
});
|
|
@@ -122550,7 +122843,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
122550
122843
|
if (!slug2 || !key) {
|
|
122551
122844
|
throw ApiError.badRequest("Missing game slug or file key");
|
|
122552
122845
|
}
|
|
122553
|
-
|
|
122846
|
+
logger43.debug("Getting file", { userId: ctx.user.id, slug: slug2, key });
|
|
122554
122847
|
const object = await ctx.services.bucket.getFile(slug2, key, ctx.user);
|
|
122555
122848
|
return new Response(Buffer.from(object.body), {
|
|
122556
122849
|
status: 200,
|
|
@@ -122569,7 +122862,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
122569
122862
|
const arrayBuffer = await ctx.request.arrayBuffer();
|
|
122570
122863
|
const body2 = new Uint8Array(arrayBuffer);
|
|
122571
122864
|
const contentType = ctx.request.headers.get("content-type") || undefined;
|
|
122572
|
-
|
|
122865
|
+
logger43.debug("Uploading file", {
|
|
122573
122866
|
userId: ctx.user.id,
|
|
122574
122867
|
slug: slug2,
|
|
122575
122868
|
key,
|
|
@@ -122585,7 +122878,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
122585
122878
|
if (!slug2 || !key) {
|
|
122586
122879
|
throw ApiError.badRequest("Missing game slug or file key");
|
|
122587
122880
|
}
|
|
122588
|
-
|
|
122881
|
+
logger43.debug("Deleting file", { userId: ctx.user.id, slug: slug2, key });
|
|
122589
122882
|
await ctx.services.bucket.deleteFile(slug2, key, ctx.user);
|
|
122590
122883
|
return { success: true, key };
|
|
122591
122884
|
});
|
|
@@ -122597,12 +122890,12 @@ var init_bucket_controller = __esm(() => {
|
|
|
122597
122890
|
} catch (error2) {
|
|
122598
122891
|
if (error2 instanceof exports_external.ZodError) {
|
|
122599
122892
|
const details = formatZodError(error2);
|
|
122600
|
-
|
|
122893
|
+
logger43.warn("Initiate upload validation failed", { details });
|
|
122601
122894
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
122602
122895
|
}
|
|
122603
122896
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122604
122897
|
}
|
|
122605
|
-
|
|
122898
|
+
logger43.debug("Initiating multipart upload", {
|
|
122606
122899
|
userId: ctx.user.id,
|
|
122607
122900
|
gameId: body2.gameId,
|
|
122608
122901
|
fileName: body2.fileName
|
|
@@ -122617,10 +122910,10 @@ async function listComponents(ctx) {
|
|
|
122617
122910
|
if (!isNaN(parsed) && isFinite(parsed)) {
|
|
122618
122911
|
level = Math.floor(Math.max(0, parsed));
|
|
122619
122912
|
}
|
|
122620
|
-
|
|
122913
|
+
logger44.debug("Listing components", { level });
|
|
122621
122914
|
return ctx.services.character.listAvailableComponents(level);
|
|
122622
122915
|
}
|
|
122623
|
-
var
|
|
122916
|
+
var logger44;
|
|
122624
122917
|
var get;
|
|
122625
122918
|
var getByUserId;
|
|
122626
122919
|
var create;
|
|
@@ -122634,9 +122927,9 @@ var init_character_controller = __esm(() => {
|
|
|
122634
122927
|
init_src2();
|
|
122635
122928
|
init_errors();
|
|
122636
122929
|
init_utils11();
|
|
122637
|
-
|
|
122930
|
+
logger44 = log.scope("CharacterController");
|
|
122638
122931
|
get = requireNonAnonymous(async (ctx) => {
|
|
122639
|
-
|
|
122932
|
+
logger44.debug("Getting character", { userId: ctx.user.id });
|
|
122640
122933
|
return ctx.services.character.getByUser(ctx.user);
|
|
122641
122934
|
});
|
|
122642
122935
|
getByUserId = requireNonAnonymous(async (ctx) => {
|
|
@@ -122644,7 +122937,7 @@ var init_character_controller = __esm(() => {
|
|
|
122644
122937
|
if (!userId) {
|
|
122645
122938
|
throw ApiError.badRequest("User ID is required in the URL path");
|
|
122646
122939
|
}
|
|
122647
|
-
|
|
122940
|
+
logger44.debug("Getting character by user ID", { requestedUserId: userId });
|
|
122648
122941
|
return ctx.services.character.getByUserId(userId);
|
|
122649
122942
|
});
|
|
122650
122943
|
create = requireNonAnonymous(async (ctx) => {
|
|
@@ -122655,12 +122948,12 @@ var init_character_controller = __esm(() => {
|
|
|
122655
122948
|
} catch (error2) {
|
|
122656
122949
|
if (error2 instanceof exports_external.ZodError) {
|
|
122657
122950
|
const details = formatZodError(error2);
|
|
122658
|
-
|
|
122951
|
+
logger44.warn("Create character validation failed", { details });
|
|
122659
122952
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
122660
122953
|
}
|
|
122661
122954
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122662
122955
|
}
|
|
122663
|
-
|
|
122956
|
+
logger44.debug("Creating character", {
|
|
122664
122957
|
userId: ctx.user.id,
|
|
122665
122958
|
bodyComponentId: body2.bodyComponentId,
|
|
122666
122959
|
hairstyleComponentId: body2.hairstyleComponentId
|
|
@@ -122675,12 +122968,12 @@ var init_character_controller = __esm(() => {
|
|
|
122675
122968
|
} catch (error2) {
|
|
122676
122969
|
if (error2 instanceof exports_external.ZodError) {
|
|
122677
122970
|
const details = formatZodError(error2);
|
|
122678
|
-
|
|
122971
|
+
logger44.warn("Update character validation failed", { details });
|
|
122679
122972
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
122680
122973
|
}
|
|
122681
122974
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122682
122975
|
}
|
|
122683
|
-
|
|
122976
|
+
logger44.debug("Updating character", {
|
|
122684
122977
|
userId: ctx.user.id,
|
|
122685
122978
|
bodyComponentId: body2.bodyComponentId,
|
|
122686
122979
|
hairstyleComponentId: body2.hairstyleComponentId,
|
|
@@ -122696,12 +122989,12 @@ var init_character_controller = __esm(() => {
|
|
|
122696
122989
|
} catch (error2) {
|
|
122697
122990
|
if (error2 instanceof exports_external.ZodError) {
|
|
122698
122991
|
const details = formatZodError(error2);
|
|
122699
|
-
|
|
122992
|
+
logger44.warn("Equip accessory validation failed", { details });
|
|
122700
122993
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
122701
122994
|
}
|
|
122702
122995
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122703
122996
|
}
|
|
122704
|
-
|
|
122997
|
+
logger44.debug("Equipping accessory", {
|
|
122705
122998
|
userId: ctx.user.id,
|
|
122706
122999
|
slot: body2.slot,
|
|
122707
123000
|
accessoryComponentId: body2.accessoryComponentId
|
|
@@ -122713,7 +123006,7 @@ var init_character_controller = __esm(() => {
|
|
|
122713
123006
|
if (!slot) {
|
|
122714
123007
|
throw ApiError.badRequest("Slot is required in the URL path");
|
|
122715
123008
|
}
|
|
122716
|
-
|
|
123009
|
+
logger44.debug("Removing accessory", { userId: ctx.user.id, slot });
|
|
122717
123010
|
await ctx.services.character.removeAccessory(slot, ctx.user);
|
|
122718
123011
|
return { success: true };
|
|
122719
123012
|
});
|
|
@@ -122727,7 +123020,7 @@ var init_character_controller = __esm(() => {
|
|
|
122727
123020
|
removeAccessory
|
|
122728
123021
|
};
|
|
122729
123022
|
});
|
|
122730
|
-
var
|
|
123023
|
+
var logger45;
|
|
122731
123024
|
var list;
|
|
122732
123025
|
var getById;
|
|
122733
123026
|
var create2;
|
|
@@ -122741,9 +123034,9 @@ var init_currency_controller = __esm(() => {
|
|
|
122741
123034
|
init_src4();
|
|
122742
123035
|
init_errors();
|
|
122743
123036
|
init_utils11();
|
|
122744
|
-
|
|
123037
|
+
logger45 = log.scope("CurrencyController");
|
|
122745
123038
|
list = requireNonAnonymous(async (ctx) => {
|
|
122746
|
-
|
|
123039
|
+
logger45.debug("Listing currencies", { userId: ctx.user.id });
|
|
122747
123040
|
return ctx.services.currency.list();
|
|
122748
123041
|
});
|
|
122749
123042
|
getById = requireNonAnonymous(async (ctx) => {
|
|
@@ -122754,7 +123047,7 @@ var init_currency_controller = __esm(() => {
|
|
|
122754
123047
|
if (!isValidUUID(currencyId)) {
|
|
122755
123048
|
throw ApiError.unprocessableEntity("currencyId must be a valid UUID format");
|
|
122756
123049
|
}
|
|
122757
|
-
|
|
123050
|
+
logger45.debug("Getting currency", { userId: ctx.user.id, currencyId });
|
|
122758
123051
|
return ctx.services.currency.getById(currencyId);
|
|
122759
123052
|
});
|
|
122760
123053
|
create2 = requireAdmin(async (ctx) => {
|
|
@@ -122765,12 +123058,12 @@ var init_currency_controller = __esm(() => {
|
|
|
122765
123058
|
} catch (error2) {
|
|
122766
123059
|
if (error2 instanceof exports_external.ZodError) {
|
|
122767
123060
|
const details = formatZodError(error2);
|
|
122768
|
-
|
|
123061
|
+
logger45.warn("Create currency validation failed", { details });
|
|
122769
123062
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
122770
123063
|
}
|
|
122771
123064
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122772
123065
|
}
|
|
122773
|
-
|
|
123066
|
+
logger45.debug("Creating currency", {
|
|
122774
123067
|
userId: ctx.user.id,
|
|
122775
123068
|
symbol: body2.symbol,
|
|
122776
123069
|
itemId: body2.itemId,
|
|
@@ -122793,12 +123086,12 @@ var init_currency_controller = __esm(() => {
|
|
|
122793
123086
|
} catch (error2) {
|
|
122794
123087
|
if (error2 instanceof exports_external.ZodError) {
|
|
122795
123088
|
const details = formatZodError(error2);
|
|
122796
|
-
|
|
123089
|
+
logger45.warn("Update currency validation failed", { details });
|
|
122797
123090
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
122798
123091
|
}
|
|
122799
123092
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122800
123093
|
}
|
|
122801
|
-
|
|
123094
|
+
logger45.debug("Updating currency", {
|
|
122802
123095
|
userId: ctx.user.id,
|
|
122803
123096
|
currencyId,
|
|
122804
123097
|
symbol: body2.symbol,
|
|
@@ -122815,7 +123108,7 @@ var init_currency_controller = __esm(() => {
|
|
|
122815
123108
|
if (!isValidUUID(currencyId)) {
|
|
122816
123109
|
throw ApiError.unprocessableEntity("currencyId must be a valid UUID format");
|
|
122817
123110
|
}
|
|
122818
|
-
|
|
123111
|
+
logger45.debug("Deleting currency", { userId: ctx.user.id, currencyId });
|
|
122819
123112
|
await ctx.services.currency.delete(currencyId);
|
|
122820
123113
|
});
|
|
122821
123114
|
currencyController = {
|
|
@@ -122826,7 +123119,7 @@ var init_currency_controller = __esm(() => {
|
|
|
122826
123119
|
remove
|
|
122827
123120
|
};
|
|
122828
123121
|
});
|
|
122829
|
-
var
|
|
123122
|
+
var logger46;
|
|
122830
123123
|
var reset;
|
|
122831
123124
|
var init_database_controller = __esm(() => {
|
|
122832
123125
|
init_esm();
|
|
@@ -122834,7 +123127,7 @@ var init_database_controller = __esm(() => {
|
|
|
122834
123127
|
init_src2();
|
|
122835
123128
|
init_errors();
|
|
122836
123129
|
init_utils11();
|
|
122837
|
-
|
|
123130
|
+
logger46 = log.scope("DatabaseController");
|
|
122838
123131
|
reset = requireDeveloper(async (ctx) => {
|
|
122839
123132
|
const slug2 = ctx.params.slug;
|
|
122840
123133
|
if (!slug2) {
|
|
@@ -122847,11 +123140,11 @@ var init_database_controller = __esm(() => {
|
|
|
122847
123140
|
} catch (error2) {
|
|
122848
123141
|
if (error2 instanceof exports_external.ZodError) {
|
|
122849
123142
|
const details = formatZodError(error2);
|
|
122850
|
-
|
|
123143
|
+
logger46.warn("Database reset validation failed", { details });
|
|
122851
123144
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
122852
123145
|
}
|
|
122853
123146
|
}
|
|
122854
|
-
|
|
123147
|
+
logger46.debug("Resetting database", {
|
|
122855
123148
|
userId: ctx.user.id,
|
|
122856
123149
|
slug: slug2,
|
|
122857
123150
|
hasSchema: Boolean(body2.schema)
|
|
@@ -122867,7 +123160,7 @@ async function createJob(ctx) {
|
|
|
122867
123160
|
let body2;
|
|
122868
123161
|
try {
|
|
122869
123162
|
const json4 = await ctx.request.json();
|
|
122870
|
-
|
|
123163
|
+
logger47.debug("Deploy request body", {
|
|
122871
123164
|
keys: Object.keys(json4 || {}),
|
|
122872
123165
|
hasUploadToken: Boolean(json4?.uploadToken),
|
|
122873
123166
|
hasCode: Boolean(json4?.code),
|
|
@@ -122877,7 +123170,7 @@ async function createJob(ctx) {
|
|
|
122877
123170
|
} catch (error2) {
|
|
122878
123171
|
if (error2 instanceof exports_external.ZodError) {
|
|
122879
123172
|
const details = formatZodError(error2);
|
|
122880
|
-
|
|
123173
|
+
logger47.warn("Deploy validation failed", { details });
|
|
122881
123174
|
throw ApiError.unprocessableEntity("Invalid deploy request", details);
|
|
122882
123175
|
}
|
|
122883
123176
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -122898,7 +123191,7 @@ async function getJob(ctx) {
|
|
|
122898
123191
|
}
|
|
122899
123192
|
return ctx.services.deployJobs.get(jobId, slug2, ctx.user);
|
|
122900
123193
|
}
|
|
122901
|
-
var
|
|
123194
|
+
var logger47;
|
|
122902
123195
|
var deploy;
|
|
122903
123196
|
var init_deploy_controller = __esm(() => {
|
|
122904
123197
|
init_esm();
|
|
@@ -122906,26 +123199,26 @@ var init_deploy_controller = __esm(() => {
|
|
|
122906
123199
|
init_src2();
|
|
122907
123200
|
init_errors();
|
|
122908
123201
|
init_utils11();
|
|
122909
|
-
|
|
123202
|
+
logger47 = log.scope("DeployController");
|
|
122910
123203
|
deploy = {
|
|
122911
123204
|
createJob: requireDeveloper(createJob),
|
|
122912
123205
|
getJob: requireDeveloper(getJob)
|
|
122913
123206
|
};
|
|
122914
123207
|
});
|
|
122915
|
-
var
|
|
123208
|
+
var logger48;
|
|
122916
123209
|
var apply;
|
|
122917
123210
|
var getStatus;
|
|
122918
123211
|
var developer;
|
|
122919
123212
|
var init_developer_controller = __esm(() => {
|
|
122920
123213
|
init_src2();
|
|
122921
123214
|
init_utils11();
|
|
122922
|
-
|
|
123215
|
+
logger48 = log.scope("DeveloperController");
|
|
122923
123216
|
apply = requireNonAnonymous(async (ctx) => {
|
|
122924
|
-
|
|
123217
|
+
logger48.debug("Applying for developer status", { userId: ctx.user.id });
|
|
122925
123218
|
await ctx.services.developer.apply(ctx.user);
|
|
122926
123219
|
});
|
|
122927
123220
|
getStatus = requireNonAnonymous(async (ctx) => {
|
|
122928
|
-
|
|
123221
|
+
logger48.debug("Getting developer status", { userId: ctx.user.id });
|
|
122929
123222
|
const status = await ctx.services.developer.getStatus(ctx.user.id);
|
|
122930
123223
|
return { status };
|
|
122931
123224
|
});
|
|
@@ -122934,7 +123227,7 @@ var init_developer_controller = __esm(() => {
|
|
|
122934
123227
|
getStatus
|
|
122935
123228
|
};
|
|
122936
123229
|
});
|
|
122937
|
-
var
|
|
123230
|
+
var logger49;
|
|
122938
123231
|
var add;
|
|
122939
123232
|
var list2;
|
|
122940
123233
|
var getStatus2;
|
|
@@ -122947,7 +123240,7 @@ var init_domain_controller = __esm(() => {
|
|
|
122947
123240
|
init_config2();
|
|
122948
123241
|
init_errors();
|
|
122949
123242
|
init_utils11();
|
|
122950
|
-
|
|
123243
|
+
logger49 = log.scope("DomainController");
|
|
122951
123244
|
add = requireDeveloper(async (ctx) => {
|
|
122952
123245
|
const slug2 = ctx.params.slug;
|
|
122953
123246
|
if (!slug2) {
|
|
@@ -122960,13 +123253,13 @@ var init_domain_controller = __esm(() => {
|
|
|
122960
123253
|
} catch (error2) {
|
|
122961
123254
|
if (error2 instanceof exports_external.ZodError) {
|
|
122962
123255
|
const details = formatZodError(error2);
|
|
122963
|
-
|
|
123256
|
+
logger49.warn("Add domain validation failed", { details });
|
|
122964
123257
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
122965
123258
|
}
|
|
122966
123259
|
throw ApiError.badRequest("Invalid JSON body");
|
|
122967
123260
|
}
|
|
122968
123261
|
const environment = getPlatformEnvironment(ctx.config);
|
|
122969
|
-
|
|
123262
|
+
logger49.debug("Adding domain", {
|
|
122970
123263
|
userId: ctx.user.id,
|
|
122971
123264
|
slug: slug2,
|
|
122972
123265
|
hostname: body2.hostname,
|
|
@@ -122980,7 +123273,7 @@ var init_domain_controller = __esm(() => {
|
|
|
122980
123273
|
throw ApiError.badRequest("Missing game slug");
|
|
122981
123274
|
}
|
|
122982
123275
|
const environment = getPlatformEnvironment(ctx.config);
|
|
122983
|
-
|
|
123276
|
+
logger49.debug("Listing domains", { userId: ctx.user.id, slug: slug2, environment });
|
|
122984
123277
|
const domains22 = await ctx.services.domain.list(slug2, environment, ctx.user);
|
|
122985
123278
|
return { domains: domains22 };
|
|
122986
123279
|
});
|
|
@@ -122995,7 +123288,7 @@ var init_domain_controller = __esm(() => {
|
|
|
122995
123288
|
}
|
|
122996
123289
|
const refresh = ctx.url.searchParams.get("refresh") === "true";
|
|
122997
123290
|
const environment = getPlatformEnvironment(ctx.config);
|
|
122998
|
-
|
|
123291
|
+
logger49.debug("Getting domain status", { userId: ctx.user.id, slug: slug2, hostname, refresh });
|
|
122999
123292
|
return ctx.services.domain.getStatus(slug2, hostname, environment, ctx.user, refresh);
|
|
123000
123293
|
});
|
|
123001
123294
|
remove2 = requireDeveloper(async (ctx) => {
|
|
@@ -123008,7 +123301,7 @@ var init_domain_controller = __esm(() => {
|
|
|
123008
123301
|
throw ApiError.badRequest("Missing hostname");
|
|
123009
123302
|
}
|
|
123010
123303
|
const environment = getPlatformEnvironment(ctx.config);
|
|
123011
|
-
|
|
123304
|
+
logger49.debug("Removing domain", { userId: ctx.user.id, slug: slug2, hostname, environment });
|
|
123012
123305
|
await ctx.services.domain.delete(slug2, hostname, environment, ctx.user);
|
|
123013
123306
|
});
|
|
123014
123307
|
domains2 = {
|
|
@@ -123018,7 +123311,7 @@ var init_domain_controller = __esm(() => {
|
|
|
123018
123311
|
remove: remove2
|
|
123019
123312
|
};
|
|
123020
123313
|
});
|
|
123021
|
-
var
|
|
123314
|
+
var logger50;
|
|
123022
123315
|
var list3;
|
|
123023
123316
|
var listAccessible;
|
|
123024
123317
|
var getSubjects;
|
|
@@ -123035,17 +123328,17 @@ var init_game_controller = __esm(() => {
|
|
|
123035
123328
|
init_src4();
|
|
123036
123329
|
init_errors();
|
|
123037
123330
|
init_utils11();
|
|
123038
|
-
|
|
123331
|
+
logger50 = log.scope("GameController");
|
|
123039
123332
|
list3 = requireNonAnonymous(async (ctx) => {
|
|
123040
|
-
|
|
123333
|
+
logger50.debug("Listing games", { userId: ctx.user.id });
|
|
123041
123334
|
return ctx.services.game.list(ctx.user);
|
|
123042
123335
|
});
|
|
123043
123336
|
listAccessible = requireNonAnonymous(async (ctx) => {
|
|
123044
|
-
|
|
123337
|
+
logger50.debug("Listing accessible games", { userId: ctx.user.id });
|
|
123045
123338
|
return ctx.services.game.listAccessible(ctx.user);
|
|
123046
123339
|
});
|
|
123047
123340
|
getSubjects = requireNonAnonymous(async (ctx) => {
|
|
123048
|
-
|
|
123341
|
+
logger50.debug("Getting game subjects", { userId: ctx.user.id });
|
|
123049
123342
|
return ctx.services.game.getSubjects();
|
|
123050
123343
|
});
|
|
123051
123344
|
getById2 = requireNonAnonymous(async (ctx) => {
|
|
@@ -123056,7 +123349,7 @@ var init_game_controller = __esm(() => {
|
|
|
123056
123349
|
if (!isValidUUID(gameId)) {
|
|
123057
123350
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
123058
123351
|
}
|
|
123059
|
-
|
|
123352
|
+
logger50.debug("Getting game by ID", { userId: ctx.user.id, gameId, launchId: ctx.launchId });
|
|
123060
123353
|
return ctx.services.game.getById(gameId, ctx.user);
|
|
123061
123354
|
});
|
|
123062
123355
|
getBySlug = requireNonAnonymous(async (ctx) => {
|
|
@@ -123064,7 +123357,7 @@ var init_game_controller = __esm(() => {
|
|
|
123064
123357
|
if (!slug2) {
|
|
123065
123358
|
throw ApiError.badRequest("Missing game slug");
|
|
123066
123359
|
}
|
|
123067
|
-
|
|
123360
|
+
logger50.debug("Getting game by slug", { userId: ctx.user.id, slug: slug2, launchId: ctx.launchId });
|
|
123068
123361
|
return ctx.services.game.getBySlug(slug2, ctx.user);
|
|
123069
123362
|
});
|
|
123070
123363
|
getManifest = requireNonAnonymous(async (ctx) => {
|
|
@@ -123075,7 +123368,7 @@ var init_game_controller = __esm(() => {
|
|
|
123075
123368
|
if (!isValidUUID(gameId)) {
|
|
123076
123369
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
123077
123370
|
}
|
|
123078
|
-
|
|
123371
|
+
logger50.debug("Getting game manifest by ID", {
|
|
123079
123372
|
userId: ctx.user.id,
|
|
123080
123373
|
gameId,
|
|
123081
123374
|
launchId: ctx.launchId
|
|
@@ -123094,12 +123387,12 @@ var init_game_controller = __esm(() => {
|
|
|
123094
123387
|
} catch (error2) {
|
|
123095
123388
|
if (error2 instanceof exports_external.ZodError) {
|
|
123096
123389
|
const details = formatZodError(error2);
|
|
123097
|
-
|
|
123390
|
+
logger50.warn("Upsert game validation failed", { details });
|
|
123098
123391
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123099
123392
|
}
|
|
123100
123393
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123101
123394
|
}
|
|
123102
|
-
|
|
123395
|
+
logger50.debug("Upserting game", { userId: ctx.user.id, slug: slug2, displayName: body2.displayName });
|
|
123103
123396
|
return ctx.services.game.upsertBySlug(slug2, body2, ctx.user);
|
|
123104
123397
|
});
|
|
123105
123398
|
remove3 = requireNonAnonymous(async (ctx) => {
|
|
@@ -123110,7 +123403,7 @@ var init_game_controller = __esm(() => {
|
|
|
123110
123403
|
if (!isValidUUID(gameId)) {
|
|
123111
123404
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
123112
123405
|
}
|
|
123113
|
-
|
|
123406
|
+
logger50.debug("Deleting game", { userId: ctx.user.id, gameId });
|
|
123114
123407
|
await ctx.services.game.delete(gameId, ctx.user);
|
|
123115
123408
|
});
|
|
123116
123409
|
games2 = {
|
|
@@ -123124,7 +123417,7 @@ var init_game_controller = __esm(() => {
|
|
|
123124
123417
|
remove: remove3
|
|
123125
123418
|
};
|
|
123126
123419
|
});
|
|
123127
|
-
var
|
|
123420
|
+
var logger51;
|
|
123128
123421
|
var list4;
|
|
123129
123422
|
var addItem;
|
|
123130
123423
|
var removeItem;
|
|
@@ -123135,9 +123428,9 @@ var init_inventory_controller = __esm(() => {
|
|
|
123135
123428
|
init_src2();
|
|
123136
123429
|
init_errors();
|
|
123137
123430
|
init_utils11();
|
|
123138
|
-
|
|
123431
|
+
logger51 = log.scope("InventoryController");
|
|
123139
123432
|
list4 = requireNonAnonymous(async (ctx) => {
|
|
123140
|
-
|
|
123433
|
+
logger51.debug("Listing inventory", { userId: ctx.user.id });
|
|
123141
123434
|
return ctx.services.inventory.list(ctx.user);
|
|
123142
123435
|
});
|
|
123143
123436
|
addItem = requireNonAnonymous(async (ctx) => {
|
|
@@ -123148,12 +123441,12 @@ var init_inventory_controller = __esm(() => {
|
|
|
123148
123441
|
} catch (error2) {
|
|
123149
123442
|
if (error2 instanceof exports_external.ZodError) {
|
|
123150
123443
|
const details = formatZodError(error2);
|
|
123151
|
-
|
|
123444
|
+
logger51.warn("Add inventory item validation failed", { details });
|
|
123152
123445
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
123153
123446
|
}
|
|
123154
123447
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123155
123448
|
}
|
|
123156
|
-
|
|
123449
|
+
logger51.debug("Adding item", {
|
|
123157
123450
|
userId: ctx.user.id,
|
|
123158
123451
|
itemId: body2.itemId,
|
|
123159
123452
|
qty: body2.qty
|
|
@@ -123168,12 +123461,12 @@ var init_inventory_controller = __esm(() => {
|
|
|
123168
123461
|
} catch (error2) {
|
|
123169
123462
|
if (error2 instanceof exports_external.ZodError) {
|
|
123170
123463
|
const details = formatZodError(error2);
|
|
123171
|
-
|
|
123464
|
+
logger51.warn("Remove inventory item validation failed", { details });
|
|
123172
123465
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
123173
123466
|
}
|
|
123174
123467
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123175
123468
|
}
|
|
123176
|
-
|
|
123469
|
+
logger51.debug("Removing item", {
|
|
123177
123470
|
userId: ctx.user.id,
|
|
123178
123471
|
itemId: body2.itemId,
|
|
123179
123472
|
qty: body2.qty
|
|
@@ -123186,7 +123479,7 @@ var init_inventory_controller = __esm(() => {
|
|
|
123186
123479
|
removeItem
|
|
123187
123480
|
};
|
|
123188
123481
|
});
|
|
123189
|
-
var
|
|
123482
|
+
var logger52;
|
|
123190
123483
|
var list5;
|
|
123191
123484
|
var getById3;
|
|
123192
123485
|
var resolve2;
|
|
@@ -123205,10 +123498,10 @@ var init_item_controller = __esm(() => {
|
|
|
123205
123498
|
init_src4();
|
|
123206
123499
|
init_errors();
|
|
123207
123500
|
init_utils11();
|
|
123208
|
-
|
|
123501
|
+
logger52 = log.scope("ItemController");
|
|
123209
123502
|
list5 = requireNonAnonymous(async (ctx) => {
|
|
123210
123503
|
const gameId = ctx.url.searchParams.get("gameId") || undefined;
|
|
123211
|
-
|
|
123504
|
+
logger52.debug("Listing items", { userId: ctx.user.id, gameId });
|
|
123212
123505
|
return ctx.services.item.list(gameId);
|
|
123213
123506
|
});
|
|
123214
123507
|
getById3 = requireNonAnonymous(async (ctx) => {
|
|
@@ -123219,7 +123512,7 @@ var init_item_controller = __esm(() => {
|
|
|
123219
123512
|
if (!isValidUUID(itemId)) {
|
|
123220
123513
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
123221
123514
|
}
|
|
123222
|
-
|
|
123515
|
+
logger52.debug("Getting item", { userId: ctx.user.id, itemId });
|
|
123223
123516
|
return ctx.services.item.getById(itemId);
|
|
123224
123517
|
});
|
|
123225
123518
|
resolve2 = requireNonAnonymous(async (ctx) => {
|
|
@@ -123231,7 +123524,7 @@ var init_item_controller = __esm(() => {
|
|
|
123231
123524
|
if (gameId && !isValidUUID(gameId)) {
|
|
123232
123525
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
123233
123526
|
}
|
|
123234
|
-
|
|
123527
|
+
logger52.debug("Resolving item", { userId: ctx.user.id, slug: slug2, gameId });
|
|
123235
123528
|
return ctx.services.item.resolveBySlug(slug2, gameId);
|
|
123236
123529
|
});
|
|
123237
123530
|
create3 = requireRole(["admin"], async (ctx) => {
|
|
@@ -123242,12 +123535,12 @@ var init_item_controller = __esm(() => {
|
|
|
123242
123535
|
} catch (error2) {
|
|
123243
123536
|
if (error2 instanceof exports_external.ZodError) {
|
|
123244
123537
|
const details = formatZodError(error2);
|
|
123245
|
-
|
|
123538
|
+
logger52.warn("Create item validation failed", { details });
|
|
123246
123539
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123247
123540
|
}
|
|
123248
123541
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123249
123542
|
}
|
|
123250
|
-
|
|
123543
|
+
logger52.debug("Creating item", {
|
|
123251
123544
|
userId: ctx.user.id,
|
|
123252
123545
|
slug: body2.slug,
|
|
123253
123546
|
displayName: body2.displayName
|
|
@@ -123269,7 +123562,7 @@ var init_item_controller = __esm(() => {
|
|
|
123269
123562
|
} catch (error2) {
|
|
123270
123563
|
if (error2 instanceof exports_external.ZodError) {
|
|
123271
123564
|
const details = formatZodError(error2);
|
|
123272
|
-
|
|
123565
|
+
logger52.warn("Update item validation failed", { details });
|
|
123273
123566
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123274
123567
|
}
|
|
123275
123568
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -123277,7 +123570,7 @@ var init_item_controller = __esm(() => {
|
|
|
123277
123570
|
if (Object.keys(body2).length === 0) {
|
|
123278
123571
|
throw ApiError.badRequest("No update data provided");
|
|
123279
123572
|
}
|
|
123280
|
-
|
|
123573
|
+
logger52.debug("Updating item", {
|
|
123281
123574
|
userId: ctx.user.id,
|
|
123282
123575
|
itemId,
|
|
123283
123576
|
slug: body2.slug,
|
|
@@ -123294,7 +123587,7 @@ var init_item_controller = __esm(() => {
|
|
|
123294
123587
|
if (!isValidUUID(itemId)) {
|
|
123295
123588
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
123296
123589
|
}
|
|
123297
|
-
|
|
123590
|
+
logger52.debug("Deleting item", { userId: ctx.user.id, itemId });
|
|
123298
123591
|
await ctx.services.item.delete(itemId);
|
|
123299
123592
|
});
|
|
123300
123593
|
listByGame = requireNonAnonymous(async (ctx) => {
|
|
@@ -123305,7 +123598,7 @@ var init_item_controller = __esm(() => {
|
|
|
123305
123598
|
if (!isValidUUID(gameId)) {
|
|
123306
123599
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
123307
123600
|
}
|
|
123308
|
-
|
|
123601
|
+
logger52.debug("Listing game items", { userId: ctx.user.id, gameId });
|
|
123309
123602
|
return ctx.services.item.listByGame(gameId);
|
|
123310
123603
|
});
|
|
123311
123604
|
createForGame = requireNonAnonymous(async (ctx) => {
|
|
@@ -123323,12 +123616,12 @@ var init_item_controller = __esm(() => {
|
|
|
123323
123616
|
} catch (error2) {
|
|
123324
123617
|
if (error2 instanceof exports_external.ZodError) {
|
|
123325
123618
|
const details = formatZodError(error2);
|
|
123326
|
-
|
|
123619
|
+
logger52.warn("Create game item validation failed", { details });
|
|
123327
123620
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123328
123621
|
}
|
|
123329
123622
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123330
123623
|
}
|
|
123331
|
-
|
|
123624
|
+
logger52.debug("Creating game item", {
|
|
123332
123625
|
userId: ctx.user.id,
|
|
123333
123626
|
gameId,
|
|
123334
123627
|
slug: body2.slug,
|
|
@@ -123355,7 +123648,7 @@ var init_item_controller = __esm(() => {
|
|
|
123355
123648
|
} catch (error2) {
|
|
123356
123649
|
if (error2 instanceof exports_external.ZodError) {
|
|
123357
123650
|
const details = formatZodError(error2);
|
|
123358
|
-
|
|
123651
|
+
logger52.warn("Update game item validation failed", { details });
|
|
123359
123652
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123360
123653
|
}
|
|
123361
123654
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -123363,7 +123656,7 @@ var init_item_controller = __esm(() => {
|
|
|
123363
123656
|
if (Object.keys(body2).length === 0) {
|
|
123364
123657
|
throw ApiError.badRequest("No update data provided");
|
|
123365
123658
|
}
|
|
123366
|
-
|
|
123659
|
+
logger52.debug("Updating game item", {
|
|
123367
123660
|
userId: ctx.user.id,
|
|
123368
123661
|
gameId,
|
|
123369
123662
|
itemId,
|
|
@@ -123385,7 +123678,7 @@ var init_item_controller = __esm(() => {
|
|
|
123385
123678
|
if (!isValidUUID(itemId)) {
|
|
123386
123679
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
123387
123680
|
}
|
|
123388
|
-
|
|
123681
|
+
logger52.debug("Deleting game item", { userId: ctx.user.id, gameId, itemId });
|
|
123389
123682
|
await ctx.services.item.deleteForGame(gameId, itemId, ctx.user);
|
|
123390
123683
|
});
|
|
123391
123684
|
items2 = {
|
|
@@ -123401,7 +123694,7 @@ var init_item_controller = __esm(() => {
|
|
|
123401
123694
|
deleteForGame
|
|
123402
123695
|
};
|
|
123403
123696
|
});
|
|
123404
|
-
var
|
|
123697
|
+
var logger53;
|
|
123405
123698
|
var listKeys;
|
|
123406
123699
|
var getStats;
|
|
123407
123700
|
var seed;
|
|
@@ -123416,7 +123709,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123416
123709
|
init_src2();
|
|
123417
123710
|
init_errors();
|
|
123418
123711
|
init_utils11();
|
|
123419
|
-
|
|
123712
|
+
logger53 = log.scope("KVController");
|
|
123420
123713
|
listKeys = requireDeveloper(async (ctx) => {
|
|
123421
123714
|
const slug2 = ctx.params.slug;
|
|
123422
123715
|
if (!slug2) {
|
|
@@ -123424,7 +123717,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123424
123717
|
}
|
|
123425
123718
|
const url2 = ctx.url;
|
|
123426
123719
|
const prefix2 = url2.searchParams.get("prefix") || undefined;
|
|
123427
|
-
|
|
123720
|
+
logger53.debug("Listing keys", { userId: ctx.user.id, slug: slug2, prefix: prefix2 });
|
|
123428
123721
|
const keys = await ctx.services.kv.listKeys(slug2, ctx.user, prefix2);
|
|
123429
123722
|
return { keys };
|
|
123430
123723
|
});
|
|
@@ -123433,7 +123726,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123433
123726
|
if (!slug2) {
|
|
123434
123727
|
throw ApiError.badRequest("Missing game slug");
|
|
123435
123728
|
}
|
|
123436
|
-
|
|
123729
|
+
logger53.debug("Getting stats", { userId: ctx.user.id, slug: slug2 });
|
|
123437
123730
|
return ctx.services.kv.getStats(slug2, ctx.user);
|
|
123438
123731
|
});
|
|
123439
123732
|
seed = requireDeveloper(async (ctx) => {
|
|
@@ -123448,12 +123741,12 @@ var init_kv_controller = __esm(() => {
|
|
|
123448
123741
|
} catch (error2) {
|
|
123449
123742
|
if (error2 instanceof exports_external.ZodError) {
|
|
123450
123743
|
const details = formatZodError(error2);
|
|
123451
|
-
|
|
123744
|
+
logger53.warn("Seed validation failed", { details });
|
|
123452
123745
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123453
123746
|
}
|
|
123454
123747
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123455
123748
|
}
|
|
123456
|
-
|
|
123749
|
+
logger53.debug("Seeding values", { userId: ctx.user.id, slug: slug2, count: body2.entries.length });
|
|
123457
123750
|
await ctx.services.kv.seed(slug2, body2.entries, ctx.user);
|
|
123458
123751
|
return { success: true, count: body2.entries.length };
|
|
123459
123752
|
});
|
|
@@ -123463,7 +123756,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123463
123756
|
if (!slug2 || !key) {
|
|
123464
123757
|
throw ApiError.badRequest("Missing game slug or key");
|
|
123465
123758
|
}
|
|
123466
|
-
|
|
123759
|
+
logger53.debug("Getting value", { userId: ctx.user.id, slug: slug2, key });
|
|
123467
123760
|
const value = await ctx.services.kv.getValue(slug2, key, ctx.user);
|
|
123468
123761
|
return { key, value };
|
|
123469
123762
|
});
|
|
@@ -123477,7 +123770,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123477
123770
|
if (!value) {
|
|
123478
123771
|
throw ApiError.badRequest("Missing value in request body");
|
|
123479
123772
|
}
|
|
123480
|
-
|
|
123773
|
+
logger53.debug("Setting value", { userId: ctx.user.id, slug: slug2, key, size: value.length });
|
|
123481
123774
|
await ctx.services.kv.setValue(slug2, key, value, ctx.user);
|
|
123482
123775
|
return { success: true, key };
|
|
123483
123776
|
});
|
|
@@ -123487,7 +123780,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123487
123780
|
if (!slug2 || !key) {
|
|
123488
123781
|
throw ApiError.badRequest("Missing game slug or key");
|
|
123489
123782
|
}
|
|
123490
|
-
|
|
123783
|
+
logger53.debug("Deleting value", { userId: ctx.user.id, slug: slug2, key });
|
|
123491
123784
|
await ctx.services.kv.deleteValue(slug2, key, ctx.user);
|
|
123492
123785
|
return { success: true, key };
|
|
123493
123786
|
});
|
|
@@ -123497,7 +123790,7 @@ var init_kv_controller = __esm(() => {
|
|
|
123497
123790
|
if (!slug2 || !key) {
|
|
123498
123791
|
throw ApiError.badRequest("Missing game slug or key");
|
|
123499
123792
|
}
|
|
123500
|
-
|
|
123793
|
+
logger53.debug("Getting metadata", { userId: ctx.user.id, slug: slug2, key });
|
|
123501
123794
|
const metadata2 = await ctx.services.kv.getMetadata(slug2, key, ctx.user);
|
|
123502
123795
|
return { key, metadata: metadata2 };
|
|
123503
123796
|
});
|
|
@@ -123506,12 +123799,12 @@ var init_kv_controller = __esm(() => {
|
|
|
123506
123799
|
if (!slug2) {
|
|
123507
123800
|
throw ApiError.badRequest("Missing game slug");
|
|
123508
123801
|
}
|
|
123509
|
-
|
|
123802
|
+
logger53.debug("Clearing all keys", { userId: ctx.user.id, slug: slug2 });
|
|
123510
123803
|
const deleted = await ctx.services.kv.clear(slug2, ctx.user);
|
|
123511
123804
|
return { success: true, deleted };
|
|
123512
123805
|
});
|
|
123513
123806
|
});
|
|
123514
|
-
var
|
|
123807
|
+
var logger54;
|
|
123515
123808
|
var submitScore;
|
|
123516
123809
|
var getGlobalLeaderboard;
|
|
123517
123810
|
var getLeaderboard;
|
|
@@ -123525,7 +123818,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123525
123818
|
init_src2();
|
|
123526
123819
|
init_errors();
|
|
123527
123820
|
init_utils11();
|
|
123528
|
-
|
|
123821
|
+
logger54 = log.scope("LeaderboardController");
|
|
123529
123822
|
submitScore = requireAuth(async (ctx) => {
|
|
123530
123823
|
const gameId = ctx.params.gameId;
|
|
123531
123824
|
if (!gameId) {
|
|
@@ -123538,12 +123831,12 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123538
123831
|
} catch (error2) {
|
|
123539
123832
|
if (error2 instanceof exports_external.ZodError) {
|
|
123540
123833
|
const details = formatZodError(error2);
|
|
123541
|
-
|
|
123834
|
+
logger54.warn("Submit score validation failed", { details });
|
|
123542
123835
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123543
123836
|
}
|
|
123544
123837
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123545
123838
|
}
|
|
123546
|
-
|
|
123839
|
+
logger54.debug("Submitting score", {
|
|
123547
123840
|
userId: ctx.user.id,
|
|
123548
123841
|
gameId,
|
|
123549
123842
|
score: body2.score
|
|
@@ -123566,12 +123859,12 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123566
123859
|
} catch (error2) {
|
|
123567
123860
|
if (error2 instanceof exports_external.ZodError) {
|
|
123568
123861
|
const details = formatZodError(error2);
|
|
123569
|
-
|
|
123862
|
+
logger54.warn("Get global leaderboard query validation failed", { details });
|
|
123570
123863
|
throw ApiError.badRequest("Invalid query parameters", details);
|
|
123571
123864
|
}
|
|
123572
123865
|
throw ApiError.badRequest("Invalid query parameters");
|
|
123573
123866
|
}
|
|
123574
|
-
|
|
123867
|
+
logger54.debug("Getting global leaderboard", {
|
|
123575
123868
|
userId: ctx.user.id,
|
|
123576
123869
|
gameId,
|
|
123577
123870
|
...query
|
|
@@ -123594,12 +123887,12 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123594
123887
|
} catch (error2) {
|
|
123595
123888
|
if (error2 instanceof exports_external.ZodError) {
|
|
123596
123889
|
const details = formatZodError(error2);
|
|
123597
|
-
|
|
123890
|
+
logger54.warn("Get leaderboard query validation failed", { details });
|
|
123598
123891
|
throw ApiError.badRequest("Invalid query parameters", details);
|
|
123599
123892
|
}
|
|
123600
123893
|
throw ApiError.badRequest("Invalid query parameters");
|
|
123601
123894
|
}
|
|
123602
|
-
|
|
123895
|
+
logger54.debug("Getting leaderboard", {
|
|
123603
123896
|
userId: ctx.user.id,
|
|
123604
123897
|
gameId,
|
|
123605
123898
|
...query
|
|
@@ -123611,7 +123904,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123611
123904
|
if (!gameId || !userId) {
|
|
123612
123905
|
throw ApiError.badRequest("Game ID and User ID are required");
|
|
123613
123906
|
}
|
|
123614
|
-
|
|
123907
|
+
logger54.debug("Getting user rank", {
|
|
123615
123908
|
requesterId: ctx.user.id,
|
|
123616
123909
|
gameId,
|
|
123617
123910
|
targetUserId: userId
|
|
@@ -123626,7 +123919,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123626
123919
|
const url2 = ctx.url;
|
|
123627
123920
|
const limit = Math.min(Number(url2.searchParams.get("limit") || "50"), 100);
|
|
123628
123921
|
const gameId = url2.searchParams.get("gameId") || undefined;
|
|
123629
|
-
|
|
123922
|
+
logger54.debug("Getting user all scores", {
|
|
123630
123923
|
requesterId: ctx.user.id,
|
|
123631
123924
|
targetUserId: userId,
|
|
123632
123925
|
gameId,
|
|
@@ -123641,7 +123934,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123641
123934
|
}
|
|
123642
123935
|
const url2 = ctx.url;
|
|
123643
123936
|
const limit = Math.min(Number(url2.searchParams.get("limit") || "10"), 100);
|
|
123644
|
-
|
|
123937
|
+
logger54.debug("Getting user scores", {
|
|
123645
123938
|
requesterId: ctx.user.id,
|
|
123646
123939
|
gameId,
|
|
123647
123940
|
targetUserId: userId,
|
|
@@ -123659,7 +123952,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
123659
123952
|
};
|
|
123660
123953
|
});
|
|
123661
123954
|
async function listConfigs(ctx) {
|
|
123662
|
-
|
|
123955
|
+
logger55.debug("Listing level configs");
|
|
123663
123956
|
return ctx.services.level.listConfigs();
|
|
123664
123957
|
}
|
|
123665
123958
|
async function getConfig(ctx) {
|
|
@@ -123671,10 +123964,10 @@ async function getConfig(ctx) {
|
|
|
123671
123964
|
if (isNaN(level) || level < 1) {
|
|
123672
123965
|
throw ApiError.badRequest("Level must be a positive integer");
|
|
123673
123966
|
}
|
|
123674
|
-
|
|
123967
|
+
logger55.debug("Getting level config", { level });
|
|
123675
123968
|
return ctx.services.level.getConfig(level);
|
|
123676
123969
|
}
|
|
123677
|
-
var
|
|
123970
|
+
var logger55;
|
|
123678
123971
|
var getByUser;
|
|
123679
123972
|
var getProgress;
|
|
123680
123973
|
var levels;
|
|
@@ -123682,13 +123975,13 @@ var init_level_controller = __esm(() => {
|
|
|
123682
123975
|
init_src2();
|
|
123683
123976
|
init_errors();
|
|
123684
123977
|
init_utils11();
|
|
123685
|
-
|
|
123978
|
+
logger55 = log.scope("LevelController");
|
|
123686
123979
|
getByUser = requireNonAnonymous(async (ctx) => {
|
|
123687
|
-
|
|
123980
|
+
logger55.debug("Getting user level", { userId: ctx.user.id });
|
|
123688
123981
|
return ctx.services.level.getByUser(ctx.user);
|
|
123689
123982
|
});
|
|
123690
123983
|
getProgress = requireNonAnonymous(async (ctx) => {
|
|
123691
|
-
|
|
123984
|
+
logger55.debug("Getting level progress", { userId: ctx.user.id });
|
|
123692
123985
|
return ctx.services.level.getProgress(ctx.user);
|
|
123693
123986
|
});
|
|
123694
123987
|
levels = {
|
|
@@ -123698,14 +123991,14 @@ var init_level_controller = __esm(() => {
|
|
|
123698
123991
|
getProgress
|
|
123699
123992
|
};
|
|
123700
123993
|
});
|
|
123701
|
-
var
|
|
123994
|
+
var logger56;
|
|
123702
123995
|
var generateToken;
|
|
123703
123996
|
var logs;
|
|
123704
123997
|
var init_logs_controller = __esm(() => {
|
|
123705
123998
|
init_src2();
|
|
123706
123999
|
init_errors();
|
|
123707
124000
|
init_utils11();
|
|
123708
|
-
|
|
124001
|
+
logger56 = log.scope("LogsController");
|
|
123709
124002
|
generateToken = requireDeveloper(async (ctx) => {
|
|
123710
124003
|
const slug2 = ctx.params.slug;
|
|
123711
124004
|
if (!slug2) {
|
|
@@ -123724,7 +124017,7 @@ var init_logs_controller = __esm(() => {
|
|
|
123724
124017
|
}
|
|
123725
124018
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123726
124019
|
}
|
|
123727
|
-
|
|
124020
|
+
logger56.debug("Generating log stream token", {
|
|
123728
124021
|
userId: ctx.user.id,
|
|
123729
124022
|
slug: slug2,
|
|
123730
124023
|
environment: body2.environment
|
|
@@ -123741,22 +124034,22 @@ var init_logs_controller = __esm(() => {
|
|
|
123741
124034
|
generateToken
|
|
123742
124035
|
};
|
|
123743
124036
|
});
|
|
123744
|
-
var
|
|
124037
|
+
var logger57;
|
|
123745
124038
|
var getStatus3;
|
|
123746
124039
|
var lti;
|
|
123747
124040
|
var init_lti_controller = __esm(() => {
|
|
123748
124041
|
init_src2();
|
|
123749
124042
|
init_utils11();
|
|
123750
|
-
|
|
124043
|
+
logger57 = log.scope("LtiController");
|
|
123751
124044
|
getStatus3 = requireNonAnonymous(async (ctx) => {
|
|
123752
|
-
|
|
124045
|
+
logger57.debug("Getting status", { userId: ctx.user.id });
|
|
123753
124046
|
return ctx.services.lti.getStatus(ctx.user);
|
|
123754
124047
|
});
|
|
123755
124048
|
lti = {
|
|
123756
124049
|
getStatus: getStatus3
|
|
123757
124050
|
};
|
|
123758
124051
|
});
|
|
123759
|
-
var
|
|
124052
|
+
var logger58;
|
|
123760
124053
|
var getByIdentifier;
|
|
123761
124054
|
var getElements;
|
|
123762
124055
|
var getObjects;
|
|
@@ -123770,13 +124063,13 @@ var init_map_controller = __esm(() => {
|
|
|
123770
124063
|
init_src4();
|
|
123771
124064
|
init_errors();
|
|
123772
124065
|
init_utils11();
|
|
123773
|
-
|
|
124066
|
+
logger58 = log.scope("MapController");
|
|
123774
124067
|
getByIdentifier = requireNonAnonymous(async (ctx) => {
|
|
123775
124068
|
const identifier = ctx.params.identifier;
|
|
123776
124069
|
if (!identifier) {
|
|
123777
124070
|
throw ApiError.badRequest("Missing map identifier");
|
|
123778
124071
|
}
|
|
123779
|
-
|
|
124072
|
+
logger58.debug("Getting map", { userId: ctx.user.id, identifier });
|
|
123780
124073
|
return ctx.services.map.getByIdentifier(identifier);
|
|
123781
124074
|
});
|
|
123782
124075
|
getElements = requireNonAnonymous(async (ctx) => {
|
|
@@ -123787,7 +124080,7 @@ var init_map_controller = __esm(() => {
|
|
|
123787
124080
|
if (!isValidUUID(mapId)) {
|
|
123788
124081
|
throw ApiError.unprocessableEntity("mapId must be a valid UUID format");
|
|
123789
124082
|
}
|
|
123790
|
-
|
|
124083
|
+
logger58.debug("Getting map elements", { userId: ctx.user.id, mapId });
|
|
123791
124084
|
return ctx.services.map.getElements(mapId);
|
|
123792
124085
|
});
|
|
123793
124086
|
getObjects = requireNonAnonymous(async (ctx) => {
|
|
@@ -123798,7 +124091,7 @@ var init_map_controller = __esm(() => {
|
|
|
123798
124091
|
if (!isValidUUID(mapId)) {
|
|
123799
124092
|
throw ApiError.unprocessableEntity("mapId must be a valid UUID format");
|
|
123800
124093
|
}
|
|
123801
|
-
|
|
124094
|
+
logger58.debug("Getting map objects", { userId: ctx.user.id, mapId });
|
|
123802
124095
|
return ctx.services.map.getObjects(mapId, ctx.user.id);
|
|
123803
124096
|
});
|
|
123804
124097
|
createObject = requireNonAnonymous(async (ctx) => {
|
|
@@ -123820,12 +124113,12 @@ var init_map_controller = __esm(() => {
|
|
|
123820
124113
|
} catch (error2) {
|
|
123821
124114
|
if (error2 instanceof exports_external.ZodError) {
|
|
123822
124115
|
const details = formatZodError(error2);
|
|
123823
|
-
|
|
124116
|
+
logger58.warn("Create map object validation failed", { details });
|
|
123824
124117
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
123825
124118
|
}
|
|
123826
124119
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123827
124120
|
}
|
|
123828
|
-
|
|
124121
|
+
logger58.debug("Creating map object", {
|
|
123829
124122
|
userId: ctx.user.id,
|
|
123830
124123
|
mapId,
|
|
123831
124124
|
itemId: body2.itemId,
|
|
@@ -123849,7 +124142,7 @@ var init_map_controller = __esm(() => {
|
|
|
123849
124142
|
if (!isValidUUID(objectId)) {
|
|
123850
124143
|
throw ApiError.unprocessableEntity("objectId must be a valid UUID format");
|
|
123851
124144
|
}
|
|
123852
|
-
|
|
124145
|
+
logger58.debug("Deleting map object", { userId: ctx.user.id, mapId, objectId });
|
|
123853
124146
|
await ctx.services.map.deleteObject(mapId, objectId, ctx.user);
|
|
123854
124147
|
});
|
|
123855
124148
|
maps2 = {
|
|
@@ -123860,7 +124153,7 @@ var init_map_controller = __esm(() => {
|
|
|
123860
124153
|
deleteObject
|
|
123861
124154
|
};
|
|
123862
124155
|
});
|
|
123863
|
-
var
|
|
124156
|
+
var logger59;
|
|
123864
124157
|
var list6;
|
|
123865
124158
|
var updateStatus;
|
|
123866
124159
|
var getStats2;
|
|
@@ -123873,7 +124166,7 @@ var init_notification_controller = __esm(() => {
|
|
|
123873
124166
|
init_src2();
|
|
123874
124167
|
init_errors();
|
|
123875
124168
|
init_utils11();
|
|
123876
|
-
|
|
124169
|
+
logger59 = log.scope("NotificationController");
|
|
123877
124170
|
list6 = requireNonAnonymous(async (ctx) => {
|
|
123878
124171
|
const query = {
|
|
123879
124172
|
status: ctx.url.searchParams.get("status") || undefined,
|
|
@@ -123884,10 +124177,10 @@ var init_notification_controller = __esm(() => {
|
|
|
123884
124177
|
const result = NotificationListQuerySchema.omit({ userId: true }).safeParse(query);
|
|
123885
124178
|
if (!result.success) {
|
|
123886
124179
|
const details = formatZodError(result.error);
|
|
123887
|
-
|
|
124180
|
+
logger59.warn("List notifications query validation failed", { details });
|
|
123888
124181
|
throw ApiError.badRequest("Invalid query parameters", details);
|
|
123889
124182
|
}
|
|
123890
|
-
|
|
124183
|
+
logger59.debug("Listing notifications", { userId: ctx.user.id, ...result.data });
|
|
123891
124184
|
return ctx.services.notification.list(ctx.user, result.data);
|
|
123892
124185
|
});
|
|
123893
124186
|
updateStatus = requireNonAnonymous(async (ctx) => {
|
|
@@ -123902,12 +124195,12 @@ var init_notification_controller = __esm(() => {
|
|
|
123902
124195
|
} catch (error2) {
|
|
123903
124196
|
if (error2 instanceof exports_external.ZodError) {
|
|
123904
124197
|
const details = formatZodError(error2);
|
|
123905
|
-
|
|
124198
|
+
logger59.warn("Update notification status validation failed", { details });
|
|
123906
124199
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
123907
124200
|
}
|
|
123908
124201
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123909
124202
|
}
|
|
123910
|
-
|
|
124203
|
+
logger59.debug("Updating status", {
|
|
123911
124204
|
userId: ctx.user.id,
|
|
123912
124205
|
notificationId,
|
|
123913
124206
|
status: body2.status
|
|
@@ -123917,7 +124210,7 @@ var init_notification_controller = __esm(() => {
|
|
|
123917
124210
|
getStats2 = requireNonAnonymous(async (ctx) => {
|
|
123918
124211
|
const startDate = ctx.url.searchParams.get("startDate");
|
|
123919
124212
|
const endDate = ctx.url.searchParams.get("endDate");
|
|
123920
|
-
|
|
124213
|
+
logger59.debug("Getting stats", { userId: ctx.user.id, startDate, endDate });
|
|
123921
124214
|
return ctx.services.notification.getStats(ctx.user, {
|
|
123922
124215
|
startDate: startDate ? new Date(startDate) : undefined,
|
|
123923
124216
|
endDate: endDate ? new Date(endDate) : undefined
|
|
@@ -123931,12 +124224,12 @@ var init_notification_controller = __esm(() => {
|
|
|
123931
124224
|
} catch (error2) {
|
|
123932
124225
|
if (error2 instanceof exports_external.ZodError) {
|
|
123933
124226
|
const details = formatZodError(error2);
|
|
123934
|
-
|
|
124227
|
+
logger59.warn("Create notification validation failed", { details });
|
|
123935
124228
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
123936
124229
|
}
|
|
123937
124230
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123938
124231
|
}
|
|
123939
|
-
|
|
124232
|
+
logger59.debug("Creating notification", {
|
|
123940
124233
|
userId: ctx.user.id,
|
|
123941
124234
|
targetUserId: body2.userId,
|
|
123942
124235
|
type: body2.type
|
|
@@ -123954,12 +124247,12 @@ var init_notification_controller = __esm(() => {
|
|
|
123954
124247
|
});
|
|
123955
124248
|
});
|
|
123956
124249
|
deliver = requireNonAnonymous(async (ctx) => {
|
|
123957
|
-
|
|
124250
|
+
logger59.debug("Delivering notifications", { userId: ctx.user.id });
|
|
123958
124251
|
try {
|
|
123959
124252
|
await ctx.services.notification.deliverPending(ctx.user.id);
|
|
123960
124253
|
return { success: true };
|
|
123961
124254
|
} catch (error2) {
|
|
123962
|
-
|
|
124255
|
+
logger59.error("Failed to deliver notifications", { error: error2 });
|
|
123963
124256
|
throw ApiError.internal("Failed to deliver notifications");
|
|
123964
124257
|
}
|
|
123965
124258
|
});
|
|
@@ -123971,16 +124264,16 @@ var init_notification_controller = __esm(() => {
|
|
|
123971
124264
|
deliver
|
|
123972
124265
|
};
|
|
123973
124266
|
});
|
|
123974
|
-
var
|
|
124267
|
+
var logger60;
|
|
123975
124268
|
var generateToken2;
|
|
123976
124269
|
var realtime;
|
|
123977
124270
|
var init_realtime_controller = __esm(() => {
|
|
123978
124271
|
init_src2();
|
|
123979
124272
|
init_utils11();
|
|
123980
|
-
|
|
124273
|
+
logger60 = log.scope("RealtimeController");
|
|
123981
124274
|
generateToken2 = requireNonAnonymous(async (ctx) => {
|
|
123982
124275
|
const gameIdOrSlug = ctx.params.gameId;
|
|
123983
|
-
|
|
124276
|
+
logger60.debug("Generating token", {
|
|
123984
124277
|
userId: ctx.user.id,
|
|
123985
124278
|
gameId: gameIdOrSlug || "global",
|
|
123986
124279
|
launchId: ctx.launchId
|
|
@@ -123991,7 +124284,7 @@ var init_realtime_controller = __esm(() => {
|
|
|
123991
124284
|
generateToken: generateToken2
|
|
123992
124285
|
};
|
|
123993
124286
|
});
|
|
123994
|
-
var
|
|
124287
|
+
var logger61;
|
|
123995
124288
|
var listKeys2;
|
|
123996
124289
|
var setSecrets;
|
|
123997
124290
|
var deleteSecret;
|
|
@@ -124002,13 +124295,13 @@ var init_secrets_controller = __esm(() => {
|
|
|
124002
124295
|
init_src2();
|
|
124003
124296
|
init_errors();
|
|
124004
124297
|
init_utils11();
|
|
124005
|
-
|
|
124298
|
+
logger61 = log.scope("SecretsController");
|
|
124006
124299
|
listKeys2 = requireDeveloper(async (ctx) => {
|
|
124007
124300
|
const slug2 = ctx.params.slug;
|
|
124008
124301
|
if (!slug2) {
|
|
124009
124302
|
throw ApiError.badRequest("Missing game slug");
|
|
124010
124303
|
}
|
|
124011
|
-
|
|
124304
|
+
logger61.debug("Listing secret keys", { userId: ctx.user.id, slug: slug2 });
|
|
124012
124305
|
const keys = await ctx.services.secrets.listKeys(slug2, ctx.user);
|
|
124013
124306
|
return { keys };
|
|
124014
124307
|
});
|
|
@@ -124024,12 +124317,12 @@ var init_secrets_controller = __esm(() => {
|
|
|
124024
124317
|
} catch (error2) {
|
|
124025
124318
|
if (error2 instanceof exports_external.ZodError) {
|
|
124026
124319
|
const details = formatZodError(error2);
|
|
124027
|
-
|
|
124320
|
+
logger61.warn("Set secrets validation failed", { details });
|
|
124028
124321
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124029
124322
|
}
|
|
124030
124323
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124031
124324
|
}
|
|
124032
|
-
|
|
124325
|
+
logger61.debug("Setting secrets", {
|
|
124033
124326
|
userId: ctx.user.id,
|
|
124034
124327
|
slug: slug2,
|
|
124035
124328
|
keyCount: Object.keys(body2).length
|
|
@@ -124046,7 +124339,7 @@ var init_secrets_controller = __esm(() => {
|
|
|
124046
124339
|
if (!key) {
|
|
124047
124340
|
throw ApiError.badRequest("Missing secret key");
|
|
124048
124341
|
}
|
|
124049
|
-
|
|
124342
|
+
logger61.debug("Deleting secret", { userId: ctx.user.id, slug: slug2, key });
|
|
124050
124343
|
await ctx.services.secrets.deleteSecret(slug2, key, ctx.user);
|
|
124051
124344
|
return { success: true };
|
|
124052
124345
|
});
|
|
@@ -124056,7 +124349,7 @@ var init_secrets_controller = __esm(() => {
|
|
|
124056
124349
|
deleteSecret
|
|
124057
124350
|
};
|
|
124058
124351
|
});
|
|
124059
|
-
var
|
|
124352
|
+
var logger62;
|
|
124060
124353
|
var seed2;
|
|
124061
124354
|
var init_seed_controller = __esm(() => {
|
|
124062
124355
|
init_esm();
|
|
@@ -124064,7 +124357,7 @@ var init_seed_controller = __esm(() => {
|
|
|
124064
124357
|
init_src2();
|
|
124065
124358
|
init_errors();
|
|
124066
124359
|
init_utils11();
|
|
124067
|
-
|
|
124360
|
+
logger62 = log.scope("SeedController");
|
|
124068
124361
|
seed2 = requireDeveloper(async (ctx) => {
|
|
124069
124362
|
const slug2 = ctx.params.slug;
|
|
124070
124363
|
if (!slug2) {
|
|
@@ -124077,12 +124370,12 @@ var init_seed_controller = __esm(() => {
|
|
|
124077
124370
|
} catch (error2) {
|
|
124078
124371
|
if (error2 instanceof exports_external.ZodError) {
|
|
124079
124372
|
const details = formatZodError(error2);
|
|
124080
|
-
|
|
124373
|
+
logger62.warn("Seed database validation failed", { details });
|
|
124081
124374
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124082
124375
|
}
|
|
124083
124376
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124084
124377
|
}
|
|
124085
|
-
|
|
124378
|
+
logger62.debug("Seeding database", {
|
|
124086
124379
|
userId: ctx.user.id,
|
|
124087
124380
|
slug: slug2,
|
|
124088
124381
|
codeLength: body2.code.length,
|
|
@@ -124091,7 +124384,7 @@ var init_seed_controller = __esm(() => {
|
|
|
124091
124384
|
return ctx.services.seed.seed(slug2, body2.code, ctx.user, body2.secrets);
|
|
124092
124385
|
});
|
|
124093
124386
|
});
|
|
124094
|
-
var
|
|
124387
|
+
var logger63;
|
|
124095
124388
|
var start2;
|
|
124096
124389
|
var end;
|
|
124097
124390
|
var mintToken;
|
|
@@ -124101,13 +124394,13 @@ var init_session_controller = __esm(() => {
|
|
|
124101
124394
|
init_tunnel();
|
|
124102
124395
|
init_errors();
|
|
124103
124396
|
init_utils11();
|
|
124104
|
-
|
|
124397
|
+
logger63 = log.scope("SessionController");
|
|
124105
124398
|
start2 = requireAuth(async (ctx) => {
|
|
124106
124399
|
const gameIdOrSlug = ctx.params.gameId;
|
|
124107
124400
|
if (!gameIdOrSlug) {
|
|
124108
124401
|
throw ApiError.badRequest("Missing game ID or slug");
|
|
124109
124402
|
}
|
|
124110
|
-
|
|
124403
|
+
logger63.debug("Starting session", { userId: ctx.user.id, gameIdOrSlug, launchId: ctx.launchId });
|
|
124111
124404
|
return ctx.services.session.start(gameIdOrSlug, ctx.user.id);
|
|
124112
124405
|
});
|
|
124113
124406
|
end = requireAuth(async (ctx) => {
|
|
@@ -124119,7 +124412,7 @@ var init_session_controller = __esm(() => {
|
|
|
124119
124412
|
if (!sessionId) {
|
|
124120
124413
|
throw ApiError.badRequest("Missing session ID");
|
|
124121
124414
|
}
|
|
124122
|
-
|
|
124415
|
+
logger63.debug("Ending session", {
|
|
124123
124416
|
userId: ctx.user.id,
|
|
124124
124417
|
gameIdOrSlug,
|
|
124125
124418
|
sessionId,
|
|
@@ -124132,7 +124425,7 @@ var init_session_controller = __esm(() => {
|
|
|
124132
124425
|
if (!gameIdOrSlug) {
|
|
124133
124426
|
throw ApiError.badRequest("Missing game ID or slug");
|
|
124134
124427
|
}
|
|
124135
|
-
|
|
124428
|
+
logger63.debug("Minting token", { userId: ctx.user.id, gameIdOrSlug, launchId: ctx.launchId });
|
|
124136
124429
|
const { token, exp } = await ctx.services.session.mintToken(gameIdOrSlug, ctx.user.id);
|
|
124137
124430
|
let baseUrl;
|
|
124138
124431
|
if (ctx.config.isLocal) {
|
|
@@ -124148,22 +124441,22 @@ var init_session_controller = __esm(() => {
|
|
|
124148
124441
|
mintToken
|
|
124149
124442
|
};
|
|
124150
124443
|
});
|
|
124151
|
-
var
|
|
124444
|
+
var logger64;
|
|
124152
124445
|
var getShopView;
|
|
124153
124446
|
var shop;
|
|
124154
124447
|
var init_shop_controller = __esm(() => {
|
|
124155
124448
|
init_src2();
|
|
124156
124449
|
init_utils11();
|
|
124157
|
-
|
|
124450
|
+
logger64 = log.scope("ShopController");
|
|
124158
124451
|
getShopView = requireNonAnonymous(async (ctx) => {
|
|
124159
|
-
|
|
124452
|
+
logger64.debug("Getting shop view", { userId: ctx.user.id });
|
|
124160
124453
|
return ctx.services.shop.getShopView(ctx.user);
|
|
124161
124454
|
});
|
|
124162
124455
|
shop = {
|
|
124163
124456
|
getShopView
|
|
124164
124457
|
};
|
|
124165
124458
|
});
|
|
124166
|
-
var
|
|
124459
|
+
var logger65;
|
|
124167
124460
|
var list7;
|
|
124168
124461
|
var getById4;
|
|
124169
124462
|
var create5;
|
|
@@ -124182,9 +124475,9 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124182
124475
|
init_src4();
|
|
124183
124476
|
init_errors();
|
|
124184
124477
|
init_utils11();
|
|
124185
|
-
|
|
124478
|
+
logger65 = log.scope("ShopListingController");
|
|
124186
124479
|
list7 = requireAdmin(async (ctx) => {
|
|
124187
|
-
|
|
124480
|
+
logger65.debug("Listing shop listings", { userId: ctx.user.id });
|
|
124188
124481
|
return ctx.services.shopListing.list();
|
|
124189
124482
|
});
|
|
124190
124483
|
getById4 = requireAdmin(async (ctx) => {
|
|
@@ -124195,7 +124488,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124195
124488
|
if (!isValidUUID(listingId)) {
|
|
124196
124489
|
throw ApiError.unprocessableEntity("listingId must be a valid UUID format");
|
|
124197
124490
|
}
|
|
124198
|
-
|
|
124491
|
+
logger65.debug("Getting listing", { userId: ctx.user.id, listingId });
|
|
124199
124492
|
return ctx.services.shopListing.getById(listingId);
|
|
124200
124493
|
});
|
|
124201
124494
|
create5 = requireAdmin(async (ctx) => {
|
|
@@ -124206,12 +124499,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124206
124499
|
} catch (error2) {
|
|
124207
124500
|
if (error2 instanceof exports_external.ZodError) {
|
|
124208
124501
|
const details = formatZodError(error2);
|
|
124209
|
-
|
|
124502
|
+
logger65.warn("Create shop listing validation failed", { details });
|
|
124210
124503
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124211
124504
|
}
|
|
124212
124505
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124213
124506
|
}
|
|
124214
|
-
|
|
124507
|
+
logger65.debug("Creating listing", {
|
|
124215
124508
|
userId: ctx.user.id,
|
|
124216
124509
|
itemId: body2.itemId,
|
|
124217
124510
|
currencyId: body2.currencyId,
|
|
@@ -124234,12 +124527,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124234
124527
|
} catch (error2) {
|
|
124235
124528
|
if (error2 instanceof exports_external.ZodError) {
|
|
124236
124529
|
const details = formatZodError(error2);
|
|
124237
|
-
|
|
124530
|
+
logger65.warn("Update shop listing validation failed", { details });
|
|
124238
124531
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124239
124532
|
}
|
|
124240
124533
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124241
124534
|
}
|
|
124242
|
-
|
|
124535
|
+
logger65.debug("Updating listing", {
|
|
124243
124536
|
userId: ctx.user.id,
|
|
124244
124537
|
listingId,
|
|
124245
124538
|
price: body2.price,
|
|
@@ -124256,7 +124549,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124256
124549
|
if (!isValidUUID(listingId)) {
|
|
124257
124550
|
throw ApiError.unprocessableEntity("listingId must be a valid UUID format");
|
|
124258
124551
|
}
|
|
124259
|
-
|
|
124552
|
+
logger65.debug("Deleting listing", { userId: ctx.user.id, listingId });
|
|
124260
124553
|
await ctx.services.shopListing.delete(listingId);
|
|
124261
124554
|
});
|
|
124262
124555
|
listByGame2 = requireNonAnonymous(async (ctx) => {
|
|
@@ -124267,7 +124560,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124267
124560
|
if (!isValidUUID(gameId)) {
|
|
124268
124561
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
124269
124562
|
}
|
|
124270
|
-
|
|
124563
|
+
logger65.debug("Listing game listings", { userId: ctx.user.id, gameId });
|
|
124271
124564
|
return ctx.services.shopListing.listByGame(gameId, ctx.user);
|
|
124272
124565
|
});
|
|
124273
124566
|
getByGameItem = requireNonAnonymous(async (ctx) => {
|
|
@@ -124282,7 +124575,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124282
124575
|
if (!isValidUUID(itemId)) {
|
|
124283
124576
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
124284
124577
|
}
|
|
124285
|
-
|
|
124578
|
+
logger65.debug("Getting game item listing", { userId: ctx.user.id, gameId, itemId });
|
|
124286
124579
|
return ctx.services.shopListing.getByGameItem(gameId, itemId, ctx.user);
|
|
124287
124580
|
});
|
|
124288
124581
|
createForGameItem = requireNonAnonymous(async (ctx) => {
|
|
@@ -124304,12 +124597,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124304
124597
|
} catch (error2) {
|
|
124305
124598
|
if (error2 instanceof exports_external.ZodError) {
|
|
124306
124599
|
const details = formatZodError(error2);
|
|
124307
|
-
|
|
124600
|
+
logger65.warn("Create game item listing validation failed", { details });
|
|
124308
124601
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124309
124602
|
}
|
|
124310
124603
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124311
124604
|
}
|
|
124312
|
-
|
|
124605
|
+
logger65.debug("Creating game item listing", {
|
|
124313
124606
|
userId: ctx.user.id,
|
|
124314
124607
|
gameId,
|
|
124315
124608
|
itemId,
|
|
@@ -124337,12 +124630,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124337
124630
|
} catch (error2) {
|
|
124338
124631
|
if (error2 instanceof exports_external.ZodError) {
|
|
124339
124632
|
const details = formatZodError(error2);
|
|
124340
|
-
|
|
124633
|
+
logger65.warn("Update game item listing validation failed", { details });
|
|
124341
124634
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124342
124635
|
}
|
|
124343
124636
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124344
124637
|
}
|
|
124345
|
-
|
|
124638
|
+
logger65.debug("Updating game item listing", {
|
|
124346
124639
|
userId: ctx.user.id,
|
|
124347
124640
|
gameId,
|
|
124348
124641
|
itemId,
|
|
@@ -124364,7 +124657,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
124364
124657
|
if (!isValidUUID(itemId)) {
|
|
124365
124658
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
124366
124659
|
}
|
|
124367
|
-
|
|
124660
|
+
logger65.debug("Deleting game item listing", {
|
|
124368
124661
|
userId: ctx.user.id,
|
|
124369
124662
|
gameId,
|
|
124370
124663
|
itemId
|
|
@@ -124389,20 +124682,20 @@ async function getBySlug2(ctx) {
|
|
|
124389
124682
|
if (!slug2) {
|
|
124390
124683
|
throw ApiError.badRequest("Template slug is required");
|
|
124391
124684
|
}
|
|
124392
|
-
|
|
124685
|
+
logger66.debug("Getting sprite by slug", { slug: slug2 });
|
|
124393
124686
|
return ctx.services.sprite.getBySlug(slug2);
|
|
124394
124687
|
}
|
|
124395
|
-
var
|
|
124688
|
+
var logger66;
|
|
124396
124689
|
var sprites;
|
|
124397
124690
|
var init_sprite_controller = __esm(() => {
|
|
124398
124691
|
init_src2();
|
|
124399
124692
|
init_errors();
|
|
124400
|
-
|
|
124693
|
+
logger66 = log.scope("SpriteController");
|
|
124401
124694
|
sprites = {
|
|
124402
124695
|
getBySlug: getBySlug2
|
|
124403
124696
|
};
|
|
124404
124697
|
});
|
|
124405
|
-
var
|
|
124698
|
+
var logger67;
|
|
124406
124699
|
var getTodayXp;
|
|
124407
124700
|
var getTotalXp;
|
|
124408
124701
|
var updateTodayXp;
|
|
@@ -124412,6 +124705,8 @@ var getUser;
|
|
|
124412
124705
|
var getUserById;
|
|
124413
124706
|
var setupIntegration;
|
|
124414
124707
|
var getIntegrations;
|
|
124708
|
+
var updateIntegration;
|
|
124709
|
+
var getIntegrationConfig;
|
|
124415
124710
|
var verifyIntegration;
|
|
124416
124711
|
var getConfig2;
|
|
124417
124712
|
var deleteIntegrations;
|
|
@@ -124427,6 +124722,7 @@ var getActivityDetail;
|
|
|
124427
124722
|
var grantXp;
|
|
124428
124723
|
var adjustTime;
|
|
124429
124724
|
var adjustMastery;
|
|
124725
|
+
var reconcileMasteryForConfigChange;
|
|
124430
124726
|
var searchStudents;
|
|
124431
124727
|
var enrollStudent;
|
|
124432
124728
|
var unenrollStudent;
|
|
@@ -124452,15 +124748,15 @@ var init_timeback_controller = __esm(() => {
|
|
|
124452
124748
|
init_src4();
|
|
124453
124749
|
init_errors();
|
|
124454
124750
|
init_utils11();
|
|
124455
|
-
|
|
124751
|
+
logger67 = log.scope("TimebackController");
|
|
124456
124752
|
getTodayXp = requireNonAnonymous(async (ctx) => {
|
|
124457
124753
|
const date4 = ctx.url.searchParams.get("date") || undefined;
|
|
124458
124754
|
const tz = ctx.url.searchParams.get("tz") || undefined;
|
|
124459
|
-
|
|
124755
|
+
logger67.debug("Getting today XP", { userId: ctx.user.id, date: date4, tz });
|
|
124460
124756
|
return ctx.services.timeback.getTodayXp(ctx.user.id, date4, tz);
|
|
124461
124757
|
});
|
|
124462
124758
|
getTotalXp = requireNonAnonymous(async (ctx) => {
|
|
124463
|
-
|
|
124759
|
+
logger67.debug("Getting total XP", { userId: ctx.user.id });
|
|
124464
124760
|
return ctx.services.timeback.getTotalXp(ctx.user.id);
|
|
124465
124761
|
});
|
|
124466
124762
|
updateTodayXp = requireNonAnonymous(async (ctx) => {
|
|
@@ -124471,18 +124767,18 @@ var init_timeback_controller = __esm(() => {
|
|
|
124471
124767
|
} catch (error2) {
|
|
124472
124768
|
if (error2 instanceof exports_external.ZodError) {
|
|
124473
124769
|
const details = formatZodError(error2);
|
|
124474
|
-
|
|
124770
|
+
logger67.warn("Update today XP validation failed", { details });
|
|
124475
124771
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124476
124772
|
}
|
|
124477
124773
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124478
124774
|
}
|
|
124479
|
-
|
|
124775
|
+
logger67.debug("Updating today XP", { userId: ctx.user.id, xp: body2.xp });
|
|
124480
124776
|
return ctx.services.timeback.updateTodayXp(ctx.user.id, body2);
|
|
124481
124777
|
});
|
|
124482
124778
|
getXpHistory = requireNonAnonymous(async (ctx) => {
|
|
124483
124779
|
const startDate = ctx.url.searchParams.get("startDate") || undefined;
|
|
124484
124780
|
const endDate = ctx.url.searchParams.get("endDate") || undefined;
|
|
124485
|
-
|
|
124781
|
+
logger67.debug("Getting XP history", { userId: ctx.user.id, startDate, endDate });
|
|
124486
124782
|
return ctx.services.timeback.getXpHistory(ctx.user.id, startDate, endDate);
|
|
124487
124783
|
});
|
|
124488
124784
|
populateStudent = requireNonAnonymous(async (ctx) => {
|
|
@@ -124493,18 +124789,18 @@ var init_timeback_controller = __esm(() => {
|
|
|
124493
124789
|
} catch (error2) {
|
|
124494
124790
|
if (error2 instanceof exports_external.ZodError) {
|
|
124495
124791
|
const details = formatZodError(error2);
|
|
124496
|
-
|
|
124792
|
+
logger67.warn("Populate student validation failed", { details });
|
|
124497
124793
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124498
124794
|
}
|
|
124499
124795
|
}
|
|
124500
|
-
|
|
124796
|
+
logger67.debug("Populating student", {
|
|
124501
124797
|
userId: ctx.user.id,
|
|
124502
124798
|
hasProvidedNames: Boolean(providedNames)
|
|
124503
124799
|
});
|
|
124504
124800
|
return ctx.services.timeback.populateStudent(ctx.user, providedNames);
|
|
124505
124801
|
});
|
|
124506
124802
|
getUser = requireNonAnonymous(async (ctx) => {
|
|
124507
|
-
|
|
124803
|
+
logger67.debug("Getting user", { userId: ctx.user.id, gameId: ctx.gameId });
|
|
124508
124804
|
return ctx.services.timeback.getUserData(ctx.user.id, ctx.gameId);
|
|
124509
124805
|
});
|
|
124510
124806
|
getUserById = requireNonAnonymous(async (ctx) => {
|
|
@@ -124512,7 +124808,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124512
124808
|
if (!timebackId) {
|
|
124513
124809
|
throw ApiError.badRequest("Missing timebackId parameter");
|
|
124514
124810
|
}
|
|
124515
|
-
|
|
124811
|
+
logger67.debug("Getting user by ID", { requesterId: ctx.user.id, timebackId });
|
|
124516
124812
|
return ctx.services.timeback.getUserDataByTimebackId(timebackId);
|
|
124517
124813
|
});
|
|
124518
124814
|
setupIntegration = requireDeveloper(async (ctx) => {
|
|
@@ -124523,12 +124819,12 @@ var init_timeback_controller = __esm(() => {
|
|
|
124523
124819
|
} catch (error2) {
|
|
124524
124820
|
if (error2 instanceof exports_external.ZodError) {
|
|
124525
124821
|
const details = formatZodError(error2);
|
|
124526
|
-
|
|
124822
|
+
logger67.warn("Setup integration validation failed", { details });
|
|
124527
124823
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124528
124824
|
}
|
|
124529
124825
|
throw ApiError.badRequest("Invalid JSON body");
|
|
124530
124826
|
}
|
|
124531
|
-
|
|
124827
|
+
logger67.debug("Setting up integration", {
|
|
124532
124828
|
userId: ctx.user.id,
|
|
124533
124829
|
gameId: body2.gameId
|
|
124534
124830
|
});
|
|
@@ -124542,9 +124838,37 @@ var init_timeback_controller = __esm(() => {
|
|
|
124542
124838
|
if (!isValidUUID(gameId)) {
|
|
124543
124839
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124544
124840
|
}
|
|
124545
|
-
|
|
124841
|
+
logger67.debug("Getting integrations", { userId: ctx.user.id, gameId });
|
|
124546
124842
|
return ctx.services.timeback.getIntegrations(gameId, ctx.user);
|
|
124547
124843
|
});
|
|
124844
|
+
updateIntegration = requireDeveloper(async (ctx) => {
|
|
124845
|
+
const { gameId, courseId } = ctx.params;
|
|
124846
|
+
if (!gameId || !courseId) {
|
|
124847
|
+
throw ApiError.badRequest("Missing gameId or courseId parameter");
|
|
124848
|
+
}
|
|
124849
|
+
if (!isValidUUID(gameId)) {
|
|
124850
|
+
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124851
|
+
}
|
|
124852
|
+
const body2 = await parseRequestBody(ctx.request, UpdateGameTimebackIntegrationRequestSchema);
|
|
124853
|
+
logger67.debug("Updating integration", {
|
|
124854
|
+
userId: ctx.user.id,
|
|
124855
|
+
gameId,
|
|
124856
|
+
courseId,
|
|
124857
|
+
fields: Object.keys(body2)
|
|
124858
|
+
});
|
|
124859
|
+
return ctx.services.timeback.updateIntegration(gameId, courseId, ctx.user, body2);
|
|
124860
|
+
});
|
|
124861
|
+
getIntegrationConfig = requireGameManagementAccess(async (ctx) => {
|
|
124862
|
+
const { gameId, courseId } = ctx.params;
|
|
124863
|
+
if (!gameId || !courseId) {
|
|
124864
|
+
throw ApiError.badRequest("Missing gameId or courseId parameter");
|
|
124865
|
+
}
|
|
124866
|
+
if (!isValidUUID(gameId)) {
|
|
124867
|
+
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124868
|
+
}
|
|
124869
|
+
logger67.debug("Getting integration config", { userId: ctx.user.id, gameId, courseId });
|
|
124870
|
+
return ctx.services.timeback.getIntegrationConfig(gameId, courseId, ctx.user);
|
|
124871
|
+
});
|
|
124548
124872
|
verifyIntegration = requireDeveloper(async (ctx) => {
|
|
124549
124873
|
const gameId = ctx.params.gameId;
|
|
124550
124874
|
if (!gameId) {
|
|
@@ -124553,7 +124877,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124553
124877
|
if (!isValidUUID(gameId)) {
|
|
124554
124878
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124555
124879
|
}
|
|
124556
|
-
|
|
124880
|
+
logger67.debug("Verifying integration", { userId: ctx.user.id, gameId });
|
|
124557
124881
|
return ctx.services.timeback.verifyIntegration(gameId, ctx.user);
|
|
124558
124882
|
});
|
|
124559
124883
|
getConfig2 = requireDeveloper(async (ctx) => {
|
|
@@ -124564,7 +124888,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124564
124888
|
if (!isValidUUID(gameId)) {
|
|
124565
124889
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124566
124890
|
}
|
|
124567
|
-
|
|
124891
|
+
logger67.debug("Getting config", { userId: ctx.user.id, gameId });
|
|
124568
124892
|
return ctx.services.timeback.getConfig(gameId, ctx.user);
|
|
124569
124893
|
});
|
|
124570
124894
|
deleteIntegrations = requireDeveloper(async (ctx) => {
|
|
@@ -124575,7 +124899,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124575
124899
|
if (!isValidUUID(gameId)) {
|
|
124576
124900
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
124577
124901
|
}
|
|
124578
|
-
|
|
124902
|
+
logger67.debug("Deleting integrations", { userId: ctx.user.id, gameId });
|
|
124579
124903
|
await ctx.services.timeback.deleteIntegrations(gameId, ctx.user);
|
|
124580
124904
|
});
|
|
124581
124905
|
endActivity = requireDeveloper(async (ctx) => {
|
|
@@ -124586,7 +124910,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124586
124910
|
} catch (error2) {
|
|
124587
124911
|
if (error2 instanceof exports_external.ZodError) {
|
|
124588
124912
|
const details = formatZodError(error2);
|
|
124589
|
-
|
|
124913
|
+
logger67.warn("End activity validation failed", { details });
|
|
124590
124914
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124591
124915
|
}
|
|
124592
124916
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -124604,7 +124928,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124604
124928
|
masteredUnits,
|
|
124605
124929
|
extensions
|
|
124606
124930
|
} = body2;
|
|
124607
|
-
|
|
124931
|
+
logger67.debug("Ending activity", { userId: ctx.user.id, gameId });
|
|
124608
124932
|
return ctx.services.timeback.endActivity({
|
|
124609
124933
|
gameId,
|
|
124610
124934
|
studentId,
|
|
@@ -124628,7 +124952,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124628
124952
|
} catch (error2) {
|
|
124629
124953
|
if (error2 instanceof exports_external.ZodError) {
|
|
124630
124954
|
const details = formatZodError(error2);
|
|
124631
|
-
|
|
124955
|
+
logger67.warn("Heartbeat validation failed", { details });
|
|
124632
124956
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
124633
124957
|
}
|
|
124634
124958
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -124644,7 +124968,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124644
124968
|
windowSequence,
|
|
124645
124969
|
isFinal
|
|
124646
124970
|
} = body2;
|
|
124647
|
-
|
|
124971
|
+
logger67.debug("Recording heartbeat", {
|
|
124648
124972
|
userId: ctx.user.id,
|
|
124649
124973
|
gameId,
|
|
124650
124974
|
runId,
|
|
@@ -124669,7 +124993,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124669
124993
|
});
|
|
124670
124994
|
advanceCourse = requireDeveloper(async (ctx) => {
|
|
124671
124995
|
const body2 = await parseRequestBody(ctx.request, AdvanceCourseRequestSchema);
|
|
124672
|
-
|
|
124996
|
+
logger67.debug("Advancing student manually", {
|
|
124673
124997
|
userId: ctx.user.id,
|
|
124674
124998
|
gameId: body2.gameId,
|
|
124675
124999
|
studentId: body2.studentId,
|
|
@@ -124710,7 +125034,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124710
125034
|
perCourse: includeOptions.includes("percourse"),
|
|
124711
125035
|
today: includeOptions.includes("today")
|
|
124712
125036
|
};
|
|
124713
|
-
|
|
125037
|
+
logger67.debug("Getting student XP", {
|
|
124714
125038
|
requesterId: ctx.user.id,
|
|
124715
125039
|
timebackId,
|
|
124716
125040
|
gameId,
|
|
@@ -124732,7 +125056,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124732
125056
|
if (!gameId || !courseId) {
|
|
124733
125057
|
throw ApiError.badRequest("Missing gameId or courseId parameter");
|
|
124734
125058
|
}
|
|
124735
|
-
|
|
125059
|
+
logger67.debug("Getting course roster", {
|
|
124736
125060
|
requesterId: ctx.user.id,
|
|
124737
125061
|
gameId,
|
|
124738
125062
|
courseId,
|
|
@@ -124749,7 +125073,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124749
125073
|
if (!timebackId || !gameId) {
|
|
124750
125074
|
throw ApiError.badRequest("Missing timebackId parameter or gameId query parameter");
|
|
124751
125075
|
}
|
|
124752
|
-
|
|
125076
|
+
logger67.debug("Getting student overview", {
|
|
124753
125077
|
requesterId: ctx.user.id,
|
|
124754
125078
|
timebackId,
|
|
124755
125079
|
gameId,
|
|
@@ -124763,7 +125087,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124763
125087
|
if (!gameId || !timebackId) {
|
|
124764
125088
|
throw ApiError.badRequest("Missing gameId or timebackId path parameter");
|
|
124765
125089
|
}
|
|
124766
|
-
|
|
125090
|
+
logger67.debug("Getting game metrics", {
|
|
124767
125091
|
requesterId: ctx.user.id,
|
|
124768
125092
|
gameId,
|
|
124769
125093
|
timebackId
|
|
@@ -124781,7 +125105,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124781
125105
|
if (!timebackId || !courseId || !gameId) {
|
|
124782
125106
|
throw ApiError.badRequest("Missing timebackId or courseId path parameter, or gameId query parameter");
|
|
124783
125107
|
}
|
|
124784
|
-
|
|
125108
|
+
logger67.debug("Getting student activity", {
|
|
124785
125109
|
requesterId: ctx.user.id,
|
|
124786
125110
|
timebackId,
|
|
124787
125111
|
courseId,
|
|
@@ -124806,7 +125130,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124806
125130
|
if (!timebackId || !courseId || !activityId || !gameId) {
|
|
124807
125131
|
throw ApiError.badRequest("Missing timebackId, courseId, or activityId path parameter, or gameId query parameter");
|
|
124808
125132
|
}
|
|
124809
|
-
|
|
125133
|
+
logger67.debug("Getting activity detail", {
|
|
124810
125134
|
requesterId: ctx.user.id,
|
|
124811
125135
|
timebackId,
|
|
124812
125136
|
courseId,
|
|
@@ -124824,7 +125148,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124824
125148
|
});
|
|
124825
125149
|
grantXp = requireDeveloper(async (ctx) => {
|
|
124826
125150
|
const body2 = await parseRequestBody(ctx.request, GrantTimebackXpRequestSchema);
|
|
124827
|
-
|
|
125151
|
+
logger67.debug("Granting manual XP", {
|
|
124828
125152
|
requesterId: ctx.user.id,
|
|
124829
125153
|
gameId: body2.gameId,
|
|
124830
125154
|
courseId: body2.courseId,
|
|
@@ -124836,7 +125160,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124836
125160
|
});
|
|
124837
125161
|
adjustTime = requireDeveloper(async (ctx) => {
|
|
124838
125162
|
const body2 = await parseRequestBody(ctx.request, AdjustTimebackTimeRequestSchema);
|
|
124839
|
-
|
|
125163
|
+
logger67.debug("Adjusting time spent", {
|
|
124840
125164
|
requesterId: ctx.user.id,
|
|
124841
125165
|
gameId: body2.gameId,
|
|
124842
125166
|
courseId: body2.courseId,
|
|
@@ -124848,7 +125172,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124848
125172
|
});
|
|
124849
125173
|
adjustMastery = requireDeveloper(async (ctx) => {
|
|
124850
125174
|
const body2 = await parseRequestBody(ctx.request, AdjustTimebackMasteryRequestSchema);
|
|
124851
|
-
|
|
125175
|
+
logger67.debug("Adjusting mastered units", {
|
|
124852
125176
|
requesterId: ctx.user.id,
|
|
124853
125177
|
gameId: body2.gameId,
|
|
124854
125178
|
courseId: body2.courseId,
|
|
@@ -124858,6 +125182,22 @@ var init_timeback_controller = __esm(() => {
|
|
|
124858
125182
|
});
|
|
124859
125183
|
return ctx.services.timebackAdmin.adjustMasteredUnits(body2, ctx.user);
|
|
124860
125184
|
});
|
|
125185
|
+
reconcileMasteryForConfigChange = requireDeveloper(async (ctx) => {
|
|
125186
|
+
const body2 = await parseRequestBody(ctx.request, ReconcileMasteryForConfigChangeSchema);
|
|
125187
|
+
logger67.debug("Reconciling mastery completion for config change", {
|
|
125188
|
+
requesterId: ctx.user.id,
|
|
125189
|
+
gameId: body2.gameId,
|
|
125190
|
+
courseId: body2.courseId,
|
|
125191
|
+
oldMasterableUnits: body2.oldMasterableUnits,
|
|
125192
|
+
newMasterableUnits: body2.newMasterableUnits,
|
|
125193
|
+
affectedCount: body2.affectedStudentIds.length
|
|
125194
|
+
});
|
|
125195
|
+
return ctx.services.timebackAdmin.reconcileMasteryForConfigChange(body2.gameId, body2.courseId, ctx.user, {
|
|
125196
|
+
oldMasterableUnits: body2.oldMasterableUnits,
|
|
125197
|
+
newMasterableUnits: body2.newMasterableUnits,
|
|
125198
|
+
affectedStudentIds: body2.affectedStudentIds
|
|
125199
|
+
});
|
|
125200
|
+
});
|
|
124861
125201
|
searchStudents = requireGameManagementAccess(async (ctx) => {
|
|
124862
125202
|
const gameId = ctx.params.gameId;
|
|
124863
125203
|
const courseId = ctx.params.courseId;
|
|
@@ -124865,7 +125205,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124865
125205
|
if (!gameId || !courseId) {
|
|
124866
125206
|
throw ApiError.badRequest("Missing gameId or courseId parameter");
|
|
124867
125207
|
}
|
|
124868
|
-
|
|
125208
|
+
logger67.debug("Searching students for enrollment", {
|
|
124869
125209
|
requesterId: ctx.user.id,
|
|
124870
125210
|
gameId,
|
|
124871
125211
|
courseId,
|
|
@@ -124875,7 +125215,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124875
125215
|
});
|
|
124876
125216
|
enrollStudent = requireGameManagementAccess(async (ctx) => {
|
|
124877
125217
|
const body2 = await parseRequestBody(ctx.request, EnrollStudentRequestSchema);
|
|
124878
|
-
|
|
125218
|
+
logger67.debug("Enrolling student", {
|
|
124879
125219
|
requesterId: ctx.user.id,
|
|
124880
125220
|
gameId: body2.gameId,
|
|
124881
125221
|
courseId: body2.courseId,
|
|
@@ -124885,7 +125225,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124885
125225
|
});
|
|
124886
125226
|
unenrollStudent = requireGameManagementAccess(async (ctx) => {
|
|
124887
125227
|
const body2 = await parseRequestBody(ctx.request, UnenrollStudentRequestSchema);
|
|
124888
|
-
|
|
125228
|
+
logger67.debug("Unenrolling student", {
|
|
124889
125229
|
requesterId: ctx.user.id,
|
|
124890
125230
|
gameId: body2.gameId,
|
|
124891
125231
|
courseId: body2.courseId,
|
|
@@ -124895,7 +125235,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
124895
125235
|
});
|
|
124896
125236
|
reactivateEnrollment = requireGameManagementAccess(async (ctx) => {
|
|
124897
125237
|
const body2 = await parseRequestBody(ctx.request, ReactivateEnrollmentRequestSchema);
|
|
124898
|
-
|
|
125238
|
+
logger67.debug("Reactivating enrollment", {
|
|
124899
125239
|
requesterId: ctx.user.id,
|
|
124900
125240
|
gameId: body2.gameId,
|
|
124901
125241
|
courseId: body2.courseId,
|
|
@@ -125035,6 +125375,8 @@ var init_timeback_controller = __esm(() => {
|
|
|
125035
125375
|
getUserById,
|
|
125036
125376
|
setupIntegration,
|
|
125037
125377
|
getIntegrations,
|
|
125378
|
+
updateIntegration,
|
|
125379
|
+
getIntegrationConfig,
|
|
125038
125380
|
verifyIntegration,
|
|
125039
125381
|
getConfig: getConfig2,
|
|
125040
125382
|
deleteIntegrations,
|
|
@@ -125050,6 +125392,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
125050
125392
|
grantXp,
|
|
125051
125393
|
adjustTime,
|
|
125052
125394
|
adjustMastery,
|
|
125395
|
+
reconcileMasteryForConfigChange,
|
|
125053
125396
|
searchStudents,
|
|
125054
125397
|
enrollStudent,
|
|
125055
125398
|
unenrollStudent,
|
|
@@ -125069,7 +125412,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
125069
125412
|
destroyAssessmentBank
|
|
125070
125413
|
};
|
|
125071
125414
|
});
|
|
125072
|
-
var
|
|
125415
|
+
var logger68;
|
|
125073
125416
|
var initiate;
|
|
125074
125417
|
var init_upload_controller = __esm(() => {
|
|
125075
125418
|
init_esm();
|
|
@@ -125077,7 +125420,7 @@ var init_upload_controller = __esm(() => {
|
|
|
125077
125420
|
init_src2();
|
|
125078
125421
|
init_errors();
|
|
125079
125422
|
init_utils11();
|
|
125080
|
-
|
|
125423
|
+
logger68 = log.scope("UploadController");
|
|
125081
125424
|
initiate = requireDeveloper(async (ctx) => {
|
|
125082
125425
|
let body2;
|
|
125083
125426
|
try {
|
|
@@ -125086,16 +125429,16 @@ var init_upload_controller = __esm(() => {
|
|
|
125086
125429
|
} catch (error2) {
|
|
125087
125430
|
if (error2 instanceof exports_external.ZodError) {
|
|
125088
125431
|
const details = formatZodError(error2);
|
|
125089
|
-
|
|
125432
|
+
logger68.warn("Initiate upload validation failed", { details });
|
|
125090
125433
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
125091
125434
|
}
|
|
125092
125435
|
throw ApiError.badRequest("Invalid JSON body");
|
|
125093
125436
|
}
|
|
125094
|
-
|
|
125437
|
+
logger68.debug("Initiating upload", { userId: ctx.user.id, gameId: body2.gameId });
|
|
125095
125438
|
return ctx.services.upload.initiate(body2, ctx.user);
|
|
125096
125439
|
});
|
|
125097
125440
|
});
|
|
125098
|
-
var
|
|
125441
|
+
var logger69;
|
|
125099
125442
|
var getMe;
|
|
125100
125443
|
var getDemoProfile;
|
|
125101
125444
|
var updateDemoProfile;
|
|
@@ -125104,18 +125447,18 @@ var init_user_controller = __esm(() => {
|
|
|
125104
125447
|
init_schemas_index();
|
|
125105
125448
|
init_src2();
|
|
125106
125449
|
init_utils11();
|
|
125107
|
-
|
|
125450
|
+
logger69 = log.scope("UserController");
|
|
125108
125451
|
getMe = requireNonAnonymous(async (ctx) => {
|
|
125109
|
-
|
|
125452
|
+
logger69.debug("Getting current user", { userId: ctx.user.id, gameId: ctx.gameId });
|
|
125110
125453
|
return ctx.services.user.getMe(ctx.user, ctx.gameId);
|
|
125111
125454
|
});
|
|
125112
125455
|
getDemoProfile = requireAnonymous(async (ctx) => {
|
|
125113
|
-
|
|
125456
|
+
logger69.debug("Getting demo profile", { userId: ctx.user.id });
|
|
125114
125457
|
return ctx.services.user.getDemoProfile(ctx.user.id);
|
|
125115
125458
|
});
|
|
125116
125459
|
updateDemoProfile = requireAnonymous(async (ctx) => {
|
|
125117
125460
|
const body2 = await parseRequestBody(ctx.request, DemoProfileSchema);
|
|
125118
|
-
|
|
125461
|
+
logger69.debug("Updating demo profile", {
|
|
125119
125462
|
userId: ctx.user.id,
|
|
125120
125463
|
displayName: body2.displayName
|
|
125121
125464
|
});
|
|
@@ -125127,13 +125470,13 @@ var init_user_controller = __esm(() => {
|
|
|
125127
125470
|
updateDemoProfile
|
|
125128
125471
|
};
|
|
125129
125472
|
});
|
|
125130
|
-
var
|
|
125473
|
+
var logger70;
|
|
125131
125474
|
var init_verify_controller = __esm(() => {
|
|
125132
125475
|
init_schemas_index();
|
|
125133
125476
|
init_src2();
|
|
125134
125477
|
init_errors();
|
|
125135
125478
|
init_utils11();
|
|
125136
|
-
|
|
125479
|
+
logger70 = log.scope("VerifyController");
|
|
125137
125480
|
});
|
|
125138
125481
|
var init_controllers = __esm(() => {
|
|
125139
125482
|
init_achievement_controller();
|
|
@@ -125431,7 +125774,7 @@ var init_uploads = __esm(() => {
|
|
|
125431
125774
|
gameUploadsRouter.post("/uploads/finalize", finalizeHandler);
|
|
125432
125775
|
gameUploadsRouter.post("/uploads/finalize/", finalizeHandler);
|
|
125433
125776
|
});
|
|
125434
|
-
var
|
|
125777
|
+
var logger71;
|
|
125435
125778
|
var gameDeployRouter;
|
|
125436
125779
|
var init_deploy = __esm(() => {
|
|
125437
125780
|
init_drizzle_orm();
|
|
@@ -125442,7 +125785,7 @@ var init_deploy = __esm(() => {
|
|
|
125442
125785
|
init_src2();
|
|
125443
125786
|
init_api();
|
|
125444
125787
|
init_uploads();
|
|
125445
|
-
|
|
125788
|
+
logger71 = log.scope("SandboxDeploy");
|
|
125446
125789
|
gameDeployRouter = new Hono2;
|
|
125447
125790
|
gameDeployRouter.post("/:slug/deploy", async (c2) => {
|
|
125448
125791
|
const user = c2.get("user");
|
|
@@ -125568,7 +125911,7 @@ var init_deploy = __esm(() => {
|
|
|
125568
125911
|
completedAt: now2
|
|
125569
125912
|
};
|
|
125570
125913
|
const [insertedJob] = await db2.insert(gameDeployJobs).values([jobValues]).returning();
|
|
125571
|
-
|
|
125914
|
+
logger71.info("Mock deploy job completed", { jobId: insertedJob.id, slug: slug2 });
|
|
125572
125915
|
return c2.json({
|
|
125573
125916
|
id: insertedJob.id,
|
|
125574
125917
|
status: "succeeded",
|
|
@@ -126166,7 +126509,7 @@ function verifyMockToken(idToken) {
|
|
|
126166
126509
|
throw new Error("Invalid LTI token format");
|
|
126167
126510
|
}
|
|
126168
126511
|
}
|
|
126169
|
-
var
|
|
126512
|
+
var logger72;
|
|
126170
126513
|
var ltiRouter;
|
|
126171
126514
|
var init_lti = __esm(() => {
|
|
126172
126515
|
init_drizzle_orm();
|
|
@@ -126177,7 +126520,7 @@ var init_lti = __esm(() => {
|
|
|
126177
126520
|
init_src2();
|
|
126178
126521
|
init_constants();
|
|
126179
126522
|
init_api();
|
|
126180
|
-
|
|
126523
|
+
logger72 = log.scope("SandboxLti");
|
|
126181
126524
|
ltiRouter = new Hono2;
|
|
126182
126525
|
ltiRouter.post("/launch", async (c2) => {
|
|
126183
126526
|
const db2 = c2.get("db");
|
|
@@ -126195,7 +126538,7 @@ var init_lti = __esm(() => {
|
|
|
126195
126538
|
claims = verifyMockToken(idToken);
|
|
126196
126539
|
} catch (error2) {
|
|
126197
126540
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
126198
|
-
|
|
126541
|
+
logger72.error("LTI token verification failed", { error: errorMessage });
|
|
126199
126542
|
return c2.json({
|
|
126200
126543
|
error: "invalid_token",
|
|
126201
126544
|
message: errorMessage
|
|
@@ -126203,7 +126546,7 @@ var init_lti = __esm(() => {
|
|
|
126203
126546
|
}
|
|
126204
126547
|
const validationError = validateLtiClaims(claims);
|
|
126205
126548
|
if (validationError) {
|
|
126206
|
-
|
|
126549
|
+
logger72.warn("LTI claims validation failed", {
|
|
126207
126550
|
error: validationError,
|
|
126208
126551
|
sub: claims.sub
|
|
126209
126552
|
});
|
|
@@ -126223,7 +126566,7 @@ var init_lti = __esm(() => {
|
|
|
126223
126566
|
createdAt: new Date,
|
|
126224
126567
|
updatedAt: new Date
|
|
126225
126568
|
});
|
|
126226
|
-
|
|
126569
|
+
logger72.info("LTI launch successful", { userId: user.id });
|
|
126227
126570
|
const targetUri = claims["https://purl.imsglobal.org/spec/lti/claim/target_link_uri"];
|
|
126228
126571
|
const currentHost = new URL(c2.req.url).hostname;
|
|
126229
126572
|
const redirectPath = extractRedirectPath(targetUri, currentHost);
|
|
@@ -126231,7 +126574,7 @@ var init_lti = __esm(() => {
|
|
|
126231
126574
|
return c2.redirect(redirectPath);
|
|
126232
126575
|
} catch (error2) {
|
|
126233
126576
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
126234
|
-
|
|
126577
|
+
logger72.error("Unexpected error during LTI launch", { error: errorMessage });
|
|
126235
126578
|
return c2.json({
|
|
126236
126579
|
error: "unexpected_error",
|
|
126237
126580
|
message: "An unexpected error occurred during LTI launch"
|
|
@@ -127905,7 +128248,7 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
|
127905
128248
|
// package.json
|
|
127906
128249
|
var package_default2 = {
|
|
127907
128250
|
name: "@playcademy/vite-plugin",
|
|
127908
|
-
version: "0.2.
|
|
128251
|
+
version: "0.2.35-beta.2",
|
|
127909
128252
|
type: "module",
|
|
127910
128253
|
exports: {
|
|
127911
128254
|
".": {
|