@playcademy/vite-plugin 0.2.6 → 0.2.8
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 +809 -1716
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -41142,10 +41142,6 @@ import { homedir } from "node:os";
|
|
|
41142
41142
|
import { join } from "node:path";
|
|
41143
41143
|
import { stdout } from "process";
|
|
41144
41144
|
import crypto3 from "node:crypto";
|
|
41145
|
-
import { request } from "https";
|
|
41146
|
-
import { pipeline } from "stream";
|
|
41147
|
-
import { createPublicKey, createVerify, verify } from "crypto";
|
|
41148
|
-
import * as crypto4 from "node:crypto";
|
|
41149
41145
|
import * as s3 from "fs";
|
|
41150
41146
|
import * as o3 from "path";
|
|
41151
41147
|
import fs22 from "node:fs";
|
|
@@ -41153,9 +41149,10 @@ import { dirname, isAbsolute, join as join3 } from "node:path";
|
|
|
41153
41149
|
import process2 from "process";
|
|
41154
41150
|
import os from "os";
|
|
41155
41151
|
import tty from "tty";
|
|
41156
|
-
import { randomUUID
|
|
41152
|
+
import { randomUUID } from "crypto";
|
|
41157
41153
|
import fs3 from "node:fs";
|
|
41158
41154
|
import fs4 from "node:fs";
|
|
41155
|
+
import * as crypto4 from "node:crypto";
|
|
41159
41156
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
41160
41157
|
var __create2 = Object.create;
|
|
41161
41158
|
var __getProtoOf2 = Object.getPrototypeOf;
|
|
@@ -42382,7 +42379,7 @@ var package_default;
|
|
|
42382
42379
|
var init_package = __esm(() => {
|
|
42383
42380
|
package_default = {
|
|
42384
42381
|
name: "@playcademy/sandbox",
|
|
42385
|
-
version: "0.3.
|
|
42382
|
+
version: "0.3.10",
|
|
42386
42383
|
description: "Local development server for Playcademy game development",
|
|
42387
42384
|
type: "module",
|
|
42388
42385
|
exports: {
|
|
@@ -46989,7 +46986,7 @@ var realtimeConfigSchema;
|
|
|
46989
46986
|
var apiConfigSchema;
|
|
46990
46987
|
var init_schema = __esm(() => {
|
|
46991
46988
|
init_esm();
|
|
46992
|
-
stageSchema = exports_external.enum(["production", "
|
|
46989
|
+
stageSchema = exports_external.enum(["production", "dev", "local"]);
|
|
46993
46990
|
ltiConfigSchema = exports_external.object({
|
|
46994
46991
|
audience: exports_external.string(),
|
|
46995
46992
|
jwksUrl: exports_external.string().url(),
|
|
@@ -54625,7 +54622,7 @@ class DeployService {
|
|
|
54625
54622
|
}
|
|
54626
54623
|
return cf;
|
|
54627
54624
|
}
|
|
54628
|
-
async
|
|
54625
|
+
async createApiKey(user, slug2, keyName) {
|
|
54629
54626
|
const { id, key: apiKey } = await this.ctx.providers.auth.createApiKey({
|
|
54630
54627
|
userId: user.id,
|
|
54631
54628
|
name: keyName,
|
|
@@ -54634,16 +54631,6 @@ class DeployService {
|
|
|
54634
54631
|
games: [`read:${slug2}`, `write:${slug2}`]
|
|
54635
54632
|
}
|
|
54636
54633
|
});
|
|
54637
|
-
try {
|
|
54638
|
-
const existingSecrets = await this.ctx.providers.secrets.readSecrets(game.id) || {};
|
|
54639
|
-
await this.ctx.providers.secrets.writeSecrets(game.id, {
|
|
54640
|
-
...existingSecrets,
|
|
54641
|
-
PLAYCADEMY_API_KEY: apiKey
|
|
54642
|
-
});
|
|
54643
|
-
logger8.debug("Persisted API key to secrets", { gameId: game.id });
|
|
54644
|
-
} catch (error) {
|
|
54645
|
-
logger8.warn("Failed to persist API key to secrets", { error });
|
|
54646
|
-
}
|
|
54647
54634
|
logger8.info("Created new game-scoped API key", {
|
|
54648
54635
|
userId: user.id,
|
|
54649
54636
|
slug: slug2,
|
|
@@ -54651,56 +54638,55 @@ class DeployService {
|
|
|
54651
54638
|
});
|
|
54652
54639
|
return apiKey;
|
|
54653
54640
|
}
|
|
54654
|
-
async
|
|
54655
|
-
|
|
54656
|
-
|
|
54657
|
-
|
|
54658
|
-
|
|
54659
|
-
|
|
54660
|
-
}
|
|
54661
|
-
return null;
|
|
54662
|
-
} catch (error) {
|
|
54663
|
-
logger8.warn("Failed to retrieve secrets", { error });
|
|
54664
|
-
return null;
|
|
54665
|
-
}
|
|
54666
|
-
}
|
|
54667
|
-
async regenerateAndPersistApiKey(user, slug2, game, existingKeyId, keyName) {
|
|
54668
|
-
logger8.info("Regenerating API key (migration)", {
|
|
54669
|
-
userId: user.id,
|
|
54670
|
-
slug: slug2,
|
|
54671
|
-
oldKeyId: existingKeyId
|
|
54672
|
-
});
|
|
54673
|
-
try {
|
|
54674
|
-
await this.ctx.providers.auth.deleteApiKey(existingKeyId);
|
|
54675
|
-
logger8.debug("Revoked old API key", { keyId: existingKeyId });
|
|
54676
|
-
} catch (error) {
|
|
54677
|
-
logger8.warn("Failed to revoke old API key", {
|
|
54678
|
-
keyId: existingKeyId,
|
|
54679
|
-
error
|
|
54641
|
+
async regenerateApiKey(user, slug2, existingKeyId, keyName) {
|
|
54642
|
+
if (existingKeyId) {
|
|
54643
|
+
logger8.info("Regenerating API key", {
|
|
54644
|
+
userId: user.id,
|
|
54645
|
+
slug: slug2,
|
|
54646
|
+
oldKeyId: existingKeyId
|
|
54680
54647
|
});
|
|
54648
|
+
try {
|
|
54649
|
+
await this.ctx.providers.auth.deleteApiKey(existingKeyId);
|
|
54650
|
+
logger8.debug("Revoked old API key", { keyId: existingKeyId });
|
|
54651
|
+
} catch (error) {
|
|
54652
|
+
logger8.warn("Failed to revoke old API key", {
|
|
54653
|
+
keyId: existingKeyId,
|
|
54654
|
+
error
|
|
54655
|
+
});
|
|
54656
|
+
}
|
|
54681
54657
|
}
|
|
54682
|
-
return this.
|
|
54658
|
+
return this.createApiKey(user, slug2, keyName);
|
|
54683
54659
|
}
|
|
54684
|
-
async
|
|
54660
|
+
async ensureApiKeyOnWorker(user, slug2, deploymentId, headers) {
|
|
54661
|
+
const cf = this.getCloudflare();
|
|
54685
54662
|
const keyName = getGameWorkerApiKeyName(slug2);
|
|
54686
54663
|
const existingKeys = await this.ctx.providers.auth.listApiKeys(headers);
|
|
54687
54664
|
const existingKey = existingKeys.find((k) => k.name === keyName);
|
|
54665
|
+
let apiKey;
|
|
54688
54666
|
if (!existingKey) {
|
|
54689
|
-
|
|
54690
|
-
}
|
|
54691
|
-
|
|
54692
|
-
|
|
54693
|
-
|
|
54667
|
+
apiKey = await this.createApiKey(user, slug2, keyName);
|
|
54668
|
+
} else {
|
|
54669
|
+
try {
|
|
54670
|
+
const workerSecrets = await cf.listSecrets(deploymentId);
|
|
54671
|
+
if (workerSecrets.includes("PLAYCADEMY_API_KEY")) {
|
|
54672
|
+
logger8.debug("API key already on worker", { slug: slug2, deploymentId });
|
|
54673
|
+
return;
|
|
54674
|
+
}
|
|
54675
|
+
} catch (error) {
|
|
54676
|
+
logger8.warn("Could not check worker secrets, will regenerate key", { error });
|
|
54677
|
+
}
|
|
54678
|
+
apiKey = await this.regenerateApiKey(user, slug2, existingKey.id, keyName);
|
|
54694
54679
|
}
|
|
54695
|
-
|
|
54680
|
+
await cf.setSecrets(deploymentId, { PLAYCADEMY_API_KEY: apiKey });
|
|
54681
|
+
logger8.info("Set API key on worker", { slug: slug2, deploymentId });
|
|
54696
54682
|
}
|
|
54697
|
-
async* deploy(slug2,
|
|
54683
|
+
async* deploy(slug2, request, user, uploadDeps, extractZip) {
|
|
54698
54684
|
const cf = this.getCloudflare();
|
|
54699
54685
|
const db2 = this.ctx.db;
|
|
54700
54686
|
const game = await this.ctx.services.game.validateDeveloperAccessBySlug(user, slug2);
|
|
54701
|
-
const hasBackend = !!
|
|
54702
|
-
const hasFrontend = !!
|
|
54703
|
-
const hasMetadata = !!
|
|
54687
|
+
const hasBackend = !!request.code;
|
|
54688
|
+
const hasFrontend = !!request.uploadToken;
|
|
54689
|
+
const hasMetadata = !!request.metadata;
|
|
54704
54690
|
logger8.debug("Deploying game", { slug: slug2, hasBackend, hasFrontend, hasMetadata });
|
|
54705
54691
|
if (!hasBackend && !hasFrontend && !hasMetadata) {
|
|
54706
54692
|
throw new ValidationError("Must provide at least one of: uploadToken (frontend), code (backend), or metadata");
|
|
@@ -54720,11 +54706,11 @@ class DeployService {
|
|
|
54720
54706
|
throw new ValidationError("Upload dependencies not configured for frontend deployment");
|
|
54721
54707
|
}
|
|
54722
54708
|
yield { type: "status", data: { message: "Fetching temporary files" } };
|
|
54723
|
-
const frontendZip = await uploadDeps.getObjectAsByteArray(
|
|
54709
|
+
const frontendZip = await uploadDeps.getObjectAsByteArray(request.uploadToken);
|
|
54724
54710
|
if (!frontendZip || frontendZip.length === 0) {
|
|
54725
54711
|
logger8.error("Frontend upload empty or not found", {
|
|
54726
54712
|
slug: slug2,
|
|
54727
|
-
uploadToken:
|
|
54713
|
+
uploadToken: request.uploadToken
|
|
54728
54714
|
});
|
|
54729
54715
|
throw new ValidationError("Uploaded file is empty or not found");
|
|
54730
54716
|
}
|
|
@@ -54734,23 +54720,21 @@ class DeployService {
|
|
|
54734
54720
|
tempDir = path2.join(os2.tmpdir(), `playcademy-deploy-${game.id}-${Date.now()}`);
|
|
54735
54721
|
frontendAssetsPath = path2.join(tempDir, "dist");
|
|
54736
54722
|
await extractZip(frontendZip, frontendAssetsPath);
|
|
54737
|
-
uploadDeps.deleteObject(
|
|
54738
|
-
logger8.warn("Failed to delete temp object", { key:
|
|
54723
|
+
uploadDeps.deleteObject(request.uploadToken).catch(() => {
|
|
54724
|
+
logger8.warn("Failed to delete temp object", { key: request.uploadToken });
|
|
54739
54725
|
});
|
|
54740
54726
|
}
|
|
54741
54727
|
const env = {
|
|
54742
54728
|
GAME_ID: game.id,
|
|
54743
|
-
PLAYCADEMY_BASE_URL: playcademyBaseUrl
|
|
54744
|
-
...request2._gameApiKey && { PLAYCADEMY_API_KEY: request2._gameApiKey },
|
|
54745
|
-
...request2.secrets && { secrets: request2.secrets }
|
|
54729
|
+
PLAYCADEMY_BASE_URL: playcademyBaseUrl
|
|
54746
54730
|
};
|
|
54747
54731
|
const deployMsg = hasBackend ? "Deploying backend code" : "Deploying to platform";
|
|
54748
54732
|
yield { type: "status", data: { message: deployMsg } };
|
|
54749
54733
|
const keepAssets = hasBackend && !hasFrontend;
|
|
54750
|
-
const deploymentOptions = this.mapBindingsToOptions(
|
|
54734
|
+
const deploymentOptions = this.mapBindingsToOptions(request.bindings, request.schema);
|
|
54751
54735
|
let result;
|
|
54752
54736
|
try {
|
|
54753
|
-
result = await cf.deploy(deploymentId,
|
|
54737
|
+
result = await cf.deploy(deploymentId, request.code, env, {
|
|
54754
54738
|
...deploymentOptions,
|
|
54755
54739
|
assetsPath: frontendAssetsPath,
|
|
54756
54740
|
keepAssets
|
|
@@ -54763,8 +54747,12 @@ class DeployService {
|
|
|
54763
54747
|
});
|
|
54764
54748
|
}
|
|
54765
54749
|
}
|
|
54766
|
-
const codeHash = hasBackend ? await generateDeploymentHash(
|
|
54750
|
+
const codeHash = hasBackend ? await generateDeploymentHash(request.code) : null;
|
|
54767
54751
|
await this.saveDeployment(game.id, result.deploymentId, result.url, codeHash, result.resources);
|
|
54752
|
+
if (hasBackend && request._headers) {
|
|
54753
|
+
yield { type: "status", data: { message: "Configuring worker secrets" } };
|
|
54754
|
+
await this.ensureApiKeyOnWorker(user, slug2, result.deploymentId, request._headers);
|
|
54755
|
+
}
|
|
54768
54756
|
yield { type: "status", data: { message: "Finalizing deployment" } };
|
|
54769
54757
|
if (hasMetadata || hasFrontend) {
|
|
54770
54758
|
const updates = { updatedAt: new Date };
|
|
@@ -54772,12 +54760,12 @@ class DeployService {
|
|
|
54772
54760
|
updates.deploymentUrl = result.url;
|
|
54773
54761
|
}
|
|
54774
54762
|
if (hasMetadata) {
|
|
54775
|
-
if (
|
|
54776
|
-
updates.displayName =
|
|
54777
|
-
if (
|
|
54778
|
-
updates.platform =
|
|
54779
|
-
if (
|
|
54780
|
-
updates.metadata =
|
|
54763
|
+
if (request.metadata.displayName)
|
|
54764
|
+
updates.displayName = request.metadata.displayName;
|
|
54765
|
+
if (request.metadata.platform)
|
|
54766
|
+
updates.platform = request.metadata.platform;
|
|
54767
|
+
if (request.metadata.metadata)
|
|
54768
|
+
updates.metadata = request.metadata.metadata;
|
|
54781
54769
|
}
|
|
54782
54770
|
await db2.update(games).set(updates).where(eq(games.id, game.id));
|
|
54783
54771
|
}
|
|
@@ -55245,12 +55233,6 @@ class GameService {
|
|
|
55245
55233
|
} catch (keyError) {
|
|
55246
55234
|
logger11.warn("Failed to cleanup API key", { gameId, error: keyError });
|
|
55247
55235
|
}
|
|
55248
|
-
try {
|
|
55249
|
-
await this.ctx.providers.secrets.deleteSecrets(gameId);
|
|
55250
|
-
logger11.info("Cleaned up secrets for deleted game", { gameId });
|
|
55251
|
-
} catch (secretsError) {
|
|
55252
|
-
logger11.warn("Failed to cleanup secrets", { gameId, error: secretsError });
|
|
55253
|
-
}
|
|
55254
55236
|
}
|
|
55255
55237
|
return {
|
|
55256
55238
|
slug: gameToDelete.slug,
|
|
@@ -56138,1087 +56120,67 @@ var init_level_service = __esm(() => {
|
|
|
56138
56120
|
init_errors();
|
|
56139
56121
|
logger15 = log.scope("LevelService");
|
|
56140
56122
|
});
|
|
56141
|
-
var JwtBaseError;
|
|
56142
|
-
var FailedAssertionError;
|
|
56143
|
-
var JwtParseError;
|
|
56144
|
-
var ParameterValidationError;
|
|
56145
|
-
var JwtInvalidSignatureError;
|
|
56146
|
-
var JwtInvalidSignatureAlgorithmError;
|
|
56147
|
-
var JwtInvalidClaimError;
|
|
56148
|
-
var JwtInvalidIssuerError;
|
|
56149
|
-
var JwtInvalidAudienceError;
|
|
56150
|
-
var JwtInvalidScopeError;
|
|
56151
|
-
var JwtExpiredError;
|
|
56152
|
-
var JwtNotBeforeError;
|
|
56153
|
-
var CognitoJwtInvalidGroupError;
|
|
56154
|
-
var CognitoJwtInvalidTokenUseError;
|
|
56155
|
-
var CognitoJwtInvalidClientIdError;
|
|
56156
|
-
var JwksValidationError;
|
|
56157
|
-
var JwkValidationError;
|
|
56158
|
-
var JwtWithoutValidKidError;
|
|
56159
|
-
var KidNotFoundInJwksError;
|
|
56160
|
-
var WaitPeriodNotYetEndedJwkError;
|
|
56161
|
-
var JwksNotAvailableInCacheError;
|
|
56162
|
-
var JwkInvalidUseError;
|
|
56163
|
-
var JwkInvalidKtyError;
|
|
56164
|
-
var FetchError;
|
|
56165
|
-
var NonRetryableFetchError;
|
|
56166
|
-
var init_error = __esm(() => {
|
|
56167
|
-
JwtBaseError = class JwtBaseError2 extends Error {
|
|
56168
|
-
};
|
|
56169
|
-
FailedAssertionError = class FailedAssertionError2 extends JwtBaseError {
|
|
56170
|
-
constructor(msg, actual, expected) {
|
|
56171
|
-
super(msg);
|
|
56172
|
-
this.failedAssertion = {
|
|
56173
|
-
actual,
|
|
56174
|
-
expected
|
|
56175
|
-
};
|
|
56176
|
-
}
|
|
56177
|
-
};
|
|
56178
|
-
JwtParseError = class JwtParseError2 extends JwtBaseError {
|
|
56179
|
-
constructor(msg, error) {
|
|
56180
|
-
const message = error != null ? `${msg}: ${error}` : msg;
|
|
56181
|
-
super(message);
|
|
56182
|
-
}
|
|
56183
|
-
};
|
|
56184
|
-
ParameterValidationError = class ParameterValidationError2 extends JwtBaseError {
|
|
56185
|
-
};
|
|
56186
|
-
JwtInvalidSignatureError = class JwtInvalidSignatureError2 extends JwtBaseError {
|
|
56187
|
-
};
|
|
56188
|
-
JwtInvalidSignatureAlgorithmError = class JwtInvalidSignatureAlgorithmError2 extends FailedAssertionError {
|
|
56189
|
-
};
|
|
56190
|
-
JwtInvalidClaimError = class JwtInvalidClaimError2 extends FailedAssertionError {
|
|
56191
|
-
withRawJwt({ header, payload }) {
|
|
56192
|
-
this.rawJwt = {
|
|
56193
|
-
header,
|
|
56194
|
-
payload
|
|
56195
|
-
};
|
|
56196
|
-
return this;
|
|
56197
|
-
}
|
|
56198
|
-
};
|
|
56199
|
-
JwtInvalidIssuerError = class JwtInvalidIssuerError2 extends JwtInvalidClaimError {
|
|
56200
|
-
};
|
|
56201
|
-
JwtInvalidAudienceError = class JwtInvalidAudienceError2 extends JwtInvalidClaimError {
|
|
56202
|
-
};
|
|
56203
|
-
JwtInvalidScopeError = class JwtInvalidScopeError2 extends JwtInvalidClaimError {
|
|
56204
|
-
};
|
|
56205
|
-
JwtExpiredError = class JwtExpiredError2 extends JwtInvalidClaimError {
|
|
56206
|
-
};
|
|
56207
|
-
JwtNotBeforeError = class JwtNotBeforeError2 extends JwtInvalidClaimError {
|
|
56208
|
-
};
|
|
56209
|
-
CognitoJwtInvalidGroupError = class CognitoJwtInvalidGroupError2 extends JwtInvalidClaimError {
|
|
56210
|
-
};
|
|
56211
|
-
CognitoJwtInvalidTokenUseError = class CognitoJwtInvalidTokenUseError2 extends JwtInvalidClaimError {
|
|
56212
|
-
};
|
|
56213
|
-
CognitoJwtInvalidClientIdError = class CognitoJwtInvalidClientIdError2 extends JwtInvalidClaimError {
|
|
56214
|
-
};
|
|
56215
|
-
JwksValidationError = class JwksValidationError2 extends JwtBaseError {
|
|
56216
|
-
};
|
|
56217
|
-
JwkValidationError = class JwkValidationError2 extends JwtBaseError {
|
|
56218
|
-
};
|
|
56219
|
-
JwtWithoutValidKidError = class JwtWithoutValidKidError2 extends JwtBaseError {
|
|
56220
|
-
};
|
|
56221
|
-
KidNotFoundInJwksError = class KidNotFoundInJwksError2 extends JwtBaseError {
|
|
56222
|
-
};
|
|
56223
|
-
WaitPeriodNotYetEndedJwkError = class WaitPeriodNotYetEndedJwkError2 extends JwtBaseError {
|
|
56224
|
-
};
|
|
56225
|
-
JwksNotAvailableInCacheError = class JwksNotAvailableInCacheError2 extends JwtBaseError {
|
|
56226
|
-
};
|
|
56227
|
-
JwkInvalidUseError = class JwkInvalidUseError2 extends FailedAssertionError {
|
|
56228
|
-
};
|
|
56229
|
-
JwkInvalidKtyError = class JwkInvalidKtyError2 extends FailedAssertionError {
|
|
56230
|
-
};
|
|
56231
|
-
FetchError = class FetchError2 extends JwtBaseError {
|
|
56232
|
-
constructor(uri, msg) {
|
|
56233
|
-
super(`Failed to fetch ${uri}: ${msg}`);
|
|
56234
|
-
}
|
|
56235
|
-
};
|
|
56236
|
-
NonRetryableFetchError = class NonRetryableFetchError2 extends FetchError {
|
|
56237
|
-
};
|
|
56238
|
-
});
|
|
56239
|
-
async function fetch2(uri, requestOptions, data) {
|
|
56240
|
-
let responseTimeout;
|
|
56241
|
-
return new Promise((resolve2, reject) => {
|
|
56242
|
-
const req = request(uri, {
|
|
56243
|
-
method: "GET",
|
|
56244
|
-
...requestOptions
|
|
56245
|
-
}, (response) => {
|
|
56246
|
-
if (response.statusCode !== 200) {
|
|
56247
|
-
done(new NonRetryableFetchError(uri, `Status code is ${response.statusCode}, expected 200`));
|
|
56248
|
-
return;
|
|
56249
|
-
}
|
|
56250
|
-
pipeline(response, async (responseBody) => {
|
|
56251
|
-
const chunks = [];
|
|
56252
|
-
for await (const chunk of responseBody) {
|
|
56253
|
-
chunks.push(chunk);
|
|
56254
|
-
}
|
|
56255
|
-
return Buffer.concat(chunks);
|
|
56256
|
-
}, done);
|
|
56257
|
-
});
|
|
56258
|
-
if (requestOptions?.responseTimeout) {
|
|
56259
|
-
responseTimeout = setTimeout(() => done(new FetchError(uri, `Response time-out (after ${requestOptions.responseTimeout} ms.)`)), requestOptions.responseTimeout);
|
|
56260
|
-
responseTimeout.unref();
|
|
56261
|
-
}
|
|
56262
|
-
function done(err2, data2) {
|
|
56263
|
-
if (responseTimeout)
|
|
56264
|
-
clearTimeout(responseTimeout);
|
|
56265
|
-
if (err2 == null) {
|
|
56266
|
-
resolve2(data2);
|
|
56267
|
-
return;
|
|
56268
|
-
}
|
|
56269
|
-
req.socket?.emit("agentRemove");
|
|
56270
|
-
if (!(err2 instanceof FetchError)) {
|
|
56271
|
-
err2 = new FetchError(uri, err2.message);
|
|
56272
|
-
}
|
|
56273
|
-
req.destroy();
|
|
56274
|
-
reject(err2);
|
|
56275
|
-
}
|
|
56276
|
-
req.on("error", done);
|
|
56277
|
-
req.end(data);
|
|
56278
|
-
});
|
|
56279
|
-
}
|
|
56280
|
-
var init_https_node = __esm(() => {
|
|
56281
|
-
init_error();
|
|
56282
|
-
});
|
|
56283
|
-
var JwtSignatureAlgorithmHashNames;
|
|
56284
|
-
var nodeWebCompat;
|
|
56285
|
-
var init_node_web_compat_node = __esm(() => {
|
|
56286
|
-
init_https_node();
|
|
56287
|
-
(function(JwtSignatureAlgorithmHashNames2) {
|
|
56288
|
-
JwtSignatureAlgorithmHashNames2["RS256"] = "RSA-SHA256";
|
|
56289
|
-
JwtSignatureAlgorithmHashNames2["RS384"] = "RSA-SHA384";
|
|
56290
|
-
JwtSignatureAlgorithmHashNames2["RS512"] = "RSA-SHA512";
|
|
56291
|
-
JwtSignatureAlgorithmHashNames2["ES256"] = "RSA-SHA256";
|
|
56292
|
-
JwtSignatureAlgorithmHashNames2["ES384"] = "RSA-SHA384";
|
|
56293
|
-
JwtSignatureAlgorithmHashNames2["ES512"] = "RSA-SHA512";
|
|
56294
|
-
})(JwtSignatureAlgorithmHashNames || (JwtSignatureAlgorithmHashNames = {}));
|
|
56295
|
-
nodeWebCompat = {
|
|
56296
|
-
fetch: fetch2,
|
|
56297
|
-
transformJwkToKeyObjectSync: (jwk) => createPublicKey({
|
|
56298
|
-
key: jwk,
|
|
56299
|
-
format: "jwk"
|
|
56300
|
-
}),
|
|
56301
|
-
transformJwkToKeyObjectAsync: async (jwk) => createPublicKey({
|
|
56302
|
-
key: jwk,
|
|
56303
|
-
format: "jwk"
|
|
56304
|
-
}),
|
|
56305
|
-
parseB64UrlString: (b64) => Buffer.from(b64, "base64").toString("utf8"),
|
|
56306
|
-
verifySignatureSync: ({ alg, keyObject, jwsSigningInput, signature }) => alg !== "EdDSA" ? createVerify(JwtSignatureAlgorithmHashNames[alg]).update(jwsSigningInput).verify({
|
|
56307
|
-
key: keyObject,
|
|
56308
|
-
dsaEncoding: "ieee-p1363"
|
|
56309
|
-
}, signature, "base64") : verify(null, Buffer.from(jwsSigningInput), keyObject, Buffer.from(signature, "base64")),
|
|
56310
|
-
verifySignatureAsync: async (args2) => nodeWebCompat.verifySignatureSync(args2),
|
|
56311
|
-
defaultFetchTimeouts: {
|
|
56312
|
-
socketIdle: 1500,
|
|
56313
|
-
response: 3000
|
|
56314
|
-
},
|
|
56315
|
-
setTimeoutUnref: (...args2) => setTimeout(...args2).unref(),
|
|
56316
|
-
transformPemToJwk: async (pem) => {
|
|
56317
|
-
return createPublicKey({
|
|
56318
|
-
key: Buffer.from(pem),
|
|
56319
|
-
format: "pem"
|
|
56320
|
-
}).export({
|
|
56321
|
-
format: "jwk"
|
|
56322
|
-
});
|
|
56323
|
-
}
|
|
56324
|
-
};
|
|
56325
|
-
});
|
|
56326
|
-
|
|
56327
|
-
class SimpleFetcher {
|
|
56328
|
-
constructor(props) {
|
|
56329
|
-
this.defaultRequestOptions = {
|
|
56330
|
-
timeout: nodeWebCompat.defaultFetchTimeouts.socketIdle,
|
|
56331
|
-
responseTimeout: nodeWebCompat.defaultFetchTimeouts.response,
|
|
56332
|
-
...props?.defaultRequestOptions
|
|
56333
|
-
};
|
|
56334
|
-
}
|
|
56335
|
-
async fetch(uri, requestOptions, data) {
|
|
56336
|
-
requestOptions = { ...this.defaultRequestOptions, ...requestOptions };
|
|
56337
|
-
try {
|
|
56338
|
-
return await fetch3(uri, requestOptions, data);
|
|
56339
|
-
} catch (err2) {
|
|
56340
|
-
if (err2 instanceof NonRetryableFetchError) {
|
|
56341
|
-
throw err2;
|
|
56342
|
-
}
|
|
56343
|
-
return fetch3(uri, requestOptions, data);
|
|
56344
|
-
}
|
|
56345
|
-
}
|
|
56346
|
-
}
|
|
56347
|
-
var fetch3;
|
|
56348
|
-
var init_https = __esm(() => {
|
|
56349
|
-
init_error();
|
|
56350
|
-
init_node_web_compat_node();
|
|
56351
|
-
fetch3 = nodeWebCompat.fetch.bind(undefined);
|
|
56352
|
-
});
|
|
56353
|
-
function isJsonObject(j) {
|
|
56354
|
-
return typeof j === "object" && !Array.isArray(j) && j !== null;
|
|
56355
|
-
}
|
|
56356
|
-
function safeJsonParse(s) {
|
|
56357
|
-
return JSON.parse(s, (_2, value) => {
|
|
56358
|
-
if (typeof value === "object" && !Array.isArray(value) && value !== null) {
|
|
56359
|
-
delete value.__proto__;
|
|
56360
|
-
delete value.constructor;
|
|
56361
|
-
}
|
|
56362
|
-
return value;
|
|
56363
|
-
});
|
|
56364
|
-
}
|
|
56365
|
-
function assertStringEquals(name3, actual, expected, errorConstructor = FailedAssertionError) {
|
|
56366
|
-
if (!actual) {
|
|
56367
|
-
throw new errorConstructor(`Missing ${name3}. Expected: ${expected}`, actual, expected);
|
|
56368
|
-
}
|
|
56369
|
-
if (typeof actual !== "string") {
|
|
56370
|
-
throw new errorConstructor(`${name3} is not of type string`, actual, expected);
|
|
56371
|
-
}
|
|
56372
|
-
if (expected !== actual) {
|
|
56373
|
-
throw new errorConstructor(`${name3} not allowed: ${actual}. Expected: ${expected}`, actual, expected);
|
|
56374
|
-
}
|
|
56375
|
-
}
|
|
56376
|
-
function assertStringArrayContainsString(name3, actual, expected, errorConstructor = FailedAssertionError) {
|
|
56377
|
-
if (!actual) {
|
|
56378
|
-
throw new errorConstructor(`Missing ${name3}. ${expectationMessage(expected)}`, actual, expected);
|
|
56379
|
-
}
|
|
56380
|
-
if (typeof actual !== "string") {
|
|
56381
|
-
throw new errorConstructor(`${name3} is not of type string`, actual, expected);
|
|
56382
|
-
}
|
|
56383
|
-
return assertStringArraysOverlap(name3, actual, expected, errorConstructor);
|
|
56384
|
-
}
|
|
56385
|
-
function assertStringArraysOverlap(name3, actual, expected, errorConstructor = FailedAssertionError) {
|
|
56386
|
-
if (!actual) {
|
|
56387
|
-
throw new errorConstructor(`Missing ${name3}. ${expectationMessage(expected)}`, actual, expected);
|
|
56388
|
-
}
|
|
56389
|
-
const expectedAsSet = new Set(Array.isArray(expected) ? expected : [expected]);
|
|
56390
|
-
if (typeof actual === "string") {
|
|
56391
|
-
actual = [actual];
|
|
56392
|
-
}
|
|
56393
|
-
if (!Array.isArray(actual)) {
|
|
56394
|
-
throw new errorConstructor(`${name3} is not an array`, actual, expected);
|
|
56395
|
-
}
|
|
56396
|
-
const overlaps = actual.some((actualItem) => {
|
|
56397
|
-
if (typeof actualItem !== "string") {
|
|
56398
|
-
throw new errorConstructor(`${name3} includes elements that are not of type string`, actual, expected);
|
|
56399
|
-
}
|
|
56400
|
-
return expectedAsSet.has(actualItem);
|
|
56401
|
-
});
|
|
56402
|
-
if (!overlaps) {
|
|
56403
|
-
throw new errorConstructor(`${name3} not allowed: ${actual.join(", ")}. ${expectationMessage(expected)}`, actual, expected);
|
|
56404
|
-
}
|
|
56405
|
-
}
|
|
56406
|
-
function expectationMessage(expected) {
|
|
56407
|
-
if (Array.isArray(expected)) {
|
|
56408
|
-
if (expected.length > 1) {
|
|
56409
|
-
return `Expected one of: ${expected.join(", ")}`;
|
|
56410
|
-
}
|
|
56411
|
-
return `Expected: ${expected[0]}`;
|
|
56412
|
-
}
|
|
56413
|
-
return `Expected: ${expected}`;
|
|
56414
|
-
}
|
|
56415
|
-
function assertIsNotPromise(actual, errorFactory) {
|
|
56416
|
-
if (actual && typeof actual.then === "function") {
|
|
56417
|
-
throw errorFactory();
|
|
56418
|
-
}
|
|
56419
|
-
}
|
|
56420
|
-
var init_assert = __esm(() => {
|
|
56421
|
-
init_error();
|
|
56422
|
-
});
|
|
56423
|
-
function findJwkInJwks(jwks, kid) {
|
|
56424
|
-
return jwks.keys.find((jwk) => jwk.kid != null && jwk.kid === kid);
|
|
56425
|
-
}
|
|
56426
|
-
function assertIsJwks(jwks) {
|
|
56427
|
-
if (!jwks) {
|
|
56428
|
-
throw new JwksValidationError("JWKS empty");
|
|
56429
|
-
}
|
|
56430
|
-
if (!isJsonObject(jwks)) {
|
|
56431
|
-
throw new JwksValidationError("JWKS should be an object");
|
|
56432
|
-
}
|
|
56433
|
-
if (!Object.keys(jwks).includes("keys")) {
|
|
56434
|
-
throw new JwksValidationError("JWKS does not include keys");
|
|
56435
|
-
}
|
|
56436
|
-
if (!Array.isArray(jwks.keys)) {
|
|
56437
|
-
throw new JwksValidationError("JWKS keys should be an array");
|
|
56438
|
-
}
|
|
56439
|
-
for (const jwk of jwks.keys) {
|
|
56440
|
-
assertIsJwk(jwk);
|
|
56441
|
-
}
|
|
56442
|
-
}
|
|
56443
|
-
function assertIsSignatureJwk(jwk) {
|
|
56444
|
-
assertStringArrayContainsString("JWK kty", jwk.kty, ["EC", "RSA", "OKP"], JwkInvalidKtyError);
|
|
56445
|
-
if (jwk.kty === "EC") {
|
|
56446
|
-
assertIsEsSignatureJwk(jwk);
|
|
56447
|
-
} else if (jwk.kty === "RSA") {
|
|
56448
|
-
assertIsRsaSignatureJwk(jwk);
|
|
56449
|
-
} else if (jwk.kty === "OKP") {
|
|
56450
|
-
assertIsEdDSASignatureJwk(jwk);
|
|
56451
|
-
}
|
|
56452
|
-
}
|
|
56453
|
-
function assertIsEdDSASignatureJwk(jwk) {
|
|
56454
|
-
if (jwk.use) {
|
|
56455
|
-
assertStringEquals("JWK use", jwk.use, "sig", JwkInvalidUseError);
|
|
56456
|
-
}
|
|
56457
|
-
assertStringEquals("JWK kty", jwk.kty, "OKP", JwkInvalidKtyError);
|
|
56458
|
-
if (!jwk.crv)
|
|
56459
|
-
throw new JwkValidationError("Missing Curve (crv)");
|
|
56460
|
-
if (!jwk.x)
|
|
56461
|
-
throw new JwkValidationError("Missing X Coordinate (x)");
|
|
56462
|
-
}
|
|
56463
|
-
function assertIsEsSignatureJwk(jwk) {
|
|
56464
|
-
if (jwk.use) {
|
|
56465
|
-
assertStringEquals("JWK use", jwk.use, "sig", JwkInvalidUseError);
|
|
56466
|
-
}
|
|
56467
|
-
assertStringEquals("JWK kty", jwk.kty, "EC", JwkInvalidKtyError);
|
|
56468
|
-
if (!jwk.crv)
|
|
56469
|
-
throw new JwkValidationError("Missing Curve (crv)");
|
|
56470
|
-
if (!jwk.x)
|
|
56471
|
-
throw new JwkValidationError("Missing X Coordinate (x)");
|
|
56472
|
-
if (!jwk.y)
|
|
56473
|
-
throw new JwkValidationError("Missing Y Coordinate (y)");
|
|
56474
|
-
}
|
|
56475
|
-
function assertIsRsaSignatureJwk(jwk) {
|
|
56476
|
-
if (jwk.use) {
|
|
56477
|
-
assertStringEquals("JWK use", jwk.use, "sig", JwkInvalidUseError);
|
|
56478
|
-
}
|
|
56479
|
-
assertStringEquals("JWK kty", jwk.kty, "RSA", JwkInvalidKtyError);
|
|
56480
|
-
if (!jwk.n)
|
|
56481
|
-
throw new JwkValidationError("Missing modulus (n)");
|
|
56482
|
-
if (!jwk.e)
|
|
56483
|
-
throw new JwkValidationError("Missing exponent (e)");
|
|
56484
|
-
}
|
|
56485
|
-
function assertIsJwk(jwk) {
|
|
56486
|
-
if (!jwk) {
|
|
56487
|
-
throw new JwkValidationError("JWK empty");
|
|
56488
|
-
}
|
|
56489
|
-
if (!isJsonObject(jwk)) {
|
|
56490
|
-
throw new JwkValidationError("JWK should be an object");
|
|
56491
|
-
}
|
|
56492
|
-
for (const field of mandatoryJwkFieldNames) {
|
|
56493
|
-
if (typeof jwk[field] !== "string") {
|
|
56494
|
-
throw new JwkValidationError(`JWK ${field} should be a string`);
|
|
56495
|
-
}
|
|
56496
|
-
}
|
|
56497
|
-
for (const field of optionalJwkFieldNames) {
|
|
56498
|
-
if (field in jwk && typeof jwk[field] !== "string") {
|
|
56499
|
-
throw new JwkValidationError(`JWK ${field} should be a string`);
|
|
56500
|
-
}
|
|
56501
|
-
}
|
|
56502
|
-
}
|
|
56503
|
-
function isJwks(jwks) {
|
|
56504
|
-
try {
|
|
56505
|
-
assertIsJwks(jwks);
|
|
56506
|
-
return true;
|
|
56507
|
-
} catch {
|
|
56508
|
-
return false;
|
|
56509
|
-
}
|
|
56510
|
-
}
|
|
56511
|
-
function isJwk(jwk) {
|
|
56512
|
-
try {
|
|
56513
|
-
assertIsJwk(jwk);
|
|
56514
|
-
return true;
|
|
56515
|
-
} catch {
|
|
56516
|
-
return false;
|
|
56517
|
-
}
|
|
56518
|
-
}
|
|
56519
|
-
|
|
56520
|
-
class SimplePenaltyBox {
|
|
56521
|
-
constructor(props) {
|
|
56522
|
-
this.waitingUris = new Map;
|
|
56523
|
-
this.waitSeconds = props?.waitSeconds ?? 10;
|
|
56524
|
-
}
|
|
56525
|
-
async wait(jwksUri) {
|
|
56526
|
-
if (this.waitingUris.has(jwksUri)) {
|
|
56527
|
-
throw new WaitPeriodNotYetEndedJwkError("Not allowed to fetch JWKS yet, still waiting for back off period to end");
|
|
56528
|
-
}
|
|
56529
|
-
}
|
|
56530
|
-
release(jwksUri) {
|
|
56531
|
-
const i2 = this.waitingUris.get(jwksUri);
|
|
56532
|
-
if (i2) {
|
|
56533
|
-
clearTimeout(i2);
|
|
56534
|
-
this.waitingUris.delete(jwksUri);
|
|
56535
|
-
}
|
|
56536
|
-
}
|
|
56537
|
-
registerFailedAttempt(jwksUri) {
|
|
56538
|
-
const i2 = nodeWebCompat.setTimeoutUnref(() => {
|
|
56539
|
-
this.waitingUris.delete(jwksUri);
|
|
56540
|
-
}, this.waitSeconds * 1000);
|
|
56541
|
-
this.waitingUris.set(jwksUri, i2);
|
|
56542
|
-
}
|
|
56543
|
-
registerSuccessfulAttempt(jwksUri) {
|
|
56544
|
-
this.release(jwksUri);
|
|
56545
|
-
}
|
|
56546
|
-
}
|
|
56547
56123
|
|
|
56548
|
-
class
|
|
56549
|
-
|
|
56550
|
-
|
|
56551
|
-
this.
|
|
56552
|
-
this.penaltyBox = props?.penaltyBox ?? new SimplePenaltyBox;
|
|
56553
|
-
this.fetcher = props?.fetcher ?? new SimpleFetcher;
|
|
56554
|
-
this.jwksParser = props?.jwksParser ?? parseJwks;
|
|
56555
|
-
}
|
|
56556
|
-
addJwks(jwksUri, jwks) {
|
|
56557
|
-
this.jwksCache.set(jwksUri, jwks);
|
|
56558
|
-
}
|
|
56559
|
-
async getJwks(jwksUri) {
|
|
56560
|
-
const existingFetch = this.fetchingJwks.get(jwksUri);
|
|
56561
|
-
if (existingFetch) {
|
|
56562
|
-
return existingFetch;
|
|
56563
|
-
}
|
|
56564
|
-
const jwksPromise = this.fetcher.fetch(jwksUri).then(this.jwksParser);
|
|
56565
|
-
this.fetchingJwks.set(jwksUri, jwksPromise);
|
|
56566
|
-
let jwks;
|
|
56567
|
-
try {
|
|
56568
|
-
jwks = await jwksPromise;
|
|
56569
|
-
} finally {
|
|
56570
|
-
this.fetchingJwks.delete(jwksUri);
|
|
56571
|
-
}
|
|
56572
|
-
this.jwksCache.set(jwksUri, jwks);
|
|
56573
|
-
return jwks;
|
|
56574
|
-
}
|
|
56575
|
-
getCachedJwk(jwksUri, decomposedJwt) {
|
|
56576
|
-
if (typeof decomposedJwt.header.kid !== "string") {
|
|
56577
|
-
throw new JwtWithoutValidKidError("JWT header does not have valid kid claim");
|
|
56578
|
-
}
|
|
56579
|
-
if (!this.jwksCache.has(jwksUri)) {
|
|
56580
|
-
throw new JwksNotAvailableInCacheError(`JWKS for uri ${jwksUri} not yet available in cache`);
|
|
56581
|
-
}
|
|
56582
|
-
const jwk = findJwkInJwks(this.jwksCache.get(jwksUri), decomposedJwt.header.kid);
|
|
56583
|
-
if (!jwk) {
|
|
56584
|
-
throw new KidNotFoundInJwksError(`JWK for kid ${decomposedJwt.header.kid} not found in the JWKS`);
|
|
56585
|
-
}
|
|
56586
|
-
return jwk;
|
|
56587
|
-
}
|
|
56588
|
-
async getJwk(jwksUri, decomposedJwt) {
|
|
56589
|
-
if (typeof decomposedJwt.header.kid !== "string") {
|
|
56590
|
-
throw new JwtWithoutValidKidError("JWT header does not have valid kid claim");
|
|
56591
|
-
}
|
|
56592
|
-
const cachedJwks = this.jwksCache.get(jwksUri);
|
|
56593
|
-
if (cachedJwks) {
|
|
56594
|
-
const cachedJwk = findJwkInJwks(cachedJwks, decomposedJwt.header.kid);
|
|
56595
|
-
if (cachedJwk) {
|
|
56596
|
-
return cachedJwk;
|
|
56597
|
-
}
|
|
56598
|
-
}
|
|
56599
|
-
await this.penaltyBox.wait(jwksUri, decomposedJwt.header.kid);
|
|
56600
|
-
const jwks = await this.getJwks(jwksUri);
|
|
56601
|
-
const jwk = findJwkInJwks(jwks, decomposedJwt.header.kid);
|
|
56602
|
-
if (!jwk) {
|
|
56603
|
-
this.penaltyBox.registerFailedAttempt(jwksUri, decomposedJwt.header.kid);
|
|
56604
|
-
throw new KidNotFoundInJwksError(`JWK for kid "${decomposedJwt.header.kid}" not found in the JWKS`);
|
|
56605
|
-
} else {
|
|
56606
|
-
this.penaltyBox.registerSuccessfulAttempt(jwksUri, decomposedJwt.header.kid);
|
|
56607
|
-
}
|
|
56608
|
-
return jwk;
|
|
56609
|
-
}
|
|
56610
|
-
}
|
|
56611
|
-
var optionalJwkFieldNames;
|
|
56612
|
-
var mandatoryJwkFieldNames;
|
|
56613
|
-
var parseJwks = function(jwksBin) {
|
|
56614
|
-
let jwks;
|
|
56615
|
-
try {
|
|
56616
|
-
const jwksText = new TextDecoder("utf8", {
|
|
56617
|
-
fatal: true,
|
|
56618
|
-
ignoreBOM: true
|
|
56619
|
-
}).decode(jwksBin);
|
|
56620
|
-
jwks = safeJsonParse(jwksText);
|
|
56621
|
-
} catch (err2) {
|
|
56622
|
-
throw new JwksValidationError(`JWKS could not be parsed as JSON: ${err2}`);
|
|
56623
|
-
}
|
|
56624
|
-
assertIsJwks(jwks);
|
|
56625
|
-
return jwks;
|
|
56626
|
-
};
|
|
56627
|
-
var init_jwk = __esm(() => {
|
|
56628
|
-
init_https();
|
|
56629
|
-
init_error();
|
|
56630
|
-
init_node_web_compat_node();
|
|
56631
|
-
init_assert();
|
|
56632
|
-
optionalJwkFieldNames = [
|
|
56633
|
-
"use",
|
|
56634
|
-
"alg",
|
|
56635
|
-
"kid",
|
|
56636
|
-
"n",
|
|
56637
|
-
"e",
|
|
56638
|
-
"x",
|
|
56639
|
-
"y",
|
|
56640
|
-
"crv"
|
|
56641
|
-
];
|
|
56642
|
-
mandatoryJwkFieldNames = [
|
|
56643
|
-
"kty"
|
|
56644
|
-
];
|
|
56645
|
-
});
|
|
56646
|
-
function assertJwtHeader(header) {
|
|
56647
|
-
if (!isJsonObject(header)) {
|
|
56648
|
-
throw new JwtParseError("JWT header is not an object");
|
|
56649
|
-
}
|
|
56650
|
-
if (header.alg !== undefined && typeof header.alg !== "string") {
|
|
56651
|
-
throw new JwtParseError("JWT header alg claim is not a string");
|
|
56652
|
-
}
|
|
56653
|
-
if (header.kid !== undefined && typeof header.kid !== "string") {
|
|
56654
|
-
throw new JwtParseError("JWT header kid claim is not a string");
|
|
56655
|
-
}
|
|
56656
|
-
}
|
|
56657
|
-
function assertJwtPayload(payload) {
|
|
56658
|
-
if (!isJsonObject(payload)) {
|
|
56659
|
-
throw new JwtParseError("JWT payload is not an object");
|
|
56660
|
-
}
|
|
56661
|
-
if (payload.exp !== undefined && !Number.isFinite(payload.exp)) {
|
|
56662
|
-
throw new JwtParseError("JWT payload exp claim is not a number");
|
|
56663
|
-
}
|
|
56664
|
-
if (payload.iss !== undefined && typeof payload.iss !== "string") {
|
|
56665
|
-
throw new JwtParseError("JWT payload iss claim is not a string");
|
|
56666
|
-
}
|
|
56667
|
-
if (payload.sub !== undefined && typeof payload.sub !== "string") {
|
|
56668
|
-
throw new JwtParseError("JWT payload sub claim is not a string");
|
|
56669
|
-
}
|
|
56670
|
-
if (payload.aud !== undefined && typeof payload.aud !== "string" && (!Array.isArray(payload.aud) || payload.aud.some((aud) => typeof aud !== "string"))) {
|
|
56671
|
-
throw new JwtParseError("JWT payload aud claim is not a string or array of strings");
|
|
56672
|
-
}
|
|
56673
|
-
if (payload.nbf !== undefined && !Number.isFinite(payload.nbf)) {
|
|
56674
|
-
throw new JwtParseError("JWT payload nbf claim is not a number");
|
|
56675
|
-
}
|
|
56676
|
-
if (payload.iat !== undefined && !Number.isFinite(payload.iat)) {
|
|
56677
|
-
throw new JwtParseError("JWT payload iat claim is not a number");
|
|
56678
|
-
}
|
|
56679
|
-
if (payload.scope !== undefined && typeof payload.scope !== "string") {
|
|
56680
|
-
throw new JwtParseError("JWT payload scope claim is not a string");
|
|
56681
|
-
}
|
|
56682
|
-
if (payload.jti !== undefined && typeof payload.jti !== "string") {
|
|
56683
|
-
throw new JwtParseError("JWT payload jti claim is not a string");
|
|
56684
|
-
}
|
|
56685
|
-
}
|
|
56686
|
-
function decomposeUnverifiedJwt(jwt) {
|
|
56687
|
-
if (!jwt) {
|
|
56688
|
-
throw new JwtParseError("Empty JWT");
|
|
56689
|
-
}
|
|
56690
|
-
if (typeof jwt !== "string") {
|
|
56691
|
-
throw new JwtParseError("JWT is not a string");
|
|
56692
|
-
}
|
|
56693
|
-
if (!JWT_REGEX.test(jwt)) {
|
|
56694
|
-
throw new JwtParseError("JWT string does not consist of exactly 3 parts (header, payload, signature)");
|
|
56695
|
-
}
|
|
56696
|
-
const [headerB64, payloadB64, signatureB64] = jwt.split(".");
|
|
56697
|
-
const [headerString, payloadString] = [headerB64, payloadB64].map(nodeWebCompat.parseB64UrlString);
|
|
56698
|
-
let header;
|
|
56699
|
-
try {
|
|
56700
|
-
header = safeJsonParse(headerString);
|
|
56701
|
-
} catch (err2) {
|
|
56702
|
-
throw new JwtParseError("Invalid JWT. Header is not a valid JSON object", err2);
|
|
56703
|
-
}
|
|
56704
|
-
assertJwtHeader(header);
|
|
56705
|
-
let payload;
|
|
56706
|
-
try {
|
|
56707
|
-
payload = safeJsonParse(payloadString);
|
|
56708
|
-
} catch (err2) {
|
|
56709
|
-
throw new JwtParseError("Invalid JWT. Payload is not a valid JSON object", err2);
|
|
56710
|
-
}
|
|
56711
|
-
assertJwtPayload(payload);
|
|
56712
|
-
return {
|
|
56713
|
-
header,
|
|
56714
|
-
headerB64,
|
|
56715
|
-
payload,
|
|
56716
|
-
payloadB64,
|
|
56717
|
-
signatureB64
|
|
56718
|
-
};
|
|
56719
|
-
}
|
|
56720
|
-
function validateJwtFields(payload, options) {
|
|
56721
|
-
if (payload.exp !== undefined) {
|
|
56722
|
-
if (payload.exp + (options.graceSeconds ?? 0) < Date.now() / 1000) {
|
|
56723
|
-
throw new JwtExpiredError(`Token expired at ${new Date(payload.exp * 1000).toISOString()}`, payload.exp);
|
|
56724
|
-
}
|
|
56725
|
-
}
|
|
56726
|
-
if (payload.nbf !== undefined) {
|
|
56727
|
-
if (payload.nbf - (options.graceSeconds ?? 0) > Date.now() / 1000) {
|
|
56728
|
-
throw new JwtNotBeforeError(`Token can't be used before ${new Date(payload.nbf * 1000).toISOString()}`, payload.nbf);
|
|
56729
|
-
}
|
|
56730
|
-
}
|
|
56731
|
-
if (options.issuer !== null) {
|
|
56732
|
-
if (options.issuer === undefined) {
|
|
56733
|
-
throw new ParameterValidationError("issuer must be provided or set to null explicitly");
|
|
56734
|
-
}
|
|
56735
|
-
assertStringArrayContainsString("Issuer", payload.iss, options.issuer, JwtInvalidIssuerError);
|
|
56736
|
-
}
|
|
56737
|
-
if (options.audience !== null) {
|
|
56738
|
-
if (options.audience === undefined) {
|
|
56739
|
-
throw new ParameterValidationError("audience must be provided or set to null explicitly");
|
|
56740
|
-
}
|
|
56741
|
-
assertStringArraysOverlap("Audience", payload.aud, options.audience, JwtInvalidAudienceError);
|
|
56742
|
-
}
|
|
56743
|
-
if (options.scope != null) {
|
|
56744
|
-
assertStringArraysOverlap("Scope", payload.scope?.split(" "), options.scope, JwtInvalidScopeError);
|
|
56745
|
-
}
|
|
56746
|
-
}
|
|
56747
|
-
var JWT_REGEX;
|
|
56748
|
-
var init_jwt = __esm(() => {
|
|
56749
|
-
init_assert();
|
|
56750
|
-
init_error();
|
|
56751
|
-
init_node_web_compat_node();
|
|
56752
|
-
JWT_REGEX = /^[A-Za-z0-9_-]+={0,2}\.[A-Za-z0-9_-]+={0,2}\.[A-Za-z0-9_-]+={0,2}$/;
|
|
56753
|
-
});
|
|
56754
|
-
function validateJwtHeaderAndJwk(header, jwk) {
|
|
56755
|
-
assertIsSignatureJwk(jwk);
|
|
56756
|
-
if (jwk.alg) {
|
|
56757
|
-
assertStringEquals("JWT signature algorithm", header.alg, jwk.alg, JwtInvalidSignatureAlgorithmError);
|
|
56758
|
-
}
|
|
56759
|
-
assertStringArrayContainsString("JWT signature algorithm", header.alg, supportedSignatureAlgorithms, JwtInvalidSignatureAlgorithmError);
|
|
56760
|
-
}
|
|
56761
|
-
async function verifyDecomposedJwt(decomposedJwt, jwksUri, options, jwkFetcher, transformJwkToKeyObjectFn) {
|
|
56762
|
-
const { header, headerB64, payload, payloadB64, signatureB64 } = decomposedJwt;
|
|
56763
|
-
const jwk = await jwkFetcher(jwksUri, decomposedJwt);
|
|
56764
|
-
validateJwtHeaderAndJwk(decomposedJwt.header, jwk);
|
|
56765
|
-
const keyObject = await transformJwkToKeyObjectFn(jwk, header.alg, payload.iss);
|
|
56766
|
-
const valid = await nodeWebCompat.verifySignatureAsync({
|
|
56767
|
-
jwsSigningInput: `${headerB64}.${payloadB64}`,
|
|
56768
|
-
signature: signatureB64,
|
|
56769
|
-
alg: header.alg,
|
|
56770
|
-
keyObject
|
|
56771
|
-
});
|
|
56772
|
-
if (!valid) {
|
|
56773
|
-
throw new JwtInvalidSignatureError("Invalid signature");
|
|
56774
|
-
}
|
|
56775
|
-
try {
|
|
56776
|
-
validateJwtFields(payload, options);
|
|
56777
|
-
if (options.customJwtCheck) {
|
|
56778
|
-
await options.customJwtCheck({ header, payload, jwk });
|
|
56779
|
-
}
|
|
56780
|
-
} catch (err2) {
|
|
56781
|
-
if (options.includeRawJwtInErrors && err2 instanceof JwtInvalidClaimError) {
|
|
56782
|
-
throw err2.withRawJwt(decomposedJwt);
|
|
56783
|
-
}
|
|
56784
|
-
throw err2;
|
|
56785
|
-
}
|
|
56786
|
-
return payload;
|
|
56787
|
-
}
|
|
56788
|
-
function verifyDecomposedJwtSync(decomposedJwt, jwkOrJwks, options, transformJwkToKeyObjectFn) {
|
|
56789
|
-
const { header, headerB64, payload, payloadB64, signatureB64 } = decomposedJwt;
|
|
56790
|
-
let jwk;
|
|
56791
|
-
if (isJwk(jwkOrJwks)) {
|
|
56792
|
-
jwk = jwkOrJwks;
|
|
56793
|
-
} else if (isJwks(jwkOrJwks)) {
|
|
56794
|
-
const locatedJwk = header.kid ? findJwkInJwks(jwkOrJwks, header.kid) : undefined;
|
|
56795
|
-
if (!locatedJwk) {
|
|
56796
|
-
throw new KidNotFoundInJwksError(`JWK for kid ${header.kid} not found in the JWKS`);
|
|
56797
|
-
}
|
|
56798
|
-
jwk = locatedJwk;
|
|
56799
|
-
} else {
|
|
56800
|
-
throw new ParameterValidationError([
|
|
56801
|
-
`Expected a valid JWK or JWKS (parsed as JavaScript object), but received: ${jwkOrJwks}.`,
|
|
56802
|
-
"If you're passing a JWKS URI, use the async verify() method instead, it will download and parse the JWKS for you"
|
|
56803
|
-
].join());
|
|
56804
|
-
}
|
|
56805
|
-
validateJwtHeaderAndJwk(decomposedJwt.header, jwk);
|
|
56806
|
-
const keyObject = transformJwkToKeyObjectFn(jwk, header.alg, payload.iss);
|
|
56807
|
-
const valid = nodeWebCompat.verifySignatureSync({
|
|
56808
|
-
jwsSigningInput: `${headerB64}.${payloadB64}`,
|
|
56809
|
-
signature: signatureB64,
|
|
56810
|
-
alg: header.alg,
|
|
56811
|
-
keyObject
|
|
56812
|
-
});
|
|
56813
|
-
if (!valid) {
|
|
56814
|
-
throw new JwtInvalidSignatureError("Invalid signature");
|
|
56815
|
-
}
|
|
56816
|
-
try {
|
|
56817
|
-
validateJwtFields(payload, options);
|
|
56818
|
-
if (options.customJwtCheck) {
|
|
56819
|
-
const res = options.customJwtCheck({ header, payload, jwk });
|
|
56820
|
-
assertIsNotPromise(res, () => new ParameterValidationError("Custom JWT checks must be synchronous but a promise was returned"));
|
|
56821
|
-
}
|
|
56822
|
-
} catch (err2) {
|
|
56823
|
-
if (options.includeRawJwtInErrors && err2 instanceof JwtInvalidClaimError) {
|
|
56824
|
-
throw err2.withRawJwt(decomposedJwt);
|
|
56825
|
-
}
|
|
56826
|
-
throw err2;
|
|
56124
|
+
class LogsService {
|
|
56125
|
+
ctx;
|
|
56126
|
+
constructor(ctx) {
|
|
56127
|
+
this.ctx = ctx;
|
|
56827
56128
|
}
|
|
56828
|
-
|
|
56829
|
-
|
|
56830
|
-
|
|
56831
|
-
|
|
56832
|
-
|
|
56833
|
-
|
|
56834
|
-
this.issuersConfig = new Map;
|
|
56835
|
-
this.publicKeyCache = new KeyObjectCache;
|
|
56836
|
-
if (Array.isArray(verifyProperties)) {
|
|
56837
|
-
if (!verifyProperties.length) {
|
|
56838
|
-
throw new ParameterValidationError("Provide at least one issuer configuration");
|
|
56839
|
-
}
|
|
56840
|
-
verifyProperties.forEach((prop, index2) => {
|
|
56841
|
-
if (this.issuersConfig.has(prop.issuer)) {
|
|
56842
|
-
throw new ParameterValidationError(`issuer ${prop.issuer} supplied multiple times`);
|
|
56843
|
-
} else if (prop.issuer === null && verifyProperties.length >= 2) {
|
|
56844
|
-
throw new ParameterValidationError(`issuer cannot be null when multiple issuers are supplied (at issuer: ${index2})`);
|
|
56845
|
-
}
|
|
56846
|
-
this.issuersConfig.set(prop.issuer, this.withJwksUri(prop));
|
|
56129
|
+
async generateToken(user, slug2, environment) {
|
|
56130
|
+
const db2 = this.ctx.db;
|
|
56131
|
+
if (user.role === "admin") {
|
|
56132
|
+
const game = await db2.query.games.findFirst({
|
|
56133
|
+
where: eq(games.slug, slug2),
|
|
56134
|
+
columns: { id: true }
|
|
56847
56135
|
});
|
|
56848
|
-
|
|
56849
|
-
|
|
56850
|
-
}
|
|
56851
|
-
}
|
|
56852
|
-
getIssuerConfig(issuer) {
|
|
56853
|
-
if (this.issuersConfig.size === 1) {
|
|
56854
|
-
issuer = this.issuersConfig.keys().next().value;
|
|
56855
|
-
}
|
|
56856
|
-
if (issuer === undefined) {
|
|
56857
|
-
throw new ParameterValidationError("issuer must be provided");
|
|
56858
|
-
}
|
|
56859
|
-
const config2 = this.issuersConfig.get(issuer);
|
|
56860
|
-
if (!config2) {
|
|
56861
|
-
throw new ParameterValidationError(`issuer not configured: ${issuer}`);
|
|
56862
|
-
}
|
|
56863
|
-
return config2;
|
|
56864
|
-
}
|
|
56865
|
-
cacheJwks(...[jwks, issuer]) {
|
|
56866
|
-
const issuerConfig = this.getIssuerConfig(issuer);
|
|
56867
|
-
this.jwksCache.addJwks(issuerConfig.jwksUri, jwks);
|
|
56868
|
-
this.publicKeyCache.clearCache(issuerConfig.issuer);
|
|
56869
|
-
}
|
|
56870
|
-
async hydrate() {
|
|
56871
|
-
const jwksFetches = Array.from(this.issuersConfig.values()).map(({ jwksUri }) => this.jwksCache.getJwks(jwksUri));
|
|
56872
|
-
await Promise.all(jwksFetches);
|
|
56873
|
-
}
|
|
56874
|
-
verifySync(...[jwt, properties]) {
|
|
56875
|
-
const { decomposedJwt, jwksUri, verifyProperties } = this.getVerifyParameters(jwt, properties);
|
|
56876
|
-
return this.verifyDecomposedJwtSync(decomposedJwt, jwksUri, verifyProperties);
|
|
56877
|
-
}
|
|
56878
|
-
verifyDecomposedJwtSync(decomposedJwt, jwksUri, verifyProperties) {
|
|
56879
|
-
const jwk = this.jwksCache.getCachedJwk(jwksUri, decomposedJwt);
|
|
56880
|
-
return verifyDecomposedJwtSync(decomposedJwt, jwk, verifyProperties, this.publicKeyCache.transformJwkToKeyObjectSync.bind(this.publicKeyCache));
|
|
56881
|
-
}
|
|
56882
|
-
async verify(...[jwt, properties]) {
|
|
56883
|
-
const { decomposedJwt, jwksUri, verifyProperties } = this.getVerifyParameters(jwt, properties);
|
|
56884
|
-
return this.verifyDecomposedJwt(decomposedJwt, jwksUri, verifyProperties);
|
|
56885
|
-
}
|
|
56886
|
-
verifyDecomposedJwt(decomposedJwt, jwksUri, verifyProperties) {
|
|
56887
|
-
return verifyDecomposedJwt(decomposedJwt, jwksUri, verifyProperties, this.jwksCache.getJwk.bind(this.jwksCache), this.publicKeyCache.transformJwkToKeyObjectAsync.bind(this.publicKeyCache));
|
|
56888
|
-
}
|
|
56889
|
-
getVerifyParameters(jwt, verifyProperties) {
|
|
56890
|
-
const decomposedJwt = decomposeUnverifiedJwt(jwt);
|
|
56891
|
-
const issuerConfig = this.getIssuerConfig(decomposedJwt.payload.iss);
|
|
56892
|
-
return {
|
|
56893
|
-
decomposedJwt,
|
|
56894
|
-
jwksUri: issuerConfig.jwksUri,
|
|
56895
|
-
verifyProperties: {
|
|
56896
|
-
...issuerConfig,
|
|
56897
|
-
...verifyProperties
|
|
56136
|
+
if (!game) {
|
|
56137
|
+
throw new NotFoundError("Game", slug2);
|
|
56898
56138
|
}
|
|
56899
|
-
|
|
56900
|
-
}
|
|
56901
|
-
withJwksUri(config2) {
|
|
56902
|
-
if (config2.jwksUri) {
|
|
56903
|
-
return config2;
|
|
56904
|
-
}
|
|
56905
|
-
const issuer = config2.issuer;
|
|
56906
|
-
if (!issuer) {
|
|
56907
|
-
throw new ParameterValidationError("jwksUri must be provided for issuer null");
|
|
56908
|
-
}
|
|
56909
|
-
const issuerUri = new URL(issuer).pathname.replace(/\/$/, "");
|
|
56910
|
-
return {
|
|
56911
|
-
jwksUri: new URL(`${issuerUri}/.well-known/jwks.json`, issuer).href,
|
|
56912
|
-
...config2
|
|
56913
|
-
};
|
|
56914
|
-
}
|
|
56915
|
-
}
|
|
56916
|
-
|
|
56917
|
-
class KeyObjectCache {
|
|
56918
|
-
constructor(transformJwkToKeyObjectSyncFn = nodeWebCompat.transformJwkToKeyObjectSync, transformJwkToKeyObjectAsyncFn = nodeWebCompat.transformJwkToKeyObjectAsync) {
|
|
56919
|
-
this.transformJwkToKeyObjectSyncFn = transformJwkToKeyObjectSyncFn;
|
|
56920
|
-
this.transformJwkToKeyObjectAsyncFn = transformJwkToKeyObjectAsyncFn;
|
|
56921
|
-
this.publicKeys = new Map;
|
|
56922
|
-
}
|
|
56923
|
-
transformJwkToKeyObjectSync(jwk, jwtHeaderAlg, issuer) {
|
|
56924
|
-
const alg = jwk.alg ?? jwtHeaderAlg;
|
|
56925
|
-
if (!issuer || !jwk.kid || !alg) {
|
|
56926
|
-
return this.transformJwkToKeyObjectSyncFn(jwk, alg, issuer);
|
|
56927
|
-
}
|
|
56928
|
-
const fromCache = this.publicKeys.get(issuer)?.get(jwk.kid)?.get(alg);
|
|
56929
|
-
if (fromCache)
|
|
56930
|
-
return fromCache;
|
|
56931
|
-
const publicKey = this.transformJwkToKeyObjectSyncFn(jwk, alg, issuer);
|
|
56932
|
-
this.putKeyObjectInCache(issuer, jwk.kid, alg, publicKey);
|
|
56933
|
-
return publicKey;
|
|
56934
|
-
}
|
|
56935
|
-
async transformJwkToKeyObjectAsync(jwk, jwtHeaderAlg, issuer) {
|
|
56936
|
-
const alg = jwk.alg ?? jwtHeaderAlg;
|
|
56937
|
-
if (!issuer || !jwk.kid || !alg) {
|
|
56938
|
-
return this.transformJwkToKeyObjectAsyncFn(jwk, alg, issuer);
|
|
56939
|
-
}
|
|
56940
|
-
const fromCache = this.publicKeys.get(issuer)?.get(jwk.kid)?.get(alg);
|
|
56941
|
-
if (fromCache)
|
|
56942
|
-
return fromCache;
|
|
56943
|
-
const publicKey = await this.transformJwkToKeyObjectAsyncFn(jwk, alg, issuer);
|
|
56944
|
-
this.putKeyObjectInCache(issuer, jwk.kid, alg, publicKey);
|
|
56945
|
-
return publicKey;
|
|
56946
|
-
}
|
|
56947
|
-
putKeyObjectInCache(issuer, kid, alg, publicKey) {
|
|
56948
|
-
const cachedIssuer = this.publicKeys.get(issuer);
|
|
56949
|
-
const cachedIssuerKid = cachedIssuer?.get(kid);
|
|
56950
|
-
if (cachedIssuerKid) {
|
|
56951
|
-
cachedIssuerKid.set(alg, publicKey);
|
|
56952
|
-
} else if (cachedIssuer) {
|
|
56953
|
-
cachedIssuer.set(kid, new Map([[alg, publicKey]]));
|
|
56139
|
+
logger16.info("Admin accessing game logs", { adminId: user.id, slug: slug2, environment });
|
|
56954
56140
|
} else {
|
|
56955
|
-
|
|
56956
|
-
|
|
56957
|
-
|
|
56958
|
-
|
|
56959
|
-
this.publicKeys.delete(issuer);
|
|
56960
|
-
}
|
|
56961
|
-
}
|
|
56962
|
-
var supportedSignatureAlgorithms;
|
|
56963
|
-
var JwtVerifier;
|
|
56964
|
-
var init_jwt_verifier = __esm(() => {
|
|
56965
|
-
init_jwk();
|
|
56966
|
-
init_assert();
|
|
56967
|
-
init_jwt();
|
|
56968
|
-
init_error();
|
|
56969
|
-
init_node_web_compat_node();
|
|
56970
|
-
supportedSignatureAlgorithms = [
|
|
56971
|
-
"RS256",
|
|
56972
|
-
"RS384",
|
|
56973
|
-
"RS512",
|
|
56974
|
-
"ES256",
|
|
56975
|
-
"ES384",
|
|
56976
|
-
"ES512",
|
|
56977
|
-
"EdDSA"
|
|
56978
|
-
];
|
|
56979
|
-
JwtVerifier = class JwtVerifier2 extends JwtVerifierBase {
|
|
56980
|
-
static create(verifyProperties, additionalProperties) {
|
|
56981
|
-
return new this(verifyProperties, additionalProperties?.jwksCache);
|
|
56982
|
-
}
|
|
56983
|
-
};
|
|
56984
|
-
});
|
|
56985
|
-
function validateCognitoJwtFields(payload, options) {
|
|
56986
|
-
if (options.groups != null) {
|
|
56987
|
-
assertStringArraysOverlap("Cognito group", payload["cognito:groups"], options.groups, CognitoJwtInvalidGroupError);
|
|
56988
|
-
}
|
|
56989
|
-
assertStringArrayContainsString("Token use", payload.token_use, ["id", "access"], CognitoJwtInvalidTokenUseError);
|
|
56990
|
-
if (options.tokenUse !== null) {
|
|
56991
|
-
if (options.tokenUse === undefined) {
|
|
56992
|
-
throw new ParameterValidationError("tokenUse must be provided or set to null explicitly");
|
|
56993
|
-
}
|
|
56994
|
-
assertStringEquals("Token use", payload.token_use, options.tokenUse, CognitoJwtInvalidTokenUseError);
|
|
56995
|
-
}
|
|
56996
|
-
if (options.clientId !== null) {
|
|
56997
|
-
if (options.clientId === undefined) {
|
|
56998
|
-
throw new ParameterValidationError("clientId must be provided or set to null explicitly");
|
|
56999
|
-
}
|
|
57000
|
-
if (payload.token_use === "id") {
|
|
57001
|
-
assertStringArrayContainsString('Client ID ("audience")', payload.aud, options.clientId, CognitoJwtInvalidClientIdError);
|
|
57002
|
-
} else {
|
|
57003
|
-
assertStringArrayContainsString("Client ID", payload.client_id, options.clientId, CognitoJwtInvalidClientIdError);
|
|
57004
|
-
}
|
|
57005
|
-
}
|
|
57006
|
-
}
|
|
57007
|
-
var CognitoJwtVerifier;
|
|
57008
|
-
var init_cognito_verifier = __esm(() => {
|
|
57009
|
-
init_error();
|
|
57010
|
-
init_jwt_verifier();
|
|
57011
|
-
init_assert();
|
|
57012
|
-
CognitoJwtVerifier = class CognitoJwtVerifier2 extends JwtVerifierBase {
|
|
57013
|
-
constructor(props, jwksCache) {
|
|
57014
|
-
const issuerConfig = Array.isArray(props) ? props.map((p) => ({
|
|
57015
|
-
...p,
|
|
57016
|
-
...CognitoJwtVerifier2.parseUserPoolId(p.userPoolId),
|
|
57017
|
-
audience: null
|
|
57018
|
-
})) : {
|
|
57019
|
-
...props,
|
|
57020
|
-
...CognitoJwtVerifier2.parseUserPoolId(props.userPoolId),
|
|
57021
|
-
audience: null
|
|
57022
|
-
};
|
|
57023
|
-
super(issuerConfig, jwksCache);
|
|
57024
|
-
}
|
|
57025
|
-
static parseUserPoolId(userPoolId) {
|
|
57026
|
-
const match = userPoolId.match(this.USER_POOL_ID_REGEX);
|
|
57027
|
-
if (!match) {
|
|
57028
|
-
throw new ParameterValidationError(`Invalid Cognito User Pool ID: ${userPoolId}`);
|
|
57029
|
-
}
|
|
57030
|
-
const region = match.groups.region;
|
|
57031
|
-
const issuer = `https://cognito-idp.${region}.amazonaws.com/${userPoolId}`;
|
|
57032
|
-
return {
|
|
57033
|
-
issuer,
|
|
57034
|
-
jwksUri: `${issuer}/.well-known/jwks.json`
|
|
57035
|
-
};
|
|
57036
|
-
}
|
|
57037
|
-
static create(verifyProperties, additionalProperties) {
|
|
57038
|
-
return new this(verifyProperties, additionalProperties?.jwksCache);
|
|
57039
|
-
}
|
|
57040
|
-
verifySync(...[jwt, properties]) {
|
|
57041
|
-
const { decomposedJwt, jwksUri, verifyProperties } = this.getVerifyParameters(jwt, properties);
|
|
57042
|
-
this.verifyDecomposedJwtSync(decomposedJwt, jwksUri, verifyProperties);
|
|
57043
|
-
try {
|
|
57044
|
-
validateCognitoJwtFields(decomposedJwt.payload, verifyProperties);
|
|
57045
|
-
} catch (err2) {
|
|
57046
|
-
if (verifyProperties.includeRawJwtInErrors && err2 instanceof JwtInvalidClaimError) {
|
|
57047
|
-
throw err2.withRawJwt(decomposedJwt);
|
|
57048
|
-
}
|
|
57049
|
-
throw err2;
|
|
57050
|
-
}
|
|
57051
|
-
return decomposedJwt.payload;
|
|
57052
|
-
}
|
|
57053
|
-
async verify(...[jwt, properties]) {
|
|
57054
|
-
const { decomposedJwt, jwksUri, verifyProperties } = this.getVerifyParameters(jwt, properties);
|
|
57055
|
-
await this.verifyDecomposedJwt(decomposedJwt, jwksUri, verifyProperties);
|
|
57056
|
-
try {
|
|
57057
|
-
validateCognitoJwtFields(decomposedJwt.payload, verifyProperties);
|
|
57058
|
-
} catch (err2) {
|
|
57059
|
-
if (verifyProperties.includeRawJwtInErrors && err2 instanceof JwtInvalidClaimError) {
|
|
57060
|
-
throw err2.withRawJwt(decomposedJwt);
|
|
57061
|
-
}
|
|
57062
|
-
throw err2;
|
|
56141
|
+
const isApprovedDev = user.developerStatus === "approved";
|
|
56142
|
+
if (!isApprovedDev) {
|
|
56143
|
+
logger16.warn("Unapproved developer attempted log access", { userId: user.id, slug: slug2 });
|
|
56144
|
+
throw new AccessDeniedError("Must be an approved developer");
|
|
57063
56145
|
}
|
|
57064
|
-
|
|
57065
|
-
|
|
57066
|
-
|
|
57067
|
-
|
|
57068
|
-
if (
|
|
57069
|
-
|
|
57070
|
-
|
|
57071
|
-
|
|
56146
|
+
const game = await db2.query.games.findFirst({
|
|
56147
|
+
where: and(eq(games.slug, slug2), eq(games.developerId, user.id)),
|
|
56148
|
+
columns: { id: true }
|
|
56149
|
+
});
|
|
56150
|
+
if (!game) {
|
|
56151
|
+
logger16.warn("Developer attempted access to unowned game logs", {
|
|
56152
|
+
userId: user.id,
|
|
56153
|
+
slug: slug2
|
|
56154
|
+
});
|
|
56155
|
+
throw new NotFoundError("Game", slug2);
|
|
57072
56156
|
}
|
|
57073
|
-
const issuerConfig = this.getIssuerConfig(issuer);
|
|
57074
|
-
super.cacheJwks(jwks, issuerConfig.issuer);
|
|
57075
|
-
}
|
|
57076
|
-
};
|
|
57077
|
-
CognitoJwtVerifier.USER_POOL_ID_REGEX = /^(?<region>[a-z]{2}-(gov-)?[a-z]+-\d)_[a-zA-Z0-9]+$/;
|
|
57078
|
-
});
|
|
57079
|
-
var init_alb_cache = __esm(() => {
|
|
57080
|
-
init_error();
|
|
57081
|
-
init_https();
|
|
57082
|
-
init_node_web_compat_node();
|
|
57083
|
-
});
|
|
57084
|
-
var init_alb_verifier = __esm(() => {
|
|
57085
|
-
init_alb_cache();
|
|
57086
|
-
init_assert();
|
|
57087
|
-
init_error();
|
|
57088
|
-
init_jwt_verifier();
|
|
57089
|
-
});
|
|
57090
|
-
var init_esm2 = __esm(() => {
|
|
57091
|
-
init_jwt_verifier();
|
|
57092
|
-
init_cognito_verifier();
|
|
57093
|
-
init_alb_verifier();
|
|
57094
|
-
init_jwt_verifier();
|
|
57095
|
-
});
|
|
57096
|
-
function generateUsername(email) {
|
|
57097
|
-
const baseUsername = (email.split("@")[0] || "user").toLowerCase();
|
|
57098
|
-
const cleanUsername = baseUsername.replace(/[^a-z0-9]/g, "");
|
|
57099
|
-
const randomSuffix = Math.random().toString(36).substring(2, 7);
|
|
57100
|
-
return `${cleanUsername}_${randomSuffix}`;
|
|
57101
|
-
}
|
|
57102
|
-
function extractRedirectPath(targetUri, currentHost) {
|
|
57103
|
-
try {
|
|
57104
|
-
const targetUrl = new URL(targetUri);
|
|
57105
|
-
if (targetUrl.hostname === currentHost) {
|
|
57106
|
-
return targetUrl.pathname + targetUrl.search;
|
|
57107
56157
|
}
|
|
57108
|
-
|
|
57109
|
-
|
|
57110
|
-
|
|
57111
|
-
|
|
57112
|
-
|
|
57113
|
-
|
|
57114
|
-
|
|
57115
|
-
|
|
57116
|
-
}
|
|
57117
|
-
function validateLtiClaims(claims) {
|
|
57118
|
-
const messageType = claims["https://purl.imsglobal.org/spec/lti/claim/message_type"];
|
|
57119
|
-
const version2 = claims["https://purl.imsglobal.org/spec/lti/claim/version"];
|
|
57120
|
-
if (messageType !== "LtiResourceLinkRequest") {
|
|
57121
|
-
return `Invalid LTI message type: ${messageType}`;
|
|
57122
|
-
}
|
|
57123
|
-
if (version2 !== "1.3.0") {
|
|
57124
|
-
return `Unsupported LTI version: ${version2}`;
|
|
56158
|
+
const isProduction3 = environment === "production";
|
|
56159
|
+
const workerId = getDeploymentId(slug2, isProduction3);
|
|
56160
|
+
const token = await this.ctx.providers.auth.mintLogStreamToken(user.id, workerId);
|
|
56161
|
+
logger16.debug("Generated log stream token", {
|
|
56162
|
+
userId: user.id,
|
|
56163
|
+
slug: slug2,
|
|
56164
|
+
workerId
|
|
56165
|
+
});
|
|
56166
|
+
return { token, workerId };
|
|
57125
56167
|
}
|
|
57126
|
-
return null;
|
|
57127
56168
|
}
|
|
57128
|
-
var
|
|
57129
|
-
var
|
|
57130
|
-
|
|
57131
|
-
|
|
57132
|
-
|
|
57133
|
-
|
|
57134
|
-
|
|
57135
|
-
|
|
57136
|
-
};
|
|
56169
|
+
var logger16;
|
|
56170
|
+
var init_logs_service = __esm(() => {
|
|
56171
|
+
init_drizzle_orm();
|
|
56172
|
+
init_tables_index();
|
|
56173
|
+
init_src2();
|
|
56174
|
+
init_errors();
|
|
56175
|
+
init_deployment_util();
|
|
56176
|
+
logger16 = log.scope("LogsService");
|
|
57137
56177
|
});
|
|
57138
56178
|
|
|
57139
56179
|
class LtiService {
|
|
57140
56180
|
ctx;
|
|
57141
|
-
verifier = null;
|
|
57142
56181
|
constructor(ctx) {
|
|
57143
56182
|
this.ctx = ctx;
|
|
57144
56183
|
}
|
|
57145
|
-
getConfig() {
|
|
57146
|
-
if (!this.ctx.config.lti) {
|
|
57147
|
-
logger16.error("LTI configuration not available");
|
|
57148
|
-
throw new ValidationError("LTI is not configured");
|
|
57149
|
-
}
|
|
57150
|
-
return this.ctx.config.lti;
|
|
57151
|
-
}
|
|
57152
|
-
getVerifier() {
|
|
57153
|
-
if (!this.verifier) {
|
|
57154
|
-
const lti = this.getConfig();
|
|
57155
|
-
this.verifier = JwtVerifier.create({
|
|
57156
|
-
issuer: lti.issuer,
|
|
57157
|
-
audience: lti.audience,
|
|
57158
|
-
jwksUri: lti.jwksUrl
|
|
57159
|
-
});
|
|
57160
|
-
}
|
|
57161
|
-
return this.verifier;
|
|
57162
|
-
}
|
|
57163
|
-
async verifyToken(idToken) {
|
|
57164
|
-
if (this.ctx.config.ltiTestMode) {
|
|
57165
|
-
if (!idToken.startsWith("mock:")) {
|
|
57166
|
-
throw new ValidationError("Invalid LTI token");
|
|
57167
|
-
}
|
|
57168
|
-
try {
|
|
57169
|
-
const jsonStr = Buffer.from(idToken.slice(5), "base64").toString();
|
|
57170
|
-
return JSON.parse(jsonStr);
|
|
57171
|
-
} catch {
|
|
57172
|
-
throw new ValidationError("Invalid LTI token format");
|
|
57173
|
-
}
|
|
57174
|
-
}
|
|
57175
|
-
try {
|
|
57176
|
-
const verifier = this.getVerifier();
|
|
57177
|
-
const claims = await verifier.verify(idToken);
|
|
57178
|
-
logger16.info("Verified token", {
|
|
57179
|
-
sub: claims.sub,
|
|
57180
|
-
email: claims.email,
|
|
57181
|
-
roles: claims["https://purl.imsglobal.org/spec/lti/claim/roles"]
|
|
57182
|
-
});
|
|
57183
|
-
return claims;
|
|
57184
|
-
} catch (error) {
|
|
57185
|
-
logger16.error("Token verification failed", {
|
|
57186
|
-
error: error instanceof Error ? error.message : String(error)
|
|
57187
|
-
});
|
|
57188
|
-
throw new ValidationError("Invalid LTI token");
|
|
57189
|
-
}
|
|
57190
|
-
}
|
|
57191
|
-
async processLaunch(idToken, currentHost) {
|
|
57192
|
-
const claims = await this.verifyToken(idToken);
|
|
57193
|
-
const validationError = validateLtiClaims(claims);
|
|
57194
|
-
if (validationError) {
|
|
57195
|
-
logger16.warn("LTI claims validation failed", {
|
|
57196
|
-
error: validationError,
|
|
57197
|
-
sub: claims.sub
|
|
57198
|
-
});
|
|
57199
|
-
throw new ValidationError(validationError);
|
|
57200
|
-
}
|
|
57201
|
-
const user = await this.provisionUser(claims);
|
|
57202
|
-
logger16.info("Processed launch roles", {
|
|
57203
|
-
userId: user.id,
|
|
57204
|
-
isLearner: LtiRoleChecks.isLearner(claims),
|
|
57205
|
-
isInstructor: LtiRoleChecks.isInstructor(claims),
|
|
57206
|
-
isAdministrator: LtiRoleChecks.isAdministrator(claims),
|
|
57207
|
-
allRoles: claims["https://purl.imsglobal.org/spec/lti/claim/roles"]
|
|
57208
|
-
});
|
|
57209
|
-
const sessionToken = await this.createSession(user.id);
|
|
57210
|
-
const targetUri = claims["https://purl.imsglobal.org/spec/lti/claim/target_link_uri"];
|
|
57211
|
-
const redirectPath = extractRedirectPath(targetUri, currentHost);
|
|
57212
|
-
logger16.info("Launch processed", { userId: user.id, redirectPath });
|
|
57213
|
-
const userInfo = {
|
|
57214
|
-
sub: user.id,
|
|
57215
|
-
email: user.email,
|
|
57216
|
-
name: user.name,
|
|
57217
|
-
email_verified: user.emailVerified,
|
|
57218
|
-
timeback_id: user.timebackId ?? undefined
|
|
57219
|
-
};
|
|
57220
|
-
return { user: userInfo, redirectPath, sessionToken };
|
|
57221
|
-
}
|
|
57222
56184
|
async getStatus(user) {
|
|
57223
56185
|
const db2 = this.ctx.db;
|
|
57224
56186
|
const [ltiAccount, oauthAccount, userRecord] = await Promise.all([
|
|
@@ -57242,134 +56204,11 @@ class LtiService {
|
|
|
57242
56204
|
userId: user.id
|
|
57243
56205
|
};
|
|
57244
56206
|
}
|
|
57245
|
-
async createSession(userId) {
|
|
57246
|
-
const db2 = this.ctx.db;
|
|
57247
|
-
const sessionToken = crypto4.randomUUID();
|
|
57248
|
-
const expiresAt = new Date(Date.now() + 2592000000);
|
|
57249
|
-
const [session2] = await db2.insert(sessions).values({
|
|
57250
|
-
id: crypto4.randomUUID(),
|
|
57251
|
-
userId,
|
|
57252
|
-
token: sessionToken,
|
|
57253
|
-
expiresAt,
|
|
57254
|
-
createdAt: new Date,
|
|
57255
|
-
updatedAt: new Date
|
|
57256
|
-
}).returning({ id: sessions.id });
|
|
57257
|
-
if (!session2) {
|
|
57258
|
-
logger16.error("Session insert returned no rows", { userId });
|
|
57259
|
-
throw new InternalError("Failed to create session");
|
|
57260
|
-
}
|
|
57261
|
-
logger16.info("Created session", {
|
|
57262
|
-
userId,
|
|
57263
|
-
providerId: AUTH_PROVIDER_IDS.TIMEBACK_LTI
|
|
57264
|
-
});
|
|
57265
|
-
return sessionToken;
|
|
57266
|
-
}
|
|
57267
|
-
async provisionUser(claims) {
|
|
57268
|
-
const db2 = this.ctx.db;
|
|
57269
|
-
const email = claims.email;
|
|
57270
|
-
const ltiTimebackId = claims.sub;
|
|
57271
|
-
const providerId = AUTH_PROVIDER_IDS.TIMEBACK_LTI;
|
|
57272
|
-
if (!email) {
|
|
57273
|
-
throw new ValidationError("Email is required in LTI claims");
|
|
57274
|
-
}
|
|
57275
|
-
const existingAccount = await db2.query.accounts.findFirst({
|
|
57276
|
-
where: and(eq(accounts.accountId, ltiTimebackId), eq(accounts.providerId, providerId))
|
|
57277
|
-
});
|
|
57278
|
-
if (existingAccount) {
|
|
57279
|
-
const user = await db2.query.users.findFirst({
|
|
57280
|
-
where: eq(users.id, existingAccount.userId)
|
|
57281
|
-
});
|
|
57282
|
-
if (user) {
|
|
57283
|
-
logger16.info("Found user by account", {
|
|
57284
|
-
userId: user.id,
|
|
57285
|
-
ltiTimebackId
|
|
57286
|
-
});
|
|
57287
|
-
return user;
|
|
57288
|
-
}
|
|
57289
|
-
}
|
|
57290
|
-
const existingUser = await db2.query.users.findFirst({
|
|
57291
|
-
where: eq(users.email, email)
|
|
57292
|
-
});
|
|
57293
|
-
if (existingUser) {
|
|
57294
|
-
await db2.transaction(async (tx) => {
|
|
57295
|
-
const existingLtiAccount = await tx.query.accounts.findFirst({
|
|
57296
|
-
where: and(eq(accounts.userId, existingUser.id), eq(accounts.providerId, providerId))
|
|
57297
|
-
});
|
|
57298
|
-
if (!existingLtiAccount) {
|
|
57299
|
-
const [account] = await tx.insert(accounts).values({
|
|
57300
|
-
id: crypto4.randomUUID(),
|
|
57301
|
-
userId: existingUser.id,
|
|
57302
|
-
accountId: ltiTimebackId,
|
|
57303
|
-
providerId,
|
|
57304
|
-
accessToken: null,
|
|
57305
|
-
refreshToken: null,
|
|
57306
|
-
accessTokenExpiresAt: null,
|
|
57307
|
-
refreshTokenExpiresAt: null,
|
|
57308
|
-
createdAt: new Date,
|
|
57309
|
-
updatedAt: new Date
|
|
57310
|
-
}).returning({ id: accounts.id });
|
|
57311
|
-
if (!account) {
|
|
57312
|
-
logger16.error("LTI account link insert returned no rows", {
|
|
57313
|
-
userId: existingUser.id,
|
|
57314
|
-
ltiTimebackId
|
|
57315
|
-
});
|
|
57316
|
-
throw new InternalError("Failed to link LTI account");
|
|
57317
|
-
}
|
|
57318
|
-
logger16.info("Linked existing user", {
|
|
57319
|
-
userId: existingUser.id,
|
|
57320
|
-
ltiTimebackId
|
|
57321
|
-
});
|
|
57322
|
-
}
|
|
57323
|
-
});
|
|
57324
|
-
return existingUser;
|
|
57325
|
-
}
|
|
57326
|
-
const newUserId = crypto4.randomUUID();
|
|
57327
|
-
const createdUser = await db2.transaction(async (tx) => {
|
|
57328
|
-
const [insertedUser] = await tx.insert(users).values({
|
|
57329
|
-
id: newUserId,
|
|
57330
|
-
email,
|
|
57331
|
-
emailVerified: true,
|
|
57332
|
-
timebackId: ltiTimebackId,
|
|
57333
|
-
username: generateUsername(email),
|
|
57334
|
-
name: claims.name || claims.given_name || email.split("@")[0] || "Timeback User",
|
|
57335
|
-
createdAt: new Date,
|
|
57336
|
-
updatedAt: new Date
|
|
57337
|
-
}).returning();
|
|
57338
|
-
if (!insertedUser) {
|
|
57339
|
-
logger16.error("LTI user insert returned no rows", { email, ltiTimebackId });
|
|
57340
|
-
throw new InternalError("Failed to create user");
|
|
57341
|
-
}
|
|
57342
|
-
await tx.insert(accounts).values({
|
|
57343
|
-
id: crypto4.randomUUID(),
|
|
57344
|
-
userId: newUserId,
|
|
57345
|
-
accountId: ltiTimebackId,
|
|
57346
|
-
providerId,
|
|
57347
|
-
accessToken: null,
|
|
57348
|
-
refreshToken: null,
|
|
57349
|
-
accessTokenExpiresAt: null,
|
|
57350
|
-
refreshTokenExpiresAt: null,
|
|
57351
|
-
createdAt: new Date,
|
|
57352
|
-
updatedAt: new Date
|
|
57353
|
-
});
|
|
57354
|
-
logger16.info("Provisioned user", {
|
|
57355
|
-
userId: insertedUser.id,
|
|
57356
|
-
ltiTimebackId
|
|
57357
|
-
});
|
|
57358
|
-
return insertedUser;
|
|
57359
|
-
});
|
|
57360
|
-
return createdUser;
|
|
57361
|
-
}
|
|
57362
56207
|
}
|
|
57363
|
-
var logger16;
|
|
57364
56208
|
var init_lti_service = __esm(() => {
|
|
57365
|
-
init_esm2();
|
|
57366
56209
|
init_drizzle_orm();
|
|
57367
56210
|
init_src();
|
|
57368
56211
|
init_tables_index();
|
|
57369
|
-
init_src2();
|
|
57370
|
-
init_errors();
|
|
57371
|
-
init_lti_util();
|
|
57372
|
-
logger16 = log.scope("LtiService");
|
|
57373
56212
|
});
|
|
57374
56213
|
|
|
57375
56214
|
class MapService {
|
|
@@ -57860,56 +56699,88 @@ class SecretsService {
|
|
|
57860
56699
|
constructor(ctx) {
|
|
57861
56700
|
this.ctx = ctx;
|
|
57862
56701
|
}
|
|
57863
|
-
|
|
57864
|
-
|
|
57865
|
-
|
|
57866
|
-
|
|
57867
|
-
|
|
57868
|
-
return keys;
|
|
56702
|
+
getCloudflare() {
|
|
56703
|
+
if (!this.ctx.cloudflare) {
|
|
56704
|
+
throw new ValidationError("Secrets management requires Cloudflare provider");
|
|
56705
|
+
}
|
|
56706
|
+
return this.ctx.cloudflare;
|
|
57869
56707
|
}
|
|
57870
|
-
|
|
56708
|
+
getDeploymentId(slug2) {
|
|
56709
|
+
const isProd = isProduction2(this.ctx.config);
|
|
56710
|
+
return getDeploymentId(slug2, isProd);
|
|
56711
|
+
}
|
|
56712
|
+
async listKeys(slug2, user) {
|
|
57871
56713
|
const game = await this.ctx.services.game.validateDeveloperAccessBySlug(user, slug2);
|
|
57872
|
-
const
|
|
57873
|
-
|
|
57874
|
-
|
|
57875
|
-
|
|
57876
|
-
|
|
57877
|
-
|
|
57878
|
-
|
|
57879
|
-
|
|
56714
|
+
const cf = this.getCloudflare();
|
|
56715
|
+
const deploymentId = this.getDeploymentId(slug2);
|
|
56716
|
+
try {
|
|
56717
|
+
const allKeys = await cf.listSecrets(deploymentId);
|
|
56718
|
+
const keys = allKeys.filter((k) => k.startsWith(SECRETS_PREFIX)).map((k) => k.slice(SECRETS_PREFIX.length));
|
|
56719
|
+
logger20.debug("Listed secret keys", { gameId: game.id, slug: slug2, keyCount: keys.length });
|
|
56720
|
+
return keys;
|
|
56721
|
+
} catch (error) {
|
|
56722
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
56723
|
+
if (message.includes("not found") || message.includes("10007")) {
|
|
56724
|
+
logger20.debug("Worker not found, returning empty secrets list", {
|
|
56725
|
+
gameId: game.id,
|
|
56726
|
+
slug: slug2
|
|
56727
|
+
});
|
|
56728
|
+
return [];
|
|
57880
56729
|
}
|
|
56730
|
+
throw error;
|
|
57881
56731
|
}
|
|
57882
|
-
logger20.debug("Retrieved secret values", { gameId: game.id, slug: slug2 });
|
|
57883
|
-
return filtered;
|
|
57884
56732
|
}
|
|
57885
56733
|
async setSecrets(slug2, newSecrets, user) {
|
|
57886
56734
|
const game = await this.ctx.services.game.validateDeveloperAccessBySlug(user, slug2);
|
|
56735
|
+
const cf = this.getCloudflare();
|
|
56736
|
+
const deploymentId = this.getDeploymentId(slug2);
|
|
57887
56737
|
const secretKeys = Object.keys(newSecrets);
|
|
57888
56738
|
if (secretKeys.length === 0) {
|
|
56739
|
+
logger20.warn("No secrets provided", { userId: user.id, slug: slug2 });
|
|
57889
56740
|
throw new ValidationError("At least one secret must be provided");
|
|
57890
56741
|
}
|
|
57891
56742
|
for (const [key, value] of Object.entries(newSecrets)) {
|
|
57892
56743
|
if (typeof value !== "string") {
|
|
56744
|
+
logger20.warn("Secret value must be a string", { userId: user.id, slug: slug2, key });
|
|
57893
56745
|
throw new ValidationError(`Secret value for "${key}" must be a string`);
|
|
57894
56746
|
}
|
|
57895
56747
|
if (INTERNAL_SECRET_KEYS.includes(key)) {
|
|
57896
|
-
logger20.warn("Attempted to set reserved secret", {
|
|
57897
|
-
|
|
56748
|
+
logger20.warn("Attempted to set reserved secret", { userId: user.id, slug: slug2, key });
|
|
56749
|
+
throw new ValidationError(`Cannot set reserved secret "${key}"`);
|
|
56750
|
+
}
|
|
56751
|
+
}
|
|
56752
|
+
try {
|
|
56753
|
+
const prefixedSecrets = {};
|
|
56754
|
+
for (const [key, value] of Object.entries(newSecrets)) {
|
|
56755
|
+
prefixedSecrets[`${SECRETS_PREFIX}${key}`] = value;
|
|
56756
|
+
}
|
|
56757
|
+
await cf.setSecrets(deploymentId, prefixedSecrets);
|
|
56758
|
+
logger20.info("Set secrets", {
|
|
56759
|
+
gameId: game.id,
|
|
56760
|
+
slug: slug2,
|
|
56761
|
+
deploymentId,
|
|
56762
|
+
keys: secretKeys
|
|
56763
|
+
});
|
|
56764
|
+
const allKeys = await cf.listSecrets(deploymentId);
|
|
56765
|
+
return allKeys.filter((k) => k.startsWith(SECRETS_PREFIX)).map((k) => k.slice(SECRETS_PREFIX.length));
|
|
56766
|
+
} catch (error) {
|
|
56767
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
56768
|
+
if (message.includes("not found") || message.includes("10007")) {
|
|
56769
|
+
logger20.warn("Cannot set secrets - game not deployed", {
|
|
57898
56770
|
gameId: game.id,
|
|
57899
|
-
|
|
56771
|
+
slug: slug2,
|
|
56772
|
+
deploymentId
|
|
57900
56773
|
});
|
|
57901
|
-
throw new ValidationError(
|
|
56774
|
+
throw new ValidationError("Game must be deployed before setting secrets. Run `playcademy deploy` first.");
|
|
57902
56775
|
}
|
|
56776
|
+
logger20.error("Failed to set secrets", {
|
|
56777
|
+
gameId: game.id,
|
|
56778
|
+
slug: slug2,
|
|
56779
|
+
deploymentId,
|
|
56780
|
+
error: message
|
|
56781
|
+
});
|
|
56782
|
+
throw error;
|
|
57903
56783
|
}
|
|
57904
|
-
const existingSecrets = await this.ctx.providers.secrets.readSecrets(game.id) || {};
|
|
57905
|
-
const updatedSecrets = { ...existingSecrets, ...newSecrets };
|
|
57906
|
-
await this.ctx.providers.secrets.writeSecrets(game.id, updatedSecrets);
|
|
57907
|
-
logger20.info("Set secrets", {
|
|
57908
|
-
gameId: game.id,
|
|
57909
|
-
slug: slug2,
|
|
57910
|
-
addedKeys: secretKeys
|
|
57911
|
-
});
|
|
57912
|
-
return Object.keys(updatedSecrets).filter((k) => !INTERNAL_SECRET_KEYS.includes(k));
|
|
57913
56784
|
}
|
|
57914
56785
|
async deleteSecret(slug2, key, user) {
|
|
57915
56786
|
if (INTERNAL_SECRET_KEYS.includes(key)) {
|
|
@@ -57921,26 +56792,55 @@ class SecretsService {
|
|
|
57921
56792
|
throw new ValidationError(`Cannot delete reserved secret "${key}"`);
|
|
57922
56793
|
}
|
|
57923
56794
|
const game = await this.ctx.services.game.validateDeveloperAccessBySlug(user, slug2);
|
|
57924
|
-
const
|
|
57925
|
-
|
|
57926
|
-
|
|
57927
|
-
|
|
57928
|
-
|
|
57929
|
-
|
|
57930
|
-
|
|
57931
|
-
|
|
57932
|
-
await
|
|
56795
|
+
const cf = this.getCloudflare();
|
|
56796
|
+
const deploymentId = this.getDeploymentId(slug2);
|
|
56797
|
+
try {
|
|
56798
|
+
const prefixedKey = `${SECRETS_PREFIX}${key}`;
|
|
56799
|
+
const existingKeys = await cf.listSecrets(deploymentId);
|
|
56800
|
+
if (!existingKeys.includes(prefixedKey)) {
|
|
56801
|
+
throw new NotFoundError("Secret", key);
|
|
56802
|
+
}
|
|
56803
|
+
await cf.deleteSecret(deploymentId, prefixedKey);
|
|
56804
|
+
logger20.info("Deleted secret", {
|
|
56805
|
+
gameId: game.id,
|
|
56806
|
+
slug: slug2,
|
|
56807
|
+
deploymentId,
|
|
56808
|
+
key
|
|
56809
|
+
});
|
|
56810
|
+
} catch (error) {
|
|
56811
|
+
if (error instanceof NotFoundError) {
|
|
56812
|
+
throw error;
|
|
56813
|
+
}
|
|
56814
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
56815
|
+
if (message.includes("not found") || message.includes("10007")) {
|
|
56816
|
+
logger20.warn("Cannot delete secret - game not deployed", {
|
|
56817
|
+
gameId: game.id,
|
|
56818
|
+
slug: slug2,
|
|
56819
|
+
deploymentId
|
|
56820
|
+
});
|
|
56821
|
+
throw new ValidationError("Game must be deployed before managing secrets. Run `playcademy deploy` first.");
|
|
56822
|
+
}
|
|
56823
|
+
logger20.error("Failed to delete secret", {
|
|
56824
|
+
gameId: game.id,
|
|
56825
|
+
slug: slug2,
|
|
56826
|
+
deploymentId,
|
|
56827
|
+
key,
|
|
56828
|
+
error: message
|
|
56829
|
+
});
|
|
56830
|
+
throw error;
|
|
57933
56831
|
}
|
|
57934
|
-
logger20.info("Deleted secret", { gameId: game.id, slug: slug2, key });
|
|
57935
56832
|
}
|
|
57936
56833
|
}
|
|
57937
56834
|
var logger20;
|
|
56835
|
+
var SECRETS_PREFIX = "secrets_";
|
|
57938
56836
|
var INTERNAL_SECRET_KEYS;
|
|
57939
56837
|
var init_secrets_service = __esm(() => {
|
|
57940
56838
|
init_src2();
|
|
56839
|
+
init_config2();
|
|
57941
56840
|
init_errors();
|
|
56841
|
+
init_deployment_util();
|
|
57942
56842
|
logger20 = log.scope("SecretsService");
|
|
57943
|
-
INTERNAL_SECRET_KEYS = ["PLAYCADEMY_API_KEY"];
|
|
56843
|
+
INTERNAL_SECRET_KEYS = ["PLAYCADEMY_API_KEY", "GAME_ID", "PLAYCADEMY_BASE_URL"];
|
|
57944
56844
|
});
|
|
57945
56845
|
|
|
57946
56846
|
class SeedService {
|
|
@@ -59370,11 +58270,11 @@ class TimebackService {
|
|
|
59370
58270
|
return [];
|
|
59371
58271
|
}
|
|
59372
58272
|
}
|
|
59373
|
-
async setupIntegration(gameId,
|
|
58273
|
+
async setupIntegration(gameId, request, user) {
|
|
59374
58274
|
const client = this.requireClient();
|
|
59375
58275
|
const db2 = this.ctx.db;
|
|
59376
58276
|
await this.ctx.services.game.validateDeveloperAccess(user, gameId);
|
|
59377
|
-
const { courses, baseConfig, verbose } =
|
|
58277
|
+
const { courses, baseConfig, verbose } = request;
|
|
59378
58278
|
const existing = await db2.query.gameTimebackIntegrations.findMany({
|
|
59379
58279
|
where: eq(gameTimebackIntegrations.gameId, gameId)
|
|
59380
58280
|
});
|
|
@@ -59618,8 +58518,8 @@ class UploadService {
|
|
|
59618
58518
|
constructor(ctx) {
|
|
59619
58519
|
this.ctx = ctx;
|
|
59620
58520
|
}
|
|
59621
|
-
async initiate(
|
|
59622
|
-
const { fileName, gameId } =
|
|
58521
|
+
async initiate(request, user) {
|
|
58522
|
+
const { fileName, gameId } = request;
|
|
59623
58523
|
const bucketName = this.ctx.config.uploadBucket;
|
|
59624
58524
|
if (!bucketName) {
|
|
59625
58525
|
logger27.error("Upload bucket not configured in environment");
|
|
@@ -59865,6 +58765,7 @@ function createServices(ctx) {
|
|
|
59865
58765
|
item: new ItemService(ctx),
|
|
59866
58766
|
leaderboard: new LeaderboardService(ctx),
|
|
59867
58767
|
level: new LevelService(ctx),
|
|
58768
|
+
logs: new LogsService(ctx),
|
|
59868
58769
|
lti: new LtiService(ctx),
|
|
59869
58770
|
map: new MapService(ctx),
|
|
59870
58771
|
notification: new NotificationService(ctx),
|
|
@@ -59896,6 +58797,7 @@ var init_services = __esm(() => {
|
|
|
59896
58797
|
init_item_service();
|
|
59897
58798
|
init_leaderboard_service();
|
|
59898
58799
|
init_level_service();
|
|
58800
|
+
init_logs_service();
|
|
59899
58801
|
init_lti_service();
|
|
59900
58802
|
init_map_service();
|
|
59901
58803
|
init_notification_service();
|
|
@@ -59990,6 +58892,38 @@ function createSandboxAuthProvider() {
|
|
|
59990
58892
|
const header = btoa(JSON.stringify({ alg: "none", typ: "sandbox" }));
|
|
59991
58893
|
const payloadStr = btoa(JSON.stringify(payload));
|
|
59992
58894
|
return `${header}.${payloadStr}.sandbox`;
|
|
58895
|
+
},
|
|
58896
|
+
async mintLogStreamToken(userId, workerId) {
|
|
58897
|
+
const jti = crypto.randomUUID();
|
|
58898
|
+
const payload = {
|
|
58899
|
+
sub: userId,
|
|
58900
|
+
game: workerId,
|
|
58901
|
+
jti,
|
|
58902
|
+
exp: Date.now() + 60000
|
|
58903
|
+
};
|
|
58904
|
+
const header = btoa(JSON.stringify({ alg: "none", typ: "sandbox" }));
|
|
58905
|
+
const payloadStr = btoa(JSON.stringify(payload));
|
|
58906
|
+
return `${header}.${payloadStr}.sandbox`;
|
|
58907
|
+
},
|
|
58908
|
+
async validateLogStreamToken(token) {
|
|
58909
|
+
try {
|
|
58910
|
+
const parts2 = token.split(".");
|
|
58911
|
+
if (parts2.length !== 3)
|
|
58912
|
+
return null;
|
|
58913
|
+
if (parts2[2] === "sandbox") {
|
|
58914
|
+
const payload = JSON.parse(atob(parts2[1]));
|
|
58915
|
+
if (payload.jti && payload.sub && payload.game) {
|
|
58916
|
+
if (payload.exp && payload.exp < Date.now()) {
|
|
58917
|
+
log.debug("[SandboxAuthProvider] Log stream token expired");
|
|
58918
|
+
return null;
|
|
58919
|
+
}
|
|
58920
|
+
return { jti: payload.jti, sub: payload.sub, game: payload.game };
|
|
58921
|
+
}
|
|
58922
|
+
}
|
|
58923
|
+
return null;
|
|
58924
|
+
} catch {
|
|
58925
|
+
return null;
|
|
58926
|
+
}
|
|
59993
58927
|
}
|
|
59994
58928
|
};
|
|
59995
58929
|
}
|
|
@@ -60044,33 +58978,6 @@ var init_cache_provider = __esm(() => {
|
|
|
60044
58978
|
cache = new Map;
|
|
60045
58979
|
gameOrigins = [];
|
|
60046
58980
|
});
|
|
60047
|
-
function createSandboxSecretsProvider() {
|
|
60048
|
-
return {
|
|
60049
|
-
async readSecrets(gameId) {
|
|
60050
|
-
const secrets = secretsStorage.get(gameId);
|
|
60051
|
-
return secrets ?? null;
|
|
60052
|
-
},
|
|
60053
|
-
async writeSecrets(gameId, secrets) {
|
|
60054
|
-
secretsStorage.set(gameId, { ...secrets });
|
|
60055
|
-
log.debug("[SandboxSecretsProvider] Stored secrets", {
|
|
60056
|
-
gameId,
|
|
60057
|
-
keyCount: Object.keys(secrets).length
|
|
60058
|
-
});
|
|
60059
|
-
},
|
|
60060
|
-
async deleteSecrets(gameId) {
|
|
60061
|
-
secretsStorage.delete(gameId);
|
|
60062
|
-
log.debug("[SandboxSecretsProvider] Deleted secrets", { gameId });
|
|
60063
|
-
}
|
|
60064
|
-
};
|
|
60065
|
-
}
|
|
60066
|
-
function clearSandboxSecrets() {
|
|
60067
|
-
secretsStorage.clear();
|
|
60068
|
-
}
|
|
60069
|
-
var secretsStorage;
|
|
60070
|
-
var init_secrets_provider = __esm(() => {
|
|
60071
|
-
init_src2();
|
|
60072
|
-
secretsStorage = new Map;
|
|
60073
|
-
});
|
|
60074
58981
|
function getBucket(bucketName) {
|
|
60075
58982
|
let bucket = storage.get(bucketName);
|
|
60076
58983
|
if (!bucket) {
|
|
@@ -60142,7 +59049,6 @@ var init_storage_provider = __esm(() => {
|
|
|
60142
59049
|
var init_providers = __esm(() => {
|
|
60143
59050
|
init_auth_provider();
|
|
60144
59051
|
init_cache_provider();
|
|
60145
|
-
init_secrets_provider();
|
|
60146
59052
|
init_storage_provider();
|
|
60147
59053
|
});
|
|
60148
59054
|
function buildConfig(options) {
|
|
@@ -60159,7 +59065,6 @@ function buildProviders() {
|
|
|
60159
59065
|
return {
|
|
60160
59066
|
auth: createSandboxAuthProvider(),
|
|
60161
59067
|
storage: createSandboxStorageProvider(),
|
|
60162
|
-
secrets: createSandboxSecretsProvider(),
|
|
60163
59068
|
cache: createSandboxCacheProvider()
|
|
60164
59069
|
};
|
|
60165
59070
|
}
|
|
@@ -60292,8 +59197,8 @@ var GET_MATCH_RESULT;
|
|
|
60292
59197
|
var init_constants3 = __esm(() => {
|
|
60293
59198
|
GET_MATCH_RESULT = Symbol();
|
|
60294
59199
|
});
|
|
60295
|
-
async function parseFormData(
|
|
60296
|
-
const formData = await
|
|
59200
|
+
async function parseFormData(request, options) {
|
|
59201
|
+
const formData = await request.formData();
|
|
60297
59202
|
if (formData) {
|
|
60298
59203
|
return convertFormDataToBodyData(formData, options);
|
|
60299
59204
|
}
|
|
@@ -60320,12 +59225,12 @@ function convertFormDataToBodyData(formData, options) {
|
|
|
60320
59225
|
}
|
|
60321
59226
|
return form;
|
|
60322
59227
|
}
|
|
60323
|
-
var parseBody = async (
|
|
59228
|
+
var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
|
|
60324
59229
|
const { all = false, dot = false } = options;
|
|
60325
|
-
const headers =
|
|
59230
|
+
const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
|
|
60326
59231
|
const contentType = headers.get("Content-Type");
|
|
60327
59232
|
if (contentType?.startsWith("multipart/form-data") || contentType?.startsWith("application/x-www-form-urlencoded")) {
|
|
60328
|
-
return parseFormData(
|
|
59233
|
+
return parseFormData(request, { all, dot });
|
|
60329
59234
|
}
|
|
60330
59235
|
return {};
|
|
60331
59236
|
};
|
|
@@ -60427,8 +59332,8 @@ var tryDecode = (str, decoder) => {
|
|
|
60427
59332
|
}
|
|
60428
59333
|
};
|
|
60429
59334
|
var tryDecodeURI = (str) => tryDecode(str, decodeURI);
|
|
60430
|
-
var getPath = (
|
|
60431
|
-
const url =
|
|
59335
|
+
var getPath = (request) => {
|
|
59336
|
+
const url = request.url;
|
|
60432
59337
|
const start2 = url.indexOf("/", url.indexOf(":") + 4);
|
|
60433
59338
|
let i2 = start2;
|
|
60434
59339
|
for (;i2 < url.length; i2++) {
|
|
@@ -60443,8 +59348,8 @@ var getPath = (request2) => {
|
|
|
60443
59348
|
}
|
|
60444
59349
|
return url.slice(start2, i2);
|
|
60445
59350
|
};
|
|
60446
|
-
var getPathNoStrict = (
|
|
60447
|
-
const result = getPath(
|
|
59351
|
+
var getPathNoStrict = (request) => {
|
|
59352
|
+
const result = getPath(request);
|
|
60448
59353
|
return result.length > 1 && result.at(-1) === "/" ? result.slice(0, -1) : result;
|
|
60449
59354
|
};
|
|
60450
59355
|
var mergePath = (base, sub, ...rest) => {
|
|
@@ -60576,8 +59481,8 @@ var init_request = __esm(() => {
|
|
|
60576
59481
|
routeIndex = 0;
|
|
60577
59482
|
path;
|
|
60578
59483
|
bodyCache = {};
|
|
60579
|
-
constructor(
|
|
60580
|
-
this.raw =
|
|
59484
|
+
constructor(request, path2 = "/", matchResult = [[]]) {
|
|
59485
|
+
this.raw = request;
|
|
60581
59486
|
this.path = path2;
|
|
60582
59487
|
this.#matchResult = matchResult;
|
|
60583
59488
|
this.#validatedData = {};
|
|
@@ -61013,7 +59918,7 @@ var Hono = class {
|
|
|
61013
59918
|
} else {
|
|
61014
59919
|
optionHandler = options.optionHandler;
|
|
61015
59920
|
if (options.replaceRequest === false) {
|
|
61016
|
-
replaceRequest = (
|
|
59921
|
+
replaceRequest = (request) => request;
|
|
61017
59922
|
} else {
|
|
61018
59923
|
replaceRequest = options.replaceRequest;
|
|
61019
59924
|
}
|
|
@@ -61032,10 +59937,10 @@ var Hono = class {
|
|
|
61032
59937
|
replaceRequest ||= (() => {
|
|
61033
59938
|
const mergedPath = mergePath(this._basePath, path2);
|
|
61034
59939
|
const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
|
|
61035
|
-
return (
|
|
61036
|
-
const url = new URL(
|
|
59940
|
+
return (request) => {
|
|
59941
|
+
const url = new URL(request.url);
|
|
61037
59942
|
url.pathname = url.pathname.slice(pathPrefixLength) || "/";
|
|
61038
|
-
return new Request(url,
|
|
59943
|
+
return new Request(url, request);
|
|
61039
59944
|
};
|
|
61040
59945
|
})();
|
|
61041
59946
|
const handler = async (c, next) => {
|
|
@@ -61061,13 +59966,13 @@ var Hono = class {
|
|
|
61061
59966
|
}
|
|
61062
59967
|
throw err2;
|
|
61063
59968
|
}
|
|
61064
|
-
#dispatch(
|
|
59969
|
+
#dispatch(request, executionCtx, env, method) {
|
|
61065
59970
|
if (method === "HEAD") {
|
|
61066
|
-
return (async () => new Response(null, await this.#dispatch(
|
|
59971
|
+
return (async () => new Response(null, await this.#dispatch(request, executionCtx, env, "GET")))();
|
|
61067
59972
|
}
|
|
61068
|
-
const path2 = this.getPath(
|
|
59973
|
+
const path2 = this.getPath(request, { env });
|
|
61069
59974
|
const matchResult = this.router.match(method, path2);
|
|
61070
|
-
const c = new Context(
|
|
59975
|
+
const c = new Context(request, {
|
|
61071
59976
|
path: path2,
|
|
61072
59977
|
matchResult,
|
|
61073
59978
|
env,
|
|
@@ -61098,8 +60003,8 @@ var Hono = class {
|
|
|
61098
60003
|
}
|
|
61099
60004
|
})();
|
|
61100
60005
|
}
|
|
61101
|
-
fetch = (
|
|
61102
|
-
return this.#dispatch(
|
|
60006
|
+
fetch = (request, ...rest) => {
|
|
60007
|
+
return this.#dispatch(request, rest[1], rest[0], request.method);
|
|
61103
60008
|
};
|
|
61104
60009
|
request = (input, requestInit, Env, executionCtx) => {
|
|
61105
60010
|
if (input instanceof Request) {
|
|
@@ -69766,24 +68671,24 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
69766
68671
|
throw new Error("The service is no longer running" + closeData.reason);
|
|
69767
68672
|
streamIn.writeToStdin(encodePacket({ id, isRequest: false, value }));
|
|
69768
68673
|
};
|
|
69769
|
-
let handleRequest = async (id,
|
|
68674
|
+
let handleRequest = async (id, request) => {
|
|
69770
68675
|
try {
|
|
69771
|
-
if (
|
|
68676
|
+
if (request.command === "ping") {
|
|
69772
68677
|
sendResponse(id, {});
|
|
69773
68678
|
return;
|
|
69774
68679
|
}
|
|
69775
|
-
if (typeof
|
|
69776
|
-
const requestCallbacks = requestCallbacksByKey[
|
|
68680
|
+
if (typeof request.key === "number") {
|
|
68681
|
+
const requestCallbacks = requestCallbacksByKey[request.key];
|
|
69777
68682
|
if (!requestCallbacks) {
|
|
69778
68683
|
return;
|
|
69779
68684
|
}
|
|
69780
|
-
const callback = requestCallbacks[
|
|
68685
|
+
const callback = requestCallbacks[request.command];
|
|
69781
68686
|
if (callback) {
|
|
69782
|
-
await callback(id,
|
|
68687
|
+
await callback(id, request);
|
|
69783
68688
|
return;
|
|
69784
68689
|
}
|
|
69785
68690
|
}
|
|
69786
|
-
throw new Error(`Invalid command: ` +
|
|
68691
|
+
throw new Error(`Invalid command: ` + request.command);
|
|
69787
68692
|
} catch (e) {
|
|
69788
68693
|
const errors3 = [extractErrorMessageV8(e, streamIn, null, undefined, "")];
|
|
69789
68694
|
try {
|
|
@@ -69852,15 +68757,15 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
69852
68757
|
flags: flags2,
|
|
69853
68758
|
mangleCache
|
|
69854
68759
|
} = flagsForTransformOptions(callName, options, isTTY2, transformLogLevelDefault);
|
|
69855
|
-
let
|
|
68760
|
+
let request = {
|
|
69856
68761
|
command: "transform",
|
|
69857
68762
|
flags: flags2,
|
|
69858
68763
|
inputFS: inputPath !== null,
|
|
69859
68764
|
input: inputPath !== null ? encodeUTF8(inputPath) : typeof input === "string" ? encodeUTF8(input) : input
|
|
69860
68765
|
};
|
|
69861
68766
|
if (mangleCache)
|
|
69862
|
-
|
|
69863
|
-
sendRequest(refs,
|
|
68767
|
+
request.mangleCache = mangleCache;
|
|
68768
|
+
sendRequest(refs, request, (error, response) => {
|
|
69864
68769
|
if (error)
|
|
69865
68770
|
return callback(new Error(error), null);
|
|
69866
68771
|
let errors3 = replaceDetailsInMessages(response.errors, details);
|
|
@@ -69938,16 +68843,16 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
69938
68843
|
throw new Error(`Missing "kind" in ${callName}() call`);
|
|
69939
68844
|
if (kind !== "error" && kind !== "warning")
|
|
69940
68845
|
throw new Error(`Expected "kind" to be "error" or "warning" in ${callName}() call`);
|
|
69941
|
-
let
|
|
68846
|
+
let request = {
|
|
69942
68847
|
command: "format-msgs",
|
|
69943
68848
|
messages: sanitizeMessages(messages, "messages", null, "", terminalWidth),
|
|
69944
68849
|
isWarning: kind === "warning"
|
|
69945
68850
|
};
|
|
69946
68851
|
if (color !== undefined)
|
|
69947
|
-
|
|
68852
|
+
request.color = color;
|
|
69948
68853
|
if (terminalWidth !== undefined)
|
|
69949
|
-
|
|
69950
|
-
sendRequest(refs,
|
|
68854
|
+
request.terminalWidth = terminalWidth;
|
|
68855
|
+
sendRequest(refs, request, (error, response) => {
|
|
69951
68856
|
if (error)
|
|
69952
68857
|
return callback(new Error(error), null);
|
|
69953
68858
|
callback(null, response.messages);
|
|
@@ -69960,15 +68865,15 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
69960
68865
|
let color = getFlag(options, keys, "color", mustBeBoolean);
|
|
69961
68866
|
let verbose = getFlag(options, keys, "verbose", mustBeBoolean);
|
|
69962
68867
|
checkForInvalidFlags(options, keys, `in ${callName}() call`);
|
|
69963
|
-
let
|
|
68868
|
+
let request = {
|
|
69964
68869
|
command: "analyze-metafile",
|
|
69965
68870
|
metafile
|
|
69966
68871
|
};
|
|
69967
68872
|
if (color !== undefined)
|
|
69968
|
-
|
|
68873
|
+
request.color = color;
|
|
69969
68874
|
if (verbose !== undefined)
|
|
69970
|
-
|
|
69971
|
-
sendRequest(refs,
|
|
68875
|
+
request.verbose = verbose;
|
|
68876
|
+
sendRequest(refs, request, (error, response) => {
|
|
69972
68877
|
if (error)
|
|
69973
68878
|
return callback(new Error(error), null);
|
|
69974
68879
|
callback(null, response.result);
|
|
@@ -70041,7 +68946,7 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70041
68946
|
} = flagsForBuildOptions(callName, options, isTTY2, buildLogLevelDefault, writeDefault);
|
|
70042
68947
|
if (write && !streamIn.hasFS)
|
|
70043
68948
|
throw new Error(`The "write" option is unavailable in this environment`);
|
|
70044
|
-
const
|
|
68949
|
+
const request = {
|
|
70045
68950
|
command: "build",
|
|
70046
68951
|
key: buildKey,
|
|
70047
68952
|
entries,
|
|
@@ -70054,9 +68959,9 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70054
68959
|
context: isContext
|
|
70055
68960
|
};
|
|
70056
68961
|
if (requestPlugins)
|
|
70057
|
-
|
|
68962
|
+
request.plugins = requestPlugins;
|
|
70058
68963
|
if (mangleCache)
|
|
70059
|
-
|
|
68964
|
+
request.mangleCache = mangleCache;
|
|
70060
68965
|
const buildResponseToResult = (response, callback2) => {
|
|
70061
68966
|
const result = {
|
|
70062
68967
|
errors: replaceDetailsInMessages(response.errors, details),
|
|
@@ -70086,8 +68991,8 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70086
68991
|
let latestResultPromise;
|
|
70087
68992
|
let provideLatestResult;
|
|
70088
68993
|
if (isContext)
|
|
70089
|
-
requestCallbacks["on-end"] = (id,
|
|
70090
|
-
buildResponseToResult(
|
|
68994
|
+
requestCallbacks["on-end"] = (id, request2) => new Promise((resolve2) => {
|
|
68995
|
+
buildResponseToResult(request2, (err2, result, onEndErrors, onEndWarnings) => {
|
|
70091
68996
|
const response = {
|
|
70092
68997
|
errors: onEndErrors,
|
|
70093
68998
|
warnings: onEndWarnings
|
|
@@ -70100,7 +69005,7 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70100
69005
|
resolve2();
|
|
70101
69006
|
});
|
|
70102
69007
|
});
|
|
70103
|
-
sendRequest(refs,
|
|
69008
|
+
sendRequest(refs, request, (error, response) => {
|
|
70104
69009
|
if (error)
|
|
70105
69010
|
return callback(new Error(error), null);
|
|
70106
69011
|
if (!isContext) {
|
|
@@ -70123,11 +69028,11 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70123
69028
|
settlePromise = () => err2 ? reject(err2) : resolve2(result2);
|
|
70124
69029
|
};
|
|
70125
69030
|
const triggerAnotherBuild = () => {
|
|
70126
|
-
const
|
|
69031
|
+
const request2 = {
|
|
70127
69032
|
command: "rebuild",
|
|
70128
69033
|
key: buildKey
|
|
70129
69034
|
};
|
|
70130
|
-
sendRequest(refs,
|
|
69035
|
+
sendRequest(refs, request2, (error2, response2) => {
|
|
70131
69036
|
if (error2) {
|
|
70132
69037
|
reject(new Error(error2));
|
|
70133
69038
|
} else if (settlePromise) {
|
|
@@ -70147,13 +69052,13 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70147
69052
|
const keys = {};
|
|
70148
69053
|
const delay = getFlag(options2, keys, "delay", mustBeInteger);
|
|
70149
69054
|
checkForInvalidFlags(options2, keys, `in watch() call`);
|
|
70150
|
-
const
|
|
69055
|
+
const request2 = {
|
|
70151
69056
|
command: "watch",
|
|
70152
69057
|
key: buildKey
|
|
70153
69058
|
};
|
|
70154
69059
|
if (delay)
|
|
70155
|
-
|
|
70156
|
-
sendRequest(refs,
|
|
69060
|
+
request2.delay = delay;
|
|
69061
|
+
sendRequest(refs, request2, (error2) => {
|
|
70157
69062
|
if (error2)
|
|
70158
69063
|
reject(new Error(error2));
|
|
70159
69064
|
else
|
|
@@ -70173,33 +69078,33 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70173
69078
|
const cors2 = getFlag(options2, keys, "cors", mustBeObject);
|
|
70174
69079
|
const onRequest = getFlag(options2, keys, "onRequest", mustBeFunction);
|
|
70175
69080
|
checkForInvalidFlags(options2, keys, `in serve() call`);
|
|
70176
|
-
const
|
|
69081
|
+
const request2 = {
|
|
70177
69082
|
command: "serve",
|
|
70178
69083
|
key: buildKey,
|
|
70179
69084
|
onRequest: !!onRequest
|
|
70180
69085
|
};
|
|
70181
69086
|
if (port !== undefined)
|
|
70182
|
-
|
|
69087
|
+
request2.port = port;
|
|
70183
69088
|
if (host !== undefined)
|
|
70184
|
-
|
|
69089
|
+
request2.host = host;
|
|
70185
69090
|
if (servedir !== undefined)
|
|
70186
|
-
|
|
69091
|
+
request2.servedir = servedir;
|
|
70187
69092
|
if (keyfile !== undefined)
|
|
70188
|
-
|
|
69093
|
+
request2.keyfile = keyfile;
|
|
70189
69094
|
if (certfile !== undefined)
|
|
70190
|
-
|
|
69095
|
+
request2.certfile = certfile;
|
|
70191
69096
|
if (fallback !== undefined)
|
|
70192
|
-
|
|
69097
|
+
request2.fallback = fallback;
|
|
70193
69098
|
if (cors2) {
|
|
70194
69099
|
const corsKeys = {};
|
|
70195
69100
|
const origin = getFlag(cors2, corsKeys, "origin", mustBeStringOrArrayOfStrings);
|
|
70196
69101
|
checkForInvalidFlags(cors2, corsKeys, `on "cors" object`);
|
|
70197
69102
|
if (Array.isArray(origin))
|
|
70198
|
-
|
|
69103
|
+
request2.corsOrigin = origin;
|
|
70199
69104
|
else if (origin !== undefined)
|
|
70200
|
-
|
|
69105
|
+
request2.corsOrigin = [origin];
|
|
70201
69106
|
}
|
|
70202
|
-
sendRequest(refs,
|
|
69107
|
+
sendRequest(refs, request2, (error2, response2) => {
|
|
70203
69108
|
if (error2)
|
|
70204
69109
|
return reject(new Error(error2));
|
|
70205
69110
|
if (onRequest) {
|
|
@@ -70214,11 +69119,11 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70214
69119
|
cancel: () => new Promise((resolve2) => {
|
|
70215
69120
|
if (didDispose)
|
|
70216
69121
|
return resolve2();
|
|
70217
|
-
const
|
|
69122
|
+
const request2 = {
|
|
70218
69123
|
command: "cancel",
|
|
70219
69124
|
key: buildKey
|
|
70220
69125
|
};
|
|
70221
|
-
sendRequest(refs,
|
|
69126
|
+
sendRequest(refs, request2, () => {
|
|
70222
69127
|
resolve2();
|
|
70223
69128
|
});
|
|
70224
69129
|
}),
|
|
@@ -70226,11 +69131,11 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70226
69131
|
if (didDispose)
|
|
70227
69132
|
return resolve2();
|
|
70228
69133
|
didDispose = true;
|
|
70229
|
-
const
|
|
69134
|
+
const request2 = {
|
|
70230
69135
|
command: "dispose",
|
|
70231
69136
|
key: buildKey
|
|
70232
69137
|
};
|
|
70233
|
-
sendRequest(refs,
|
|
69138
|
+
sendRequest(refs, request2, () => {
|
|
70234
69139
|
resolve2();
|
|
70235
69140
|
scheduleOnDisposeCallbacks();
|
|
70236
69141
|
refs.unref();
|
|
@@ -70288,29 +69193,29 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70288
69193
|
let importAttributes = getFlag(options, keys2, "with", mustBeObject);
|
|
70289
69194
|
checkForInvalidFlags(options, keys2, "in resolve() call");
|
|
70290
69195
|
return new Promise((resolve22, reject) => {
|
|
70291
|
-
const
|
|
69196
|
+
const request = {
|
|
70292
69197
|
command: "resolve",
|
|
70293
69198
|
path: path3,
|
|
70294
69199
|
key: buildKey,
|
|
70295
69200
|
pluginName: name3
|
|
70296
69201
|
};
|
|
70297
69202
|
if (pluginName != null)
|
|
70298
|
-
|
|
69203
|
+
request.pluginName = pluginName;
|
|
70299
69204
|
if (importer != null)
|
|
70300
|
-
|
|
69205
|
+
request.importer = importer;
|
|
70301
69206
|
if (namespace != null)
|
|
70302
|
-
|
|
69207
|
+
request.namespace = namespace;
|
|
70303
69208
|
if (resolveDir != null)
|
|
70304
|
-
|
|
69209
|
+
request.resolveDir = resolveDir;
|
|
70305
69210
|
if (kind != null)
|
|
70306
|
-
|
|
69211
|
+
request.kind = kind;
|
|
70307
69212
|
else
|
|
70308
69213
|
throw new Error(`Must specify "kind" when calling "resolve"`);
|
|
70309
69214
|
if (pluginData != null)
|
|
70310
|
-
|
|
69215
|
+
request.pluginData = details.store(pluginData);
|
|
70311
69216
|
if (importAttributes != null)
|
|
70312
|
-
|
|
70313
|
-
sendRequest(refs,
|
|
69217
|
+
request.with = sanitizeStringMap(importAttributes, "with");
|
|
69218
|
+
sendRequest(refs, request, (error, response) => {
|
|
70314
69219
|
if (error !== null)
|
|
70315
69220
|
reject(new Error(error));
|
|
70316
69221
|
else
|
|
@@ -70380,7 +69285,7 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70380
69285
|
return { ok: false, error: e, pluginName: name3 };
|
|
70381
69286
|
}
|
|
70382
69287
|
}
|
|
70383
|
-
requestCallbacks["on-start"] = async (id,
|
|
69288
|
+
requestCallbacks["on-start"] = async (id, request) => {
|
|
70384
69289
|
details.clear();
|
|
70385
69290
|
let response = { errors: [], warnings: [] };
|
|
70386
69291
|
await Promise.all(onStartCallbacks.map(async ({ name: name3, callback, note }) => {
|
|
@@ -70404,19 +69309,19 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70404
69309
|
}));
|
|
70405
69310
|
sendResponse(id, response);
|
|
70406
69311
|
};
|
|
70407
|
-
requestCallbacks["on-resolve"] = async (id,
|
|
69312
|
+
requestCallbacks["on-resolve"] = async (id, request) => {
|
|
70408
69313
|
let response = {}, name3 = "", callback, note;
|
|
70409
|
-
for (let id2 of
|
|
69314
|
+
for (let id2 of request.ids) {
|
|
70410
69315
|
try {
|
|
70411
69316
|
({ name: name3, callback, note } = onResolveCallbacks[id2]);
|
|
70412
69317
|
let result = await callback({
|
|
70413
|
-
path:
|
|
70414
|
-
importer:
|
|
70415
|
-
namespace:
|
|
70416
|
-
resolveDir:
|
|
70417
|
-
kind:
|
|
70418
|
-
pluginData: details.load(
|
|
70419
|
-
with:
|
|
69318
|
+
path: request.path,
|
|
69319
|
+
importer: request.importer,
|
|
69320
|
+
namespace: request.namespace,
|
|
69321
|
+
resolveDir: request.resolveDir,
|
|
69322
|
+
kind: request.kind,
|
|
69323
|
+
pluginData: details.load(request.pluginData),
|
|
69324
|
+
with: request.with
|
|
70420
69325
|
});
|
|
70421
69326
|
if (result != null) {
|
|
70422
69327
|
if (typeof result !== "object")
|
|
@@ -70466,17 +69371,17 @@ is not a problem with esbuild. You need to fix your environment instead.
|
|
|
70466
69371
|
}
|
|
70467
69372
|
sendResponse(id, response);
|
|
70468
69373
|
};
|
|
70469
|
-
requestCallbacks["on-load"] = async (id,
|
|
69374
|
+
requestCallbacks["on-load"] = async (id, request) => {
|
|
70470
69375
|
let response = {}, name3 = "", callback, note;
|
|
70471
|
-
for (let id2 of
|
|
69376
|
+
for (let id2 of request.ids) {
|
|
70472
69377
|
try {
|
|
70473
69378
|
({ name: name3, callback, note } = onLoadCallbacks[id2]);
|
|
70474
69379
|
let result = await callback({
|
|
70475
|
-
path:
|
|
70476
|
-
namespace:
|
|
70477
|
-
suffix:
|
|
70478
|
-
pluginData: details.load(
|
|
70479
|
-
with:
|
|
69380
|
+
path: request.path,
|
|
69381
|
+
namespace: request.namespace,
|
|
69382
|
+
suffix: request.suffix,
|
|
69383
|
+
pluginData: details.load(request.pluginData),
|
|
69384
|
+
with: request.with
|
|
70480
69385
|
});
|
|
70481
69386
|
if (result != null) {
|
|
70482
69387
|
if (typeof result !== "object")
|
|
@@ -71003,7 +69908,7 @@ for your current platform.`);
|
|
|
71003
69908
|
return { binPath, isWASM };
|
|
71004
69909
|
}
|
|
71005
69910
|
var child_process = __require2("child_process");
|
|
71006
|
-
var
|
|
69911
|
+
var crypto42 = __require2("crypto");
|
|
71007
69912
|
var path22 = __require2("path");
|
|
71008
69913
|
var fs222 = __require2("fs");
|
|
71009
69914
|
var os22 = __require2("os");
|
|
@@ -71317,7 +70222,7 @@ More information: The file containing the code for esbuild's JavaScript API (${_
|
|
|
71317
70222
|
afterClose(null);
|
|
71318
70223
|
};
|
|
71319
70224
|
var randomFileName = () => {
|
|
71320
|
-
return path22.join(os22.tmpdir(), `esbuild-${
|
|
70225
|
+
return path22.join(os22.tmpdir(), `esbuild-${crypto42.randomBytes(32).toString("hex")}`);
|
|
71321
70226
|
};
|
|
71322
70227
|
var workerThreadService = null;
|
|
71323
70228
|
var startWorkerThreadService = (worker_threads2) => {
|
|
@@ -73904,8 +72809,8 @@ var require_node22 = __commonJS2((exports) => {
|
|
|
73904
72809
|
}
|
|
73905
72810
|
} catch (err2) {}
|
|
73906
72811
|
var bufferFrom = require_buffer_from();
|
|
73907
|
-
function dynamicRequire(mod,
|
|
73908
|
-
return mod.require(
|
|
72812
|
+
function dynamicRequire(mod, request) {
|
|
72813
|
+
return mod.require(request);
|
|
73909
72814
|
}
|
|
73910
72815
|
var errorFormatterInstalled = false;
|
|
73911
72816
|
var uncaughtShimInstalled = false;
|
|
@@ -76709,10 +75614,10 @@ If you have no idea what this means or what Pirates is, let me explain: Pirates
|
|
|
76709
75614
|
var Module2 = __require2("module");
|
|
76710
75615
|
var originalResolveFilename = Module2._resolveFilename;
|
|
76711
75616
|
var coreModules = getCoreModules(Module2.builtinModules);
|
|
76712
|
-
Module2._resolveFilename = function(
|
|
76713
|
-
var isCoreModule = coreModules.hasOwnProperty(
|
|
75617
|
+
Module2._resolveFilename = function(request, _parent) {
|
|
75618
|
+
var isCoreModule = coreModules.hasOwnProperty(request);
|
|
76714
75619
|
if (!isCoreModule) {
|
|
76715
|
-
var found = matchPath(
|
|
75620
|
+
var found = matchPath(request);
|
|
76716
75621
|
if (found) {
|
|
76717
75622
|
var modifiedArguments = __spreadArray([found], [].slice.call(arguments, 1), true);
|
|
76718
75623
|
return originalResolveFilename.apply(this, modifiedArguments);
|
|
@@ -76879,10 +75784,10 @@ If you have no idea what this means or what Pirates is, let me explain: Pirates
|
|
|
76879
75784
|
const matchPath = (0, import_tsconfig_paths.createMatchPath)(configLoaderResult.absoluteBaseUrl, configLoaderResult.paths, configLoaderResult.mainFields, configLoaderResult.addMatchAll);
|
|
76880
75785
|
const Module2 = __require2("module");
|
|
76881
75786
|
const originalResolveFilename = Module2._resolveFilename;
|
|
76882
|
-
Module2._resolveFilename = function(
|
|
76883
|
-
const isCoreModule = _module2.builtinModules.includes(
|
|
75787
|
+
Module2._resolveFilename = function(request, _parent) {
|
|
75788
|
+
const isCoreModule = _module2.builtinModules.includes(request);
|
|
76884
75789
|
if (!isCoreModule) {
|
|
76885
|
-
const found = matchPath(
|
|
75790
|
+
const found = matchPath(request);
|
|
76886
75791
|
if (found) {
|
|
76887
75792
|
const modifiedArguments = [found, ...[].slice.call(arguments, 1)];
|
|
76888
75793
|
return originalResolveFilename.apply(this, modifiedArguments);
|
|
@@ -79901,7 +78806,7 @@ var coerce2;
|
|
|
79901
78806
|
var init_types8;
|
|
79902
78807
|
var init_external2;
|
|
79903
78808
|
var init_v32;
|
|
79904
|
-
var
|
|
78809
|
+
var init_esm2;
|
|
79905
78810
|
var enumSchema;
|
|
79906
78811
|
var enumSchemaV1;
|
|
79907
78812
|
var indexColumn;
|
|
@@ -82371,7 +81276,7 @@ var sqlitePushIntrospect = async (db2, filters) => {
|
|
|
82371
81276
|
};
|
|
82372
81277
|
var generateDrizzleJson = (imports, prevId, schemaFilters, casing2) => {
|
|
82373
81278
|
const prepared = prepareFromExports(imports);
|
|
82374
|
-
const id =
|
|
81279
|
+
const id = randomUUID();
|
|
82375
81280
|
const snapshot = generatePgSnapshot(prepared.tables, prepared.enums, prepared.schemas, prepared.sequences, prepared.roles, prepared.policies, prepared.views, prepared.matViews, casing2, schemaFilters);
|
|
82376
81281
|
return fillPgSnapshot({
|
|
82377
81282
|
serialized: snapshot,
|
|
@@ -82420,7 +81325,7 @@ var pushSchema = async (imports, drizzleInstance, schemaFilters, tablesFilter, e
|
|
|
82420
81325
|
var generateSQLiteDrizzleJson = async (imports, prevId, casing2) => {
|
|
82421
81326
|
const { prepareFromExports: prepareFromExports5 } = await Promise.resolve().then(() => (init_sqliteImports(), sqliteImports_exports));
|
|
82422
81327
|
const prepared = prepareFromExports5(imports);
|
|
82423
|
-
const id =
|
|
81328
|
+
const id = randomUUID();
|
|
82424
81329
|
const snapshot = generateSqliteSnapshot(prepared.tables, prepared.views, casing2);
|
|
82425
81330
|
return {
|
|
82426
81331
|
...snapshot,
|
|
@@ -82471,7 +81376,7 @@ var pushSQLiteSchema = async (imports, drizzleInstance) => {
|
|
|
82471
81376
|
var generateMySQLDrizzleJson = async (imports, prevId, casing2) => {
|
|
82472
81377
|
const { prepareFromExports: prepareFromExports5 } = await Promise.resolve().then(() => (init_mysqlImports(), mysqlImports_exports));
|
|
82473
81378
|
const prepared = prepareFromExports5(imports);
|
|
82474
|
-
const id =
|
|
81379
|
+
const id = randomUUID();
|
|
82475
81380
|
const snapshot = generateMySqlSnapshot(prepared.tables, prepared.views, casing2);
|
|
82476
81381
|
return {
|
|
82477
81382
|
...snapshot,
|
|
@@ -82521,7 +81426,7 @@ var pushMySQLSchema = async (imports, drizzleInstance, databaseName) => {
|
|
|
82521
81426
|
var generateSingleStoreDrizzleJson = async (imports, prevId, casing2) => {
|
|
82522
81427
|
const { prepareFromExports: prepareFromExports5 } = await Promise.resolve().then(() => (init_singlestoreImports(), singlestoreImports_exports));
|
|
82523
81428
|
const prepared = prepareFromExports5(imports);
|
|
82524
|
-
const id =
|
|
81429
|
+
const id = randomUUID();
|
|
82525
81430
|
const snapshot = generateSingleStoreSnapshot(prepared.tables, casing2);
|
|
82526
81431
|
return {
|
|
82527
81432
|
...snapshot,
|
|
@@ -89311,7 +88216,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
89311
88216
|
init_external2();
|
|
89312
88217
|
}
|
|
89313
88218
|
});
|
|
89314
|
-
|
|
88219
|
+
init_esm2 = __esm3({
|
|
89315
88220
|
"../node_modules/.pnpm/zod@3.25.42/node_modules/zod/dist/esm/index.js"() {
|
|
89316
88221
|
init_v32();
|
|
89317
88222
|
init_v32();
|
|
@@ -89320,7 +88225,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
89320
88225
|
init_gelSchema = __esm3({
|
|
89321
88226
|
"src/serializer/gelSchema.ts"() {
|
|
89322
88227
|
init_global2();
|
|
89323
|
-
|
|
88228
|
+
init_esm2();
|
|
89324
88229
|
enumSchema = objectType2({
|
|
89325
88230
|
name: stringType2(),
|
|
89326
88231
|
schema: stringType2(),
|
|
@@ -89574,7 +88479,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
89574
88479
|
});
|
|
89575
88480
|
init_mysqlSchema = __esm3({
|
|
89576
88481
|
"src/serializer/mysqlSchema.ts"() {
|
|
89577
|
-
|
|
88482
|
+
init_esm2();
|
|
89578
88483
|
init_global2();
|
|
89579
88484
|
index22 = objectType2({
|
|
89580
88485
|
name: stringType2(),
|
|
@@ -89880,7 +88785,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
89880
88785
|
init_pgSchema = __esm3({
|
|
89881
88786
|
"src/serializer/pgSchema.ts"() {
|
|
89882
88787
|
init_global2();
|
|
89883
|
-
|
|
88788
|
+
init_esm2();
|
|
89884
88789
|
indexV2 = objectType2({
|
|
89885
88790
|
name: stringType2(),
|
|
89886
88791
|
columns: recordType2(stringType2(), objectType2({
|
|
@@ -90601,7 +89506,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
90601
89506
|
});
|
|
90602
89507
|
init_singlestoreSchema = __esm3({
|
|
90603
89508
|
"src/serializer/singlestoreSchema.ts"() {
|
|
90604
|
-
|
|
89509
|
+
init_esm2();
|
|
90605
89510
|
init_global2();
|
|
90606
89511
|
index4 = objectType2({
|
|
90607
89512
|
name: stringType2(),
|
|
@@ -90760,7 +89665,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
90760
89665
|
});
|
|
90761
89666
|
init_sqliteSchema = __esm3({
|
|
90762
89667
|
"src/serializer/sqliteSchema.ts"() {
|
|
90763
|
-
|
|
89668
|
+
init_esm2();
|
|
90764
89669
|
init_global2();
|
|
90765
89670
|
index5 = objectType2({
|
|
90766
89671
|
name: stringType2(),
|
|
@@ -98438,7 +97343,7 @@ ${BREAKPOINT}ALTER TABLE ${tableNameWithSchema} ADD CONSTRAINT "${statement.newC
|
|
|
98438
97343
|
});
|
|
98439
97344
|
init_snapshotsDiffer = __esm3({
|
|
98440
97345
|
"src/snapshotsDiffer.ts"() {
|
|
98441
|
-
|
|
97346
|
+
init_esm2();
|
|
98442
97347
|
init_jsonDiffer();
|
|
98443
97348
|
init_sqlgenerator();
|
|
98444
97349
|
init_jsonStatements();
|
|
@@ -100549,7 +99454,7 @@ ${BREAKPOINT}ALTER TABLE ${tableNameWithSchema} ADD CONSTRAINT "${statement.newC
|
|
|
100549
99454
|
});
|
|
100550
99455
|
init_schemaValidator = __esm3({
|
|
100551
99456
|
"src/schemaValidator.ts"() {
|
|
100552
|
-
|
|
99457
|
+
init_esm2();
|
|
100553
99458
|
init_mysqlSchema();
|
|
100554
99459
|
init_pgSchema();
|
|
100555
99460
|
init_singlestoreSchema();
|
|
@@ -100567,7 +99472,7 @@ ${BREAKPOINT}ALTER TABLE ${tableNameWithSchema} ADD CONSTRAINT "${statement.newC
|
|
|
100567
99472
|
});
|
|
100568
99473
|
init_common2 = __esm3({
|
|
100569
99474
|
"src/cli/validations/common.ts"() {
|
|
100570
|
-
|
|
99475
|
+
init_esm2();
|
|
100571
99476
|
init_schemaValidator();
|
|
100572
99477
|
init_outputs();
|
|
100573
99478
|
sqliteDriversLiterals = [
|
|
@@ -115769,7 +114674,7 @@ AND
|
|
|
115769
114674
|
});
|
|
115770
114675
|
init_cli = __esm3({
|
|
115771
114676
|
"src/cli/validations/cli.ts"() {
|
|
115772
|
-
|
|
114677
|
+
init_esm2();
|
|
115773
114678
|
init_schemaValidator();
|
|
115774
114679
|
init_common2();
|
|
115775
114680
|
cliConfigGenerate = objectType2({
|
|
@@ -115830,7 +114735,7 @@ AND
|
|
|
115830
114735
|
});
|
|
115831
114736
|
init_gel = __esm3({
|
|
115832
114737
|
"src/cli/validations/gel.ts"() {
|
|
115833
|
-
|
|
114738
|
+
init_esm2();
|
|
115834
114739
|
init_views();
|
|
115835
114740
|
init_common2();
|
|
115836
114741
|
gelCredentials = unionType2([
|
|
@@ -115874,7 +114779,7 @@ AND
|
|
|
115874
114779
|
});
|
|
115875
114780
|
init_libsql = __esm3({
|
|
115876
114781
|
"src/cli/validations/libsql.ts"() {
|
|
115877
|
-
|
|
114782
|
+
init_esm2();
|
|
115878
114783
|
init_views();
|
|
115879
114784
|
init_common2();
|
|
115880
114785
|
libSQLCredentials = objectType2({
|
|
@@ -115885,7 +114790,7 @@ AND
|
|
|
115885
114790
|
});
|
|
115886
114791
|
init_mysql = __esm3({
|
|
115887
114792
|
"src/cli/validations/mysql.ts"() {
|
|
115888
|
-
|
|
114793
|
+
init_esm2();
|
|
115889
114794
|
init_views();
|
|
115890
114795
|
init_common2();
|
|
115891
114796
|
init_outputs();
|
|
@@ -115918,7 +114823,7 @@ AND
|
|
|
115918
114823
|
});
|
|
115919
114824
|
init_postgres = __esm3({
|
|
115920
114825
|
"src/cli/validations/postgres.ts"() {
|
|
115921
|
-
|
|
114826
|
+
init_esm2();
|
|
115922
114827
|
init_views();
|
|
115923
114828
|
init_common2();
|
|
115924
114829
|
postgresCredentials = unionType2([
|
|
@@ -115963,7 +114868,7 @@ AND
|
|
|
115963
114868
|
});
|
|
115964
114869
|
init_singlestore = __esm3({
|
|
115965
114870
|
"src/cli/validations/singlestore.ts"() {
|
|
115966
|
-
|
|
114871
|
+
init_esm2();
|
|
115967
114872
|
init_views();
|
|
115968
114873
|
init_common2();
|
|
115969
114874
|
init_outputs();
|
|
@@ -115997,7 +114902,7 @@ AND
|
|
|
115997
114902
|
init_sqlite = __esm3({
|
|
115998
114903
|
"src/cli/validations/sqlite.ts"() {
|
|
115999
114904
|
init_global2();
|
|
116000
|
-
|
|
114905
|
+
init_esm2();
|
|
116001
114906
|
init_views();
|
|
116002
114907
|
init_common2();
|
|
116003
114908
|
sqliteCredentials = unionType2([
|
|
@@ -116024,7 +114929,7 @@ AND
|
|
|
116024
114929
|
});
|
|
116025
114930
|
init_studio = __esm3({
|
|
116026
114931
|
"src/cli/validations/studio.ts"() {
|
|
116027
|
-
|
|
114932
|
+
init_esm2();
|
|
116028
114933
|
init_schemaValidator();
|
|
116029
114934
|
init_common2();
|
|
116030
114935
|
init_mysql();
|
|
@@ -116056,7 +114961,7 @@ AND
|
|
|
116056
114961
|
init_utils9 = __esm3({
|
|
116057
114962
|
"src/cli/commands/utils.ts"() {
|
|
116058
114963
|
import_hanji7 = __toESM22(require_hanji());
|
|
116059
|
-
|
|
114964
|
+
init_esm2();
|
|
116060
114965
|
init_getTablesFilterByExtensions();
|
|
116061
114966
|
init_global2();
|
|
116062
114967
|
init_schemaValidator();
|
|
@@ -121502,6 +120407,137 @@ var init_auth_util = __esm(() => {
|
|
|
121502
120407
|
init_errors();
|
|
121503
120408
|
init_types9();
|
|
121504
120409
|
});
|
|
120410
|
+
function generateUsername(email) {
|
|
120411
|
+
const baseUsername = (email.split("@")[0] || "user").toLowerCase();
|
|
120412
|
+
const cleanUsername = baseUsername.replace(/[^a-z0-9]/g, "");
|
|
120413
|
+
const randomSuffix = Math.random().toString(36).substring(2, 7);
|
|
120414
|
+
return `${cleanUsername}_${randomSuffix}`;
|
|
120415
|
+
}
|
|
120416
|
+
function extractRedirectPath(targetUri, currentHost) {
|
|
120417
|
+
try {
|
|
120418
|
+
const targetUrl = new URL(targetUri);
|
|
120419
|
+
if (targetUrl.hostname === currentHost) {
|
|
120420
|
+
return targetUrl.pathname + targetUrl.search;
|
|
120421
|
+
}
|
|
120422
|
+
} catch {}
|
|
120423
|
+
return "/";
|
|
120424
|
+
}
|
|
120425
|
+
function validateLtiClaims(claims) {
|
|
120426
|
+
const messageType = claims["https://purl.imsglobal.org/spec/lti/claim/message_type"];
|
|
120427
|
+
const version4 = claims["https://purl.imsglobal.org/spec/lti/claim/version"];
|
|
120428
|
+
if (messageType !== "LtiResourceLinkRequest") {
|
|
120429
|
+
return `Invalid LTI message type: ${messageType}`;
|
|
120430
|
+
}
|
|
120431
|
+
if (version4 !== "1.3.0") {
|
|
120432
|
+
return `Unsupported LTI version: ${version4}`;
|
|
120433
|
+
}
|
|
120434
|
+
return null;
|
|
120435
|
+
}
|
|
120436
|
+
var init_lti_util = () => {};
|
|
120437
|
+
async function provisionLtiUser(db2, claims) {
|
|
120438
|
+
const database2 = db2;
|
|
120439
|
+
const email = claims.email;
|
|
120440
|
+
const ltiTimebackId = claims.sub;
|
|
120441
|
+
const providerId = AUTH_PROVIDER_IDS.TIMEBACK_LTI;
|
|
120442
|
+
if (!email) {
|
|
120443
|
+
throw new ValidationError("Email is required in LTI claims");
|
|
120444
|
+
}
|
|
120445
|
+
const existingAccount = await database2.query.accounts.findFirst({
|
|
120446
|
+
where: and(eq(accounts.accountId, ltiTimebackId), eq(accounts.providerId, providerId))
|
|
120447
|
+
});
|
|
120448
|
+
if (existingAccount) {
|
|
120449
|
+
const user = await database2.query.users.findFirst({
|
|
120450
|
+
where: eq(users.id, existingAccount.userId)
|
|
120451
|
+
});
|
|
120452
|
+
if (user) {
|
|
120453
|
+
logger32.info("Found user by LTI account", {
|
|
120454
|
+
userId: user.id,
|
|
120455
|
+
ltiTimebackId
|
|
120456
|
+
});
|
|
120457
|
+
return user;
|
|
120458
|
+
}
|
|
120459
|
+
}
|
|
120460
|
+
const existingUser = await database2.query.users.findFirst({
|
|
120461
|
+
where: eq(users.email, email)
|
|
120462
|
+
});
|
|
120463
|
+
if (existingUser) {
|
|
120464
|
+
await database2.transaction(async (tx) => {
|
|
120465
|
+
const existingLtiAccount = await tx.query.accounts.findFirst({
|
|
120466
|
+
where: and(eq(accounts.userId, existingUser.id), eq(accounts.providerId, providerId))
|
|
120467
|
+
});
|
|
120468
|
+
if (!existingLtiAccount) {
|
|
120469
|
+
const [account] = await tx.insert(accounts).values({
|
|
120470
|
+
id: crypto4.randomUUID(),
|
|
120471
|
+
userId: existingUser.id,
|
|
120472
|
+
accountId: ltiTimebackId,
|
|
120473
|
+
providerId,
|
|
120474
|
+
accessToken: null,
|
|
120475
|
+
refreshToken: null,
|
|
120476
|
+
accessTokenExpiresAt: null,
|
|
120477
|
+
refreshTokenExpiresAt: null,
|
|
120478
|
+
createdAt: new Date,
|
|
120479
|
+
updatedAt: new Date
|
|
120480
|
+
}).returning({ id: accounts.id });
|
|
120481
|
+
if (!account) {
|
|
120482
|
+
logger32.error("LTI account link insert returned no rows", {
|
|
120483
|
+
userId: existingUser.id,
|
|
120484
|
+
ltiTimebackId
|
|
120485
|
+
});
|
|
120486
|
+
throw new InternalError("Failed to link LTI account");
|
|
120487
|
+
}
|
|
120488
|
+
logger32.info("Linked LTI account to existing user", {
|
|
120489
|
+
userId: existingUser.id,
|
|
120490
|
+
ltiTimebackId
|
|
120491
|
+
});
|
|
120492
|
+
}
|
|
120493
|
+
});
|
|
120494
|
+
return existingUser;
|
|
120495
|
+
}
|
|
120496
|
+
const newUserId = crypto4.randomUUID();
|
|
120497
|
+
const createdUser = await database2.transaction(async (tx) => {
|
|
120498
|
+
const [insertedUser] = await tx.insert(users).values({
|
|
120499
|
+
id: newUserId,
|
|
120500
|
+
email,
|
|
120501
|
+
emailVerified: true,
|
|
120502
|
+
username: generateUsername(email),
|
|
120503
|
+
name: claims.name || claims.given_name || email.split("@")[0] || "Timeback User",
|
|
120504
|
+
createdAt: new Date,
|
|
120505
|
+
updatedAt: new Date
|
|
120506
|
+
}).returning();
|
|
120507
|
+
if (!insertedUser) {
|
|
120508
|
+
logger32.error("LTI user insert returned no rows", { email, ltiTimebackId });
|
|
120509
|
+
throw new InternalError("Failed to create user");
|
|
120510
|
+
}
|
|
120511
|
+
await tx.insert(accounts).values({
|
|
120512
|
+
id: crypto4.randomUUID(),
|
|
120513
|
+
userId: newUserId,
|
|
120514
|
+
accountId: ltiTimebackId,
|
|
120515
|
+
providerId,
|
|
120516
|
+
accessToken: null,
|
|
120517
|
+
refreshToken: null,
|
|
120518
|
+
accessTokenExpiresAt: null,
|
|
120519
|
+
refreshTokenExpiresAt: null,
|
|
120520
|
+
createdAt: new Date,
|
|
120521
|
+
updatedAt: new Date
|
|
120522
|
+
});
|
|
120523
|
+
logger32.info("Provisioned new user from LTI", {
|
|
120524
|
+
userId: insertedUser.id,
|
|
120525
|
+
ltiTimebackId
|
|
120526
|
+
});
|
|
120527
|
+
return insertedUser;
|
|
120528
|
+
});
|
|
120529
|
+
return createdUser;
|
|
120530
|
+
}
|
|
120531
|
+
var logger32;
|
|
120532
|
+
var init_lti_provisioning = __esm(() => {
|
|
120533
|
+
init_drizzle_orm();
|
|
120534
|
+
init_src();
|
|
120535
|
+
init_tables_index();
|
|
120536
|
+
init_src2();
|
|
120537
|
+
init_errors();
|
|
120538
|
+
init_lti_util();
|
|
120539
|
+
logger32 = log.scope("LtiProvisioning");
|
|
120540
|
+
});
|
|
121505
120541
|
function formatZodError(error2) {
|
|
121506
120542
|
const flat = error2.flatten();
|
|
121507
120543
|
const result = {};
|
|
@@ -121524,10 +120560,11 @@ var init_utils11 = __esm(() => {
|
|
|
121524
120560
|
init_deployment_util();
|
|
121525
120561
|
init_leaderboard_util();
|
|
121526
120562
|
init_lti_util();
|
|
120563
|
+
init_lti_provisioning();
|
|
121527
120564
|
init_scope_util();
|
|
121528
120565
|
init_timeback_util();
|
|
121529
120566
|
});
|
|
121530
|
-
var
|
|
120567
|
+
var logger33;
|
|
121531
120568
|
var listCurrent;
|
|
121532
120569
|
var listHistory;
|
|
121533
120570
|
var postProgress;
|
|
@@ -121538,14 +120575,14 @@ var init_achievement_controller = __esm(() => {
|
|
|
121538
120575
|
init_src2();
|
|
121539
120576
|
init_errors();
|
|
121540
120577
|
init_utils11();
|
|
121541
|
-
|
|
120578
|
+
logger33 = log.scope("AchievementController");
|
|
121542
120579
|
listCurrent = requireAuth(async (ctx) => {
|
|
121543
|
-
|
|
120580
|
+
logger33.debug("Listing current achievements", { userId: ctx.user.id, gameId: ctx.gameId });
|
|
121544
120581
|
return ctx.services.achievement.listCurrent(ctx.user, ctx.gameId);
|
|
121545
120582
|
});
|
|
121546
120583
|
listHistory = requireAuth(async (ctx) => {
|
|
121547
120584
|
const limit = Math.max(1, Math.min(100, Number(ctx.url.searchParams.get("limit")) || 20));
|
|
121548
|
-
|
|
120585
|
+
logger33.debug("Listing achievement history", { userId: ctx.user.id, limit });
|
|
121549
120586
|
return ctx.services.achievement.listHistory(ctx.user, limit);
|
|
121550
120587
|
});
|
|
121551
120588
|
postProgress = requireAuth(async (ctx) => {
|
|
@@ -121556,12 +120593,12 @@ var init_achievement_controller = __esm(() => {
|
|
|
121556
120593
|
} catch (error2) {
|
|
121557
120594
|
if (error2 instanceof exports_external.ZodError) {
|
|
121558
120595
|
const details = formatZodError(error2);
|
|
121559
|
-
|
|
120596
|
+
logger33.warn("Submit achievement progress validation failed", { details });
|
|
121560
120597
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
121561
120598
|
}
|
|
121562
120599
|
throw ApiError.badRequest("Invalid JSON body");
|
|
121563
120600
|
}
|
|
121564
|
-
|
|
120601
|
+
logger33.debug("Submitting progress", {
|
|
121565
120602
|
userId: ctx.user.id,
|
|
121566
120603
|
achievementId: body2.achievementId
|
|
121567
120604
|
});
|
|
@@ -121573,15 +120610,15 @@ var init_achievement_controller = __esm(() => {
|
|
|
121573
120610
|
postProgress
|
|
121574
120611
|
};
|
|
121575
120612
|
});
|
|
121576
|
-
var
|
|
120613
|
+
var logger34;
|
|
121577
120614
|
var getAllowedOrigins;
|
|
121578
120615
|
var init_admin_controller = __esm(() => {
|
|
121579
120616
|
init_src2();
|
|
121580
120617
|
init_utils11();
|
|
121581
|
-
|
|
120618
|
+
logger34 = log.scope("AdminController");
|
|
121582
120619
|
getAllowedOrigins = requireAdmin(async (ctx) => {
|
|
121583
120620
|
const shouldRefresh = ctx.url.searchParams.get("refresh") === "true";
|
|
121584
|
-
|
|
120621
|
+
logger34.debug("Getting allowed origins", { userId: ctx.user.id, refresh: shouldRefresh });
|
|
121585
120622
|
if (shouldRefresh) {
|
|
121586
120623
|
await ctx.providers.cache.refreshGameOrigins();
|
|
121587
120624
|
}
|
|
@@ -121594,7 +120631,7 @@ var init_admin_controller = __esm(() => {
|
|
|
121594
120631
|
};
|
|
121595
120632
|
});
|
|
121596
120633
|
});
|
|
121597
|
-
var
|
|
120634
|
+
var logger35;
|
|
121598
120635
|
var listFiles;
|
|
121599
120636
|
var getFile;
|
|
121600
120637
|
var putFile;
|
|
@@ -121606,7 +120643,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
121606
120643
|
init_src2();
|
|
121607
120644
|
init_errors();
|
|
121608
120645
|
init_utils11();
|
|
121609
|
-
|
|
120646
|
+
logger35 = log.scope("BucketController");
|
|
121610
120647
|
listFiles = requireDeveloper(async (ctx) => {
|
|
121611
120648
|
const slug2 = ctx.params.slug;
|
|
121612
120649
|
if (!slug2) {
|
|
@@ -121614,7 +120651,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
121614
120651
|
}
|
|
121615
120652
|
const url = ctx.url;
|
|
121616
120653
|
const prefix2 = url.searchParams.get("prefix") || undefined;
|
|
121617
|
-
|
|
120654
|
+
logger35.debug("Listing files", { userId: ctx.user.id, slug: slug2, prefix: prefix2 });
|
|
121618
120655
|
const files = await ctx.services.bucket.listFiles(slug2, ctx.user, prefix2);
|
|
121619
120656
|
return { files };
|
|
121620
120657
|
});
|
|
@@ -121624,7 +120661,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
121624
120661
|
if (!slug2 || !key) {
|
|
121625
120662
|
throw ApiError.badRequest("Missing game slug or file key");
|
|
121626
120663
|
}
|
|
121627
|
-
|
|
120664
|
+
logger35.debug("Getting file", { userId: ctx.user.id, slug: slug2, key });
|
|
121628
120665
|
const object = await ctx.services.bucket.getFile(slug2, key, ctx.user);
|
|
121629
120666
|
return new Response(Buffer.from(object.body), {
|
|
121630
120667
|
status: 200,
|
|
@@ -121643,7 +120680,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
121643
120680
|
const arrayBuffer = await ctx.request.arrayBuffer();
|
|
121644
120681
|
const body2 = new Uint8Array(arrayBuffer);
|
|
121645
120682
|
const contentType = ctx.request.headers.get("content-type") || undefined;
|
|
121646
|
-
|
|
120683
|
+
logger35.debug("Uploading file", {
|
|
121647
120684
|
userId: ctx.user.id,
|
|
121648
120685
|
slug: slug2,
|
|
121649
120686
|
key,
|
|
@@ -121659,7 +120696,7 @@ var init_bucket_controller = __esm(() => {
|
|
|
121659
120696
|
if (!slug2 || !key) {
|
|
121660
120697
|
throw ApiError.badRequest("Missing game slug or file key");
|
|
121661
120698
|
}
|
|
121662
|
-
|
|
120699
|
+
logger35.debug("Deleting file", { userId: ctx.user.id, slug: slug2, key });
|
|
121663
120700
|
await ctx.services.bucket.deleteFile(slug2, key, ctx.user);
|
|
121664
120701
|
return { success: true, key };
|
|
121665
120702
|
});
|
|
@@ -121671,12 +120708,12 @@ var init_bucket_controller = __esm(() => {
|
|
|
121671
120708
|
} catch (error2) {
|
|
121672
120709
|
if (error2 instanceof exports_external.ZodError) {
|
|
121673
120710
|
const details = formatZodError(error2);
|
|
121674
|
-
|
|
120711
|
+
logger35.warn("Initiate upload validation failed", { details });
|
|
121675
120712
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
121676
120713
|
}
|
|
121677
120714
|
throw ApiError.badRequest("Invalid JSON body");
|
|
121678
120715
|
}
|
|
121679
|
-
|
|
120716
|
+
logger35.debug("Initiating multipart upload", {
|
|
121680
120717
|
userId: ctx.user.id,
|
|
121681
120718
|
gameId: body2.gameId,
|
|
121682
120719
|
fileName: body2.fileName
|
|
@@ -121691,10 +120728,10 @@ async function listComponents(ctx) {
|
|
|
121691
120728
|
if (!isNaN(parsed) && isFinite(parsed)) {
|
|
121692
120729
|
level = Math.floor(Math.max(0, parsed));
|
|
121693
120730
|
}
|
|
121694
|
-
|
|
120731
|
+
logger36.debug("Listing components", { level });
|
|
121695
120732
|
return ctx.services.character.listAvailableComponents(level);
|
|
121696
120733
|
}
|
|
121697
|
-
var
|
|
120734
|
+
var logger36;
|
|
121698
120735
|
var get;
|
|
121699
120736
|
var getByUserId;
|
|
121700
120737
|
var create;
|
|
@@ -121708,9 +120745,9 @@ var init_character_controller = __esm(() => {
|
|
|
121708
120745
|
init_src2();
|
|
121709
120746
|
init_errors();
|
|
121710
120747
|
init_utils11();
|
|
121711
|
-
|
|
120748
|
+
logger36 = log.scope("CharacterController");
|
|
121712
120749
|
get = requireAuth(async (ctx) => {
|
|
121713
|
-
|
|
120750
|
+
logger36.debug("Getting character", { userId: ctx.user.id });
|
|
121714
120751
|
return ctx.services.character.getByUser(ctx.user);
|
|
121715
120752
|
});
|
|
121716
120753
|
getByUserId = requireAuth(async (ctx) => {
|
|
@@ -121718,7 +120755,7 @@ var init_character_controller = __esm(() => {
|
|
|
121718
120755
|
if (!userId) {
|
|
121719
120756
|
throw ApiError.badRequest("User ID is required in the URL path");
|
|
121720
120757
|
}
|
|
121721
|
-
|
|
120758
|
+
logger36.debug("Getting character by user ID", { requestedUserId: userId });
|
|
121722
120759
|
return ctx.services.character.getByUserId(userId);
|
|
121723
120760
|
});
|
|
121724
120761
|
create = requireAuth(async (ctx) => {
|
|
@@ -121729,12 +120766,12 @@ var init_character_controller = __esm(() => {
|
|
|
121729
120766
|
} catch (error2) {
|
|
121730
120767
|
if (error2 instanceof exports_external.ZodError) {
|
|
121731
120768
|
const details = formatZodError(error2);
|
|
121732
|
-
|
|
120769
|
+
logger36.warn("Create character validation failed", { details });
|
|
121733
120770
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
121734
120771
|
}
|
|
121735
120772
|
throw ApiError.badRequest("Invalid JSON body");
|
|
121736
120773
|
}
|
|
121737
|
-
|
|
120774
|
+
logger36.debug("Creating character", {
|
|
121738
120775
|
userId: ctx.user.id,
|
|
121739
120776
|
bodyComponentId: body2.bodyComponentId,
|
|
121740
120777
|
hairstyleComponentId: body2.hairstyleComponentId
|
|
@@ -121749,12 +120786,12 @@ var init_character_controller = __esm(() => {
|
|
|
121749
120786
|
} catch (error2) {
|
|
121750
120787
|
if (error2 instanceof exports_external.ZodError) {
|
|
121751
120788
|
const details = formatZodError(error2);
|
|
121752
|
-
|
|
120789
|
+
logger36.warn("Update character validation failed", { details });
|
|
121753
120790
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
121754
120791
|
}
|
|
121755
120792
|
throw ApiError.badRequest("Invalid JSON body");
|
|
121756
120793
|
}
|
|
121757
|
-
|
|
120794
|
+
logger36.debug("Updating character", {
|
|
121758
120795
|
userId: ctx.user.id,
|
|
121759
120796
|
bodyComponentId: body2.bodyComponentId,
|
|
121760
120797
|
hairstyleComponentId: body2.hairstyleComponentId,
|
|
@@ -121770,12 +120807,12 @@ var init_character_controller = __esm(() => {
|
|
|
121770
120807
|
} catch (error2) {
|
|
121771
120808
|
if (error2 instanceof exports_external.ZodError) {
|
|
121772
120809
|
const details = formatZodError(error2);
|
|
121773
|
-
|
|
120810
|
+
logger36.warn("Equip accessory validation failed", { details });
|
|
121774
120811
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
121775
120812
|
}
|
|
121776
120813
|
throw ApiError.badRequest("Invalid JSON body");
|
|
121777
120814
|
}
|
|
121778
|
-
|
|
120815
|
+
logger36.debug("Equipping accessory", {
|
|
121779
120816
|
userId: ctx.user.id,
|
|
121780
120817
|
slot: body2.slot,
|
|
121781
120818
|
accessoryComponentId: body2.accessoryComponentId
|
|
@@ -121787,7 +120824,7 @@ var init_character_controller = __esm(() => {
|
|
|
121787
120824
|
if (!slot) {
|
|
121788
120825
|
throw ApiError.badRequest("Slot is required in the URL path");
|
|
121789
120826
|
}
|
|
121790
|
-
|
|
120827
|
+
logger36.debug("Removing accessory", { userId: ctx.user.id, slot });
|
|
121791
120828
|
await ctx.services.character.removeAccessory(slot, ctx.user);
|
|
121792
120829
|
return { success: true };
|
|
121793
120830
|
});
|
|
@@ -121801,7 +120838,7 @@ var init_character_controller = __esm(() => {
|
|
|
121801
120838
|
removeAccessory
|
|
121802
120839
|
};
|
|
121803
120840
|
});
|
|
121804
|
-
var
|
|
120841
|
+
var logger37;
|
|
121805
120842
|
var list;
|
|
121806
120843
|
var getById;
|
|
121807
120844
|
var create2;
|
|
@@ -121815,9 +120852,9 @@ var init_currency_controller = __esm(() => {
|
|
|
121815
120852
|
init_src4();
|
|
121816
120853
|
init_errors();
|
|
121817
120854
|
init_utils11();
|
|
121818
|
-
|
|
120855
|
+
logger37 = log.scope("CurrencyController");
|
|
121819
120856
|
list = requireAuth(async (ctx) => {
|
|
121820
|
-
|
|
120857
|
+
logger37.debug("Listing currencies", { userId: ctx.user.id });
|
|
121821
120858
|
return ctx.services.currency.list();
|
|
121822
120859
|
});
|
|
121823
120860
|
getById = requireAuth(async (ctx) => {
|
|
@@ -121828,7 +120865,7 @@ var init_currency_controller = __esm(() => {
|
|
|
121828
120865
|
if (!isValidUUID(currencyId)) {
|
|
121829
120866
|
throw ApiError.unprocessableEntity("currencyId must be a valid UUID format");
|
|
121830
120867
|
}
|
|
121831
|
-
|
|
120868
|
+
logger37.debug("Getting currency", { userId: ctx.user.id, currencyId });
|
|
121832
120869
|
return ctx.services.currency.getById(currencyId);
|
|
121833
120870
|
});
|
|
121834
120871
|
create2 = requireAdmin(async (ctx) => {
|
|
@@ -121839,12 +120876,12 @@ var init_currency_controller = __esm(() => {
|
|
|
121839
120876
|
} catch (error2) {
|
|
121840
120877
|
if (error2 instanceof exports_external.ZodError) {
|
|
121841
120878
|
const details = formatZodError(error2);
|
|
121842
|
-
|
|
120879
|
+
logger37.warn("Create currency validation failed", { details });
|
|
121843
120880
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
121844
120881
|
}
|
|
121845
120882
|
throw ApiError.badRequest("Invalid JSON body");
|
|
121846
120883
|
}
|
|
121847
|
-
|
|
120884
|
+
logger37.debug("Creating currency", {
|
|
121848
120885
|
userId: ctx.user.id,
|
|
121849
120886
|
symbol: body2.symbol,
|
|
121850
120887
|
itemId: body2.itemId,
|
|
@@ -121867,12 +120904,12 @@ var init_currency_controller = __esm(() => {
|
|
|
121867
120904
|
} catch (error2) {
|
|
121868
120905
|
if (error2 instanceof exports_external.ZodError) {
|
|
121869
120906
|
const details = formatZodError(error2);
|
|
121870
|
-
|
|
120907
|
+
logger37.warn("Update currency validation failed", { details });
|
|
121871
120908
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
121872
120909
|
}
|
|
121873
120910
|
throw ApiError.badRequest("Invalid JSON body");
|
|
121874
120911
|
}
|
|
121875
|
-
|
|
120912
|
+
logger37.debug("Updating currency", {
|
|
121876
120913
|
userId: ctx.user.id,
|
|
121877
120914
|
currencyId,
|
|
121878
120915
|
symbol: body2.symbol,
|
|
@@ -121889,7 +120926,7 @@ var init_currency_controller = __esm(() => {
|
|
|
121889
120926
|
if (!isValidUUID(currencyId)) {
|
|
121890
120927
|
throw ApiError.unprocessableEntity("currencyId must be a valid UUID format");
|
|
121891
120928
|
}
|
|
121892
|
-
|
|
120929
|
+
logger37.debug("Deleting currency", { userId: ctx.user.id, currencyId });
|
|
121893
120930
|
await ctx.services.currency.delete(currencyId);
|
|
121894
120931
|
});
|
|
121895
120932
|
currencyController = {
|
|
@@ -121900,7 +120937,7 @@ var init_currency_controller = __esm(() => {
|
|
|
121900
120937
|
remove
|
|
121901
120938
|
};
|
|
121902
120939
|
});
|
|
121903
|
-
var
|
|
120940
|
+
var logger38;
|
|
121904
120941
|
var reset;
|
|
121905
120942
|
var init_database_controller = __esm(() => {
|
|
121906
120943
|
init_esm();
|
|
@@ -121908,7 +120945,7 @@ var init_database_controller = __esm(() => {
|
|
|
121908
120945
|
init_src2();
|
|
121909
120946
|
init_errors();
|
|
121910
120947
|
init_utils11();
|
|
121911
|
-
|
|
120948
|
+
logger38 = log.scope("DatabaseController");
|
|
121912
120949
|
reset = requireDeveloper(async (ctx) => {
|
|
121913
120950
|
const slug2 = ctx.params.slug;
|
|
121914
120951
|
if (!slug2) {
|
|
@@ -121921,11 +120958,11 @@ var init_database_controller = __esm(() => {
|
|
|
121921
120958
|
} catch (error2) {
|
|
121922
120959
|
if (error2 instanceof exports_external.ZodError) {
|
|
121923
120960
|
const details = formatZodError(error2);
|
|
121924
|
-
|
|
120961
|
+
logger38.warn("Database reset validation failed", { details });
|
|
121925
120962
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
121926
120963
|
}
|
|
121927
120964
|
}
|
|
121928
|
-
|
|
120965
|
+
logger38.debug("Resetting database", {
|
|
121929
120966
|
userId: ctx.user.id,
|
|
121930
120967
|
slug: slug2,
|
|
121931
120968
|
hasSchema: !!body2.schema
|
|
@@ -130879,29 +129916,29 @@ var init_zip = __esm(() => {
|
|
|
130879
129916
|
init_src2();
|
|
130880
129917
|
import_jszip = __toESM2(require_lib4(), 1);
|
|
130881
129918
|
});
|
|
130882
|
-
var
|
|
129919
|
+
var logger39;
|
|
130883
129920
|
var init_deploy_controller = __esm(() => {
|
|
130884
129921
|
init_schemas_index();
|
|
130885
129922
|
init_src2();
|
|
130886
129923
|
init_zip();
|
|
130887
129924
|
init_errors();
|
|
130888
129925
|
init_utils11();
|
|
130889
|
-
|
|
129926
|
+
logger39 = log.scope("DeployController");
|
|
130890
129927
|
});
|
|
130891
|
-
var
|
|
129928
|
+
var logger40;
|
|
130892
129929
|
var apply;
|
|
130893
129930
|
var getStatus;
|
|
130894
129931
|
var developer;
|
|
130895
129932
|
var init_developer_controller = __esm(() => {
|
|
130896
129933
|
init_src2();
|
|
130897
129934
|
init_utils11();
|
|
130898
|
-
|
|
129935
|
+
logger40 = log.scope("DeveloperController");
|
|
130899
129936
|
apply = requireAuth(async (ctx) => {
|
|
130900
|
-
|
|
129937
|
+
logger40.debug("Applying for developer status", { userId: ctx.user.id });
|
|
130901
129938
|
await ctx.services.developer.apply(ctx.user);
|
|
130902
129939
|
});
|
|
130903
129940
|
getStatus = requireAuth(async (ctx) => {
|
|
130904
|
-
|
|
129941
|
+
logger40.debug("Getting developer status", { userId: ctx.user.id });
|
|
130905
129942
|
const status = await ctx.services.developer.getStatus(ctx.user.id);
|
|
130906
129943
|
return { status };
|
|
130907
129944
|
});
|
|
@@ -130910,7 +129947,7 @@ var init_developer_controller = __esm(() => {
|
|
|
130910
129947
|
getStatus
|
|
130911
129948
|
};
|
|
130912
129949
|
});
|
|
130913
|
-
var
|
|
129950
|
+
var logger41;
|
|
130914
129951
|
var add;
|
|
130915
129952
|
var list2;
|
|
130916
129953
|
var getStatus2;
|
|
@@ -130923,7 +129960,7 @@ var init_domain_controller = __esm(() => {
|
|
|
130923
129960
|
init_config2();
|
|
130924
129961
|
init_errors();
|
|
130925
129962
|
init_utils11();
|
|
130926
|
-
|
|
129963
|
+
logger41 = log.scope("DomainController");
|
|
130927
129964
|
add = requireDeveloper(async (ctx) => {
|
|
130928
129965
|
const slug2 = ctx.params.slug;
|
|
130929
129966
|
if (!slug2) {
|
|
@@ -130936,12 +129973,12 @@ var init_domain_controller = __esm(() => {
|
|
|
130936
129973
|
} catch (error2) {
|
|
130937
129974
|
if (error2 instanceof exports_external.ZodError) {
|
|
130938
129975
|
const details = formatZodError(error2);
|
|
130939
|
-
|
|
129976
|
+
logger41.warn("Add domain validation failed", { details });
|
|
130940
129977
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
130941
129978
|
}
|
|
130942
129979
|
throw ApiError.badRequest("Invalid JSON body");
|
|
130943
129980
|
}
|
|
130944
|
-
|
|
129981
|
+
logger41.debug("Adding domain", { userId: ctx.user.id, slug: slug2, hostname: body2.hostname });
|
|
130945
129982
|
return ctx.services.domain.add(slug2, body2.hostname, body2.environment, ctx.user);
|
|
130946
129983
|
});
|
|
130947
129984
|
list2 = requireDeveloper(async (ctx) => {
|
|
@@ -130950,7 +129987,7 @@ var init_domain_controller = __esm(() => {
|
|
|
130950
129987
|
throw ApiError.badRequest("Missing game slug");
|
|
130951
129988
|
}
|
|
130952
129989
|
const environment = getPlatformEnvironment(ctx.config);
|
|
130953
|
-
|
|
129990
|
+
logger41.debug("Listing domains", { userId: ctx.user.id, slug: slug2, environment });
|
|
130954
129991
|
const domains22 = await ctx.services.domain.list(slug2, environment, ctx.user);
|
|
130955
129992
|
return { domains: domains22 };
|
|
130956
129993
|
});
|
|
@@ -130965,7 +130002,7 @@ var init_domain_controller = __esm(() => {
|
|
|
130965
130002
|
}
|
|
130966
130003
|
const refresh = ctx.url.searchParams.get("refresh") === "true";
|
|
130967
130004
|
const environment = getPlatformEnvironment(ctx.config);
|
|
130968
|
-
|
|
130005
|
+
logger41.debug("Getting domain status", { userId: ctx.user.id, slug: slug2, hostname, refresh });
|
|
130969
130006
|
return ctx.services.domain.getStatus(slug2, hostname, environment, ctx.user, refresh);
|
|
130970
130007
|
});
|
|
130971
130008
|
remove2 = requireDeveloper(async (ctx) => {
|
|
@@ -130978,7 +130015,7 @@ var init_domain_controller = __esm(() => {
|
|
|
130978
130015
|
throw ApiError.badRequest("Missing hostname");
|
|
130979
130016
|
}
|
|
130980
130017
|
const environment = ctx.config.stage === "production" ? "production" : "staging";
|
|
130981
|
-
|
|
130018
|
+
logger41.debug("Removing domain", { userId: ctx.user.id, slug: slug2, hostname, environment });
|
|
130982
130019
|
await ctx.services.domain.delete(slug2, hostname, environment, ctx.user);
|
|
130983
130020
|
});
|
|
130984
130021
|
domains2 = {
|
|
@@ -130988,7 +130025,7 @@ var init_domain_controller = __esm(() => {
|
|
|
130988
130025
|
remove: remove2
|
|
130989
130026
|
};
|
|
130990
130027
|
});
|
|
130991
|
-
var
|
|
130028
|
+
var logger42;
|
|
130992
130029
|
var list3;
|
|
130993
130030
|
var getById2;
|
|
130994
130031
|
var getBySlug;
|
|
@@ -131002,9 +130039,9 @@ var init_game_controller = __esm(() => {
|
|
|
131002
130039
|
init_src4();
|
|
131003
130040
|
init_errors();
|
|
131004
130041
|
init_utils11();
|
|
131005
|
-
|
|
130042
|
+
logger42 = log.scope("GameController");
|
|
131006
130043
|
list3 = requireAuth(async (ctx) => {
|
|
131007
|
-
|
|
130044
|
+
logger42.debug("Listing games", { userId: ctx.user.id });
|
|
131008
130045
|
return ctx.services.game.list();
|
|
131009
130046
|
});
|
|
131010
130047
|
getById2 = requireAuth(async (ctx) => {
|
|
@@ -131015,7 +130052,7 @@ var init_game_controller = __esm(() => {
|
|
|
131015
130052
|
if (!isValidUUID(gameId)) {
|
|
131016
130053
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
131017
130054
|
}
|
|
131018
|
-
|
|
130055
|
+
logger42.debug("Getting game by ID", { userId: ctx.user.id, gameId });
|
|
131019
130056
|
return ctx.services.game.getById(gameId);
|
|
131020
130057
|
});
|
|
131021
130058
|
getBySlug = requireAuth(async (ctx) => {
|
|
@@ -131023,7 +130060,7 @@ var init_game_controller = __esm(() => {
|
|
|
131023
130060
|
if (!slug2) {
|
|
131024
130061
|
throw ApiError.badRequest("Missing game slug");
|
|
131025
130062
|
}
|
|
131026
|
-
|
|
130063
|
+
logger42.debug("Getting game by slug", { userId: ctx.user.id, slug: slug2 });
|
|
131027
130064
|
return ctx.services.game.getBySlug(slug2);
|
|
131028
130065
|
});
|
|
131029
130066
|
upsertBySlug = requireAuth(async (ctx) => {
|
|
@@ -131038,12 +130075,12 @@ var init_game_controller = __esm(() => {
|
|
|
131038
130075
|
} catch (error2) {
|
|
131039
130076
|
if (error2 instanceof exports_external.ZodError) {
|
|
131040
130077
|
const details = formatZodError(error2);
|
|
131041
|
-
|
|
130078
|
+
logger42.warn("Upsert game validation failed", { details });
|
|
131042
130079
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
131043
130080
|
}
|
|
131044
130081
|
throw ApiError.badRequest("Invalid JSON body");
|
|
131045
130082
|
}
|
|
131046
|
-
|
|
130083
|
+
logger42.debug("Upserting game", { userId: ctx.user.id, slug: slug2, displayName: body2.displayName });
|
|
131047
130084
|
return ctx.services.game.upsertBySlug(slug2, body2, ctx.user);
|
|
131048
130085
|
});
|
|
131049
130086
|
remove3 = requireAuth(async (ctx) => {
|
|
@@ -131054,7 +130091,7 @@ var init_game_controller = __esm(() => {
|
|
|
131054
130091
|
if (!isValidUUID(gameId)) {
|
|
131055
130092
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
131056
130093
|
}
|
|
131057
|
-
|
|
130094
|
+
logger42.debug("Deleting game", { userId: ctx.user.id, gameId });
|
|
131058
130095
|
await ctx.services.game.delete(gameId, ctx.user);
|
|
131059
130096
|
});
|
|
131060
130097
|
games2 = {
|
|
@@ -131065,7 +130102,7 @@ var init_game_controller = __esm(() => {
|
|
|
131065
130102
|
remove: remove3
|
|
131066
130103
|
};
|
|
131067
130104
|
});
|
|
131068
|
-
var
|
|
130105
|
+
var logger43;
|
|
131069
130106
|
var list4;
|
|
131070
130107
|
var addItem;
|
|
131071
130108
|
var removeItem;
|
|
@@ -131076,9 +130113,9 @@ var init_inventory_controller = __esm(() => {
|
|
|
131076
130113
|
init_src2();
|
|
131077
130114
|
init_errors();
|
|
131078
130115
|
init_utils11();
|
|
131079
|
-
|
|
130116
|
+
logger43 = log.scope("InventoryController");
|
|
131080
130117
|
list4 = requireAuth(async (ctx) => {
|
|
131081
|
-
|
|
130118
|
+
logger43.debug("Listing inventory", { userId: ctx.user.id });
|
|
131082
130119
|
return ctx.services.inventory.list(ctx.user);
|
|
131083
130120
|
});
|
|
131084
130121
|
addItem = requireAuth(async (ctx) => {
|
|
@@ -131089,12 +130126,12 @@ var init_inventory_controller = __esm(() => {
|
|
|
131089
130126
|
} catch (error2) {
|
|
131090
130127
|
if (error2 instanceof exports_external.ZodError) {
|
|
131091
130128
|
const details = formatZodError(error2);
|
|
131092
|
-
|
|
130129
|
+
logger43.warn("Add inventory item validation failed", { details });
|
|
131093
130130
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
131094
130131
|
}
|
|
131095
130132
|
throw ApiError.badRequest("Invalid JSON body");
|
|
131096
130133
|
}
|
|
131097
|
-
|
|
130134
|
+
logger43.debug("Adding item", {
|
|
131098
130135
|
userId: ctx.user.id,
|
|
131099
130136
|
itemId: body2.itemId,
|
|
131100
130137
|
qty: body2.qty
|
|
@@ -131109,12 +130146,12 @@ var init_inventory_controller = __esm(() => {
|
|
|
131109
130146
|
} catch (error2) {
|
|
131110
130147
|
if (error2 instanceof exports_external.ZodError) {
|
|
131111
130148
|
const details = formatZodError(error2);
|
|
131112
|
-
|
|
130149
|
+
logger43.warn("Remove inventory item validation failed", { details });
|
|
131113
130150
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
131114
130151
|
}
|
|
131115
130152
|
throw ApiError.badRequest("Invalid JSON body");
|
|
131116
130153
|
}
|
|
131117
|
-
|
|
130154
|
+
logger43.debug("Removing item", {
|
|
131118
130155
|
userId: ctx.user.id,
|
|
131119
130156
|
itemId: body2.itemId,
|
|
131120
130157
|
qty: body2.qty
|
|
@@ -131127,7 +130164,7 @@ var init_inventory_controller = __esm(() => {
|
|
|
131127
130164
|
removeItem
|
|
131128
130165
|
};
|
|
131129
130166
|
});
|
|
131130
|
-
var
|
|
130167
|
+
var logger44;
|
|
131131
130168
|
var list5;
|
|
131132
130169
|
var getById3;
|
|
131133
130170
|
var resolve2;
|
|
@@ -131146,10 +130183,10 @@ var init_item_controller = __esm(() => {
|
|
|
131146
130183
|
init_src4();
|
|
131147
130184
|
init_errors();
|
|
131148
130185
|
init_utils11();
|
|
131149
|
-
|
|
130186
|
+
logger44 = log.scope("ItemController");
|
|
131150
130187
|
list5 = requireAuth(async (ctx) => {
|
|
131151
130188
|
const gameId = ctx.url.searchParams.get("gameId") || undefined;
|
|
131152
|
-
|
|
130189
|
+
logger44.debug("Listing items", { userId: ctx.user.id, gameId });
|
|
131153
130190
|
return ctx.services.item.list(gameId);
|
|
131154
130191
|
});
|
|
131155
130192
|
getById3 = requireAuth(async (ctx) => {
|
|
@@ -131160,7 +130197,7 @@ var init_item_controller = __esm(() => {
|
|
|
131160
130197
|
if (!isValidUUID(itemId)) {
|
|
131161
130198
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
131162
130199
|
}
|
|
131163
|
-
|
|
130200
|
+
logger44.debug("Getting item", { userId: ctx.user.id, itemId });
|
|
131164
130201
|
return ctx.services.item.getById(itemId);
|
|
131165
130202
|
});
|
|
131166
130203
|
resolve2 = requireAuth(async (ctx) => {
|
|
@@ -131172,7 +130209,7 @@ var init_item_controller = __esm(() => {
|
|
|
131172
130209
|
if (gameId && !isValidUUID(gameId)) {
|
|
131173
130210
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
131174
130211
|
}
|
|
131175
|
-
|
|
130212
|
+
logger44.debug("Resolving item", { userId: ctx.user.id, slug: slug2, gameId });
|
|
131176
130213
|
return ctx.services.item.resolveBySlug(slug2, gameId);
|
|
131177
130214
|
});
|
|
131178
130215
|
create3 = requireRole(["admin"], async (ctx) => {
|
|
@@ -131183,12 +130220,12 @@ var init_item_controller = __esm(() => {
|
|
|
131183
130220
|
} catch (error2) {
|
|
131184
130221
|
if (error2 instanceof exports_external.ZodError) {
|
|
131185
130222
|
const details = formatZodError(error2);
|
|
131186
|
-
|
|
130223
|
+
logger44.warn("Create item validation failed", { details });
|
|
131187
130224
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
131188
130225
|
}
|
|
131189
130226
|
throw ApiError.badRequest("Invalid JSON body");
|
|
131190
130227
|
}
|
|
131191
|
-
|
|
130228
|
+
logger44.debug("Creating item", {
|
|
131192
130229
|
userId: ctx.user.id,
|
|
131193
130230
|
slug: body2.slug,
|
|
131194
130231
|
displayName: body2.displayName
|
|
@@ -131210,7 +130247,7 @@ var init_item_controller = __esm(() => {
|
|
|
131210
130247
|
} catch (error2) {
|
|
131211
130248
|
if (error2 instanceof exports_external.ZodError) {
|
|
131212
130249
|
const details = formatZodError(error2);
|
|
131213
|
-
|
|
130250
|
+
logger44.warn("Update item validation failed", { details });
|
|
131214
130251
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
131215
130252
|
}
|
|
131216
130253
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -131218,7 +130255,7 @@ var init_item_controller = __esm(() => {
|
|
|
131218
130255
|
if (Object.keys(body2).length === 0) {
|
|
131219
130256
|
throw ApiError.badRequest("No update data provided");
|
|
131220
130257
|
}
|
|
131221
|
-
|
|
130258
|
+
logger44.debug("Updating item", {
|
|
131222
130259
|
userId: ctx.user.id,
|
|
131223
130260
|
itemId,
|
|
131224
130261
|
slug: body2.slug,
|
|
@@ -131235,7 +130272,7 @@ var init_item_controller = __esm(() => {
|
|
|
131235
130272
|
if (!isValidUUID(itemId)) {
|
|
131236
130273
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
131237
130274
|
}
|
|
131238
|
-
|
|
130275
|
+
logger44.debug("Deleting item", { userId: ctx.user.id, itemId });
|
|
131239
130276
|
await ctx.services.item.delete(itemId);
|
|
131240
130277
|
});
|
|
131241
130278
|
listByGame = requireAuth(async (ctx) => {
|
|
@@ -131246,7 +130283,7 @@ var init_item_controller = __esm(() => {
|
|
|
131246
130283
|
if (!isValidUUID(gameId)) {
|
|
131247
130284
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
131248
130285
|
}
|
|
131249
|
-
|
|
130286
|
+
logger44.debug("Listing game items", { userId: ctx.user.id, gameId });
|
|
131250
130287
|
return ctx.services.item.listByGame(gameId);
|
|
131251
130288
|
});
|
|
131252
130289
|
createForGame = requireAuth(async (ctx) => {
|
|
@@ -131264,12 +130301,12 @@ var init_item_controller = __esm(() => {
|
|
|
131264
130301
|
} catch (error2) {
|
|
131265
130302
|
if (error2 instanceof exports_external.ZodError) {
|
|
131266
130303
|
const details = formatZodError(error2);
|
|
131267
|
-
|
|
130304
|
+
logger44.warn("Create game item validation failed", { details });
|
|
131268
130305
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
131269
130306
|
}
|
|
131270
130307
|
throw ApiError.badRequest("Invalid JSON body");
|
|
131271
130308
|
}
|
|
131272
|
-
|
|
130309
|
+
logger44.debug("Creating game item", {
|
|
131273
130310
|
userId: ctx.user.id,
|
|
131274
130311
|
gameId,
|
|
131275
130312
|
slug: body2.slug,
|
|
@@ -131296,7 +130333,7 @@ var init_item_controller = __esm(() => {
|
|
|
131296
130333
|
} catch (error2) {
|
|
131297
130334
|
if (error2 instanceof exports_external.ZodError) {
|
|
131298
130335
|
const details = formatZodError(error2);
|
|
131299
|
-
|
|
130336
|
+
logger44.warn("Update game item validation failed", { details });
|
|
131300
130337
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
131301
130338
|
}
|
|
131302
130339
|
throw ApiError.badRequest("Invalid JSON body");
|
|
@@ -131304,7 +130341,7 @@ var init_item_controller = __esm(() => {
|
|
|
131304
130341
|
if (Object.keys(body2).length === 0) {
|
|
131305
130342
|
throw ApiError.badRequest("No update data provided");
|
|
131306
130343
|
}
|
|
131307
|
-
|
|
130344
|
+
logger44.debug("Updating game item", {
|
|
131308
130345
|
userId: ctx.user.id,
|
|
131309
130346
|
gameId,
|
|
131310
130347
|
itemId,
|
|
@@ -131326,7 +130363,7 @@ var init_item_controller = __esm(() => {
|
|
|
131326
130363
|
if (!isValidUUID(itemId)) {
|
|
131327
130364
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
131328
130365
|
}
|
|
131329
|
-
|
|
130366
|
+
logger44.debug("Deleting game item", { userId: ctx.user.id, gameId, itemId });
|
|
131330
130367
|
await ctx.services.item.deleteForGame(gameId, itemId, ctx.user);
|
|
131331
130368
|
});
|
|
131332
130369
|
items2 = {
|
|
@@ -131342,7 +130379,7 @@ var init_item_controller = __esm(() => {
|
|
|
131342
130379
|
deleteForGame
|
|
131343
130380
|
};
|
|
131344
130381
|
});
|
|
131345
|
-
var
|
|
130382
|
+
var logger45;
|
|
131346
130383
|
var submitScore;
|
|
131347
130384
|
var getGlobalLeaderboard;
|
|
131348
130385
|
var getLeaderboard;
|
|
@@ -131357,7 +130394,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
131357
130394
|
init_src4();
|
|
131358
130395
|
init_errors();
|
|
131359
130396
|
init_utils11();
|
|
131360
|
-
|
|
130397
|
+
logger45 = log.scope("LeaderboardController");
|
|
131361
130398
|
submitScore = requireAuth(async (ctx) => {
|
|
131362
130399
|
const gameId = ctx.params.gameId;
|
|
131363
130400
|
if (!gameId) {
|
|
@@ -131370,12 +130407,12 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
131370
130407
|
} catch (error2) {
|
|
131371
130408
|
if (error2 instanceof exports_external.ZodError) {
|
|
131372
130409
|
const details = formatZodError(error2);
|
|
131373
|
-
|
|
130410
|
+
logger45.warn("Submit score validation failed", { details });
|
|
131374
130411
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
131375
130412
|
}
|
|
131376
130413
|
throw ApiError.badRequest("Invalid JSON body");
|
|
131377
130414
|
}
|
|
131378
|
-
|
|
130415
|
+
logger45.debug("Submitting score", {
|
|
131379
130416
|
userId: ctx.user.id,
|
|
131380
130417
|
gameId,
|
|
131381
130418
|
score: body2.score
|
|
@@ -131398,12 +130435,12 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
131398
130435
|
} catch (error2) {
|
|
131399
130436
|
if (error2 instanceof exports_external.ZodError) {
|
|
131400
130437
|
const details = formatZodError(error2);
|
|
131401
|
-
|
|
130438
|
+
logger45.warn("Get global leaderboard query validation failed", { details });
|
|
131402
130439
|
throw ApiError.badRequest("Invalid query parameters", details);
|
|
131403
130440
|
}
|
|
131404
130441
|
throw ApiError.badRequest("Invalid query parameters");
|
|
131405
130442
|
}
|
|
131406
|
-
|
|
130443
|
+
logger45.debug("Getting global leaderboard", {
|
|
131407
130444
|
userId: ctx.user.id,
|
|
131408
130445
|
gameId,
|
|
131409
130446
|
...query
|
|
@@ -131426,12 +130463,12 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
131426
130463
|
} catch (error2) {
|
|
131427
130464
|
if (error2 instanceof exports_external.ZodError) {
|
|
131428
130465
|
const details = formatZodError(error2);
|
|
131429
|
-
|
|
130466
|
+
logger45.warn("Get leaderboard query validation failed", { details });
|
|
131430
130467
|
throw ApiError.badRequest("Invalid query parameters", details);
|
|
131431
130468
|
}
|
|
131432
130469
|
throw ApiError.badRequest("Invalid query parameters");
|
|
131433
130470
|
}
|
|
131434
|
-
|
|
130471
|
+
logger45.debug("Getting leaderboard", {
|
|
131435
130472
|
userId: ctx.user.id,
|
|
131436
130473
|
gameId,
|
|
131437
130474
|
...query
|
|
@@ -131446,7 +130483,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
131446
130483
|
if (!isValidUUID(userId)) {
|
|
131447
130484
|
throw ApiError.unprocessableEntity("userId must be a valid UUID format");
|
|
131448
130485
|
}
|
|
131449
|
-
|
|
130486
|
+
logger45.debug("Getting user rank", {
|
|
131450
130487
|
requesterId: ctx.user.id,
|
|
131451
130488
|
gameId,
|
|
131452
130489
|
targetUserId: userId
|
|
@@ -131464,7 +130501,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
131464
130501
|
const url = ctx.url;
|
|
131465
130502
|
const limit = Math.min(Number(url.searchParams.get("limit") || "50"), 100);
|
|
131466
130503
|
const gameId = url.searchParams.get("gameId") || undefined;
|
|
131467
|
-
|
|
130504
|
+
logger45.debug("Getting user all scores", {
|
|
131468
130505
|
requesterId: ctx.user.id,
|
|
131469
130506
|
targetUserId: userId,
|
|
131470
130507
|
gameId,
|
|
@@ -131482,7 +130519,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
131482
130519
|
}
|
|
131483
130520
|
const url = ctx.url;
|
|
131484
130521
|
const limit = Math.min(Number(url.searchParams.get("limit") || "10"), 100);
|
|
131485
|
-
|
|
130522
|
+
logger45.debug("Getting user scores", {
|
|
131486
130523
|
requesterId: ctx.user.id,
|
|
131487
130524
|
gameId,
|
|
131488
130525
|
targetUserId: userId,
|
|
@@ -131500,7 +130537,7 @@ var init_leaderboard_controller = __esm(() => {
|
|
|
131500
130537
|
};
|
|
131501
130538
|
});
|
|
131502
130539
|
async function listConfigs(ctx) {
|
|
131503
|
-
|
|
130540
|
+
logger46.debug("Listing level configs");
|
|
131504
130541
|
return ctx.services.level.listConfigs();
|
|
131505
130542
|
}
|
|
131506
130543
|
async function getConfig(ctx) {
|
|
@@ -131512,10 +130549,10 @@ async function getConfig(ctx) {
|
|
|
131512
130549
|
if (isNaN(level) || level < 1) {
|
|
131513
130550
|
throw ApiError.badRequest("Level must be a positive integer");
|
|
131514
130551
|
}
|
|
131515
|
-
|
|
130552
|
+
logger46.debug("Getting level config", { level });
|
|
131516
130553
|
return ctx.services.level.getConfig(level);
|
|
131517
130554
|
}
|
|
131518
|
-
var
|
|
130555
|
+
var logger46;
|
|
131519
130556
|
var getByUser;
|
|
131520
130557
|
var getProgress;
|
|
131521
130558
|
var levels;
|
|
@@ -131523,13 +130560,13 @@ var init_level_controller = __esm(() => {
|
|
|
131523
130560
|
init_src2();
|
|
131524
130561
|
init_errors();
|
|
131525
130562
|
init_utils11();
|
|
131526
|
-
|
|
130563
|
+
logger46 = log.scope("LevelController");
|
|
131527
130564
|
getByUser = requireAuth(async (ctx) => {
|
|
131528
|
-
|
|
130565
|
+
logger46.debug("Getting user level", { userId: ctx.user.id });
|
|
131529
130566
|
return ctx.services.level.getByUser(ctx.user);
|
|
131530
130567
|
});
|
|
131531
130568
|
getProgress = requireAuth(async (ctx) => {
|
|
131532
|
-
|
|
130569
|
+
logger46.debug("Getting level progress", { userId: ctx.user.id });
|
|
131533
130570
|
return ctx.services.level.getProgress(ctx.user);
|
|
131534
130571
|
});
|
|
131535
130572
|
levels = {
|
|
@@ -131539,34 +130576,58 @@ var init_level_controller = __esm(() => {
|
|
|
131539
130576
|
getProgress
|
|
131540
130577
|
};
|
|
131541
130578
|
});
|
|
131542
|
-
|
|
131543
|
-
|
|
131544
|
-
|
|
131545
|
-
|
|
131546
|
-
|
|
131547
|
-
|
|
131548
|
-
|
|
131549
|
-
|
|
131550
|
-
|
|
131551
|
-
|
|
131552
|
-
|
|
130579
|
+
var logger47;
|
|
130580
|
+
var generateToken;
|
|
130581
|
+
var logs;
|
|
130582
|
+
var init_logs_controller = __esm(() => {
|
|
130583
|
+
init_src2();
|
|
130584
|
+
init_errors();
|
|
130585
|
+
init_utils11();
|
|
130586
|
+
logger47 = log.scope("LogsController");
|
|
130587
|
+
generateToken = requireDeveloper(async (ctx) => {
|
|
130588
|
+
const slug2 = ctx.params.slug;
|
|
130589
|
+
if (!slug2) {
|
|
130590
|
+
throw ApiError.badRequest("Missing game slug");
|
|
130591
|
+
}
|
|
130592
|
+
let body2;
|
|
130593
|
+
try {
|
|
130594
|
+
const json4 = await ctx.request.json();
|
|
130595
|
+
if (json4.environment !== "staging" && json4.environment !== "production") {
|
|
130596
|
+
throw ApiError.badRequest('Invalid environment. Must be "staging" or "production".');
|
|
130597
|
+
}
|
|
130598
|
+
body2 = json4;
|
|
130599
|
+
} catch (error2) {
|
|
130600
|
+
if (error2 instanceof ApiError)
|
|
130601
|
+
throw error2;
|
|
130602
|
+
throw ApiError.badRequest("Invalid JSON body");
|
|
130603
|
+
}
|
|
130604
|
+
logger47.debug("Generating log stream token", {
|
|
130605
|
+
userId: ctx.user.id,
|
|
130606
|
+
slug: slug2,
|
|
130607
|
+
environment: body2.environment
|
|
130608
|
+
});
|
|
130609
|
+
return ctx.services.logs.generateToken(ctx.user, slug2, body2.environment);
|
|
130610
|
+
});
|
|
130611
|
+
logs = {
|
|
130612
|
+
generateToken
|
|
130613
|
+
};
|
|
130614
|
+
});
|
|
130615
|
+
var logger48;
|
|
131553
130616
|
var getStatus3;
|
|
131554
130617
|
var lti;
|
|
131555
130618
|
var init_lti_controller = __esm(() => {
|
|
131556
130619
|
init_src2();
|
|
131557
|
-
init_errors();
|
|
131558
130620
|
init_utils11();
|
|
131559
|
-
|
|
130621
|
+
logger48 = log.scope("LtiController");
|
|
131560
130622
|
getStatus3 = requireAuth(async (ctx) => {
|
|
131561
|
-
|
|
130623
|
+
logger48.debug("Getting status", { userId: ctx.user.id });
|
|
131562
130624
|
return ctx.services.lti.getStatus(ctx.user);
|
|
131563
130625
|
});
|
|
131564
130626
|
lti = {
|
|
131565
|
-
launch,
|
|
131566
130627
|
getStatus: getStatus3
|
|
131567
130628
|
};
|
|
131568
130629
|
});
|
|
131569
|
-
var
|
|
130630
|
+
var logger49;
|
|
131570
130631
|
var getByIdentifier;
|
|
131571
130632
|
var getElements;
|
|
131572
130633
|
var getObjects;
|
|
@@ -131580,13 +130641,13 @@ var init_map_controller = __esm(() => {
|
|
|
131580
130641
|
init_src4();
|
|
131581
130642
|
init_errors();
|
|
131582
130643
|
init_utils11();
|
|
131583
|
-
|
|
130644
|
+
logger49 = log.scope("MapController");
|
|
131584
130645
|
getByIdentifier = requireAuth(async (ctx) => {
|
|
131585
130646
|
const identifier = ctx.params.identifier;
|
|
131586
130647
|
if (!identifier) {
|
|
131587
130648
|
throw ApiError.badRequest("Missing map identifier");
|
|
131588
130649
|
}
|
|
131589
|
-
|
|
130650
|
+
logger49.debug("Getting map", { userId: ctx.user.id, identifier });
|
|
131590
130651
|
return ctx.services.map.getByIdentifier(identifier);
|
|
131591
130652
|
});
|
|
131592
130653
|
getElements = requireAuth(async (ctx) => {
|
|
@@ -131597,7 +130658,7 @@ var init_map_controller = __esm(() => {
|
|
|
131597
130658
|
if (!isValidUUID(mapId)) {
|
|
131598
130659
|
throw ApiError.unprocessableEntity("mapId must be a valid UUID format");
|
|
131599
130660
|
}
|
|
131600
|
-
|
|
130661
|
+
logger49.debug("Getting map elements", { userId: ctx.user.id, mapId });
|
|
131601
130662
|
return ctx.services.map.getElements(mapId);
|
|
131602
130663
|
});
|
|
131603
130664
|
getObjects = requireAuth(async (ctx) => {
|
|
@@ -131608,7 +130669,7 @@ var init_map_controller = __esm(() => {
|
|
|
131608
130669
|
if (!isValidUUID(mapId)) {
|
|
131609
130670
|
throw ApiError.unprocessableEntity("mapId must be a valid UUID format");
|
|
131610
130671
|
}
|
|
131611
|
-
|
|
130672
|
+
logger49.debug("Getting map objects", { userId: ctx.user.id, mapId });
|
|
131612
130673
|
return ctx.services.map.getObjects(mapId, ctx.user.id);
|
|
131613
130674
|
});
|
|
131614
130675
|
createObject = requireAuth(async (ctx) => {
|
|
@@ -131630,12 +130691,12 @@ var init_map_controller = __esm(() => {
|
|
|
131630
130691
|
} catch (error2) {
|
|
131631
130692
|
if (error2 instanceof exports_external.ZodError) {
|
|
131632
130693
|
const details = formatZodError(error2);
|
|
131633
|
-
|
|
130694
|
+
logger49.warn("Create map object validation failed", { details });
|
|
131634
130695
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
131635
130696
|
}
|
|
131636
130697
|
throw ApiError.badRequest("Invalid JSON body");
|
|
131637
130698
|
}
|
|
131638
|
-
|
|
130699
|
+
logger49.debug("Creating map object", {
|
|
131639
130700
|
userId: ctx.user.id,
|
|
131640
130701
|
mapId,
|
|
131641
130702
|
itemId: body2.itemId,
|
|
@@ -131659,7 +130720,7 @@ var init_map_controller = __esm(() => {
|
|
|
131659
130720
|
if (!isValidUUID(objectId)) {
|
|
131660
130721
|
throw ApiError.unprocessableEntity("objectId must be a valid UUID format");
|
|
131661
130722
|
}
|
|
131662
|
-
|
|
130723
|
+
logger49.debug("Deleting map object", { userId: ctx.user.id, mapId, objectId });
|
|
131663
130724
|
await ctx.services.map.deleteObject(mapId, objectId, ctx.user);
|
|
131664
130725
|
});
|
|
131665
130726
|
maps2 = {
|
|
@@ -131670,7 +130731,7 @@ var init_map_controller = __esm(() => {
|
|
|
131670
130731
|
deleteObject
|
|
131671
130732
|
};
|
|
131672
130733
|
});
|
|
131673
|
-
var
|
|
130734
|
+
var logger50;
|
|
131674
130735
|
var list6;
|
|
131675
130736
|
var updateStatus;
|
|
131676
130737
|
var getStats;
|
|
@@ -131683,7 +130744,7 @@ var init_notification_controller = __esm(() => {
|
|
|
131683
130744
|
init_src2();
|
|
131684
130745
|
init_errors();
|
|
131685
130746
|
init_utils11();
|
|
131686
|
-
|
|
130747
|
+
logger50 = log.scope("NotificationController");
|
|
131687
130748
|
list6 = requireAuth(async (ctx) => {
|
|
131688
130749
|
const query = {
|
|
131689
130750
|
status: ctx.url.searchParams.get("status") || undefined,
|
|
@@ -131694,10 +130755,10 @@ var init_notification_controller = __esm(() => {
|
|
|
131694
130755
|
const result = NotificationListQuerySchema.omit({ userId: true }).safeParse(query);
|
|
131695
130756
|
if (!result.success) {
|
|
131696
130757
|
const details = formatZodError(result.error);
|
|
131697
|
-
|
|
130758
|
+
logger50.warn("List notifications query validation failed", { details });
|
|
131698
130759
|
throw ApiError.badRequest("Invalid query parameters", details);
|
|
131699
130760
|
}
|
|
131700
|
-
|
|
130761
|
+
logger50.debug("Listing notifications", { userId: ctx.user.id, ...result.data });
|
|
131701
130762
|
return ctx.services.notification.list(ctx.user, result.data);
|
|
131702
130763
|
});
|
|
131703
130764
|
updateStatus = requireAuth(async (ctx) => {
|
|
@@ -131712,12 +130773,12 @@ var init_notification_controller = __esm(() => {
|
|
|
131712
130773
|
} catch (error2) {
|
|
131713
130774
|
if (error2 instanceof exports_external.ZodError) {
|
|
131714
130775
|
const details = formatZodError(error2);
|
|
131715
|
-
|
|
130776
|
+
logger50.warn("Update notification status validation failed", { details });
|
|
131716
130777
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
131717
130778
|
}
|
|
131718
130779
|
throw ApiError.badRequest("Invalid JSON body");
|
|
131719
130780
|
}
|
|
131720
|
-
|
|
130781
|
+
logger50.debug("Updating status", {
|
|
131721
130782
|
userId: ctx.user.id,
|
|
131722
130783
|
notificationId,
|
|
131723
130784
|
status: body2.status
|
|
@@ -131727,7 +130788,7 @@ var init_notification_controller = __esm(() => {
|
|
|
131727
130788
|
getStats = requireAuth(async (ctx) => {
|
|
131728
130789
|
const startDate = ctx.url.searchParams.get("startDate");
|
|
131729
130790
|
const endDate = ctx.url.searchParams.get("endDate");
|
|
131730
|
-
|
|
130791
|
+
logger50.debug("Getting stats", { userId: ctx.user.id, startDate, endDate });
|
|
131731
130792
|
return ctx.services.notification.getStats(ctx.user, {
|
|
131732
130793
|
startDate: startDate ? new Date(startDate) : undefined,
|
|
131733
130794
|
endDate: endDate ? new Date(endDate) : undefined
|
|
@@ -131741,12 +130802,12 @@ var init_notification_controller = __esm(() => {
|
|
|
131741
130802
|
} catch (error2) {
|
|
131742
130803
|
if (error2 instanceof exports_external.ZodError) {
|
|
131743
130804
|
const details = formatZodError(error2);
|
|
131744
|
-
|
|
130805
|
+
logger50.warn("Create notification validation failed", { details });
|
|
131745
130806
|
throw ApiError.unprocessableEntity("Invalid request body", details);
|
|
131746
130807
|
}
|
|
131747
130808
|
throw ApiError.badRequest("Invalid JSON body");
|
|
131748
130809
|
}
|
|
131749
|
-
|
|
130810
|
+
logger50.debug("Creating notification", {
|
|
131750
130811
|
userId: ctx.user.id,
|
|
131751
130812
|
targetUserId: body2.userId,
|
|
131752
130813
|
type: body2.type
|
|
@@ -131764,12 +130825,12 @@ var init_notification_controller = __esm(() => {
|
|
|
131764
130825
|
});
|
|
131765
130826
|
});
|
|
131766
130827
|
deliver = requireAuth(async (ctx) => {
|
|
131767
|
-
|
|
130828
|
+
logger50.debug("Delivering notifications", { userId: ctx.user.id });
|
|
131768
130829
|
try {
|
|
131769
130830
|
await ctx.services.notification.deliverPending(ctx.user.id);
|
|
131770
130831
|
return { success: true };
|
|
131771
130832
|
} catch (error2) {
|
|
131772
|
-
|
|
130833
|
+
logger50.error("Failed to deliver notifications", { error: error2 });
|
|
131773
130834
|
throw ApiError.internal("Failed to deliver notifications");
|
|
131774
130835
|
}
|
|
131775
130836
|
});
|
|
@@ -131781,28 +130842,27 @@ var init_notification_controller = __esm(() => {
|
|
|
131781
130842
|
deliver
|
|
131782
130843
|
};
|
|
131783
130844
|
});
|
|
131784
|
-
var
|
|
131785
|
-
var
|
|
130845
|
+
var logger51;
|
|
130846
|
+
var generateToken2;
|
|
131786
130847
|
var realtime;
|
|
131787
130848
|
var init_realtime_controller = __esm(() => {
|
|
131788
130849
|
init_src2();
|
|
131789
130850
|
init_utils11();
|
|
131790
|
-
|
|
131791
|
-
|
|
130851
|
+
logger51 = log.scope("RealtimeController");
|
|
130852
|
+
generateToken2 = requireAuth(async (ctx) => {
|
|
131792
130853
|
const gameIdOrSlug = ctx.params.gameId;
|
|
131793
|
-
|
|
130854
|
+
logger51.debug("Generating token", {
|
|
131794
130855
|
userId: ctx.user.id,
|
|
131795
130856
|
gameId: gameIdOrSlug || "global"
|
|
131796
130857
|
});
|
|
131797
130858
|
return ctx.services.realtime.generateToken(ctx.user, gameIdOrSlug);
|
|
131798
130859
|
});
|
|
131799
130860
|
realtime = {
|
|
131800
|
-
generateToken
|
|
130861
|
+
generateToken: generateToken2
|
|
131801
130862
|
};
|
|
131802
130863
|
});
|
|
131803
|
-
var
|
|
130864
|
+
var logger52;
|
|
131804
130865
|
var listKeys;
|
|
131805
|
-
var getValues;
|
|
131806
130866
|
var setSecrets;
|
|
131807
130867
|
var deleteSecret;
|
|
131808
130868
|
var secrets;
|
|
@@ -131812,25 +130872,16 @@ var init_secrets_controller = __esm(() => {
|
|
|
131812
130872
|
init_src2();
|
|
131813
130873
|
init_errors();
|
|
131814
130874
|
init_utils11();
|
|
131815
|
-
|
|
130875
|
+
logger52 = log.scope("SecretsController");
|
|
131816
130876
|
listKeys = requireDeveloper(async (ctx) => {
|
|
131817
130877
|
const slug2 = ctx.params.slug;
|
|
131818
130878
|
if (!slug2) {
|
|
131819
130879
|
throw ApiError.badRequest("Missing game slug");
|
|
131820
130880
|
}
|
|
131821
|
-
|
|
130881
|
+
logger52.debug("Listing secret keys", { userId: ctx.user.id, slug: slug2 });
|
|
131822
130882
|
const keys = await ctx.services.secrets.listKeys(slug2, ctx.user);
|
|
131823
130883
|
return { keys };
|
|
131824
130884
|
});
|
|
131825
|
-
getValues = requireDeveloper(async (ctx) => {
|
|
131826
|
-
const slug2 = ctx.params.slug;
|
|
131827
|
-
if (!slug2) {
|
|
131828
|
-
throw ApiError.badRequest("Missing game slug");
|
|
131829
|
-
}
|
|
131830
|
-
logger50.debug("Getting secret values", { userId: ctx.user.id, slug: slug2 });
|
|
131831
|
-
const secrets2 = await ctx.services.secrets.getValues(slug2, ctx.user);
|
|
131832
|
-
return { secrets: secrets2 };
|
|
131833
|
-
});
|
|
131834
130885
|
setSecrets = requireDeveloper(async (ctx) => {
|
|
131835
130886
|
const slug2 = ctx.params.slug;
|
|
131836
130887
|
if (!slug2) {
|
|
@@ -131843,12 +130894,12 @@ var init_secrets_controller = __esm(() => {
|
|
|
131843
130894
|
} catch (error2) {
|
|
131844
130895
|
if (error2 instanceof exports_external.ZodError) {
|
|
131845
130896
|
const details = formatZodError(error2);
|
|
131846
|
-
|
|
130897
|
+
logger52.warn("Set secrets validation failed", { details });
|
|
131847
130898
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
131848
130899
|
}
|
|
131849
130900
|
throw ApiError.badRequest("Invalid JSON body");
|
|
131850
130901
|
}
|
|
131851
|
-
|
|
130902
|
+
logger52.debug("Setting secrets", {
|
|
131852
130903
|
userId: ctx.user.id,
|
|
131853
130904
|
slug: slug2,
|
|
131854
130905
|
keyCount: Object.keys(body2).length
|
|
@@ -131865,18 +130916,17 @@ var init_secrets_controller = __esm(() => {
|
|
|
131865
130916
|
if (!key) {
|
|
131866
130917
|
throw ApiError.badRequest("Missing secret key");
|
|
131867
130918
|
}
|
|
131868
|
-
|
|
130919
|
+
logger52.debug("Deleting secret", { userId: ctx.user.id, slug: slug2, key });
|
|
131869
130920
|
await ctx.services.secrets.deleteSecret(slug2, key, ctx.user);
|
|
131870
130921
|
return { success: true };
|
|
131871
130922
|
});
|
|
131872
130923
|
secrets = {
|
|
131873
130924
|
listKeys,
|
|
131874
|
-
getValues,
|
|
131875
130925
|
setSecrets,
|
|
131876
130926
|
deleteSecret
|
|
131877
130927
|
};
|
|
131878
130928
|
});
|
|
131879
|
-
var
|
|
130929
|
+
var logger53;
|
|
131880
130930
|
var seed;
|
|
131881
130931
|
var init_seed_controller = __esm(() => {
|
|
131882
130932
|
init_esm();
|
|
@@ -131884,7 +130934,7 @@ var init_seed_controller = __esm(() => {
|
|
|
131884
130934
|
init_src2();
|
|
131885
130935
|
init_errors();
|
|
131886
130936
|
init_utils11();
|
|
131887
|
-
|
|
130937
|
+
logger53 = log.scope("SeedController");
|
|
131888
130938
|
seed = requireDeveloper(async (ctx) => {
|
|
131889
130939
|
const slug2 = ctx.params.slug;
|
|
131890
130940
|
if (!slug2) {
|
|
@@ -131897,16 +130947,16 @@ var init_seed_controller = __esm(() => {
|
|
|
131897
130947
|
} catch (error2) {
|
|
131898
130948
|
if (error2 instanceof exports_external.ZodError) {
|
|
131899
130949
|
const details = formatZodError(error2);
|
|
131900
|
-
|
|
130950
|
+
logger53.warn("Seed database validation failed", { details });
|
|
131901
130951
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
131902
130952
|
}
|
|
131903
130953
|
throw ApiError.badRequest("Invalid JSON body");
|
|
131904
130954
|
}
|
|
131905
|
-
|
|
130955
|
+
logger53.debug("Seeding database", { userId: ctx.user.id, slug: slug2, codeLength: body2.code.length });
|
|
131906
130956
|
return ctx.services.seed.seed(slug2, body2.code, ctx.user);
|
|
131907
130957
|
});
|
|
131908
130958
|
});
|
|
131909
|
-
var
|
|
130959
|
+
var logger54;
|
|
131910
130960
|
var start2;
|
|
131911
130961
|
var end;
|
|
131912
130962
|
var mintToken;
|
|
@@ -131915,13 +130965,13 @@ var init_session_controller = __esm(() => {
|
|
|
131915
130965
|
init_src2();
|
|
131916
130966
|
init_errors();
|
|
131917
130967
|
init_utils11();
|
|
131918
|
-
|
|
130968
|
+
logger54 = log.scope("SessionController");
|
|
131919
130969
|
start2 = requireAuth(async (ctx) => {
|
|
131920
130970
|
const gameIdOrSlug = ctx.params.gameId;
|
|
131921
130971
|
if (!gameIdOrSlug) {
|
|
131922
130972
|
throw ApiError.badRequest("Missing game ID or slug");
|
|
131923
130973
|
}
|
|
131924
|
-
|
|
130974
|
+
logger54.debug("Starting session", { userId: ctx.user.id, gameIdOrSlug });
|
|
131925
130975
|
return ctx.services.session.start(gameIdOrSlug, ctx.user.id);
|
|
131926
130976
|
});
|
|
131927
130977
|
end = requireAuth(async (ctx) => {
|
|
@@ -131933,7 +130983,7 @@ var init_session_controller = __esm(() => {
|
|
|
131933
130983
|
if (!sessionId) {
|
|
131934
130984
|
throw ApiError.badRequest("Missing session ID");
|
|
131935
130985
|
}
|
|
131936
|
-
|
|
130986
|
+
logger54.debug("Ending session", { userId: ctx.user.id, gameIdOrSlug, sessionId });
|
|
131937
130987
|
return ctx.services.session.end(gameIdOrSlug, sessionId, ctx.user.id);
|
|
131938
130988
|
});
|
|
131939
130989
|
mintToken = requireAuth(async (ctx) => {
|
|
@@ -131941,7 +130991,7 @@ var init_session_controller = __esm(() => {
|
|
|
131941
130991
|
if (!gameIdOrSlug) {
|
|
131942
130992
|
throw ApiError.badRequest("Missing game ID or slug");
|
|
131943
130993
|
}
|
|
131944
|
-
|
|
130994
|
+
logger54.debug("Minting token", { userId: ctx.user.id, gameIdOrSlug });
|
|
131945
130995
|
return ctx.services.session.mintToken(gameIdOrSlug, ctx.user.id);
|
|
131946
130996
|
});
|
|
131947
130997
|
sessions2 = {
|
|
@@ -131950,22 +131000,22 @@ var init_session_controller = __esm(() => {
|
|
|
131950
131000
|
mintToken
|
|
131951
131001
|
};
|
|
131952
131002
|
});
|
|
131953
|
-
var
|
|
131003
|
+
var logger55;
|
|
131954
131004
|
var getShopView;
|
|
131955
131005
|
var shop;
|
|
131956
131006
|
var init_shop_controller = __esm(() => {
|
|
131957
131007
|
init_src2();
|
|
131958
131008
|
init_utils11();
|
|
131959
|
-
|
|
131009
|
+
logger55 = log.scope("ShopController");
|
|
131960
131010
|
getShopView = requireAuth(async (ctx) => {
|
|
131961
|
-
|
|
131011
|
+
logger55.debug("Getting shop view", { userId: ctx.user.id });
|
|
131962
131012
|
return ctx.services.shop.getShopView(ctx.user);
|
|
131963
131013
|
});
|
|
131964
131014
|
shop = {
|
|
131965
131015
|
getShopView
|
|
131966
131016
|
};
|
|
131967
131017
|
});
|
|
131968
|
-
var
|
|
131018
|
+
var logger56;
|
|
131969
131019
|
var list7;
|
|
131970
131020
|
var getById4;
|
|
131971
131021
|
var create5;
|
|
@@ -131984,9 +131034,9 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
131984
131034
|
init_src4();
|
|
131985
131035
|
init_errors();
|
|
131986
131036
|
init_utils11();
|
|
131987
|
-
|
|
131037
|
+
logger56 = log.scope("ShopListingController");
|
|
131988
131038
|
list7 = requireAdmin(async (ctx) => {
|
|
131989
|
-
|
|
131039
|
+
logger56.debug("Listing shop listings", { userId: ctx.user.id });
|
|
131990
131040
|
return ctx.services.shopListing.list();
|
|
131991
131041
|
});
|
|
131992
131042
|
getById4 = requireAdmin(async (ctx) => {
|
|
@@ -131997,7 +131047,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
131997
131047
|
if (!isValidUUID(listingId)) {
|
|
131998
131048
|
throw ApiError.unprocessableEntity("listingId must be a valid UUID format");
|
|
131999
131049
|
}
|
|
132000
|
-
|
|
131050
|
+
logger56.debug("Getting listing", { userId: ctx.user.id, listingId });
|
|
132001
131051
|
return ctx.services.shopListing.getById(listingId);
|
|
132002
131052
|
});
|
|
132003
131053
|
create5 = requireAdmin(async (ctx) => {
|
|
@@ -132008,12 +131058,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
132008
131058
|
} catch (error2) {
|
|
132009
131059
|
if (error2 instanceof exports_external.ZodError) {
|
|
132010
131060
|
const details = formatZodError(error2);
|
|
132011
|
-
|
|
131061
|
+
logger56.warn("Create shop listing validation failed", { details });
|
|
132012
131062
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
132013
131063
|
}
|
|
132014
131064
|
throw ApiError.badRequest("Invalid JSON body");
|
|
132015
131065
|
}
|
|
132016
|
-
|
|
131066
|
+
logger56.debug("Creating listing", {
|
|
132017
131067
|
userId: ctx.user.id,
|
|
132018
131068
|
itemId: body2.itemId,
|
|
132019
131069
|
currencyId: body2.currencyId,
|
|
@@ -132036,12 +131086,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
132036
131086
|
} catch (error2) {
|
|
132037
131087
|
if (error2 instanceof exports_external.ZodError) {
|
|
132038
131088
|
const details = formatZodError(error2);
|
|
132039
|
-
|
|
131089
|
+
logger56.warn("Update shop listing validation failed", { details });
|
|
132040
131090
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
132041
131091
|
}
|
|
132042
131092
|
throw ApiError.badRequest("Invalid JSON body");
|
|
132043
131093
|
}
|
|
132044
|
-
|
|
131094
|
+
logger56.debug("Updating listing", {
|
|
132045
131095
|
userId: ctx.user.id,
|
|
132046
131096
|
listingId,
|
|
132047
131097
|
price: body2.price,
|
|
@@ -132058,7 +131108,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
132058
131108
|
if (!isValidUUID(listingId)) {
|
|
132059
131109
|
throw ApiError.unprocessableEntity("listingId must be a valid UUID format");
|
|
132060
131110
|
}
|
|
132061
|
-
|
|
131111
|
+
logger56.debug("Deleting listing", { userId: ctx.user.id, listingId });
|
|
132062
131112
|
await ctx.services.shopListing.delete(listingId);
|
|
132063
131113
|
});
|
|
132064
131114
|
listByGame2 = requireAuth(async (ctx) => {
|
|
@@ -132069,7 +131119,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
132069
131119
|
if (!isValidUUID(gameId)) {
|
|
132070
131120
|
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
132071
131121
|
}
|
|
132072
|
-
|
|
131122
|
+
logger56.debug("Listing game listings", { userId: ctx.user.id, gameId });
|
|
132073
131123
|
return ctx.services.shopListing.listByGame(gameId, ctx.user);
|
|
132074
131124
|
});
|
|
132075
131125
|
getByGameItem = requireAuth(async (ctx) => {
|
|
@@ -132084,7 +131134,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
132084
131134
|
if (!isValidUUID(itemId)) {
|
|
132085
131135
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
132086
131136
|
}
|
|
132087
|
-
|
|
131137
|
+
logger56.debug("Getting game item listing", { userId: ctx.user.id, gameId, itemId });
|
|
132088
131138
|
return ctx.services.shopListing.getByGameItem(gameId, itemId, ctx.user);
|
|
132089
131139
|
});
|
|
132090
131140
|
createForGameItem = requireAuth(async (ctx) => {
|
|
@@ -132106,12 +131156,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
132106
131156
|
} catch (error2) {
|
|
132107
131157
|
if (error2 instanceof exports_external.ZodError) {
|
|
132108
131158
|
const details = formatZodError(error2);
|
|
132109
|
-
|
|
131159
|
+
logger56.warn("Create game item listing validation failed", { details });
|
|
132110
131160
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
132111
131161
|
}
|
|
132112
131162
|
throw ApiError.badRequest("Invalid JSON body");
|
|
132113
131163
|
}
|
|
132114
|
-
|
|
131164
|
+
logger56.debug("Creating game item listing", {
|
|
132115
131165
|
userId: ctx.user.id,
|
|
132116
131166
|
gameId,
|
|
132117
131167
|
itemId,
|
|
@@ -132139,12 +131189,12 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
132139
131189
|
} catch (error2) {
|
|
132140
131190
|
if (error2 instanceof exports_external.ZodError) {
|
|
132141
131191
|
const details = formatZodError(error2);
|
|
132142
|
-
|
|
131192
|
+
logger56.warn("Update game item listing validation failed", { details });
|
|
132143
131193
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
132144
131194
|
}
|
|
132145
131195
|
throw ApiError.badRequest("Invalid JSON body");
|
|
132146
131196
|
}
|
|
132147
|
-
|
|
131197
|
+
logger56.debug("Updating game item listing", {
|
|
132148
131198
|
userId: ctx.user.id,
|
|
132149
131199
|
gameId,
|
|
132150
131200
|
itemId,
|
|
@@ -132166,7 +131216,7 @@ var init_shop_listing_controller = __esm(() => {
|
|
|
132166
131216
|
if (!isValidUUID(itemId)) {
|
|
132167
131217
|
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
132168
131218
|
}
|
|
132169
|
-
|
|
131219
|
+
logger56.debug("Deleting game item listing", {
|
|
132170
131220
|
userId: ctx.user.id,
|
|
132171
131221
|
gameId,
|
|
132172
131222
|
itemId
|
|
@@ -132191,20 +131241,20 @@ async function getBySlug2(ctx) {
|
|
|
132191
131241
|
if (!slug2) {
|
|
132192
131242
|
throw ApiError.badRequest("Template slug is required");
|
|
132193
131243
|
}
|
|
132194
|
-
|
|
131244
|
+
logger57.debug("Getting sprite by slug", { slug: slug2 });
|
|
132195
131245
|
return ctx.services.sprite.getBySlug(slug2);
|
|
132196
131246
|
}
|
|
132197
|
-
var
|
|
131247
|
+
var logger57;
|
|
132198
131248
|
var sprites;
|
|
132199
131249
|
var init_sprite_controller = __esm(() => {
|
|
132200
131250
|
init_src2();
|
|
132201
131251
|
init_errors();
|
|
132202
|
-
|
|
131252
|
+
logger57 = log.scope("SpriteController");
|
|
132203
131253
|
sprites = {
|
|
132204
131254
|
getBySlug: getBySlug2
|
|
132205
131255
|
};
|
|
132206
131256
|
});
|
|
132207
|
-
var
|
|
131257
|
+
var logger58;
|
|
132208
131258
|
var getTodayXp;
|
|
132209
131259
|
var getTotalXp;
|
|
132210
131260
|
var updateTodayXp;
|
|
@@ -132226,15 +131276,15 @@ var init_timeback_controller = __esm(() => {
|
|
|
132226
131276
|
init_src4();
|
|
132227
131277
|
init_errors();
|
|
132228
131278
|
init_utils11();
|
|
132229
|
-
|
|
131279
|
+
logger58 = log.scope("TimebackController");
|
|
132230
131280
|
getTodayXp = requireAuth(async (ctx) => {
|
|
132231
131281
|
const date4 = ctx.url.searchParams.get("date") || undefined;
|
|
132232
131282
|
const tz = ctx.url.searchParams.get("tz") || undefined;
|
|
132233
|
-
|
|
131283
|
+
logger58.debug("Getting today XP", { userId: ctx.user.id, date: date4, tz });
|
|
132234
131284
|
return ctx.services.timeback.getTodayXp(ctx.user.id, date4, tz);
|
|
132235
131285
|
});
|
|
132236
131286
|
getTotalXp = requireAuth(async (ctx) => {
|
|
132237
|
-
|
|
131287
|
+
logger58.debug("Getting total XP", { userId: ctx.user.id });
|
|
132238
131288
|
return ctx.services.timeback.getTotalXp(ctx.user.id);
|
|
132239
131289
|
});
|
|
132240
131290
|
updateTodayXp = requireAuth(async (ctx) => {
|
|
@@ -132245,18 +131295,18 @@ var init_timeback_controller = __esm(() => {
|
|
|
132245
131295
|
} catch (error2) {
|
|
132246
131296
|
if (error2 instanceof exports_external.ZodError) {
|
|
132247
131297
|
const details = formatZodError(error2);
|
|
132248
|
-
|
|
131298
|
+
logger58.warn("Update today XP validation failed", { details });
|
|
132249
131299
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
132250
131300
|
}
|
|
132251
131301
|
throw ApiError.badRequest("Invalid JSON body");
|
|
132252
131302
|
}
|
|
132253
|
-
|
|
131303
|
+
logger58.debug("Updating today XP", { userId: ctx.user.id, xp: body2.xp });
|
|
132254
131304
|
return ctx.services.timeback.updateTodayXp(ctx.user.id, body2);
|
|
132255
131305
|
});
|
|
132256
131306
|
getXpHistory = requireAuth(async (ctx) => {
|
|
132257
131307
|
const startDate = ctx.url.searchParams.get("startDate") || undefined;
|
|
132258
131308
|
const endDate = ctx.url.searchParams.get("endDate") || undefined;
|
|
132259
|
-
|
|
131309
|
+
logger58.debug("Getting XP history", { userId: ctx.user.id, startDate, endDate });
|
|
132260
131310
|
return ctx.services.timeback.getXpHistory(ctx.user.id, startDate, endDate);
|
|
132261
131311
|
});
|
|
132262
131312
|
populateStudent = requireAuth(async (ctx) => {
|
|
@@ -132267,18 +131317,18 @@ var init_timeback_controller = __esm(() => {
|
|
|
132267
131317
|
} catch (error2) {
|
|
132268
131318
|
if (error2 instanceof exports_external.ZodError) {
|
|
132269
131319
|
const details = formatZodError(error2);
|
|
132270
|
-
|
|
131320
|
+
logger58.warn("Populate student validation failed", { details });
|
|
132271
131321
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
132272
131322
|
}
|
|
132273
131323
|
}
|
|
132274
|
-
|
|
131324
|
+
logger58.debug("Populating student", {
|
|
132275
131325
|
userId: ctx.user.id,
|
|
132276
131326
|
hasProvidedNames: !!providedNames
|
|
132277
131327
|
});
|
|
132278
131328
|
return ctx.services.timeback.populateStudent(ctx.user, providedNames);
|
|
132279
131329
|
});
|
|
132280
131330
|
getUser = requireAuth(async (ctx) => {
|
|
132281
|
-
|
|
131331
|
+
logger58.debug("Getting user", { userId: ctx.user.id, gameId: ctx.gameId });
|
|
132282
131332
|
return ctx.services.timeback.getUserData(ctx.user.id, ctx.gameId);
|
|
132283
131333
|
});
|
|
132284
131334
|
getUserById = requireAuth(async (ctx) => {
|
|
@@ -132286,7 +131336,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
132286
131336
|
if (!timebackId) {
|
|
132287
131337
|
throw ApiError.badRequest("Missing timebackId parameter");
|
|
132288
131338
|
}
|
|
132289
|
-
|
|
131339
|
+
logger58.debug("Getting user by ID", { requesterId: ctx.user.id, timebackId });
|
|
132290
131340
|
return ctx.services.timeback.getUserDataByTimebackId(timebackId);
|
|
132291
131341
|
});
|
|
132292
131342
|
setupIntegration = requireDeveloper(async (ctx) => {
|
|
@@ -132297,12 +131347,12 @@ var init_timeback_controller = __esm(() => {
|
|
|
132297
131347
|
} catch (error2) {
|
|
132298
131348
|
if (error2 instanceof exports_external.ZodError) {
|
|
132299
131349
|
const details = formatZodError(error2);
|
|
132300
|
-
|
|
131350
|
+
logger58.warn("Setup integration validation failed", { details });
|
|
132301
131351
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
132302
131352
|
}
|
|
132303
131353
|
throw ApiError.badRequest("Invalid JSON body");
|
|
132304
131354
|
}
|
|
132305
|
-
|
|
131355
|
+
logger58.debug("Setting up integration", {
|
|
132306
131356
|
userId: ctx.user.id,
|
|
132307
131357
|
gameId: body2.gameId
|
|
132308
131358
|
});
|
|
@@ -132314,7 +131364,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
132314
131364
|
throw ApiError.badRequest("Missing gameId");
|
|
132315
131365
|
if (!isValidUUID(gameId))
|
|
132316
131366
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
132317
|
-
|
|
131367
|
+
logger58.debug("Getting integrations", { userId: ctx.user.id, gameId });
|
|
132318
131368
|
return ctx.services.timeback.getIntegrations(gameId, ctx.user);
|
|
132319
131369
|
});
|
|
132320
131370
|
verifyIntegration = requireDeveloper(async (ctx) => {
|
|
@@ -132323,7 +131373,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
132323
131373
|
throw ApiError.badRequest("Missing gameId");
|
|
132324
131374
|
if (!isValidUUID(gameId))
|
|
132325
131375
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
132326
|
-
|
|
131376
|
+
logger58.debug("Verifying integration", { userId: ctx.user.id, gameId });
|
|
132327
131377
|
return ctx.services.timeback.verifyIntegration(gameId, ctx.user);
|
|
132328
131378
|
});
|
|
132329
131379
|
getConfig2 = requireDeveloper(async (ctx) => {
|
|
@@ -132332,7 +131382,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
132332
131382
|
throw ApiError.badRequest("Missing gameId");
|
|
132333
131383
|
if (!isValidUUID(gameId))
|
|
132334
131384
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
132335
|
-
|
|
131385
|
+
logger58.debug("Getting config", { userId: ctx.user.id, gameId });
|
|
132336
131386
|
return ctx.services.timeback.getConfig(gameId, ctx.user);
|
|
132337
131387
|
});
|
|
132338
131388
|
deleteIntegrations = requireDeveloper(async (ctx) => {
|
|
@@ -132341,7 +131391,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
132341
131391
|
throw ApiError.badRequest("Missing gameId");
|
|
132342
131392
|
if (!isValidUUID(gameId))
|
|
132343
131393
|
throw ApiError.unprocessableEntity("Invalid gameId format");
|
|
132344
|
-
|
|
131394
|
+
logger58.debug("Deleting integrations", { userId: ctx.user.id, gameId });
|
|
132345
131395
|
await ctx.services.timeback.deleteIntegrations(gameId, ctx.user);
|
|
132346
131396
|
});
|
|
132347
131397
|
endActivity = requireDeveloper(async (ctx) => {
|
|
@@ -132352,13 +131402,13 @@ var init_timeback_controller = __esm(() => {
|
|
|
132352
131402
|
} catch (error2) {
|
|
132353
131403
|
if (error2 instanceof exports_external.ZodError) {
|
|
132354
131404
|
const details = formatZodError(error2);
|
|
132355
|
-
|
|
131405
|
+
logger58.warn("End activity validation failed", { details });
|
|
132356
131406
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
132357
131407
|
}
|
|
132358
131408
|
throw ApiError.badRequest("Invalid JSON body");
|
|
132359
131409
|
}
|
|
132360
131410
|
const { gameId, studentId, activityData, scoreData, timingData, xpEarned, masteredUnits } = body2;
|
|
132361
|
-
|
|
131411
|
+
logger58.debug("Ending activity", { userId: ctx.user.id, gameId });
|
|
132362
131412
|
return ctx.services.timeback.endActivity(gameId, studentId, activityData, scoreData, timingData, xpEarned, masteredUnits, ctx.user);
|
|
132363
131413
|
});
|
|
132364
131414
|
timeback2 = {
|
|
@@ -132377,7 +131427,7 @@ var init_timeback_controller = __esm(() => {
|
|
|
132377
131427
|
endActivity
|
|
132378
131428
|
};
|
|
132379
131429
|
});
|
|
132380
|
-
var
|
|
131430
|
+
var logger59;
|
|
132381
131431
|
var initiate;
|
|
132382
131432
|
var init_upload_controller = __esm(() => {
|
|
132383
131433
|
init_esm();
|
|
@@ -132385,7 +131435,7 @@ var init_upload_controller = __esm(() => {
|
|
|
132385
131435
|
init_src2();
|
|
132386
131436
|
init_errors();
|
|
132387
131437
|
init_utils11();
|
|
132388
|
-
|
|
131438
|
+
logger59 = log.scope("UploadController");
|
|
132389
131439
|
initiate = requireDeveloper(async (ctx) => {
|
|
132390
131440
|
let body2;
|
|
132391
131441
|
try {
|
|
@@ -132394,37 +131444,37 @@ var init_upload_controller = __esm(() => {
|
|
|
132394
131444
|
} catch (error2) {
|
|
132395
131445
|
if (error2 instanceof exports_external.ZodError) {
|
|
132396
131446
|
const details = formatZodError(error2);
|
|
132397
|
-
|
|
131447
|
+
logger59.warn("Initiate upload validation failed", { details });
|
|
132398
131448
|
throw ApiError.unprocessableEntity("Validation failed", details);
|
|
132399
131449
|
}
|
|
132400
131450
|
throw ApiError.badRequest("Invalid JSON body");
|
|
132401
131451
|
}
|
|
132402
|
-
|
|
131452
|
+
logger59.debug("Initiating upload", { userId: ctx.user.id, gameId: body2.gameId });
|
|
132403
131453
|
return ctx.services.upload.initiate(body2, ctx.user);
|
|
132404
131454
|
});
|
|
132405
131455
|
});
|
|
132406
|
-
var
|
|
131456
|
+
var logger60;
|
|
132407
131457
|
var getMe;
|
|
132408
131458
|
var users2;
|
|
132409
131459
|
var init_user_controller = __esm(() => {
|
|
132410
131460
|
init_src2();
|
|
132411
131461
|
init_utils11();
|
|
132412
|
-
|
|
131462
|
+
logger60 = log.scope("UserController");
|
|
132413
131463
|
getMe = requireAuth(async (ctx) => {
|
|
132414
|
-
|
|
131464
|
+
logger60.debug("Getting current user", { userId: ctx.user.id, gameId: ctx.gameId });
|
|
132415
131465
|
return ctx.services.user.getMe(ctx.user, ctx.gameId);
|
|
132416
131466
|
});
|
|
132417
131467
|
users2 = {
|
|
132418
131468
|
getMe
|
|
132419
131469
|
};
|
|
132420
131470
|
});
|
|
132421
|
-
var
|
|
131471
|
+
var logger61;
|
|
132422
131472
|
var init_verify_controller = __esm(() => {
|
|
132423
131473
|
init_schemas_index();
|
|
132424
131474
|
init_src2();
|
|
132425
131475
|
init_errors();
|
|
132426
131476
|
init_utils11();
|
|
132427
|
-
|
|
131477
|
+
logger61 = log.scope("VerifyController");
|
|
132428
131478
|
});
|
|
132429
131479
|
var init_controllers = __esm(() => {
|
|
132430
131480
|
init_achievement_controller();
|
|
@@ -132441,6 +131491,7 @@ var init_controllers = __esm(() => {
|
|
|
132441
131491
|
init_item_controller();
|
|
132442
131492
|
init_leaderboard_controller();
|
|
132443
131493
|
init_level_controller();
|
|
131494
|
+
init_logs_controller();
|
|
132444
131495
|
init_lti_controller();
|
|
132445
131496
|
init_map_controller();
|
|
132446
131497
|
init_notification_controller();
|
|
@@ -132931,6 +131982,14 @@ var init_items = __esm(() => {
|
|
|
132931
131982
|
gameItemsRouter.patch("/:gameId/items/:itemId", handle2(items2.updateForGame));
|
|
132932
131983
|
gameItemsRouter.delete("/:gameId/items/:itemId", handle2(items2.deleteForGame, { status: 204 }));
|
|
132933
131984
|
});
|
|
131985
|
+
var gameLogsRouter;
|
|
131986
|
+
var init_logs = __esm(() => {
|
|
131987
|
+
init_dist3();
|
|
131988
|
+
init_controllers();
|
|
131989
|
+
init_api();
|
|
131990
|
+
gameLogsRouter = new Hono2;
|
|
131991
|
+
gameLogsRouter.post("/:slug/logs/token", handle2(logs.generateToken));
|
|
131992
|
+
});
|
|
132934
131993
|
var gameScoresRouter;
|
|
132935
131994
|
var init_scores = __esm(() => {
|
|
132936
131995
|
init_dist3();
|
|
@@ -132947,7 +132006,6 @@ var init_secrets = __esm(() => {
|
|
|
132947
132006
|
init_api();
|
|
132948
132007
|
gameSecretsRouter = new Hono2;
|
|
132949
132008
|
gameSecretsRouter.get("/:slug/secrets", handle2(secrets.listKeys));
|
|
132950
|
-
gameSecretsRouter.get("/:slug/secrets/values", handle2(secrets.getValues));
|
|
132951
132009
|
gameSecretsRouter.post("/:slug/secrets", handle2(secrets.setSecrets));
|
|
132952
132010
|
gameSecretsRouter.delete("/:slug/secrets/:key", handle2(secrets.deleteSecret));
|
|
132953
132011
|
});
|
|
@@ -133231,6 +132289,7 @@ var init_games2 = __esm(() => {
|
|
|
133231
132289
|
init_deploy();
|
|
133232
132290
|
init_domains3();
|
|
133233
132291
|
init_items();
|
|
132292
|
+
init_logs();
|
|
133234
132293
|
init_scores();
|
|
133235
132294
|
init_secrets();
|
|
133236
132295
|
init_seed2();
|
|
@@ -133246,6 +132305,7 @@ var init_games2 = __esm(() => {
|
|
|
133246
132305
|
gamesRouter.route("/", gameDeployRouter);
|
|
133247
132306
|
gamesRouter.route("/", gameDomainsRouter);
|
|
133248
132307
|
gamesRouter.route("/", gameItemsRouter);
|
|
132308
|
+
gamesRouter.route("/", gameLogsRouter);
|
|
133249
132309
|
gamesRouter.route("/", gameShopRouter);
|
|
133250
132310
|
gamesRouter.route("/", gameScoresRouter);
|
|
133251
132311
|
gamesRouter.route("/", gameSecretsRouter);
|
|
@@ -133441,51 +132501,86 @@ var init_timeback6 = __esm(() => {
|
|
|
133441
132501
|
return handle2(timeback2.getUserById)(c2);
|
|
133442
132502
|
});
|
|
133443
132503
|
});
|
|
132504
|
+
function verifyMockToken(idToken) {
|
|
132505
|
+
if (!idToken.startsWith("mock:")) {
|
|
132506
|
+
throw new Error("Invalid LTI token - must be mock token in sandbox");
|
|
132507
|
+
}
|
|
132508
|
+
try {
|
|
132509
|
+
const jsonStr = Buffer.from(idToken.slice(5), "base64").toString();
|
|
132510
|
+
return JSON.parse(jsonStr);
|
|
132511
|
+
} catch {
|
|
132512
|
+
throw new Error("Invalid LTI token format");
|
|
132513
|
+
}
|
|
132514
|
+
}
|
|
132515
|
+
var logger62;
|
|
133444
132516
|
var ltiRouter;
|
|
133445
132517
|
var init_lti = __esm(() => {
|
|
133446
132518
|
init_drizzle_orm();
|
|
133447
132519
|
init_dist3();
|
|
133448
132520
|
init_controllers();
|
|
133449
|
-
|
|
132521
|
+
init_utils11();
|
|
133450
132522
|
init_tables_index();
|
|
132523
|
+
init_src2();
|
|
133451
132524
|
init_constants();
|
|
133452
132525
|
init_api();
|
|
133453
|
-
|
|
132526
|
+
logger62 = log.scope("SandboxLti");
|
|
133454
132527
|
ltiRouter = new Hono2;
|
|
133455
|
-
ltiRouter.
|
|
133456
|
-
|
|
133457
|
-
return c2.json({
|
|
133458
|
-
error: "method_not_allowed",
|
|
133459
|
-
message: "LTI launches must use POST method"
|
|
133460
|
-
}, 405);
|
|
133461
|
-
}
|
|
133462
|
-
const sandboxCtx = getSandboxContext();
|
|
133463
|
-
const ctx = {
|
|
133464
|
-
db: sandboxCtx.db,
|
|
133465
|
-
config: sandboxCtx.config,
|
|
133466
|
-
providers: sandboxCtx.providers,
|
|
133467
|
-
services: sandboxCtx.services,
|
|
133468
|
-
user: undefined,
|
|
133469
|
-
params: {},
|
|
133470
|
-
url: new URL(c2.req.url),
|
|
133471
|
-
request: c2.req.raw
|
|
133472
|
-
};
|
|
132528
|
+
ltiRouter.post("/launch", async (c2) => {
|
|
132529
|
+
const db2 = c2.get("db");
|
|
133473
132530
|
try {
|
|
133474
|
-
const
|
|
133475
|
-
|
|
133476
|
-
|
|
133477
|
-
} catch (error2) {
|
|
133478
|
-
if (error2 instanceof ApiError) {
|
|
132531
|
+
const formData = await c2.req.formData();
|
|
132532
|
+
const idToken = formData.get("id_token");
|
|
132533
|
+
if (!idToken || typeof idToken !== "string") {
|
|
133479
132534
|
return c2.json({
|
|
133480
|
-
error: "
|
|
133481
|
-
message:
|
|
133482
|
-
|
|
133483
|
-
details: error2.details
|
|
133484
|
-
}, error2.status);
|
|
132535
|
+
error: "missing_token",
|
|
132536
|
+
message: "Missing or invalid id_token in request"
|
|
132537
|
+
}, 400);
|
|
133485
132538
|
}
|
|
132539
|
+
let claims;
|
|
132540
|
+
try {
|
|
132541
|
+
claims = verifyMockToken(idToken);
|
|
132542
|
+
} catch (error2) {
|
|
132543
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
132544
|
+
logger62.error("LTI token verification failed", { error: errorMessage });
|
|
132545
|
+
return c2.json({
|
|
132546
|
+
error: "invalid_token",
|
|
132547
|
+
message: errorMessage
|
|
132548
|
+
}, 401);
|
|
132549
|
+
}
|
|
132550
|
+
const validationError = validateLtiClaims(claims);
|
|
132551
|
+
if (validationError) {
|
|
132552
|
+
logger62.warn("LTI claims validation failed", {
|
|
132553
|
+
error: validationError,
|
|
132554
|
+
sub: claims.sub
|
|
132555
|
+
});
|
|
132556
|
+
return c2.json({
|
|
132557
|
+
error: "invalid_claims",
|
|
132558
|
+
message: validationError
|
|
132559
|
+
}, 400);
|
|
132560
|
+
}
|
|
132561
|
+
const user = await provisionLtiUser(db2, claims);
|
|
132562
|
+
const sessionToken = crypto.randomUUID();
|
|
132563
|
+
const expiresAt = new Date(Date.now() + 2592000000);
|
|
132564
|
+
await db2.insert(sessions).values({
|
|
132565
|
+
id: crypto.randomUUID(),
|
|
132566
|
+
userId: user.id,
|
|
132567
|
+
token: sessionToken,
|
|
132568
|
+
expiresAt,
|
|
132569
|
+
createdAt: new Date,
|
|
132570
|
+
updatedAt: new Date
|
|
132571
|
+
});
|
|
132572
|
+
logger62.info("LTI launch successful", { userId: user.id });
|
|
132573
|
+
const targetUri = claims["https://purl.imsglobal.org/spec/lti/claim/target_link_uri"];
|
|
132574
|
+
const currentHost = new URL(c2.req.url).hostname;
|
|
132575
|
+
const redirectPath = extractRedirectPath(targetUri, currentHost);
|
|
132576
|
+
c2.header("Set-Cookie", `sandbox-session=${sessionToken}; Path=/; HttpOnly; SameSite=Lax; Max-Age=2592000`);
|
|
132577
|
+
return c2.redirect(redirectPath);
|
|
132578
|
+
} catch (error2) {
|
|
132579
|
+
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
132580
|
+
logger62.error("Unexpected error during LTI launch", { error: errorMessage });
|
|
133486
132581
|
return c2.json({
|
|
133487
132582
|
error: "unexpected_error",
|
|
133488
|
-
message: "An unexpected error occurred during LTI launch
|
|
132583
|
+
message: "An unexpected error occurred during LTI launch"
|
|
133489
132584
|
}, 500);
|
|
133490
132585
|
}
|
|
133491
132586
|
});
|
|
@@ -133609,7 +132704,6 @@ async function startServer(port, project, options = {}) {
|
|
|
133609
132704
|
resetSandboxContext();
|
|
133610
132705
|
resetHandlers();
|
|
133611
132706
|
clearSandboxCache();
|
|
133612
|
-
clearSandboxSecrets();
|
|
133613
132707
|
clearSandboxStorage();
|
|
133614
132708
|
const db2 = await setupServerDatabase(processedOptions, project);
|
|
133615
132709
|
createSandboxContext({ db: db2, port });
|
|
@@ -133636,7 +132730,6 @@ async function startServer(port, project, options = {}) {
|
|
|
133636
132730
|
resetSandboxContext();
|
|
133637
132731
|
resetHandlers();
|
|
133638
132732
|
clearSandboxCache();
|
|
133639
|
-
clearSandboxSecrets();
|
|
133640
132733
|
clearSandboxStorage();
|
|
133641
132734
|
}
|
|
133642
132735
|
};
|
|
@@ -134819,7 +133912,7 @@ var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
|
134819
133912
|
// package.json
|
|
134820
133913
|
var package_default2 = {
|
|
134821
133914
|
name: "@playcademy/vite-plugin",
|
|
134822
|
-
version: "0.2.
|
|
133915
|
+
version: "0.2.8",
|
|
134823
133916
|
type: "module",
|
|
134824
133917
|
exports: {
|
|
134825
133918
|
".": {
|