@playcademy/vite-plugin 0.0.1-beta.12 → 0.0.1-beta.14
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 +1141 -426
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -41060,6 +41060,8 @@ import { constants, KeyObject as KeyObject3 } from "node:crypto";
|
|
|
41060
41060
|
import * as crypto5 from "node:crypto";
|
|
41061
41061
|
import { promisify } from "node:util";
|
|
41062
41062
|
import { KeyObject as KeyObject4, createSecretKey } from "node:crypto";
|
|
41063
|
+
import fs32 from "node:fs";
|
|
41064
|
+
import path22 from "node:path";
|
|
41063
41065
|
var __create2 = Object.create;
|
|
41064
41066
|
var __getProtoOf2 = Object.getPrototypeOf;
|
|
41065
41067
|
var __defProp2 = Object.defineProperty;
|
|
@@ -43831,7 +43833,7 @@ ${file}:${line2}:${column}: ERROR: ${pluginText}${e.text}`;
|
|
|
43831
43833
|
result = `(?${regexp.flags})${result}`;
|
|
43832
43834
|
return result;
|
|
43833
43835
|
}
|
|
43834
|
-
var
|
|
43836
|
+
var fs33 = __require2("fs");
|
|
43835
43837
|
var os2 = __require2("os");
|
|
43836
43838
|
var path3 = __require2("path");
|
|
43837
43839
|
var ESBUILD_BINARY_PATH = process.env.ESBUILD_BINARY_PATH || ESBUILD_BINARY_PATH;
|
|
@@ -43896,14 +43898,14 @@ ${file}:${line2}:${column}: ERROR: ${pluginText}${e.text}`;
|
|
|
43896
43898
|
for (const unixKey in knownUnixlikePackages) {
|
|
43897
43899
|
try {
|
|
43898
43900
|
const pkg = knownUnixlikePackages[unixKey];
|
|
43899
|
-
if (
|
|
43901
|
+
if (fs33.existsSync(path3.join(nodeModulesDirectory, pkg)))
|
|
43900
43902
|
return pkg;
|
|
43901
43903
|
} catch {}
|
|
43902
43904
|
}
|
|
43903
43905
|
for (const windowsKey in knownWindowsPackages) {
|
|
43904
43906
|
try {
|
|
43905
43907
|
const pkg = knownWindowsPackages[windowsKey];
|
|
43906
|
-
if (
|
|
43908
|
+
if (fs33.existsSync(path3.join(nodeModulesDirectory, pkg)))
|
|
43907
43909
|
return pkg;
|
|
43908
43910
|
} catch {}
|
|
43909
43911
|
}
|
|
@@ -43916,7 +43918,7 @@ ${file}:${line2}:${column}: ERROR: ${pluginText}${e.text}`;
|
|
|
43916
43918
|
}
|
|
43917
43919
|
function generateBinPath() {
|
|
43918
43920
|
if (isValidBinaryPath(ESBUILD_BINARY_PATH)) {
|
|
43919
|
-
if (!
|
|
43921
|
+
if (!fs33.existsSync(ESBUILD_BINARY_PATH)) {
|
|
43920
43922
|
console.warn(`[esbuild] Ignoring bad configuration: ESBUILD_BINARY_PATH=${ESBUILD_BINARY_PATH}`);
|
|
43921
43923
|
} else {
|
|
43922
43924
|
return { binPath: ESBUILD_BINARY_PATH, isWASM: false };
|
|
@@ -43928,7 +43930,7 @@ ${file}:${line2}:${column}: ERROR: ${pluginText}${e.text}`;
|
|
|
43928
43930
|
binPath = __require2.resolve(`${pkg}/${subpath}`);
|
|
43929
43931
|
} catch (e) {
|
|
43930
43932
|
binPath = downloadedBinPath(pkg, subpath);
|
|
43931
|
-
if (!
|
|
43933
|
+
if (!fs33.existsSync(binPath)) {
|
|
43932
43934
|
try {
|
|
43933
43935
|
__require2.resolve(pkg);
|
|
43934
43936
|
} catch {
|
|
@@ -44004,10 +44006,10 @@ for your current platform.`);
|
|
|
44004
44006
|
if (pnpapi) {
|
|
44005
44007
|
const root = pnpapi.getPackageInformation(pnpapi.topLevel).packageLocation;
|
|
44006
44008
|
const binTargetPath = path3.join(root, "node_modules", ".cache", "esbuild", `pnpapi-${pkg.replace("/", "-")}-0.25.5-${path3.basename(subpath)}`);
|
|
44007
|
-
if (!
|
|
44008
|
-
|
|
44009
|
-
|
|
44010
|
-
|
|
44009
|
+
if (!fs33.existsSync(binTargetPath)) {
|
|
44010
|
+
fs33.mkdirSync(path3.dirname(binTargetPath), { recursive: true });
|
|
44011
|
+
fs33.copyFileSync(binPath, binTargetPath);
|
|
44012
|
+
fs33.chmodSync(binTargetPath, 493);
|
|
44011
44013
|
}
|
|
44012
44014
|
return { binPath: binTargetPath, isWASM };
|
|
44013
44015
|
}
|
|
@@ -44016,7 +44018,7 @@ for your current platform.`);
|
|
|
44016
44018
|
}
|
|
44017
44019
|
var child_process = __require2("child_process");
|
|
44018
44020
|
var crypto32 = __require2("crypto");
|
|
44019
|
-
var
|
|
44021
|
+
var path23 = __require2("path");
|
|
44020
44022
|
var fs222 = __require2("fs");
|
|
44021
44023
|
var os22 = __require2("os");
|
|
44022
44024
|
var tty2 = __require2("tty");
|
|
@@ -44033,7 +44035,7 @@ for your current platform.`);
|
|
|
44033
44035
|
var _a;
|
|
44034
44036
|
var isInternalWorkerThread = ((_a = worker_threads == null ? undefined : worker_threads.workerData) == null ? undefined : _a.esbuildVersion) === "0.25.5";
|
|
44035
44037
|
var esbuildCommandAndArgs = () => {
|
|
44036
|
-
if ((!ESBUILD_BINARY_PATH || false) && (
|
|
44038
|
+
if ((!ESBUILD_BINARY_PATH || false) && (path23.basename(__filename2) !== "main.js" || path23.basename(__dirname2) !== "lib")) {
|
|
44037
44039
|
throw new Error(`The esbuild JavaScript API cannot be bundled. Please mark the "esbuild" package as external so it's not included in the bundle.
|
|
44038
44040
|
|
|
44039
44041
|
More information: The file containing the code for esbuild's JavaScript API (${__filename2}) does not appear to be inside the esbuild package on the file system, which usually means that the esbuild package was bundled into another file. This is problematic because the API needs to run a binary executable inside the esbuild package which is located using a relative path from the API code to the executable. If the esbuild package is bundled, the relative path will be incorrect and the executable won't be found.`);
|
|
@@ -44329,7 +44331,7 @@ More information: The file containing the code for esbuild's JavaScript API (${_
|
|
|
44329
44331
|
afterClose(null);
|
|
44330
44332
|
};
|
|
44331
44333
|
var randomFileName = () => {
|
|
44332
|
-
return
|
|
44334
|
+
return path23.join(os22.tmpdir(), `esbuild-${crypto32.randomBytes(32).toString("hex")}`);
|
|
44333
44335
|
};
|
|
44334
44336
|
var workerThreadService = null;
|
|
44335
44337
|
var startWorkerThreadService = (worker_threads2) => {
|
|
@@ -46908,11 +46910,11 @@ var require_node22 = __commonJS2((exports) => {
|
|
|
46908
46910
|
var require_source_map_support = __commonJS22((exports2, module22) => {
|
|
46909
46911
|
var SourceMapConsumer = require_source_map().SourceMapConsumer;
|
|
46910
46912
|
var path3 = __require2("path");
|
|
46911
|
-
var
|
|
46913
|
+
var fs33;
|
|
46912
46914
|
try {
|
|
46913
|
-
|
|
46914
|
-
if (!
|
|
46915
|
-
|
|
46915
|
+
fs33 = __require2("fs");
|
|
46916
|
+
if (!fs33.existsSync || !fs33.readFileSync) {
|
|
46917
|
+
fs33 = null;
|
|
46916
46918
|
}
|
|
46917
46919
|
} catch (err2) {}
|
|
46918
46920
|
var bufferFrom = require_buffer_from();
|
|
@@ -46950,30 +46952,30 @@ var require_node22 = __commonJS2((exports) => {
|
|
|
46950
46952
|
};
|
|
46951
46953
|
}
|
|
46952
46954
|
var retrieveFile = handlerExec(retrieveFileHandlers);
|
|
46953
|
-
retrieveFileHandlers.push(function(
|
|
46954
|
-
|
|
46955
|
-
if (/^file:/.test(
|
|
46956
|
-
|
|
46955
|
+
retrieveFileHandlers.push(function(path23) {
|
|
46956
|
+
path23 = path23.trim();
|
|
46957
|
+
if (/^file:/.test(path23)) {
|
|
46958
|
+
path23 = path23.replace(/file:\/\/\/(\w:)?/, function(protocol, drive) {
|
|
46957
46959
|
return drive ? "" : "/";
|
|
46958
46960
|
});
|
|
46959
46961
|
}
|
|
46960
|
-
if (
|
|
46961
|
-
return fileContentsCache[
|
|
46962
|
+
if (path23 in fileContentsCache) {
|
|
46963
|
+
return fileContentsCache[path23];
|
|
46962
46964
|
}
|
|
46963
46965
|
var contents = "";
|
|
46964
46966
|
try {
|
|
46965
|
-
if (!
|
|
46967
|
+
if (!fs33) {
|
|
46966
46968
|
var xhr = new XMLHttpRequest;
|
|
46967
|
-
xhr.open("GET",
|
|
46969
|
+
xhr.open("GET", path23, false);
|
|
46968
46970
|
xhr.send(null);
|
|
46969
46971
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
|
46970
46972
|
contents = xhr.responseText;
|
|
46971
46973
|
}
|
|
46972
|
-
} else if (
|
|
46973
|
-
contents =
|
|
46974
|
+
} else if (fs33.existsSync(path23)) {
|
|
46975
|
+
contents = fs33.readFileSync(path23, "utf8");
|
|
46974
46976
|
}
|
|
46975
46977
|
} catch (er2) {}
|
|
46976
|
-
return fileContentsCache[
|
|
46978
|
+
return fileContentsCache[path23] = contents;
|
|
46977
46979
|
});
|
|
46978
46980
|
function supportRelativeURL(file, url2) {
|
|
46979
46981
|
if (!file)
|
|
@@ -47234,9 +47236,9 @@ var require_node22 = __commonJS2((exports) => {
|
|
|
47234
47236
|
var line2 = +match[2];
|
|
47235
47237
|
var column = +match[3];
|
|
47236
47238
|
var contents = fileContentsCache[source];
|
|
47237
|
-
if (!contents &&
|
|
47239
|
+
if (!contents && fs33 && fs33.existsSync(source)) {
|
|
47238
47240
|
try {
|
|
47239
|
-
contents =
|
|
47241
|
+
contents = fs33.readFileSync(source, "utf8");
|
|
47240
47242
|
} catch (er2) {
|
|
47241
47243
|
contents = "";
|
|
47242
47244
|
}
|
|
@@ -47780,13 +47782,13 @@ If you have no idea what this means or what Pirates is, let me explain: Pirates
|
|
|
47780
47782
|
var require_filesystem = __commonJS22((exports2) => {
|
|
47781
47783
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
47782
47784
|
exports2.removeExtension = exports2.fileExistsAsync = exports2.readJsonFromDiskAsync = exports2.readJsonFromDiskSync = exports2.fileExistsSync = undefined;
|
|
47783
|
-
var
|
|
47785
|
+
var fs33 = __require2("fs");
|
|
47784
47786
|
function fileExistsSync(path3) {
|
|
47785
|
-
if (!
|
|
47787
|
+
if (!fs33.existsSync(path3)) {
|
|
47786
47788
|
return false;
|
|
47787
47789
|
}
|
|
47788
47790
|
try {
|
|
47789
|
-
var stats =
|
|
47791
|
+
var stats = fs33.statSync(path3);
|
|
47790
47792
|
return stats.isFile();
|
|
47791
47793
|
} catch (err2) {
|
|
47792
47794
|
return false;
|
|
@@ -47794,14 +47796,14 @@ If you have no idea what this means or what Pirates is, let me explain: Pirates
|
|
|
47794
47796
|
}
|
|
47795
47797
|
exports2.fileExistsSync = fileExistsSync;
|
|
47796
47798
|
function readJsonFromDiskSync(packageJsonPath) {
|
|
47797
|
-
if (!
|
|
47799
|
+
if (!fs33.existsSync(packageJsonPath)) {
|
|
47798
47800
|
return;
|
|
47799
47801
|
}
|
|
47800
47802
|
return __require2(packageJsonPath);
|
|
47801
47803
|
}
|
|
47802
47804
|
exports2.readJsonFromDiskSync = readJsonFromDiskSync;
|
|
47803
47805
|
function readJsonFromDiskAsync(path3, callback) {
|
|
47804
|
-
|
|
47806
|
+
fs33.readFile(path3, "utf8", function(err2, result) {
|
|
47805
47807
|
if (err2 || !result) {
|
|
47806
47808
|
return callback();
|
|
47807
47809
|
}
|
|
@@ -47810,8 +47812,8 @@ If you have no idea what this means or what Pirates is, let me explain: Pirates
|
|
|
47810
47812
|
});
|
|
47811
47813
|
}
|
|
47812
47814
|
exports2.readJsonFromDiskAsync = readJsonFromDiskAsync;
|
|
47813
|
-
function fileExistsAsync(
|
|
47814
|
-
|
|
47815
|
+
function fileExistsAsync(path23, callback2) {
|
|
47816
|
+
fs33.stat(path23, function(err2, stats) {
|
|
47815
47817
|
if (err2) {
|
|
47816
47818
|
return callback2(undefined, false);
|
|
47817
47819
|
}
|
|
@@ -49254,7 +49256,7 @@ If you have no idea what this means or what Pirates is, let me explain: Pirates
|
|
|
49254
49256
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
49255
49257
|
exports2.loadTsconfig = exports2.walkForTsConfig = exports2.tsConfigLoader = undefined;
|
|
49256
49258
|
var path3 = __require2("path");
|
|
49257
|
-
var
|
|
49259
|
+
var fs33 = __require2("fs");
|
|
49258
49260
|
var JSON5 = require_lib3();
|
|
49259
49261
|
var StripBom = require_strip_bom();
|
|
49260
49262
|
function tsConfigLoader(_a) {
|
|
@@ -49283,10 +49285,10 @@ If you have no idea what this means or what Pirates is, let me explain: Pirates
|
|
|
49283
49285
|
}
|
|
49284
49286
|
function resolveConfigPath(cwd, filename) {
|
|
49285
49287
|
if (filename) {
|
|
49286
|
-
var absolutePath =
|
|
49288
|
+
var absolutePath = fs33.lstatSync(filename).isDirectory() ? path3.resolve(filename, "./tsconfig.json") : path3.resolve(cwd, filename);
|
|
49287
49289
|
return absolutePath;
|
|
49288
49290
|
}
|
|
49289
|
-
if (
|
|
49291
|
+
if (fs33.statSync(cwd).isFile()) {
|
|
49290
49292
|
return path3.resolve(cwd);
|
|
49291
49293
|
}
|
|
49292
49294
|
var configAbsolutePath = walkForTsConfig(cwd);
|
|
@@ -49294,7 +49296,7 @@ If you have no idea what this means or what Pirates is, let me explain: Pirates
|
|
|
49294
49296
|
}
|
|
49295
49297
|
function walkForTsConfig(directory, readdirSync) {
|
|
49296
49298
|
if (readdirSync === undefined) {
|
|
49297
|
-
readdirSync =
|
|
49299
|
+
readdirSync = fs33.readdirSync;
|
|
49298
49300
|
}
|
|
49299
49301
|
var files = readdirSync(directory);
|
|
49300
49302
|
var filesToCheck = ["tsconfig.json", "jsconfig.json"];
|
|
@@ -49313,11 +49315,11 @@ If you have no idea what this means or what Pirates is, let me explain: Pirates
|
|
|
49313
49315
|
exports2.walkForTsConfig = walkForTsConfig;
|
|
49314
49316
|
function loadTsconfig(configFilePath, existsSync2, readFileSync) {
|
|
49315
49317
|
if (existsSync2 === undefined) {
|
|
49316
|
-
existsSync2 =
|
|
49318
|
+
existsSync2 = fs33.existsSync;
|
|
49317
49319
|
}
|
|
49318
49320
|
if (readFileSync === undefined) {
|
|
49319
49321
|
readFileSync = function(filename) {
|
|
49320
|
-
return
|
|
49322
|
+
return fs33.readFileSync(filename, "utf8");
|
|
49321
49323
|
};
|
|
49322
49324
|
}
|
|
49323
49325
|
if (!existsSync2(configFilePath)) {
|
|
@@ -50947,7 +50949,7 @@ function mapColumnsInSQLToAlias2(query, alias) {
|
|
|
50947
50949
|
}
|
|
50948
50950
|
function mapResultRow2(columns, row, joinsNotNullableMap) {
|
|
50949
50951
|
const nullifyMap = {};
|
|
50950
|
-
const result = columns.reduce((result2, { path:
|
|
50952
|
+
const result = columns.reduce((result2, { path: path23, field }, columnIndex) => {
|
|
50951
50953
|
let decoder;
|
|
50952
50954
|
if (is2(field, Column2)) {
|
|
50953
50955
|
decoder = field;
|
|
@@ -50957,8 +50959,8 @@ function mapResultRow2(columns, row, joinsNotNullableMap) {
|
|
|
50957
50959
|
decoder = field.sql.decoder;
|
|
50958
50960
|
}
|
|
50959
50961
|
let node = result2;
|
|
50960
|
-
for (const [pathChunkIndex, pathChunk] of
|
|
50961
|
-
if (pathChunkIndex <
|
|
50962
|
+
for (const [pathChunkIndex, pathChunk] of path23.entries()) {
|
|
50963
|
+
if (pathChunkIndex < path23.length - 1) {
|
|
50962
50964
|
if (!(pathChunk in node)) {
|
|
50963
50965
|
node[pathChunk] = {};
|
|
50964
50966
|
}
|
|
@@ -50966,8 +50968,8 @@ function mapResultRow2(columns, row, joinsNotNullableMap) {
|
|
|
50966
50968
|
} else {
|
|
50967
50969
|
const rawValue = row[columnIndex];
|
|
50968
50970
|
const value = node[pathChunk] = rawValue === null ? null : decoder.mapFromDriverValue(rawValue);
|
|
50969
|
-
if (joinsNotNullableMap && is2(field, Column2) &&
|
|
50970
|
-
const objectName =
|
|
50971
|
+
if (joinsNotNullableMap && is2(field, Column2) && path23.length === 2) {
|
|
50972
|
+
const objectName = path23[0];
|
|
50971
50973
|
if (!(objectName in nullifyMap)) {
|
|
50972
50974
|
nullifyMap[objectName] = value === null ? getTableName2(field.table) : false;
|
|
50973
50975
|
} else if (typeof nullifyMap[objectName] === "string" && nullifyMap[objectName] !== getTableName2(field.table)) {
|
|
@@ -55779,7 +55781,7 @@ var init_api = __esm(() => {
|
|
|
55779
55781
|
"../node_modules/.pnpm/fs.realpath@1.0.0/node_modules/fs.realpath/old.js"(exports) {
|
|
55780
55782
|
var pathModule = __require22("path");
|
|
55781
55783
|
var isWindows = process.platform === "win32";
|
|
55782
|
-
var
|
|
55784
|
+
var fs33 = __require22("fs");
|
|
55783
55785
|
var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
|
|
55784
55786
|
function rethrow() {
|
|
55785
55787
|
var callback;
|
|
@@ -55844,7 +55846,7 @@ var init_api = __esm(() => {
|
|
|
55844
55846
|
base = m4[0];
|
|
55845
55847
|
previous = "";
|
|
55846
55848
|
if (isWindows && !knownHard[base]) {
|
|
55847
|
-
|
|
55849
|
+
fs33.lstatSync(base);
|
|
55848
55850
|
knownHard[base] = true;
|
|
55849
55851
|
}
|
|
55850
55852
|
}
|
|
@@ -55862,7 +55864,7 @@ var init_api = __esm(() => {
|
|
|
55862
55864
|
if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
|
|
55863
55865
|
resolvedLink = cache[base];
|
|
55864
55866
|
} else {
|
|
55865
|
-
var stat =
|
|
55867
|
+
var stat = fs33.lstatSync(base);
|
|
55866
55868
|
if (!stat.isSymbolicLink()) {
|
|
55867
55869
|
knownHard[base] = true;
|
|
55868
55870
|
if (cache)
|
|
@@ -55877,8 +55879,8 @@ var init_api = __esm(() => {
|
|
|
55877
55879
|
}
|
|
55878
55880
|
}
|
|
55879
55881
|
if (linkTarget === null) {
|
|
55880
|
-
|
|
55881
|
-
linkTarget =
|
|
55882
|
+
fs33.statSync(base);
|
|
55883
|
+
linkTarget = fs33.readlinkSync(base);
|
|
55882
55884
|
}
|
|
55883
55885
|
resolvedLink = pathModule.resolve(previous, linkTarget);
|
|
55884
55886
|
if (cache)
|
|
@@ -55915,7 +55917,7 @@ var init_api = __esm(() => {
|
|
|
55915
55917
|
base = m4[0];
|
|
55916
55918
|
previous = "";
|
|
55917
55919
|
if (isWindows && !knownHard[base]) {
|
|
55918
|
-
|
|
55920
|
+
fs33.lstat(base, function(err2) {
|
|
55919
55921
|
if (err2)
|
|
55920
55922
|
return cb(err2);
|
|
55921
55923
|
knownHard[base] = true;
|
|
@@ -55943,7 +55945,7 @@ var init_api = __esm(() => {
|
|
|
55943
55945
|
if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
|
|
55944
55946
|
return gotResolvedLink(cache[base]);
|
|
55945
55947
|
}
|
|
55946
|
-
return
|
|
55948
|
+
return fs33.lstat(base, gotStat);
|
|
55947
55949
|
}
|
|
55948
55950
|
function gotStat(err2, stat) {
|
|
55949
55951
|
if (err2)
|
|
@@ -55960,10 +55962,10 @@ var init_api = __esm(() => {
|
|
|
55960
55962
|
return gotTarget(null, seenLinks[id], base);
|
|
55961
55963
|
}
|
|
55962
55964
|
}
|
|
55963
|
-
|
|
55965
|
+
fs33.stat(base, function(err22) {
|
|
55964
55966
|
if (err22)
|
|
55965
55967
|
return cb(err22);
|
|
55966
|
-
|
|
55968
|
+
fs33.readlink(base, function(err3, target) {
|
|
55967
55969
|
if (!isWindows)
|
|
55968
55970
|
seenLinks[id] = target;
|
|
55969
55971
|
gotTarget(err3, target);
|
|
@@ -55993,9 +55995,9 @@ var init_api = __esm(() => {
|
|
|
55993
55995
|
realpath.realpathSync = realpathSync;
|
|
55994
55996
|
realpath.monkeypatch = monkeypatch;
|
|
55995
55997
|
realpath.unmonkeypatch = unmonkeypatch;
|
|
55996
|
-
var
|
|
55997
|
-
var origRealpath =
|
|
55998
|
-
var origRealpathSync =
|
|
55998
|
+
var fs33 = __require22("fs");
|
|
55999
|
+
var origRealpath = fs33.realpath;
|
|
56000
|
+
var origRealpathSync = fs33.realpathSync;
|
|
55999
56001
|
var version22 = process.version;
|
|
56000
56002
|
var ok = /^v[0-5]\./.test(version22);
|
|
56001
56003
|
var old = require_old();
|
|
@@ -56033,12 +56035,12 @@ var init_api = __esm(() => {
|
|
|
56033
56035
|
}
|
|
56034
56036
|
}
|
|
56035
56037
|
function monkeypatch() {
|
|
56036
|
-
|
|
56037
|
-
|
|
56038
|
+
fs33.realpath = realpath;
|
|
56039
|
+
fs33.realpathSync = realpathSync;
|
|
56038
56040
|
}
|
|
56039
56041
|
function unmonkeypatch() {
|
|
56040
|
-
|
|
56041
|
-
|
|
56042
|
+
fs33.realpath = origRealpath;
|
|
56043
|
+
fs33.realpathSync = origRealpathSync;
|
|
56042
56044
|
}
|
|
56043
56045
|
}
|
|
56044
56046
|
});
|
|
@@ -56264,8 +56266,8 @@ var init_api = __esm(() => {
|
|
|
56264
56266
|
return new Minimatch2(pattern, options).match(p3);
|
|
56265
56267
|
};
|
|
56266
56268
|
module2.exports = minimatch2;
|
|
56267
|
-
var
|
|
56268
|
-
minimatch2.sep =
|
|
56269
|
+
var path23 = require_path2();
|
|
56270
|
+
minimatch2.sep = path23.sep;
|
|
56269
56271
|
var GLOBSTAR2 = Symbol("globstar **");
|
|
56270
56272
|
minimatch2.GLOBSTAR = GLOBSTAR2;
|
|
56271
56273
|
var expand2 = require_brace_expansion3();
|
|
@@ -56778,8 +56780,8 @@ globstar while`, file, fr, pattern, pr3, swallowee);
|
|
|
56778
56780
|
if (f3 === "/" && partial)
|
|
56779
56781
|
return true;
|
|
56780
56782
|
const options = this.options;
|
|
56781
|
-
if (
|
|
56782
|
-
f3 = f3.split(
|
|
56783
|
+
if (path23.sep !== "/") {
|
|
56784
|
+
f3 = f3.split(path23.sep).join("/");
|
|
56783
56785
|
}
|
|
56784
56786
|
f3 = f3.split(slashSplit);
|
|
56785
56787
|
this.debug(this.pattern, "split", f3);
|
|
@@ -56869,8 +56871,8 @@ globstar while`, file, fr, pattern, pr3, swallowee);
|
|
|
56869
56871
|
function ownProp(obj, field) {
|
|
56870
56872
|
return Object.prototype.hasOwnProperty.call(obj, field);
|
|
56871
56873
|
}
|
|
56872
|
-
var
|
|
56873
|
-
var
|
|
56874
|
+
var fs33 = __require22("fs");
|
|
56875
|
+
var path23 = __require22("path");
|
|
56874
56876
|
var minimatch2 = require_minimatch2();
|
|
56875
56877
|
var isAbsolute2 = __require22("path").isAbsolute;
|
|
56876
56878
|
var Minimatch2 = minimatch2.Minimatch;
|
|
@@ -56928,7 +56930,7 @@ globstar while`, file, fr, pattern, pr3, swallowee);
|
|
|
56928
56930
|
self2.stat = !!options.stat;
|
|
56929
56931
|
self2.noprocess = !!options.noprocess;
|
|
56930
56932
|
self2.absolute = !!options.absolute;
|
|
56931
|
-
self2.fs = options.fs ||
|
|
56933
|
+
self2.fs = options.fs || fs33;
|
|
56932
56934
|
self2.maxLength = options.maxLength || Infinity;
|
|
56933
56935
|
self2.cache = options.cache || /* @__PURE__ */ Object.create(null);
|
|
56934
56936
|
self2.statCache = options.statCache || /* @__PURE__ */ Object.create(null);
|
|
@@ -56937,13 +56939,13 @@ globstar while`, file, fr, pattern, pr3, swallowee);
|
|
|
56937
56939
|
self2.changedCwd = false;
|
|
56938
56940
|
var cwd = process.cwd();
|
|
56939
56941
|
if (!ownProp(options, "cwd"))
|
|
56940
|
-
self2.cwd =
|
|
56942
|
+
self2.cwd = path23.resolve(cwd);
|
|
56941
56943
|
else {
|
|
56942
|
-
self2.cwd =
|
|
56944
|
+
self2.cwd = path23.resolve(options.cwd);
|
|
56943
56945
|
self2.changedCwd = self2.cwd !== cwd;
|
|
56944
56946
|
}
|
|
56945
|
-
self2.root = options.root ||
|
|
56946
|
-
self2.root =
|
|
56947
|
+
self2.root = options.root || path23.resolve(self2.cwd, "/");
|
|
56948
|
+
self2.root = path23.resolve(self2.root);
|
|
56947
56949
|
self2.cwdAbs = isAbsolute2(self2.cwd) ? self2.cwd : makeAbs(self2, self2.cwd);
|
|
56948
56950
|
self2.nomount = !!options.nomount;
|
|
56949
56951
|
if (process.platform === "win32") {
|
|
@@ -57025,13 +57027,13 @@ globstar while`, file, fr, pattern, pr3, swallowee);
|
|
|
57025
57027
|
function makeAbs(self2, f3) {
|
|
57026
57028
|
var abs = f3;
|
|
57027
57029
|
if (f3.charAt(0) === "/") {
|
|
57028
|
-
abs =
|
|
57030
|
+
abs = path23.join(self2.root, f3);
|
|
57029
57031
|
} else if (isAbsolute2(f3) || f3 === "") {
|
|
57030
57032
|
abs = f3;
|
|
57031
57033
|
} else if (self2.changedCwd) {
|
|
57032
|
-
abs =
|
|
57034
|
+
abs = path23.resolve(self2.cwd, f3);
|
|
57033
57035
|
} else {
|
|
57034
|
-
abs =
|
|
57036
|
+
abs = path23.resolve(f3);
|
|
57035
57037
|
}
|
|
57036
57038
|
if (process.platform === "win32")
|
|
57037
57039
|
abs = abs.replace(/\\/g, "/");
|
|
@@ -57062,7 +57064,7 @@ globstar while`, file, fr, pattern, pr3, swallowee);
|
|
|
57062
57064
|
var Minimatch2 = minimatch2.Minimatch;
|
|
57063
57065
|
var Glob = require_glob2().Glob;
|
|
57064
57066
|
var util2 = __require22("util");
|
|
57065
|
-
var
|
|
57067
|
+
var path23 = __require22("path");
|
|
57066
57068
|
var assert2 = __require22("assert");
|
|
57067
57069
|
var isAbsolute2 = __require22("path").isAbsolute;
|
|
57068
57070
|
var common = require_common2();
|
|
@@ -57192,7 +57194,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
57192
57194
|
e = prefix2 + e;
|
|
57193
57195
|
}
|
|
57194
57196
|
if (e.charAt(0) === "/" && !this.nomount) {
|
|
57195
|
-
e =
|
|
57197
|
+
e = path23.join(this.root, e);
|
|
57196
57198
|
}
|
|
57197
57199
|
this._emitMatch(index6, e);
|
|
57198
57200
|
}
|
|
@@ -57341,9 +57343,9 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
57341
57343
|
if (prefix2 && isAbsolute2(prefix2) && !this.nomount) {
|
|
57342
57344
|
var trail = /[\/\\]$/.test(prefix2);
|
|
57343
57345
|
if (prefix2.charAt(0) === "/") {
|
|
57344
|
-
prefix2 =
|
|
57346
|
+
prefix2 = path23.join(this.root, prefix2);
|
|
57345
57347
|
} else {
|
|
57346
|
-
prefix2 =
|
|
57348
|
+
prefix2 = path23.resolve(this.root, prefix2);
|
|
57347
57349
|
if (trail)
|
|
57348
57350
|
prefix2 += "/";
|
|
57349
57351
|
}
|
|
@@ -57530,7 +57532,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
57530
57532
|
var Minimatch2 = minimatch2.Minimatch;
|
|
57531
57533
|
var inherits = require_inherits2();
|
|
57532
57534
|
var EE = __require22("events").EventEmitter;
|
|
57533
|
-
var
|
|
57535
|
+
var path23 = __require22("path");
|
|
57534
57536
|
var assert2 = __require22("assert");
|
|
57535
57537
|
var isAbsolute2 = __require22("path").isAbsolute;
|
|
57536
57538
|
var globSync = require_sync();
|
|
@@ -57813,7 +57815,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
57813
57815
|
e = prefix2 + e;
|
|
57814
57816
|
}
|
|
57815
57817
|
if (e.charAt(0) === "/" && !this.nomount) {
|
|
57816
|
-
e =
|
|
57818
|
+
e = path23.join(this.root, e);
|
|
57817
57819
|
}
|
|
57818
57820
|
this._emitMatch(index6, e);
|
|
57819
57821
|
}
|
|
@@ -58000,9 +58002,9 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
58000
58002
|
if (prefix2 && isAbsolute2(prefix2) && !this.nomount) {
|
|
58001
58003
|
var trail = /[\/\\]$/.test(prefix2);
|
|
58002
58004
|
if (prefix2.charAt(0) === "/") {
|
|
58003
|
-
prefix2 =
|
|
58005
|
+
prefix2 = path23.join(this.root, prefix2);
|
|
58004
58006
|
} else {
|
|
58005
|
-
prefix2 =
|
|
58007
|
+
prefix2 = path23.resolve(this.root, prefix2);
|
|
58006
58008
|
if (trail)
|
|
58007
58009
|
prefix2 += "/";
|
|
58008
58010
|
}
|
|
@@ -58965,8 +58967,8 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
58965
58967
|
};
|
|
58966
58968
|
overrideErrorMap = errorMap;
|
|
58967
58969
|
makeIssue = (params) => {
|
|
58968
|
-
const { data: data2, path:
|
|
58969
|
-
const fullPath = [...
|
|
58970
|
+
const { data: data2, path: path23, errorMaps, issueData } = params;
|
|
58971
|
+
const fullPath = [...path23, ...issueData.path || []];
|
|
58970
58972
|
const fullIssue = {
|
|
58971
58973
|
...issueData,
|
|
58972
58974
|
path: fullPath
|
|
@@ -59057,11 +59059,11 @@ See: https://github.com/isaacs/node-glob/issues/167`);
|
|
|
59057
59059
|
errorUtil2.toString = (message) => typeof message === "string" ? message : message === null || message === undefined ? undefined : message.message;
|
|
59058
59060
|
})(errorUtil || (errorUtil = {}));
|
|
59059
59061
|
ParseInputLazyPath = class {
|
|
59060
|
-
constructor(parent, value,
|
|
59062
|
+
constructor(parent, value, path23, key) {
|
|
59061
59063
|
this._cachedPath = [];
|
|
59062
59064
|
this.parent = parent;
|
|
59063
59065
|
this.data = value;
|
|
59064
|
-
this._path =
|
|
59066
|
+
this._path = path23;
|
|
59065
59067
|
this._key = key;
|
|
59066
59068
|
}
|
|
59067
59069
|
get path() {
|
|
@@ -93939,13 +93941,13 @@ var RegExpRouter = class {
|
|
|
93939
93941
|
}
|
|
93940
93942
|
const paths = checkOptionalParameter(path4) || [path4];
|
|
93941
93943
|
for (let i22 = 0, len2 = paths.length;i22 < len2; i22++) {
|
|
93942
|
-
const
|
|
93944
|
+
const path23 = paths[i22];
|
|
93943
93945
|
Object.keys(routes).forEach((m) => {
|
|
93944
93946
|
if (method === METHOD_NAME_ALL || method === m) {
|
|
93945
|
-
routes[m][
|
|
93946
|
-
...findMiddleware(middleware[m],
|
|
93947
|
+
routes[m][path23] ||= [
|
|
93948
|
+
...findMiddleware(middleware[m], path23) || findMiddleware(middleware[METHOD_NAME_ALL], path23) || []
|
|
93947
93949
|
];
|
|
93948
|
-
routes[m][
|
|
93950
|
+
routes[m][path23].push([handler, paramCount - len2 + i22 + 1]);
|
|
93949
93951
|
}
|
|
93950
93952
|
});
|
|
93951
93953
|
}
|
|
@@ -93953,13 +93955,13 @@ var RegExpRouter = class {
|
|
|
93953
93955
|
match(method, path4) {
|
|
93954
93956
|
clearWildcardRegExpCache();
|
|
93955
93957
|
const matchers = this.#buildAllMatchers();
|
|
93956
|
-
this.match = (method2,
|
|
93958
|
+
this.match = (method2, path23) => {
|
|
93957
93959
|
const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
|
|
93958
|
-
const staticMatch = matcher[2][
|
|
93960
|
+
const staticMatch = matcher[2][path23];
|
|
93959
93961
|
if (staticMatch) {
|
|
93960
93962
|
return staticMatch;
|
|
93961
93963
|
}
|
|
93962
|
-
const match2 =
|
|
93964
|
+
const match2 = path23.match(matcher[0]);
|
|
93963
93965
|
if (!match2) {
|
|
93964
93966
|
return [[], emptyParam];
|
|
93965
93967
|
}
|
|
@@ -94351,7 +94353,7 @@ var logger = (fn = console.log) => {
|
|
|
94351
94353
|
};
|
|
94352
94354
|
var package_default = {
|
|
94353
94355
|
name: "@playcademy/sandbox",
|
|
94354
|
-
version: "0.1.0-beta.
|
|
94356
|
+
version: "0.1.0-beta.10",
|
|
94355
94357
|
description: "Local development server for Playcademy game development",
|
|
94356
94358
|
type: "module",
|
|
94357
94359
|
exports: {
|
|
@@ -94372,7 +94374,7 @@ var package_default = {
|
|
|
94372
94374
|
],
|
|
94373
94375
|
scripts: {
|
|
94374
94376
|
build: "bun run build.ts",
|
|
94375
|
-
bump: 'bunx bumpp --no-tag --no-push -c "chore(@playcademy/sandbox): release v%s"',
|
|
94377
|
+
bump: 'SKIP_TESTS=1 bunx bumpp --no-tag --no-push -c "chore(@playcademy/sandbox): release v%s"',
|
|
94376
94378
|
dev: "bun --watch src/cli.ts",
|
|
94377
94379
|
pub: "bun run build && bun run bump && bun publish --access public",
|
|
94378
94380
|
start: "bun src/cli.ts"
|
|
@@ -114334,11 +114336,15 @@ class DatabasePathManager {
|
|
|
114334
114336
|
}
|
|
114335
114337
|
static resolveDatabasePath(customPath) {
|
|
114336
114338
|
if (customPath) {
|
|
114339
|
+
if (customPath === ":memory:")
|
|
114340
|
+
return ":memory:";
|
|
114337
114341
|
return isAbsolute(customPath) ? customPath : join2(process.cwd(), customPath);
|
|
114338
114342
|
}
|
|
114339
114343
|
return join2(this.findNodeModulesPath(), this.DEFAULT_DB_SUBPATH);
|
|
114340
114344
|
}
|
|
114341
114345
|
static ensureDatabaseDirectory(dbPath) {
|
|
114346
|
+
if (dbPath === ":memory:")
|
|
114347
|
+
return;
|
|
114342
114348
|
const dirPath = dirname(dbPath);
|
|
114343
114349
|
const absolutePath = isAbsolute(dirPath) ? dirPath : join2(process.cwd(), dirPath);
|
|
114344
114350
|
try {
|
|
@@ -114375,25 +114381,115 @@ async function createDatabaseSchema(db) {
|
|
|
114375
114381
|
async function setupDatabase(customPath) {
|
|
114376
114382
|
const dbPath = DatabasePathManager.resolveDatabasePath(customPath);
|
|
114377
114383
|
DatabasePathManager.ensureDatabaseDirectory(dbPath);
|
|
114378
|
-
const client = new Ke2(dbPath);
|
|
114384
|
+
const client = dbPath === ":memory:" ? new Ke2 : new Ke2(dbPath);
|
|
114379
114385
|
const db = drizzle(client, { schema: exports_tables_index });
|
|
114380
114386
|
await createDatabaseSchema(db);
|
|
114381
114387
|
initializeDatabase(db);
|
|
114382
114388
|
return db;
|
|
114383
114389
|
}
|
|
114390
|
+
var MAX_LEVEL = 100;
|
|
114391
|
+
var ITEM_SLUGS = {
|
|
114392
|
+
PLAYCADEMY_CREDITS: "PLAYCADEMY_CREDITS",
|
|
114393
|
+
PLAYCADEMY_XP: "PLAYCADEMY_XP",
|
|
114394
|
+
FOUNDING_MEMBER_BADGE: "FOUNDING_MEMBER_BADGE",
|
|
114395
|
+
EARLY_ADOPTER_BADGE: "EARLY_ADOPTER_BADGE",
|
|
114396
|
+
FIRST_GAME_BADGE: "FIRST_GAME_BADGE",
|
|
114397
|
+
COMMON_SWORD: "COMMON_SWORD",
|
|
114398
|
+
SMALL_HEALTH_POTION: "SMALL_HEALTH_POTION",
|
|
114399
|
+
SMALL_BACKPACK: "SMALL_BACKPACK"
|
|
114400
|
+
};
|
|
114401
|
+
var CURRENCIES = {
|
|
114402
|
+
PRIMARY: ITEM_SLUGS.PLAYCADEMY_CREDITS,
|
|
114403
|
+
XP: ITEM_SLUGS.PLAYCADEMY_XP
|
|
114404
|
+
};
|
|
114405
|
+
var CURRENCY_SYMBOLS = {
|
|
114406
|
+
PLAYCADEMY_CREDITS: "PC",
|
|
114407
|
+
PLAYCADEMY_XP: "XP",
|
|
114408
|
+
DEFAULT: "¤"
|
|
114409
|
+
};
|
|
114410
|
+
var BADGES = {
|
|
114411
|
+
FOUNDING_MEMBER: ITEM_SLUGS.FOUNDING_MEMBER_BADGE,
|
|
114412
|
+
EARLY_ADOPTER: ITEM_SLUGS.EARLY_ADOPTER_BADGE,
|
|
114413
|
+
FIRST_GAME: ITEM_SLUGS.FIRST_GAME_BADGE
|
|
114414
|
+
};
|
|
114415
|
+
var INTERACTION_TYPE = Object.fromEntries(interactionTypeEnum.enumValues.map((value) => [value, value]));
|
|
114416
|
+
var CORE_GAME_UUIDS = {
|
|
114417
|
+
PLAYGROUND: "00000000-0000-0000-0000-000000000001",
|
|
114418
|
+
EQUATION_ARENA: "00000000-0000-0000-0000-000000000002",
|
|
114419
|
+
BAMBOO: "00000000-0000-0000-0000-000000000003"
|
|
114420
|
+
};
|
|
114384
114421
|
var now = new Date;
|
|
114385
|
-
var
|
|
114386
|
-
|
|
114387
|
-
|
|
114388
|
-
|
|
114389
|
-
|
|
114390
|
-
|
|
114391
|
-
|
|
114392
|
-
|
|
114393
|
-
|
|
114394
|
-
|
|
114395
|
-
|
|
114422
|
+
var DEMO_USERS = {
|
|
114423
|
+
admin: {
|
|
114424
|
+
id: crypto.randomUUID(),
|
|
114425
|
+
name: "Admin User",
|
|
114426
|
+
username: "admin_user",
|
|
114427
|
+
email: "admin@playcademy.com",
|
|
114428
|
+
emailVerified: true,
|
|
114429
|
+
image: null,
|
|
114430
|
+
role: "admin",
|
|
114431
|
+
developerStatus: "approved",
|
|
114432
|
+
createdAt: now,
|
|
114433
|
+
updatedAt: now
|
|
114434
|
+
},
|
|
114435
|
+
player: {
|
|
114436
|
+
id: crypto.randomUUID(),
|
|
114437
|
+
name: "Player User",
|
|
114438
|
+
username: "player_user",
|
|
114439
|
+
email: "player@playcademy.com",
|
|
114440
|
+
emailVerified: true,
|
|
114441
|
+
image: null,
|
|
114442
|
+
role: "player",
|
|
114443
|
+
developerStatus: "none",
|
|
114444
|
+
createdAt: now,
|
|
114445
|
+
updatedAt: now
|
|
114446
|
+
},
|
|
114447
|
+
developer: {
|
|
114448
|
+
id: crypto.randomUUID(),
|
|
114449
|
+
name: "Developer User",
|
|
114450
|
+
username: "developer_user",
|
|
114451
|
+
email: "developer@playcademy.com",
|
|
114452
|
+
emailVerified: true,
|
|
114453
|
+
image: null,
|
|
114454
|
+
role: "developer",
|
|
114455
|
+
developerStatus: "approved",
|
|
114456
|
+
createdAt: now,
|
|
114457
|
+
updatedAt: now
|
|
114458
|
+
},
|
|
114459
|
+
pendingDeveloper: {
|
|
114460
|
+
id: crypto.randomUUID(),
|
|
114461
|
+
name: "Pending Developer",
|
|
114462
|
+
username: "pending_dev",
|
|
114463
|
+
email: "pending@playcademy.com",
|
|
114464
|
+
emailVerified: true,
|
|
114465
|
+
image: null,
|
|
114466
|
+
role: "developer",
|
|
114467
|
+
developerStatus: "pending",
|
|
114468
|
+
createdAt: now,
|
|
114469
|
+
updatedAt: now
|
|
114470
|
+
},
|
|
114471
|
+
unverifiedPlayer: {
|
|
114472
|
+
id: crypto.randomUUID(),
|
|
114473
|
+
name: "Unverified Player",
|
|
114474
|
+
username: "unverified_player",
|
|
114475
|
+
email: "unverified@playcademy.com",
|
|
114476
|
+
emailVerified: false,
|
|
114477
|
+
image: null,
|
|
114478
|
+
role: "player",
|
|
114479
|
+
developerStatus: "none",
|
|
114480
|
+
createdAt: now,
|
|
114481
|
+
updatedAt: now
|
|
114482
|
+
}
|
|
114483
|
+
};
|
|
114484
|
+
var DEMO_TOKENS = {
|
|
114485
|
+
"sandbox-demo-token": DEMO_USERS.admin,
|
|
114486
|
+
"sandbox-admin-token": DEMO_USERS.admin,
|
|
114487
|
+
"sandbox-player-token": DEMO_USERS.player,
|
|
114488
|
+
"sandbox-developer-token": DEMO_USERS.developer,
|
|
114489
|
+
"sandbox-pending-dev-token": DEMO_USERS.pendingDeveloper,
|
|
114490
|
+
"sandbox-unverified-token": DEMO_USERS.unverifiedPlayer
|
|
114396
114491
|
};
|
|
114492
|
+
var DEMO_USER = DEMO_USERS.admin;
|
|
114397
114493
|
var PLAYCADEMY_CREDITS_ID = crypto.randomUUID();
|
|
114398
114494
|
var SAMPLE_ITEMS = [
|
|
114399
114495
|
{
|
|
@@ -114403,7 +114499,7 @@ var SAMPLE_ITEMS = [
|
|
|
114403
114499
|
displayName: "PLAYCADEMY credits",
|
|
114404
114500
|
description: "The main currency used across PLAYCADEMY.",
|
|
114405
114501
|
type: "currency",
|
|
114406
|
-
imageUrl: "playcademy-credit.png",
|
|
114502
|
+
imageUrl: "http://playcademy-sandbox.local/playcademy-credit.png",
|
|
114407
114503
|
metadata: {
|
|
114408
114504
|
rarity: "common"
|
|
114409
114505
|
}
|
|
@@ -114439,7 +114535,7 @@ var SAMPLE_ITEMS = [
|
|
|
114439
114535
|
displayName: "First Game Played",
|
|
114440
114536
|
description: "Awarded for playing your first game in the Playcademy platform.",
|
|
114441
114537
|
type: "badge",
|
|
114442
|
-
imageUrl: "first-game-badge.png",
|
|
114538
|
+
imageUrl: "http://playcademy-sandbox.local/first-game-badge.png",
|
|
114443
114539
|
metadata: {
|
|
114444
114540
|
rarity: "uncommon"
|
|
114445
114541
|
}
|
|
@@ -114451,7 +114547,7 @@ var SAMPLE_ITEMS = [
|
|
|
114451
114547
|
displayName: "Common Sword",
|
|
114452
114548
|
description: "A basic sword, good for beginners.",
|
|
114453
114549
|
type: "unlock",
|
|
114454
|
-
imageUrl: "common-sword.png",
|
|
114550
|
+
imageUrl: "http://playcademy-sandbox.local/common-sword.png",
|
|
114455
114551
|
metadata: undefined
|
|
114456
114552
|
},
|
|
114457
114553
|
{
|
|
@@ -114461,7 +114557,7 @@ var SAMPLE_ITEMS = [
|
|
|
114461
114557
|
displayName: "Small Health Potion",
|
|
114462
114558
|
description: "Restores a small amount of health.",
|
|
114463
114559
|
type: "other",
|
|
114464
|
-
imageUrl: "small-health-potion.png",
|
|
114560
|
+
imageUrl: "http://playcademy-sandbox.local/small-health-potion.png",
|
|
114465
114561
|
metadata: undefined
|
|
114466
114562
|
},
|
|
114467
114563
|
{
|
|
@@ -114471,7 +114567,7 @@ var SAMPLE_ITEMS = [
|
|
|
114471
114567
|
displayName: "Small Backpack",
|
|
114472
114568
|
description: "Increases your inventory capacity by 5 slots.",
|
|
114473
114569
|
type: "upgrade",
|
|
114474
|
-
imageUrl: "small-backpack.png",
|
|
114570
|
+
imageUrl: "http://playcademy-sandbox.local/small-backpack.png",
|
|
114475
114571
|
metadata: undefined
|
|
114476
114572
|
}
|
|
114477
114573
|
];
|
|
@@ -114485,10 +114581,14 @@ var SAMPLE_INVENTORY = [
|
|
|
114485
114581
|
];
|
|
114486
114582
|
async function seedDemoData(db) {
|
|
114487
114583
|
try {
|
|
114488
|
-
|
|
114584
|
+
const allDemoUsers = Object.values(DEMO_USERS);
|
|
114585
|
+
for (const user of allDemoUsers) {
|
|
114586
|
+
await db.insert(users).values(user).onConflictDoNothing();
|
|
114587
|
+
}
|
|
114489
114588
|
for (const item of SAMPLE_ITEMS) {
|
|
114490
114589
|
await db.insert(items).values(item);
|
|
114491
114590
|
}
|
|
114591
|
+
await seedCurrencies(db);
|
|
114492
114592
|
for (const inventory of SAMPLE_INVENTORY) {
|
|
114493
114593
|
await db.insert(inventoryItems).values(inventory);
|
|
114494
114594
|
}
|
|
@@ -114496,12 +114596,90 @@ async function seedDemoData(db) {
|
|
|
114496
114596
|
for (const config of levelConfigsData) {
|
|
114497
114597
|
await db.insert(levelConfigs).values(config);
|
|
114498
114598
|
}
|
|
114599
|
+
await seedCoreGames(db);
|
|
114499
114600
|
} catch (error2) {
|
|
114500
114601
|
console.error("❌ Error seeding demo data:", error2);
|
|
114501
114602
|
throw error2;
|
|
114502
114603
|
}
|
|
114503
114604
|
return DEMO_USER;
|
|
114504
114605
|
}
|
|
114606
|
+
async function seedCurrencies(db) {
|
|
114607
|
+
const currencyItems = SAMPLE_ITEMS.filter((item) => item.type === "currency");
|
|
114608
|
+
for (const currencyItem of currencyItems) {
|
|
114609
|
+
const symbol = getCurrencySymbol(currencyItem.slug);
|
|
114610
|
+
const isPrimary = currencyItem.slug === ITEM_SLUGS.PLAYCADEMY_CREDITS;
|
|
114611
|
+
await db.insert(currencies).values({
|
|
114612
|
+
id: crypto.randomUUID(),
|
|
114613
|
+
itemId: currencyItem.id,
|
|
114614
|
+
symbol,
|
|
114615
|
+
isPrimary,
|
|
114616
|
+
createdAt: new Date,
|
|
114617
|
+
updatedAt: new Date
|
|
114618
|
+
});
|
|
114619
|
+
}
|
|
114620
|
+
}
|
|
114621
|
+
function getCurrencySymbol(slug) {
|
|
114622
|
+
switch (slug) {
|
|
114623
|
+
case ITEM_SLUGS.PLAYCADEMY_CREDITS:
|
|
114624
|
+
return CURRENCY_SYMBOLS.PLAYCADEMY_CREDITS;
|
|
114625
|
+
case ITEM_SLUGS.PLAYCADEMY_XP:
|
|
114626
|
+
return CURRENCY_SYMBOLS.PLAYCADEMY_XP;
|
|
114627
|
+
default:
|
|
114628
|
+
return CURRENCY_SYMBOLS.DEFAULT;
|
|
114629
|
+
}
|
|
114630
|
+
}
|
|
114631
|
+
async function seedCoreGames(db) {
|
|
114632
|
+
const now2 = new Date;
|
|
114633
|
+
const coreGames = [
|
|
114634
|
+
{
|
|
114635
|
+
id: CORE_GAME_UUIDS.PLAYGROUND,
|
|
114636
|
+
developerId: DEMO_USER.id,
|
|
114637
|
+
slug: "playground",
|
|
114638
|
+
displayName: "Playground",
|
|
114639
|
+
version: "local",
|
|
114640
|
+
platform: "web",
|
|
114641
|
+
assetBundleBase: "https://cdn.test.playcademy.net/games/01/internal",
|
|
114642
|
+
metadata: { description: "A playground environment for internal testing." },
|
|
114643
|
+
mapElementId: null,
|
|
114644
|
+
createdAt: now2,
|
|
114645
|
+
updatedAt: now2
|
|
114646
|
+
},
|
|
114647
|
+
{
|
|
114648
|
+
id: CORE_GAME_UUIDS.EQUATION_ARENA,
|
|
114649
|
+
developerId: DEMO_USER.id,
|
|
114650
|
+
slug: "equation-arena",
|
|
114651
|
+
displayName: "Equation Arena",
|
|
114652
|
+
version: "local",
|
|
114653
|
+
platform: "web",
|
|
114654
|
+
assetBundleBase: "https://cdn.test.playcademy.net/games/02/internal",
|
|
114655
|
+
metadata: { description: "Solve math problems to defeat the dragon!" },
|
|
114656
|
+
mapElementId: null,
|
|
114657
|
+
createdAt: now2,
|
|
114658
|
+
updatedAt: now2
|
|
114659
|
+
},
|
|
114660
|
+
{
|
|
114661
|
+
id: CORE_GAME_UUIDS.BAMBOO,
|
|
114662
|
+
developerId: DEMO_USER.id,
|
|
114663
|
+
slug: "bamboo",
|
|
114664
|
+
displayName: "Bamboo",
|
|
114665
|
+
version: "local",
|
|
114666
|
+
platform: "web",
|
|
114667
|
+
assetBundleBase: "https://cdn.test.playcademy.net/games/03/internal",
|
|
114668
|
+
metadata: { description: "A relaxing game with bamboo and pandas." },
|
|
114669
|
+
mapElementId: null,
|
|
114670
|
+
createdAt: now2,
|
|
114671
|
+
updatedAt: now2
|
|
114672
|
+
}
|
|
114673
|
+
];
|
|
114674
|
+
for (const gameData of coreGames) {
|
|
114675
|
+
try {
|
|
114676
|
+
await db.insert(games).values(gameData).onConflictDoNothing();
|
|
114677
|
+
console.log(`-> Seeded core game: ${gameData.displayName} (${gameData.slug})`);
|
|
114678
|
+
} catch (error2) {
|
|
114679
|
+
console.error(`Error seeding core game '${gameData.slug}':`, error2);
|
|
114680
|
+
}
|
|
114681
|
+
}
|
|
114682
|
+
}
|
|
114505
114683
|
function generateLevelConfigs() {
|
|
114506
114684
|
const configs = [];
|
|
114507
114685
|
for (let level = 1;level <= 100; level++) {
|
|
@@ -114550,7 +114728,7 @@ async function seedCurrentProjectGame(db, project) {
|
|
|
114550
114728
|
displayName: project.displayName,
|
|
114551
114729
|
version: project.version,
|
|
114552
114730
|
platform: "web",
|
|
114553
|
-
assetBundleBase: "",
|
|
114731
|
+
assetBundleBase: "https://localhost",
|
|
114554
114732
|
metadata: {
|
|
114555
114733
|
description: project.description || `Auto-generated game for ${project.displayName}`
|
|
114556
114734
|
},
|
|
@@ -114565,9 +114743,65 @@ async function seedCurrentProjectGame(db, project) {
|
|
|
114565
114743
|
throw error2;
|
|
114566
114744
|
}
|
|
114567
114745
|
}
|
|
114746
|
+
function extractTokenFromHeader(authHeader) {
|
|
114747
|
+
if (!authHeader?.startsWith("Bearer ")) {
|
|
114748
|
+
return null;
|
|
114749
|
+
}
|
|
114750
|
+
return authHeader.substring(7);
|
|
114751
|
+
}
|
|
114752
|
+
function parseJwtToken(token) {
|
|
114753
|
+
try {
|
|
114754
|
+
const parts2 = token.split(".");
|
|
114755
|
+
if (parts2.length === 3 && parts2[1]) {
|
|
114756
|
+
const payload = JSON.parse(atob(parts2[1]));
|
|
114757
|
+
return payload.uid || null;
|
|
114758
|
+
}
|
|
114759
|
+
} catch (error2) {
|
|
114760
|
+
console.warn("Failed to decode JWT token:", error2);
|
|
114761
|
+
}
|
|
114762
|
+
return null;
|
|
114763
|
+
}
|
|
114764
|
+
function resolveUserId(token) {
|
|
114765
|
+
const demoUser = DEMO_TOKENS[token];
|
|
114766
|
+
if (demoUser) {
|
|
114767
|
+
return demoUser.id;
|
|
114768
|
+
}
|
|
114769
|
+
if (token.includes(".")) {
|
|
114770
|
+
return parseJwtToken(token);
|
|
114771
|
+
}
|
|
114772
|
+
return null;
|
|
114773
|
+
}
|
|
114774
|
+
async function fetchUserFromDatabase(db, userId) {
|
|
114775
|
+
try {
|
|
114776
|
+
const user = await db.query.users.findFirst({
|
|
114777
|
+
where: eq(users.id, userId)
|
|
114778
|
+
});
|
|
114779
|
+
return user || null;
|
|
114780
|
+
} catch (error2) {
|
|
114781
|
+
console.error("Error fetching user from database:", error2);
|
|
114782
|
+
throw error2;
|
|
114783
|
+
}
|
|
114784
|
+
}
|
|
114568
114785
|
function setupAuth() {
|
|
114569
114786
|
return async (c2, next) => {
|
|
114570
|
-
c2.
|
|
114787
|
+
const authHeader = c2.req.header("Authorization");
|
|
114788
|
+
const token = extractTokenFromHeader(authHeader);
|
|
114789
|
+
if (!token) {
|
|
114790
|
+
throw new Error("No authorization token provided");
|
|
114791
|
+
}
|
|
114792
|
+
const targetUserId = resolveUserId(token);
|
|
114793
|
+
if (!targetUserId) {
|
|
114794
|
+
throw new Error("No user found for provided token");
|
|
114795
|
+
}
|
|
114796
|
+
const db = c2.get("db");
|
|
114797
|
+
if (!db) {
|
|
114798
|
+
throw new Error("Database not available in context");
|
|
114799
|
+
}
|
|
114800
|
+
const user = await fetchUserFromDatabase(db, targetUserId);
|
|
114801
|
+
if (!user) {
|
|
114802
|
+
throw new Error(`User not found: ${targetUserId}`);
|
|
114803
|
+
}
|
|
114804
|
+
c2.set("user", user);
|
|
114571
114805
|
await next();
|
|
114572
114806
|
};
|
|
114573
114807
|
}
|
|
@@ -114592,9 +114826,15 @@ class ApiError extends Error {
|
|
|
114592
114826
|
static notFound(message = "Not found") {
|
|
114593
114827
|
return new ApiError(404, "NOT_FOUND", message);
|
|
114594
114828
|
}
|
|
114829
|
+
static methodNotAllowed(message = "Method not allowed") {
|
|
114830
|
+
return new ApiError(405, "METHOD_NOT_ALLOWED", message);
|
|
114831
|
+
}
|
|
114595
114832
|
static badRequest(message = "Bad request", details) {
|
|
114596
114833
|
return new ApiError(400, "BAD_REQUEST", message, details);
|
|
114597
114834
|
}
|
|
114835
|
+
static unprocessableEntity(message = "Unprocessable entity", details) {
|
|
114836
|
+
return new ApiError(422, "UNPROCESSABLE_ENTITY", message, details);
|
|
114837
|
+
}
|
|
114598
114838
|
static conflict(message = "Conflict") {
|
|
114599
114839
|
return new ApiError(409, "CONFLICT", message);
|
|
114600
114840
|
}
|
|
@@ -115064,8 +115304,8 @@ function getErrorMap2() {
|
|
|
115064
115304
|
return overrideErrorMap2;
|
|
115065
115305
|
}
|
|
115066
115306
|
var makeIssue2 = (params) => {
|
|
115067
|
-
const { data: data2, path:
|
|
115068
|
-
const fullPath = [...
|
|
115307
|
+
const { data: data2, path: path23, errorMaps, issueData } = params;
|
|
115308
|
+
const fullPath = [...path23, ...issueData.path || []];
|
|
115069
115309
|
const fullIssue = {
|
|
115070
115310
|
...issueData,
|
|
115071
115311
|
path: fullPath
|
|
@@ -115175,11 +115415,11 @@ var errorUtil2;
|
|
|
115175
115415
|
})(errorUtil2 || (errorUtil2 = {}));
|
|
115176
115416
|
|
|
115177
115417
|
class ParseInputLazyPath2 {
|
|
115178
|
-
constructor(parent, value,
|
|
115418
|
+
constructor(parent, value, path23, key) {
|
|
115179
115419
|
this._cachedPath = [];
|
|
115180
115420
|
this.parent = parent;
|
|
115181
115421
|
this.data = value;
|
|
115182
|
-
this._path =
|
|
115422
|
+
this._path = path23;
|
|
115183
115423
|
this._key = key;
|
|
115184
115424
|
}
|
|
115185
115425
|
get path() {
|
|
@@ -118559,27 +118799,6 @@ var coerce2 = {
|
|
|
118559
118799
|
date: (arg) => ZodDate2.create({ ...arg, coerce: true })
|
|
118560
118800
|
};
|
|
118561
118801
|
var NEVER = INVALID2;
|
|
118562
|
-
var MAX_LEVEL = 100;
|
|
118563
|
-
var ITEM_SLUGS = {
|
|
118564
|
-
PLAYCADEMY_CREDITS: "PLAYCADEMY_CREDITS",
|
|
118565
|
-
PLAYCADEMY_XP: "PLAYCADEMY_XP",
|
|
118566
|
-
FOUNDING_MEMBER_BADGE: "FOUNDING_MEMBER_BADGE",
|
|
118567
|
-
EARLY_ADOPTER_BADGE: "EARLY_ADOPTER_BADGE",
|
|
118568
|
-
FIRST_GAME_BADGE: "FIRST_GAME_BADGE",
|
|
118569
|
-
COMMON_SWORD: "COMMON_SWORD",
|
|
118570
|
-
SMALL_HEALTH_POTION: "SMALL_HEALTH_POTION",
|
|
118571
|
-
SMALL_BACKPACK: "SMALL_BACKPACK"
|
|
118572
|
-
};
|
|
118573
|
-
var CURRENCIES = {
|
|
118574
|
-
PRIMARY: ITEM_SLUGS.PLAYCADEMY_CREDITS,
|
|
118575
|
-
XP: ITEM_SLUGS.PLAYCADEMY_XP
|
|
118576
|
-
};
|
|
118577
|
-
var BADGES = {
|
|
118578
|
-
FOUNDING_MEMBER: ITEM_SLUGS.FOUNDING_MEMBER_BADGE,
|
|
118579
|
-
EARLY_ADOPTER: ITEM_SLUGS.EARLY_ADOPTER_BADGE,
|
|
118580
|
-
FIRST_GAME: ITEM_SLUGS.FIRST_GAME_BADGE
|
|
118581
|
-
};
|
|
118582
|
-
var INTERACTION_TYPE = Object.fromEntries(interactionTypeEnum.enumValues.map((value) => [value, value]));
|
|
118583
118802
|
var CONSTANTS = {
|
|
118584
118803
|
INT8_MIN: -128,
|
|
118585
118804
|
INT8_MAX: 127,
|
|
@@ -118879,10 +119098,10 @@ var CreateDeveloperKeyInputSchema = InsertDeveloperKeySchema.pick({
|
|
|
118879
119098
|
});
|
|
118880
119099
|
var safeRelativePathRegex = /^(?!.*\.\.)(?!\/)[\w\-./]+$/;
|
|
118881
119100
|
var invalidPathMessage = "Path must be relative, contain only alphanumeric, -, _, ., / characters, and not contain .. segments.";
|
|
118882
|
-
var validateRelativePath = (
|
|
118883
|
-
if (
|
|
119101
|
+
var validateRelativePath = (path23, fieldName) => {
|
|
119102
|
+
if (path23 == null)
|
|
118884
119103
|
return true;
|
|
118885
|
-
if (typeof
|
|
119104
|
+
if (typeof path23 !== "string" || !safeRelativePathRegex.test(path23)) {
|
|
118886
119105
|
throw new exports_external.ZodError([
|
|
118887
119106
|
{
|
|
118888
119107
|
code: exports_external.ZodIssueCode.custom,
|
|
@@ -118994,10 +119213,10 @@ var ManifestV1Schema = exports_external.object({
|
|
|
118994
119213
|
});
|
|
118995
119214
|
var safeRelativePathRegex2 = /^(?!.*\.\.)(?!\/)[\w\-./]+$/;
|
|
118996
119215
|
var invalidPathMessage2 = "Path must be relative, contain only alphanumeric, -, _, ., / characters, and not contain .. segments.";
|
|
118997
|
-
var validateRelativePath2 = (
|
|
118998
|
-
if (
|
|
119216
|
+
var validateRelativePath2 = (path23, fieldName) => {
|
|
119217
|
+
if (path23 == null)
|
|
118999
119218
|
return true;
|
|
119000
|
-
if (typeof
|
|
119219
|
+
if (typeof path23 !== "string" || !safeRelativePathRegex2.test(path23)) {
|
|
119001
119220
|
throw new exports_external.ZodError([
|
|
119002
119221
|
{
|
|
119003
119222
|
code: exports_external.ZodIssueCode.custom,
|
|
@@ -119276,9 +119495,8 @@ async function getUserLevel(ctx) {
|
|
|
119276
119495
|
}
|
|
119277
119496
|
return userLevel;
|
|
119278
119497
|
} catch (error2) {
|
|
119279
|
-
if (error2 instanceof ApiError)
|
|
119498
|
+
if (error2 instanceof ApiError)
|
|
119280
119499
|
throw error2;
|
|
119281
|
-
}
|
|
119282
119500
|
log2.error(`Error fetching user level for user ${user.id}:`, { error: error2 });
|
|
119283
119501
|
throw ApiError.internal("Internal server error", error2);
|
|
119284
119502
|
}
|
|
@@ -119365,9 +119583,8 @@ async function addXP(ctx, amount) {
|
|
|
119365
119583
|
});
|
|
119366
119584
|
return result;
|
|
119367
119585
|
} catch (error2) {
|
|
119368
|
-
if (error2 instanceof ApiError)
|
|
119586
|
+
if (error2 instanceof ApiError)
|
|
119369
119587
|
throw error2;
|
|
119370
|
-
}
|
|
119371
119588
|
log2.error(`Error adding XP for user ${user.id}:`, { error: error2 });
|
|
119372
119589
|
throw ApiError.internal("Internal server error", error2);
|
|
119373
119590
|
}
|
|
@@ -119414,9 +119631,8 @@ async function getUserLevelProgress(ctx) {
|
|
|
119414
119631
|
totalXP: userLevel.totalXP
|
|
119415
119632
|
};
|
|
119416
119633
|
} catch (error2) {
|
|
119417
|
-
if (error2 instanceof ApiError)
|
|
119634
|
+
if (error2 instanceof ApiError)
|
|
119418
119635
|
throw error2;
|
|
119419
|
-
}
|
|
119420
119636
|
log2.error(`Error fetching user level progress:`, { error: error2 });
|
|
119421
119637
|
throw ApiError.internal("Internal server error", error2);
|
|
119422
119638
|
}
|
|
@@ -119435,9 +119651,8 @@ async function getLevelConfigByPath(ctx) {
|
|
|
119435
119651
|
const db = getDatabase();
|
|
119436
119652
|
return await getLevelConfig(db, level);
|
|
119437
119653
|
} catch (error2) {
|
|
119438
|
-
if (error2 instanceof ApiError)
|
|
119654
|
+
if (error2 instanceof ApiError)
|
|
119439
119655
|
throw error2;
|
|
119440
|
-
}
|
|
119441
119656
|
log2.error(`Error fetching level config for level ${level}:`, { error: error2 });
|
|
119442
119657
|
throw ApiError.internal("Internal server error", error2);
|
|
119443
119658
|
}
|
|
@@ -119459,13 +119674,34 @@ async function getUserMe(ctx) {
|
|
|
119459
119674
|
}
|
|
119460
119675
|
return userData;
|
|
119461
119676
|
} catch (error2) {
|
|
119462
|
-
if (error2 instanceof ApiError)
|
|
119677
|
+
if (error2 instanceof ApiError)
|
|
119463
119678
|
throw error2;
|
|
119464
|
-
}
|
|
119465
119679
|
log2.error("[API /users/me] Database error fetching user:", { error: error2 });
|
|
119466
119680
|
throw ApiError.internal("Internal server error", error2);
|
|
119467
119681
|
}
|
|
119468
119682
|
}
|
|
119683
|
+
function createErrorResponse(error2) {
|
|
119684
|
+
const errorResponse = {
|
|
119685
|
+
error: {
|
|
119686
|
+
code: error2.code,
|
|
119687
|
+
message: error2.message,
|
|
119688
|
+
details: error2.details
|
|
119689
|
+
}
|
|
119690
|
+
};
|
|
119691
|
+
if (errorResponse.error.details === undefined) {
|
|
119692
|
+
delete errorResponse.error.details;
|
|
119693
|
+
}
|
|
119694
|
+
return errorResponse;
|
|
119695
|
+
}
|
|
119696
|
+
function createUnknownErrorResponse(error2) {
|
|
119697
|
+
const message = error2 instanceof Error ? error2.message : "Internal server error";
|
|
119698
|
+
return {
|
|
119699
|
+
error: {
|
|
119700
|
+
code: "INTERNAL_ERROR",
|
|
119701
|
+
message
|
|
119702
|
+
}
|
|
119703
|
+
};
|
|
119704
|
+
}
|
|
119469
119705
|
var usersRouter = new Hono2;
|
|
119470
119706
|
usersRouter.get("/me", async (c2) => {
|
|
119471
119707
|
const ctx = {
|
|
@@ -119479,11 +119715,10 @@ usersRouter.get("/me", async (c2) => {
|
|
|
119479
119715
|
return c2.json(userData);
|
|
119480
119716
|
} catch (error2) {
|
|
119481
119717
|
if (error2 instanceof ApiError) {
|
|
119482
|
-
return c2.json(
|
|
119718
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
119483
119719
|
}
|
|
119484
119720
|
console.error("Error in getUserMe:", error2);
|
|
119485
|
-
|
|
119486
|
-
return c2.json({ error: message }, 500);
|
|
119721
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
119487
119722
|
}
|
|
119488
119723
|
});
|
|
119489
119724
|
usersRouter.get("/level", async (c2) => {
|
|
@@ -119498,11 +119733,10 @@ usersRouter.get("/level", async (c2) => {
|
|
|
119498
119733
|
return c2.json(levelData);
|
|
119499
119734
|
} catch (error2) {
|
|
119500
119735
|
if (error2 instanceof ApiError) {
|
|
119501
|
-
return c2.json(
|
|
119736
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
119502
119737
|
}
|
|
119503
119738
|
console.error("Error in getUserLevel:", error2);
|
|
119504
|
-
|
|
119505
|
-
return c2.json({ error: message }, 500);
|
|
119739
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
119506
119740
|
}
|
|
119507
119741
|
});
|
|
119508
119742
|
usersRouter.get("/level/progress", async (c2) => {
|
|
@@ -119517,11 +119751,10 @@ usersRouter.get("/level/progress", async (c2) => {
|
|
|
119517
119751
|
return c2.json(progressData);
|
|
119518
119752
|
} catch (error2) {
|
|
119519
119753
|
if (error2 instanceof ApiError) {
|
|
119520
|
-
return c2.json(
|
|
119754
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
119521
119755
|
}
|
|
119522
119756
|
console.error("Error in getUserLevelProgress:", error2);
|
|
119523
|
-
|
|
119524
|
-
return c2.json({ error: message }, 500);
|
|
119757
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
119525
119758
|
}
|
|
119526
119759
|
});
|
|
119527
119760
|
usersRouter.post("/xp/add", async (c2) => {
|
|
@@ -119536,13 +119769,16 @@ usersRouter.post("/xp/add", async (c2) => {
|
|
|
119536
119769
|
return c2.json(result);
|
|
119537
119770
|
} catch (error2) {
|
|
119538
119771
|
if (error2 instanceof ApiError) {
|
|
119539
|
-
return c2.json(
|
|
119772
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
119540
119773
|
}
|
|
119541
119774
|
console.error("Error in addXPFromRequest:", error2);
|
|
119542
|
-
|
|
119543
|
-
return c2.json({ error: message }, 500);
|
|
119775
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
119544
119776
|
}
|
|
119545
119777
|
});
|
|
119778
|
+
usersRouter.all("/", async (c2) => {
|
|
119779
|
+
const error2 = ApiError.methodNotAllowed("Method not allowed");
|
|
119780
|
+
return c2.json(createErrorResponse(error2), 405);
|
|
119781
|
+
});
|
|
119546
119782
|
var healthRouter = new Hono2;
|
|
119547
119783
|
healthRouter.get("/", (c2) => c2.json({ status: "ok", timestamp: new Date().toISOString() }));
|
|
119548
119784
|
async function getUserInventory(ctx) {
|
|
@@ -119704,11 +119940,10 @@ inventoryRouter.get("/", async (c2) => {
|
|
|
119704
119940
|
return c2.json(inventory);
|
|
119705
119941
|
} catch (error2) {
|
|
119706
119942
|
if (error2 instanceof ApiError) {
|
|
119707
|
-
return c2.json(
|
|
119943
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
119708
119944
|
}
|
|
119709
119945
|
console.error("Error in getUserInventory:", error2);
|
|
119710
|
-
|
|
119711
|
-
return c2.json({ error: message }, 500);
|
|
119946
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
119712
119947
|
}
|
|
119713
119948
|
});
|
|
119714
119949
|
inventoryRouter.post("/add", async (c2) => {
|
|
@@ -119723,11 +119958,10 @@ inventoryRouter.post("/add", async (c2) => {
|
|
|
119723
119958
|
return c2.json(result);
|
|
119724
119959
|
} catch (error2) {
|
|
119725
119960
|
if (error2 instanceof ApiError) {
|
|
119726
|
-
return c2.json(
|
|
119961
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
119727
119962
|
}
|
|
119728
119963
|
console.error("Error in addInventoryItem:", error2);
|
|
119729
|
-
|
|
119730
|
-
return c2.json({ error: message }, 500);
|
|
119964
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
119731
119965
|
}
|
|
119732
119966
|
});
|
|
119733
119967
|
inventoryRouter.post("/remove", async (c2) => {
|
|
@@ -119742,13 +119976,16 @@ inventoryRouter.post("/remove", async (c2) => {
|
|
|
119742
119976
|
return c2.json(result);
|
|
119743
119977
|
} catch (error2) {
|
|
119744
119978
|
if (error2 instanceof ApiError) {
|
|
119745
|
-
return c2.json(
|
|
119979
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
119746
119980
|
}
|
|
119747
119981
|
console.error("Error in removeInventoryItem:", error2);
|
|
119748
|
-
|
|
119749
|
-
return c2.json({ error: message }, 500);
|
|
119982
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
119750
119983
|
}
|
|
119751
119984
|
});
|
|
119985
|
+
inventoryRouter.all("/", async (c2) => {
|
|
119986
|
+
const error2 = ApiError.methodNotAllowed("Method not allowed");
|
|
119987
|
+
return c2.json(createErrorResponse(error2), 405);
|
|
119988
|
+
});
|
|
119752
119989
|
function assertError(err2) {
|
|
119753
119990
|
if (!isError(err2)) {
|
|
119754
119991
|
throw new Error("Parameter was not an error");
|
|
@@ -119961,9 +120198,6 @@ async function initiateUpload(ctx) {
|
|
|
119961
120198
|
if (!user) {
|
|
119962
120199
|
throw ApiError.unauthorized("Must be logged in to initiate uploads");
|
|
119963
120200
|
}
|
|
119964
|
-
if (!uploadDeps) {
|
|
119965
|
-
throw ApiError.internal("Upload dependencies not configured");
|
|
119966
|
-
}
|
|
119967
120201
|
let inputData;
|
|
119968
120202
|
try {
|
|
119969
120203
|
const requestBody = await ctx.request.json();
|
|
@@ -119980,6 +120214,9 @@ async function initiateUpload(ctx) {
|
|
|
119980
120214
|
throw ApiError.badRequest("Invalid JSON body");
|
|
119981
120215
|
}
|
|
119982
120216
|
const { fileName, gameId } = inputData;
|
|
120217
|
+
if (!uploadDeps) {
|
|
120218
|
+
throw ApiError.internal("Upload dependencies not configured");
|
|
120219
|
+
}
|
|
119983
120220
|
try {
|
|
119984
120221
|
const version3 = ulid();
|
|
119985
120222
|
const tempS3Key = `uploads-temp/${gameId}/${version3}/${fileName}`;
|
|
@@ -120000,9 +120237,6 @@ async function* finalizeUpload(ctx) {
|
|
|
120000
120237
|
if (!user) {
|
|
120001
120238
|
throw ApiError.unauthorized("Must be logged in to finalize uploads");
|
|
120002
120239
|
}
|
|
120003
|
-
if (!uploadDeps) {
|
|
120004
|
-
throw ApiError.internal("Upload dependencies not configured");
|
|
120005
|
-
}
|
|
120006
120240
|
let inputData;
|
|
120007
120241
|
try {
|
|
120008
120242
|
const requestBody = await ctx.request.json();
|
|
@@ -120019,6 +120253,9 @@ async function* finalizeUpload(ctx) {
|
|
|
120019
120253
|
throw ApiError.badRequest("Invalid JSON body");
|
|
120020
120254
|
}
|
|
120021
120255
|
const { tempS3Key, gameId, version: version3, slug, metadata: metadata2 } = inputData;
|
|
120256
|
+
if (!uploadDeps) {
|
|
120257
|
+
throw ApiError.internal("Upload dependencies not configured");
|
|
120258
|
+
}
|
|
120022
120259
|
try {
|
|
120023
120260
|
yield {
|
|
120024
120261
|
type: "status",
|
|
@@ -121358,6 +121595,13 @@ async function loadGameState(ctx) {
|
|
|
121358
121595
|
}
|
|
121359
121596
|
try {
|
|
121360
121597
|
const db = getDatabase();
|
|
121598
|
+
const game = await db.query.games.findFirst({
|
|
121599
|
+
where: eq(games.id, gameId),
|
|
121600
|
+
columns: { id: true }
|
|
121601
|
+
});
|
|
121602
|
+
if (!game) {
|
|
121603
|
+
throw ApiError.notFound("Game not found");
|
|
121604
|
+
}
|
|
121361
121605
|
const gameState = await db.query.gameStates.findFirst({
|
|
121362
121606
|
where: and(eq(gameStates.userId, user.id), eq(gameStates.gameId, gameId)),
|
|
121363
121607
|
columns: { data: true }
|
|
@@ -121389,20 +121633,27 @@ async function saveGameState(ctx) {
|
|
|
121389
121633
|
if (!gameId) {
|
|
121390
121634
|
throw ApiError.badRequest("Missing game ID");
|
|
121391
121635
|
}
|
|
121392
|
-
let inputData;
|
|
121393
|
-
try {
|
|
121394
|
-
const requestBody = await ctx.request.json();
|
|
121395
|
-
const validatedData = InsertGameStateSchema.parse(requestBody);
|
|
121396
|
-
inputData = validatedData.data || {};
|
|
121397
|
-
} catch (error2) {
|
|
121398
|
-
if (error2 instanceof ZodError2) {
|
|
121399
|
-
throw ApiError.badRequest("Invalid game state data format");
|
|
121400
|
-
}
|
|
121401
|
-
log2.error("Failed to parse request body or invalid JSON:", { error: error2 });
|
|
121402
|
-
throw ApiError.badRequest("Invalid JSON body");
|
|
121403
|
-
}
|
|
121404
121636
|
try {
|
|
121405
121637
|
const db = getDatabase();
|
|
121638
|
+
const game = await db.query.games.findFirst({
|
|
121639
|
+
where: eq(games.id, gameId),
|
|
121640
|
+
columns: { id: true }
|
|
121641
|
+
});
|
|
121642
|
+
if (!game) {
|
|
121643
|
+
throw ApiError.notFound("Game not found");
|
|
121644
|
+
}
|
|
121645
|
+
let inputData;
|
|
121646
|
+
try {
|
|
121647
|
+
const requestBody = await ctx.request.json();
|
|
121648
|
+
if (typeof requestBody === "object" && requestBody !== null) {
|
|
121649
|
+
inputData = requestBody;
|
|
121650
|
+
} else {
|
|
121651
|
+
throw new Error("Request body must be an object");
|
|
121652
|
+
}
|
|
121653
|
+
} catch (error2) {
|
|
121654
|
+
log2.error("Failed to parse request body or invalid JSON:", { error: error2 });
|
|
121655
|
+
throw ApiError.badRequest("Invalid JSON body");
|
|
121656
|
+
}
|
|
121406
121657
|
await db.insert(gameStates).values({
|
|
121407
121658
|
userId: user.id,
|
|
121408
121659
|
gameId,
|
|
@@ -121421,6 +121672,44 @@ async function saveGameState(ctx) {
|
|
|
121421
121672
|
throw ApiError.internal("Internal server error", error2);
|
|
121422
121673
|
}
|
|
121423
121674
|
}
|
|
121675
|
+
function findMonorepoRootInternal(startDir) {
|
|
121676
|
+
let currentDir = startDir;
|
|
121677
|
+
while (true) {
|
|
121678
|
+
const packageJsonPath = path22.join(currentDir, "package.json");
|
|
121679
|
+
if (fs32.existsSync(packageJsonPath)) {
|
|
121680
|
+
try {
|
|
121681
|
+
const packageJsonContent = fs32.readFileSync(packageJsonPath, "utf-8");
|
|
121682
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
121683
|
+
if (packageJson && typeof packageJson === "object" && "workspaces" in packageJson) {
|
|
121684
|
+
return currentDir;
|
|
121685
|
+
}
|
|
121686
|
+
} catch (parseError) {
|
|
121687
|
+
log2.warn(`[utils/paths] Error parsing ${packageJsonPath}:`, {
|
|
121688
|
+
error: parseError
|
|
121689
|
+
});
|
|
121690
|
+
}
|
|
121691
|
+
}
|
|
121692
|
+
const parentDir = path22.dirname(currentDir);
|
|
121693
|
+
if (parentDir === currentDir) {
|
|
121694
|
+
throw new Error("Could not find monorepo root (package.json with workspaces) starting from " + startDir);
|
|
121695
|
+
}
|
|
121696
|
+
currentDir = parentDir;
|
|
121697
|
+
}
|
|
121698
|
+
}
|
|
121699
|
+
var determinedRoot;
|
|
121700
|
+
try {
|
|
121701
|
+
determinedRoot = findMonorepoRootInternal(process.cwd());
|
|
121702
|
+
} catch (error2) {
|
|
121703
|
+
determinedRoot = process.cwd();
|
|
121704
|
+
log2.warn("[utils/paths] Could not locate monorepo root via workspace package.json scan. Falling back to process.cwd() (", { root: determinedRoot, error: error2 });
|
|
121705
|
+
}
|
|
121706
|
+
var UUID_REGEX = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
121707
|
+
function isValidUUID(value) {
|
|
121708
|
+
if (!value || typeof value !== "string") {
|
|
121709
|
+
return false;
|
|
121710
|
+
}
|
|
121711
|
+
return UUID_REGEX.test(value);
|
|
121712
|
+
}
|
|
121424
121713
|
async function validateGameOwnership(user, gameId) {
|
|
121425
121714
|
if (user.role === "admin") {
|
|
121426
121715
|
return;
|
|
@@ -121492,6 +121781,9 @@ async function getItemById(ctx) {
|
|
|
121492
121781
|
if (!itemId) {
|
|
121493
121782
|
throw ApiError.badRequest("Missing item ID");
|
|
121494
121783
|
}
|
|
121784
|
+
if (!isValidUUID(itemId)) {
|
|
121785
|
+
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
121786
|
+
}
|
|
121495
121787
|
try {
|
|
121496
121788
|
const db = getDatabase();
|
|
121497
121789
|
const item = await db.query.items.findFirst({
|
|
@@ -121563,6 +121855,9 @@ async function updateItem(ctx) {
|
|
|
121563
121855
|
if (!itemId) {
|
|
121564
121856
|
throw ApiError.badRequest("Missing item ID");
|
|
121565
121857
|
}
|
|
121858
|
+
if (!isValidUUID(itemId)) {
|
|
121859
|
+
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
121860
|
+
}
|
|
121566
121861
|
let inputData;
|
|
121567
121862
|
try {
|
|
121568
121863
|
const requestBody = await ctx.request.json();
|
|
@@ -121589,6 +121884,8 @@ async function updateItem(ctx) {
|
|
|
121589
121884
|
}
|
|
121590
121885
|
return updatedItem;
|
|
121591
121886
|
} catch (error2) {
|
|
121887
|
+
if (error2 instanceof ApiError)
|
|
121888
|
+
throw error2;
|
|
121592
121889
|
if (error2 instanceof Error) {
|
|
121593
121890
|
if (error2.message.includes("duplicate key value violates unique constraint")) {
|
|
121594
121891
|
throw ApiError.conflict("An item with this slug already exists within the same scope (platform or game)");
|
|
@@ -121611,6 +121908,9 @@ async function deleteItem(ctx) {
|
|
|
121611
121908
|
if (!itemId) {
|
|
121612
121909
|
throw ApiError.badRequest("Missing item ID");
|
|
121613
121910
|
}
|
|
121911
|
+
if (!isValidUUID(itemId)) {
|
|
121912
|
+
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
121913
|
+
}
|
|
121614
121914
|
try {
|
|
121615
121915
|
const db = getDatabase();
|
|
121616
121916
|
const result = await db.delete(items).where(eq(items.id, itemId)).returning({ id: items.id });
|
|
@@ -121641,6 +121941,9 @@ async function resolveItem(ctx) {
|
|
|
121641
121941
|
if (!slug) {
|
|
121642
121942
|
throw ApiError.badRequest("Missing slug parameter");
|
|
121643
121943
|
}
|
|
121944
|
+
if (gameId && !isValidUUID(gameId)) {
|
|
121945
|
+
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
121946
|
+
}
|
|
121644
121947
|
try {
|
|
121645
121948
|
const db = getDatabase();
|
|
121646
121949
|
if (gameId) {
|
|
@@ -121679,6 +121982,9 @@ async function listGameItems(ctx) {
|
|
|
121679
121982
|
if (!gameId) {
|
|
121680
121983
|
throw ApiError.badRequest("Missing game ID");
|
|
121681
121984
|
}
|
|
121985
|
+
if (!isValidUUID(gameId)) {
|
|
121986
|
+
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
121987
|
+
}
|
|
121682
121988
|
try {
|
|
121683
121989
|
const db = getDatabase();
|
|
121684
121990
|
const gameItems = await db.query.items.findMany({
|
|
@@ -121706,6 +122012,9 @@ async function createGameItem(ctx) {
|
|
|
121706
122012
|
if (!gameId) {
|
|
121707
122013
|
throw ApiError.badRequest("Missing game ID");
|
|
121708
122014
|
}
|
|
122015
|
+
if (!isValidUUID(gameId)) {
|
|
122016
|
+
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
122017
|
+
}
|
|
121709
122018
|
await validateGameOwnership(user, gameId);
|
|
121710
122019
|
let inputData;
|
|
121711
122020
|
try {
|
|
@@ -121758,6 +122067,12 @@ async function updateGameItem(ctx) {
|
|
|
121758
122067
|
if (!gameId || !itemId) {
|
|
121759
122068
|
throw ApiError.badRequest("Missing game ID or item ID");
|
|
121760
122069
|
}
|
|
122070
|
+
if (!isValidUUID(gameId)) {
|
|
122071
|
+
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
122072
|
+
}
|
|
122073
|
+
if (!isValidUUID(itemId)) {
|
|
122074
|
+
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
122075
|
+
}
|
|
121761
122076
|
await validateGameOwnership(user, gameId);
|
|
121762
122077
|
let inputData;
|
|
121763
122078
|
try {
|
|
@@ -121791,6 +122106,9 @@ async function updateGameItem(ctx) {
|
|
|
121791
122106
|
}
|
|
121792
122107
|
return updatedItem;
|
|
121793
122108
|
} catch (error2) {
|
|
122109
|
+
if (error2 instanceof ApiError) {
|
|
122110
|
+
throw error2;
|
|
122111
|
+
}
|
|
121794
122112
|
if (error2 instanceof Error) {
|
|
121795
122113
|
if (error2.message.includes("duplicate key value violates unique constraint")) {
|
|
121796
122114
|
throw ApiError.conflict("An item with this slug already exists for this game");
|
|
@@ -121815,6 +122133,12 @@ async function deleteGameItem(ctx) {
|
|
|
121815
122133
|
if (!gameId || !itemId) {
|
|
121816
122134
|
throw ApiError.badRequest("Missing game ID or item ID");
|
|
121817
122135
|
}
|
|
122136
|
+
if (!isValidUUID(gameId)) {
|
|
122137
|
+
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
122138
|
+
}
|
|
122139
|
+
if (!isValidUUID(itemId)) {
|
|
122140
|
+
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
122141
|
+
}
|
|
121818
122142
|
await validateGameOwnership(user, gameId);
|
|
121819
122143
|
try {
|
|
121820
122144
|
const db = getDatabase();
|
|
@@ -121830,6 +122154,288 @@ async function deleteGameItem(ctx) {
|
|
|
121830
122154
|
throw ApiError.internal("Internal server error", error2);
|
|
121831
122155
|
}
|
|
121832
122156
|
}
|
|
122157
|
+
async function createGameItemShopListing(ctx) {
|
|
122158
|
+
const user = ctx.user;
|
|
122159
|
+
const gameId = ctx.params.gameId;
|
|
122160
|
+
const itemId = ctx.params.itemId;
|
|
122161
|
+
log2.debug("[API] creating game item shop listing", {
|
|
122162
|
+
userId: user?.id || "anonymous",
|
|
122163
|
+
gameId,
|
|
122164
|
+
itemId
|
|
122165
|
+
});
|
|
122166
|
+
if (!user) {
|
|
122167
|
+
throw ApiError.unauthorized("Must be logged in to create shop listings");
|
|
122168
|
+
}
|
|
122169
|
+
if (!gameId || !itemId) {
|
|
122170
|
+
throw ApiError.badRequest("Missing game ID or item ID");
|
|
122171
|
+
}
|
|
122172
|
+
if (!isValidUUID(gameId)) {
|
|
122173
|
+
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
122174
|
+
}
|
|
122175
|
+
if (!isValidUUID(itemId)) {
|
|
122176
|
+
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
122177
|
+
}
|
|
122178
|
+
await validateGameOwnershipAndItemAccess(user.id, gameId, itemId);
|
|
122179
|
+
let inputData;
|
|
122180
|
+
try {
|
|
122181
|
+
const requestBody = await ctx.request.json();
|
|
122182
|
+
const validationResult = InsertShopListingSchema.omit({
|
|
122183
|
+
itemId: true
|
|
122184
|
+
}).safeParse(requestBody);
|
|
122185
|
+
if (!validationResult.success) {
|
|
122186
|
+
throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
|
|
122187
|
+
}
|
|
122188
|
+
inputData = validationResult.data;
|
|
122189
|
+
} catch (error2) {
|
|
122190
|
+
if (error2 instanceof ApiError) {
|
|
122191
|
+
throw error2;
|
|
122192
|
+
}
|
|
122193
|
+
log2.error("Failed to parse request body", { error: error2 });
|
|
122194
|
+
throw ApiError.badRequest("Invalid JSON body");
|
|
122195
|
+
}
|
|
122196
|
+
try {
|
|
122197
|
+
const db = getDatabase();
|
|
122198
|
+
const currency = await db.query.currencies.findFirst({
|
|
122199
|
+
where: eq(currencies.itemId, inputData.currencyId)
|
|
122200
|
+
});
|
|
122201
|
+
if (!currency) {
|
|
122202
|
+
throw ApiError.badRequest("Invalid currency: currency not found for the provided item ID");
|
|
122203
|
+
}
|
|
122204
|
+
const [newListing] = await db.insert(shopListings).values({
|
|
122205
|
+
...inputData,
|
|
122206
|
+
itemId,
|
|
122207
|
+
currencyId: currency.id
|
|
122208
|
+
}).returning();
|
|
122209
|
+
if (!newListing) {
|
|
122210
|
+
throw ApiError.internal("Failed to create shop listing in database");
|
|
122211
|
+
}
|
|
122212
|
+
return newListing;
|
|
122213
|
+
} catch (error2) {
|
|
122214
|
+
if (error2 instanceof ApiError)
|
|
122215
|
+
throw error2;
|
|
122216
|
+
if (error2 instanceof Error) {
|
|
122217
|
+
if (error2.message.includes("duplicate key value violates unique constraint")) {
|
|
122218
|
+
throw ApiError.conflict("A shop listing already exists for this item with the specified currency");
|
|
122219
|
+
}
|
|
122220
|
+
if (error2.message.includes("violates foreign key constraint")) {
|
|
122221
|
+
if (error2.message.includes("shop_listings_currency_id_fkey")) {
|
|
122222
|
+
throw ApiError.badRequest("Invalid currency ID");
|
|
122223
|
+
}
|
|
122224
|
+
}
|
|
122225
|
+
}
|
|
122226
|
+
log2.error("Error creating shop listing", { error: error2 });
|
|
122227
|
+
throw ApiError.internal("Internal server error", error2);
|
|
122228
|
+
}
|
|
122229
|
+
}
|
|
122230
|
+
async function getGameItemShopListing(ctx) {
|
|
122231
|
+
const user = ctx.user;
|
|
122232
|
+
const gameId = ctx.params.gameId;
|
|
122233
|
+
const itemId = ctx.params.itemId;
|
|
122234
|
+
log2.debug("[API] fetching game item shop listing", {
|
|
122235
|
+
userId: user?.id || "anonymous",
|
|
122236
|
+
gameId,
|
|
122237
|
+
itemId
|
|
122238
|
+
});
|
|
122239
|
+
if (!user) {
|
|
122240
|
+
throw ApiError.unauthorized("Must be logged in to view shop listings");
|
|
122241
|
+
}
|
|
122242
|
+
if (!gameId || !itemId) {
|
|
122243
|
+
throw ApiError.badRequest("Missing game ID or item ID");
|
|
122244
|
+
}
|
|
122245
|
+
if (!isValidUUID(gameId)) {
|
|
122246
|
+
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
122247
|
+
}
|
|
122248
|
+
if (!isValidUUID(itemId)) {
|
|
122249
|
+
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
122250
|
+
}
|
|
122251
|
+
await validateGameOwnershipAndItemAccess(user.id, gameId, itemId);
|
|
122252
|
+
try {
|
|
122253
|
+
const db = getDatabase();
|
|
122254
|
+
const shopListing = await db.query.shopListings.findFirst({
|
|
122255
|
+
where: eq(shopListings.itemId, itemId)
|
|
122256
|
+
});
|
|
122257
|
+
return shopListing || null;
|
|
122258
|
+
} catch (error2) {
|
|
122259
|
+
log2.error(`Error fetching shop listing for item ${itemId}:`, { error: error2 });
|
|
122260
|
+
throw ApiError.internal("Internal server error", error2);
|
|
122261
|
+
}
|
|
122262
|
+
}
|
|
122263
|
+
async function updateGameItemShopListing(ctx) {
|
|
122264
|
+
const user = ctx.user;
|
|
122265
|
+
const gameId = ctx.params.gameId;
|
|
122266
|
+
const itemId = ctx.params.itemId;
|
|
122267
|
+
log2.debug("[API] updating game item shop listing", {
|
|
122268
|
+
userId: user?.id || "anonymous",
|
|
122269
|
+
gameId,
|
|
122270
|
+
itemId
|
|
122271
|
+
});
|
|
122272
|
+
if (!user) {
|
|
122273
|
+
throw ApiError.unauthorized("Must be logged in to update shop listings");
|
|
122274
|
+
}
|
|
122275
|
+
if (!gameId || !itemId) {
|
|
122276
|
+
throw ApiError.badRequest("Missing game ID or item ID");
|
|
122277
|
+
}
|
|
122278
|
+
if (!isValidUUID(gameId)) {
|
|
122279
|
+
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
122280
|
+
}
|
|
122281
|
+
if (!isValidUUID(itemId)) {
|
|
122282
|
+
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
122283
|
+
}
|
|
122284
|
+
await validateGameOwnershipAndItemAccess(user.id, gameId, itemId);
|
|
122285
|
+
let inputData;
|
|
122286
|
+
try {
|
|
122287
|
+
const requestBody = await ctx.request.json();
|
|
122288
|
+
const validationResult = UpdateShopListingSchema.safeParse(requestBody);
|
|
122289
|
+
if (!validationResult.success) {
|
|
122290
|
+
throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
|
|
122291
|
+
}
|
|
122292
|
+
inputData = validationResult.data;
|
|
122293
|
+
} catch (error2) {
|
|
122294
|
+
if (error2 instanceof ApiError) {
|
|
122295
|
+
throw error2;
|
|
122296
|
+
}
|
|
122297
|
+
log2.error("Failed to parse request body", { error: error2 });
|
|
122298
|
+
throw ApiError.badRequest("Invalid JSON body");
|
|
122299
|
+
}
|
|
122300
|
+
try {
|
|
122301
|
+
const db = getDatabase();
|
|
122302
|
+
let resolvedCurrencyId = inputData.currencyId;
|
|
122303
|
+
if (inputData.currencyId) {
|
|
122304
|
+
const currency = await db.query.currencies.findFirst({
|
|
122305
|
+
where: eq(currencies.itemId, inputData.currencyId)
|
|
122306
|
+
});
|
|
122307
|
+
if (!currency) {
|
|
122308
|
+
throw ApiError.badRequest("Invalid currency: currency not found for the provided item ID");
|
|
122309
|
+
}
|
|
122310
|
+
resolvedCurrencyId = currency.id;
|
|
122311
|
+
}
|
|
122312
|
+
const [updatedListing] = await db.update(shopListings).set({
|
|
122313
|
+
...inputData,
|
|
122314
|
+
currencyId: resolvedCurrencyId,
|
|
122315
|
+
updatedAt: new Date
|
|
122316
|
+
}).where(eq(shopListings.itemId, itemId)).returning();
|
|
122317
|
+
if (!updatedListing) {
|
|
122318
|
+
throw ApiError.notFound("Shop listing not found for this item");
|
|
122319
|
+
}
|
|
122320
|
+
return updatedListing;
|
|
122321
|
+
} catch (error2) {
|
|
122322
|
+
if (error2 instanceof ApiError)
|
|
122323
|
+
throw error2;
|
|
122324
|
+
if (error2 instanceof Error) {
|
|
122325
|
+
if (error2.message.includes("duplicate key value violates unique constraint")) {
|
|
122326
|
+
throw ApiError.conflict("A shop listing already exists for this item with the specified currency");
|
|
122327
|
+
}
|
|
122328
|
+
if (error2.message.includes("violates foreign key constraint")) {
|
|
122329
|
+
if (error2.message.includes("shop_listings_currency_id_fkey")) {
|
|
122330
|
+
throw ApiError.badRequest("Invalid currency ID");
|
|
122331
|
+
}
|
|
122332
|
+
}
|
|
122333
|
+
}
|
|
122334
|
+
log2.error(`Error updating shop listing for item ${itemId}:`, { error: error2 });
|
|
122335
|
+
throw ApiError.internal("Internal server error", error2);
|
|
122336
|
+
}
|
|
122337
|
+
}
|
|
122338
|
+
async function deleteGameItemShopListing(ctx) {
|
|
122339
|
+
const user = ctx.user;
|
|
122340
|
+
const gameId = ctx.params.gameId;
|
|
122341
|
+
const itemId = ctx.params.itemId;
|
|
122342
|
+
log2.debug("[API] deleting game item shop listing", {
|
|
122343
|
+
userId: user?.id || "anonymous",
|
|
122344
|
+
gameId,
|
|
122345
|
+
itemId
|
|
122346
|
+
});
|
|
122347
|
+
if (!user) {
|
|
122348
|
+
throw ApiError.unauthorized("Must be logged in to delete shop listings");
|
|
122349
|
+
}
|
|
122350
|
+
if (!gameId || !itemId) {
|
|
122351
|
+
throw ApiError.badRequest("Missing game ID or item ID");
|
|
122352
|
+
}
|
|
122353
|
+
if (!isValidUUID(gameId)) {
|
|
122354
|
+
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
122355
|
+
}
|
|
122356
|
+
if (!isValidUUID(itemId)) {
|
|
122357
|
+
throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
|
|
122358
|
+
}
|
|
122359
|
+
await validateGameOwnershipAndItemAccess(user.id, gameId, itemId);
|
|
122360
|
+
try {
|
|
122361
|
+
const db = getDatabase();
|
|
122362
|
+
const result = await db.delete(shopListings).where(eq(shopListings.itemId, itemId)).returning();
|
|
122363
|
+
if (result.length === 0) {
|
|
122364
|
+
throw ApiError.notFound("Shop listing not found for this item");
|
|
122365
|
+
}
|
|
122366
|
+
log2.info(`Shop listing deleted for item ${itemId} by user ${user.id}`);
|
|
122367
|
+
} catch (error2) {
|
|
122368
|
+
if (error2 instanceof ApiError) {
|
|
122369
|
+
throw error2;
|
|
122370
|
+
}
|
|
122371
|
+
log2.error(`Error deleting shop listing for item ${itemId}:`, { error: error2 });
|
|
122372
|
+
throw ApiError.internal("Internal server error", error2);
|
|
122373
|
+
}
|
|
122374
|
+
}
|
|
122375
|
+
async function listGameShopListings(ctx) {
|
|
122376
|
+
const user = ctx.user;
|
|
122377
|
+
const gameId = ctx.params.gameId;
|
|
122378
|
+
log2.debug("[API] listing game shop listings", {
|
|
122379
|
+
userId: user?.id || "anonymous",
|
|
122380
|
+
gameId
|
|
122381
|
+
});
|
|
122382
|
+
if (!user) {
|
|
122383
|
+
throw ApiError.unauthorized("Must be logged in to view shop listings");
|
|
122384
|
+
}
|
|
122385
|
+
if (!gameId) {
|
|
122386
|
+
throw ApiError.badRequest("Missing game ID");
|
|
122387
|
+
}
|
|
122388
|
+
if (!isValidUUID(gameId)) {
|
|
122389
|
+
throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
|
|
122390
|
+
}
|
|
122391
|
+
await validateGameOwnership(user, gameId);
|
|
122392
|
+
try {
|
|
122393
|
+
const db = getDatabase();
|
|
122394
|
+
const gameItems = await db.query.items.findMany({
|
|
122395
|
+
where: eq(items.gameId, gameId)
|
|
122396
|
+
});
|
|
122397
|
+
if (gameItems.length === 0) {
|
|
122398
|
+
return [];
|
|
122399
|
+
}
|
|
122400
|
+
const itemIds = gameItems.map((item) => item.id);
|
|
122401
|
+
const gameShopListings = await db.query.shopListings.findMany({
|
|
122402
|
+
where: inArray(shopListings.itemId, itemIds),
|
|
122403
|
+
with: {
|
|
122404
|
+
item: true
|
|
122405
|
+
}
|
|
122406
|
+
});
|
|
122407
|
+
return gameShopListings;
|
|
122408
|
+
} catch (error2) {
|
|
122409
|
+
if (error2 instanceof ApiError) {
|
|
122410
|
+
throw error2;
|
|
122411
|
+
}
|
|
122412
|
+
log2.error(`Error fetching shop listings for game ${gameId}:`, { error: error2 });
|
|
122413
|
+
throw ApiError.internal("Internal server error", error2);
|
|
122414
|
+
}
|
|
122415
|
+
}
|
|
122416
|
+
async function validateGameOwnershipAndItemAccess(userId, gameId, itemId) {
|
|
122417
|
+
try {
|
|
122418
|
+
const db = getDatabase();
|
|
122419
|
+
const game = await db.query.games.findFirst({
|
|
122420
|
+
where: and(eq(games.id, gameId), eq(games.developerId, userId))
|
|
122421
|
+
});
|
|
122422
|
+
if (!game) {
|
|
122423
|
+
throw ApiError.forbidden("You do not own this game");
|
|
122424
|
+
}
|
|
122425
|
+
const item = await db.query.items.findFirst({
|
|
122426
|
+
where: and(eq(items.id, itemId), eq(items.gameId, gameId))
|
|
122427
|
+
});
|
|
122428
|
+
if (!item) {
|
|
122429
|
+
throw ApiError.notFound("Item not found in this game");
|
|
122430
|
+
}
|
|
122431
|
+
} catch (error2) {
|
|
122432
|
+
if (error2 instanceof ApiError) {
|
|
122433
|
+
throw error2;
|
|
122434
|
+
}
|
|
122435
|
+
log2.error(`Error validating game ownership and item access:`, { error: error2 });
|
|
122436
|
+
throw ApiError.internal("Internal server error", error2);
|
|
122437
|
+
}
|
|
122438
|
+
}
|
|
121833
122439
|
|
|
121834
122440
|
class BigEndian {
|
|
121835
122441
|
uint8(data2, offset) {
|
|
@@ -122650,11 +123256,10 @@ gamesRouter.get("/", async (c2) => {
|
|
|
122650
123256
|
return c2.json(result);
|
|
122651
123257
|
} catch (error2) {
|
|
122652
123258
|
if (error2 instanceof ApiError) {
|
|
122653
|
-
return c2.json(
|
|
123259
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122654
123260
|
}
|
|
122655
123261
|
console.error("Error in listGames:", error2);
|
|
122656
|
-
|
|
122657
|
-
return c2.json({ error: message2 }, 500);
|
|
123262
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122658
123263
|
}
|
|
122659
123264
|
});
|
|
122660
123265
|
gamesRouter.get("/:slug", async (c2) => {
|
|
@@ -122671,11 +123276,10 @@ gamesRouter.get("/:slug", async (c2) => {
|
|
|
122671
123276
|
return c2.json(result);
|
|
122672
123277
|
} catch (error2) {
|
|
122673
123278
|
if (error2 instanceof ApiError) {
|
|
122674
|
-
return c2.json(
|
|
123279
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122675
123280
|
}
|
|
122676
123281
|
console.error("Error in getGame:", error2);
|
|
122677
|
-
|
|
122678
|
-
return c2.json({ error: message2 }, 500);
|
|
123282
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122679
123283
|
}
|
|
122680
123284
|
});
|
|
122681
123285
|
gamesRouter.put("/:slug", async (c2) => {
|
|
@@ -122691,11 +123295,10 @@ gamesRouter.put("/:slug", async (c2) => {
|
|
|
122691
123295
|
return c2.json(result);
|
|
122692
123296
|
} catch (error2) {
|
|
122693
123297
|
if (error2 instanceof ApiError) {
|
|
122694
|
-
return c2.json(
|
|
123298
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122695
123299
|
}
|
|
122696
123300
|
console.error("Error in upsertGameBySlug:", error2);
|
|
122697
|
-
|
|
122698
|
-
return c2.json({ error: message2 }, 500);
|
|
123301
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122699
123302
|
}
|
|
122700
123303
|
});
|
|
122701
123304
|
gamesRouter.patch("/:gameId", async (c2) => {
|
|
@@ -122711,11 +123314,10 @@ gamesRouter.patch("/:gameId", async (c2) => {
|
|
|
122711
123314
|
return c2.json(result);
|
|
122712
123315
|
} catch (error2) {
|
|
122713
123316
|
if (error2 instanceof ApiError) {
|
|
122714
|
-
return c2.json(
|
|
123317
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122715
123318
|
}
|
|
122716
123319
|
console.error("Error in updateGame:", error2);
|
|
122717
|
-
|
|
122718
|
-
return c2.json({ error: message2 }, 500);
|
|
123320
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122719
123321
|
}
|
|
122720
123322
|
});
|
|
122721
123323
|
gamesRouter.delete("/:gameId", async (c2) => {
|
|
@@ -122731,11 +123333,10 @@ gamesRouter.delete("/:gameId", async (c2) => {
|
|
|
122731
123333
|
return c2.body(null, 204);
|
|
122732
123334
|
} catch (error2) {
|
|
122733
123335
|
if (error2 instanceof ApiError) {
|
|
122734
|
-
return c2.json(
|
|
123336
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122735
123337
|
}
|
|
122736
123338
|
console.error("Error in deleteGame:", error2);
|
|
122737
|
-
|
|
122738
|
-
return c2.json({ error: message2 }, 500);
|
|
123339
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122739
123340
|
}
|
|
122740
123341
|
});
|
|
122741
123342
|
gamesRouter.post("/:gameId/sessions", async (c2) => {
|
|
@@ -122751,11 +123352,10 @@ gamesRouter.post("/:gameId/sessions", async (c2) => {
|
|
|
122751
123352
|
return c2.json(result);
|
|
122752
123353
|
} catch (error2) {
|
|
122753
123354
|
if (error2 instanceof ApiError) {
|
|
122754
|
-
return c2.json(
|
|
123355
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122755
123356
|
}
|
|
122756
123357
|
console.error("Error in startGameSession:", error2);
|
|
122757
|
-
|
|
122758
|
-
return c2.json({ error: message2 }, 500);
|
|
123358
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122759
123359
|
}
|
|
122760
123360
|
});
|
|
122761
123361
|
gamesRouter.post("/:gameId/sessions/:sessionId/end", async (c2) => {
|
|
@@ -122772,14 +123372,13 @@ gamesRouter.post("/:gameId/sessions/:sessionId/end", async (c2) => {
|
|
|
122772
123372
|
return c2.json(result);
|
|
122773
123373
|
} catch (error2) {
|
|
122774
123374
|
if (error2 instanceof ApiError) {
|
|
122775
|
-
return c2.json(
|
|
123375
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122776
123376
|
}
|
|
122777
123377
|
console.error("Error in endGameSession:", error2);
|
|
122778
|
-
|
|
122779
|
-
return c2.json({ error: message2 }, 500);
|
|
123378
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122780
123379
|
}
|
|
122781
123380
|
});
|
|
122782
|
-
gamesRouter.post("/:gameId/
|
|
123381
|
+
gamesRouter.post("/:gameId/token", async (c2) => {
|
|
122783
123382
|
const gameId = c2.req.param("gameId");
|
|
122784
123383
|
const ctx = {
|
|
122785
123384
|
user: c2.get("user"),
|
|
@@ -122792,14 +123391,13 @@ gamesRouter.post("/:gameId/sessions/token", async (c2) => {
|
|
|
122792
123391
|
return c2.json(result);
|
|
122793
123392
|
} catch (error2) {
|
|
122794
123393
|
if (error2 instanceof ApiError) {
|
|
122795
|
-
return c2.json(
|
|
123394
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122796
123395
|
}
|
|
122797
123396
|
console.error("Error in mintGameToken:", error2);
|
|
122798
|
-
|
|
122799
|
-
return c2.json({ error: message2 }, 500);
|
|
123397
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122800
123398
|
}
|
|
122801
123399
|
});
|
|
122802
|
-
gamesRouter.get("/:gameId/
|
|
123400
|
+
gamesRouter.get("/:gameId/state", async (c2) => {
|
|
122803
123401
|
const gameId = c2.req.param("gameId");
|
|
122804
123402
|
const ctx = {
|
|
122805
123403
|
user: c2.get("user"),
|
|
@@ -122812,14 +123410,13 @@ gamesRouter.get("/:gameId/sessions/state", async (c2) => {
|
|
|
122812
123410
|
return c2.json(result);
|
|
122813
123411
|
} catch (error2) {
|
|
122814
123412
|
if (error2 instanceof ApiError) {
|
|
122815
|
-
return c2.json(
|
|
123413
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122816
123414
|
}
|
|
122817
123415
|
console.error("Error in loadGameState:", error2);
|
|
122818
|
-
|
|
122819
|
-
return c2.json({ error: message2 }, 500);
|
|
123416
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122820
123417
|
}
|
|
122821
123418
|
});
|
|
122822
|
-
gamesRouter.post("/:gameId/
|
|
123419
|
+
gamesRouter.post("/:gameId/state", async (c2) => {
|
|
122823
123420
|
const gameId = c2.req.param("gameId");
|
|
122824
123421
|
const ctx = {
|
|
122825
123422
|
user: c2.get("user"),
|
|
@@ -122829,14 +123426,13 @@ gamesRouter.post("/:gameId/sessions/state", async (c2) => {
|
|
|
122829
123426
|
};
|
|
122830
123427
|
try {
|
|
122831
123428
|
await saveGameState(ctx);
|
|
122832
|
-
return c2.
|
|
123429
|
+
return c2.body(null, 204);
|
|
122833
123430
|
} catch (error2) {
|
|
122834
123431
|
if (error2 instanceof ApiError) {
|
|
122835
|
-
return c2.json(
|
|
123432
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122836
123433
|
}
|
|
122837
123434
|
console.error("Error in saveGameState:", error2);
|
|
122838
|
-
|
|
122839
|
-
return c2.json({ error: message2 }, 500);
|
|
123435
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122840
123436
|
}
|
|
122841
123437
|
});
|
|
122842
123438
|
gamesRouter.post("/uploads/initiate", async (c2) => {
|
|
@@ -122851,11 +123447,10 @@ gamesRouter.post("/uploads/initiate", async (c2) => {
|
|
|
122851
123447
|
return c2.json(result);
|
|
122852
123448
|
} catch (error2) {
|
|
122853
123449
|
if (error2 instanceof ApiError) {
|
|
122854
|
-
return c2.json(
|
|
123450
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122855
123451
|
}
|
|
122856
123452
|
console.error("Error in initiateUpload:", error2);
|
|
122857
|
-
|
|
122858
|
-
return c2.json({ error: message2 }, 500);
|
|
123453
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122859
123454
|
}
|
|
122860
123455
|
});
|
|
122861
123456
|
gamesRouter.post("/uploads/finalize", async (c2) => {
|
|
@@ -122876,12 +123471,12 @@ gamesRouter.post("/uploads/finalize", async (c2) => {
|
|
|
122876
123471
|
controller.close();
|
|
122877
123472
|
} catch (error2) {
|
|
122878
123473
|
if (error2 instanceof ApiError) {
|
|
122879
|
-
|
|
123474
|
+
const errorResponse = createErrorResponse(error2);
|
|
123475
|
+
controller.enqueue(formatSSEData("error", errorResponse.error));
|
|
122880
123476
|
} else {
|
|
122881
123477
|
console.error("Error in finalize upload stream:", error2);
|
|
122882
|
-
|
|
122883
|
-
|
|
122884
|
-
}));
|
|
123478
|
+
const errorResponse = createUnknownErrorResponse(error2);
|
|
123479
|
+
controller.enqueue(formatSSEData("error", errorResponse.error));
|
|
122885
123480
|
}
|
|
122886
123481
|
controller.close();
|
|
122887
123482
|
}
|
|
@@ -122896,11 +123491,10 @@ gamesRouter.post("/uploads/finalize", async (c2) => {
|
|
|
122896
123491
|
});
|
|
122897
123492
|
} catch (error2) {
|
|
122898
123493
|
if (error2 instanceof ApiError) {
|
|
122899
|
-
return c2.json(
|
|
123494
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122900
123495
|
}
|
|
122901
123496
|
console.error("Error in finalizeUpload:", error2);
|
|
122902
|
-
|
|
122903
|
-
return c2.json({ error: message2 }, 500);
|
|
123497
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122904
123498
|
}
|
|
122905
123499
|
});
|
|
122906
123500
|
gamesRouter.get("/:gameId/items", async (c2) => {
|
|
@@ -122916,11 +123510,10 @@ gamesRouter.get("/:gameId/items", async (c2) => {
|
|
|
122916
123510
|
return c2.json(result);
|
|
122917
123511
|
} catch (error2) {
|
|
122918
123512
|
if (error2 instanceof ApiError) {
|
|
122919
|
-
return c2.json(
|
|
123513
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122920
123514
|
}
|
|
122921
123515
|
console.error("Error in listGameItems:", error2);
|
|
122922
|
-
|
|
122923
|
-
return c2.json({ error: message2 }, 500);
|
|
123516
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122924
123517
|
}
|
|
122925
123518
|
});
|
|
122926
123519
|
gamesRouter.post("/:gameId/items", async (c2) => {
|
|
@@ -122936,11 +123529,10 @@ gamesRouter.post("/:gameId/items", async (c2) => {
|
|
|
122936
123529
|
return c2.json(result, 201);
|
|
122937
123530
|
} catch (error2) {
|
|
122938
123531
|
if (error2 instanceof ApiError) {
|
|
122939
|
-
return c2.json(
|
|
123532
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122940
123533
|
}
|
|
122941
123534
|
console.error("Error in createGameItem:", error2);
|
|
122942
|
-
|
|
122943
|
-
return c2.json({ error: message2 }, 500);
|
|
123535
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122944
123536
|
}
|
|
122945
123537
|
});
|
|
122946
123538
|
gamesRouter.patch("/:gameId/items/:itemId", async (c2) => {
|
|
@@ -122957,11 +123549,10 @@ gamesRouter.patch("/:gameId/items/:itemId", async (c2) => {
|
|
|
122957
123549
|
return c2.json(result);
|
|
122958
123550
|
} catch (error2) {
|
|
122959
123551
|
if (error2 instanceof ApiError) {
|
|
122960
|
-
return c2.json(
|
|
123552
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122961
123553
|
}
|
|
122962
123554
|
console.error("Error in updateGameItem:", error2);
|
|
122963
|
-
|
|
122964
|
-
return c2.json({ error: message2 }, 500);
|
|
123555
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122965
123556
|
}
|
|
122966
123557
|
});
|
|
122967
123558
|
gamesRouter.delete("/:gameId/items/:itemId", async (c2) => {
|
|
@@ -122978,13 +123569,115 @@ gamesRouter.delete("/:gameId/items/:itemId", async (c2) => {
|
|
|
122978
123569
|
return c2.body(null, 204);
|
|
122979
123570
|
} catch (error2) {
|
|
122980
123571
|
if (error2 instanceof ApiError) {
|
|
122981
|
-
return c2.json(
|
|
123572
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
122982
123573
|
}
|
|
122983
123574
|
console.error("Error in deleteGameItem:", error2);
|
|
122984
|
-
|
|
122985
|
-
|
|
123575
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123576
|
+
}
|
|
123577
|
+
});
|
|
123578
|
+
gamesRouter.get("/:gameId/shop-listings", async (c2) => {
|
|
123579
|
+
const gameId = c2.req.param("gameId");
|
|
123580
|
+
const ctx = {
|
|
123581
|
+
user: c2.get("user"),
|
|
123582
|
+
params: { gameId },
|
|
123583
|
+
url: new URL(c2.req.url),
|
|
123584
|
+
request: c2.req.raw
|
|
123585
|
+
};
|
|
123586
|
+
try {
|
|
123587
|
+
const result = await listGameShopListings(ctx);
|
|
123588
|
+
return c2.json(result);
|
|
123589
|
+
} catch (error2) {
|
|
123590
|
+
if (error2 instanceof ApiError) {
|
|
123591
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123592
|
+
}
|
|
123593
|
+
console.error("Error in listGameShopListings:", error2);
|
|
123594
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
122986
123595
|
}
|
|
122987
123596
|
});
|
|
123597
|
+
gamesRouter.post("/:gameId/items/:itemId/shop-listing", async (c2) => {
|
|
123598
|
+
const gameId = c2.req.param("gameId");
|
|
123599
|
+
const itemId = c2.req.param("itemId");
|
|
123600
|
+
const ctx = {
|
|
123601
|
+
user: c2.get("user"),
|
|
123602
|
+
params: { gameId, itemId },
|
|
123603
|
+
url: new URL(c2.req.url),
|
|
123604
|
+
request: c2.req.raw
|
|
123605
|
+
};
|
|
123606
|
+
try {
|
|
123607
|
+
const result = await createGameItemShopListing(ctx);
|
|
123608
|
+
return c2.json(result, 201);
|
|
123609
|
+
} catch (error2) {
|
|
123610
|
+
if (error2 instanceof ApiError) {
|
|
123611
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123612
|
+
}
|
|
123613
|
+
console.error("Error in createGameItemShopListing:", error2);
|
|
123614
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123615
|
+
}
|
|
123616
|
+
});
|
|
123617
|
+
gamesRouter.get("/:gameId/items/:itemId/shop-listing", async (c2) => {
|
|
123618
|
+
const gameId = c2.req.param("gameId");
|
|
123619
|
+
const itemId = c2.req.param("itemId");
|
|
123620
|
+
const ctx = {
|
|
123621
|
+
user: c2.get("user"),
|
|
123622
|
+
params: { gameId, itemId },
|
|
123623
|
+
url: new URL(c2.req.url),
|
|
123624
|
+
request: c2.req.raw
|
|
123625
|
+
};
|
|
123626
|
+
try {
|
|
123627
|
+
const result = await getGameItemShopListing(ctx);
|
|
123628
|
+
return c2.json(result);
|
|
123629
|
+
} catch (error2) {
|
|
123630
|
+
if (error2 instanceof ApiError) {
|
|
123631
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123632
|
+
}
|
|
123633
|
+
console.error("Error in getGameItemShopListing:", error2);
|
|
123634
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123635
|
+
}
|
|
123636
|
+
});
|
|
123637
|
+
gamesRouter.patch("/:gameId/items/:itemId/shop-listing", async (c2) => {
|
|
123638
|
+
const gameId = c2.req.param("gameId");
|
|
123639
|
+
const itemId = c2.req.param("itemId");
|
|
123640
|
+
const ctx = {
|
|
123641
|
+
user: c2.get("user"),
|
|
123642
|
+
params: { gameId, itemId },
|
|
123643
|
+
url: new URL(c2.req.url),
|
|
123644
|
+
request: c2.req.raw
|
|
123645
|
+
};
|
|
123646
|
+
try {
|
|
123647
|
+
const result = await updateGameItemShopListing(ctx);
|
|
123648
|
+
return c2.json(result);
|
|
123649
|
+
} catch (error2) {
|
|
123650
|
+
if (error2 instanceof ApiError) {
|
|
123651
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123652
|
+
}
|
|
123653
|
+
console.error("Error in updateGameItemShopListing:", error2);
|
|
123654
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123655
|
+
}
|
|
123656
|
+
});
|
|
123657
|
+
gamesRouter.delete("/:gameId/items/:itemId/shop-listing", async (c2) => {
|
|
123658
|
+
const gameId = c2.req.param("gameId");
|
|
123659
|
+
const itemId = c2.req.param("itemId");
|
|
123660
|
+
const ctx = {
|
|
123661
|
+
user: c2.get("user"),
|
|
123662
|
+
params: { gameId, itemId },
|
|
123663
|
+
url: new URL(c2.req.url),
|
|
123664
|
+
request: c2.req.raw
|
|
123665
|
+
};
|
|
123666
|
+
try {
|
|
123667
|
+
await deleteGameItemShopListing(ctx);
|
|
123668
|
+
return c2.body(null, 204);
|
|
123669
|
+
} catch (error2) {
|
|
123670
|
+
if (error2 instanceof ApiError) {
|
|
123671
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123672
|
+
}
|
|
123673
|
+
console.error("Error in deleteGameItemShopListing:", error2);
|
|
123674
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123675
|
+
}
|
|
123676
|
+
});
|
|
123677
|
+
gamesRouter.all("/", async (c2) => {
|
|
123678
|
+
const error2 = ApiError.methodNotAllowed("Method not allowed");
|
|
123679
|
+
return c2.json(createErrorResponse(error2), 405);
|
|
123680
|
+
});
|
|
122988
123681
|
var manifestRouter = new Hono2;
|
|
122989
123682
|
manifestRouter.get("/", async (c2) => {
|
|
122990
123683
|
const baseUrl = new URL(c2.req.url).origin;
|
|
@@ -123006,15 +123699,15 @@ manifestRouter.get("/", async (c2) => {
|
|
|
123006
123699
|
},
|
|
123007
123700
|
{
|
|
123008
123701
|
method: "POST",
|
|
123009
|
-
url: `${baseUrl}/api/games/:gameId/
|
|
123702
|
+
url: `${baseUrl}/api/games/:gameId/token`
|
|
123010
123703
|
},
|
|
123011
123704
|
{
|
|
123012
123705
|
method: "GET",
|
|
123013
|
-
url: `${baseUrl}/api/games/:gameId/
|
|
123706
|
+
url: `${baseUrl}/api/games/:gameId/state`
|
|
123014
123707
|
},
|
|
123015
123708
|
{
|
|
123016
123709
|
method: "POST",
|
|
123017
|
-
url: `${baseUrl}/api/games/:gameId/
|
|
123710
|
+
url: `${baseUrl}/api/games/:gameId/state`
|
|
123018
123711
|
}
|
|
123019
123712
|
],
|
|
123020
123713
|
documentation: "https://docs.playcademy.dev"
|
|
@@ -123086,9 +123779,8 @@ async function getShopView(ctx) {
|
|
|
123086
123779
|
currencies: shopCurrencies
|
|
123087
123780
|
};
|
|
123088
123781
|
} catch (error2) {
|
|
123089
|
-
if (error2 instanceof ApiError)
|
|
123782
|
+
if (error2 instanceof ApiError)
|
|
123090
123783
|
throw error2;
|
|
123091
|
-
}
|
|
123092
123784
|
log2.error("Error fetching shop view data:", { error: error2 });
|
|
123093
123785
|
throw ApiError.internal("Internal server error", error2);
|
|
123094
123786
|
}
|
|
@@ -123106,13 +123798,16 @@ shopRouter.get("/view", async (c2) => {
|
|
|
123106
123798
|
return c2.json(result);
|
|
123107
123799
|
} catch (error2) {
|
|
123108
123800
|
if (error2 instanceof ApiError) {
|
|
123109
|
-
return c2.json(
|
|
123801
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123110
123802
|
}
|
|
123111
123803
|
console.error("Error in getShopView:", error2);
|
|
123112
|
-
|
|
123113
|
-
return c2.json({ error: message2 }, 500);
|
|
123804
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123114
123805
|
}
|
|
123115
123806
|
});
|
|
123807
|
+
shopRouter.all("/view", async (c2) => {
|
|
123808
|
+
const error2 = ApiError.methodNotAllowed("Method not allowed");
|
|
123809
|
+
return c2.json(createErrorResponse(error2), 405);
|
|
123810
|
+
});
|
|
123116
123811
|
var itemsRouter = new Hono2;
|
|
123117
123812
|
itemsRouter.get("/resolve", async (c2) => {
|
|
123118
123813
|
const ctx = {
|
|
@@ -123126,11 +123821,10 @@ itemsRouter.get("/resolve", async (c2) => {
|
|
|
123126
123821
|
return c2.json(result);
|
|
123127
123822
|
} catch (error2) {
|
|
123128
123823
|
if (error2 instanceof ApiError) {
|
|
123129
|
-
return c2.json(
|
|
123824
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123130
123825
|
}
|
|
123131
123826
|
console.error("Error in resolveItem:", error2);
|
|
123132
|
-
|
|
123133
|
-
return c2.json({ error: message2 }, 500);
|
|
123827
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123134
123828
|
}
|
|
123135
123829
|
});
|
|
123136
123830
|
itemsRouter.post("/", async (c2) => {
|
|
@@ -123145,11 +123839,10 @@ itemsRouter.post("/", async (c2) => {
|
|
|
123145
123839
|
return c2.json(result, 201);
|
|
123146
123840
|
} catch (error2) {
|
|
123147
123841
|
if (error2 instanceof ApiError) {
|
|
123148
|
-
return c2.json(
|
|
123842
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123149
123843
|
}
|
|
123150
123844
|
console.error("Error in createItem:", error2);
|
|
123151
|
-
|
|
123152
|
-
return c2.json({ error: message2 }, 500);
|
|
123845
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123153
123846
|
}
|
|
123154
123847
|
});
|
|
123155
123848
|
itemsRouter.get("/", async (c2) => {
|
|
@@ -123164,11 +123857,10 @@ itemsRouter.get("/", async (c2) => {
|
|
|
123164
123857
|
return c2.json(result);
|
|
123165
123858
|
} catch (error2) {
|
|
123166
123859
|
if (error2 instanceof ApiError) {
|
|
123167
|
-
return c2.json(
|
|
123860
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123168
123861
|
}
|
|
123169
123862
|
console.error("Error in listItems:", error2);
|
|
123170
|
-
|
|
123171
|
-
return c2.json({ error: message2 }, 500);
|
|
123863
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123172
123864
|
}
|
|
123173
123865
|
});
|
|
123174
123866
|
itemsRouter.get("/:itemId", async (c2) => {
|
|
@@ -123184,11 +123876,10 @@ itemsRouter.get("/:itemId", async (c2) => {
|
|
|
123184
123876
|
return c2.json(result);
|
|
123185
123877
|
} catch (error2) {
|
|
123186
123878
|
if (error2 instanceof ApiError) {
|
|
123187
|
-
return c2.json(
|
|
123879
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123188
123880
|
}
|
|
123189
123881
|
console.error("Error in getItemById:", error2);
|
|
123190
|
-
|
|
123191
|
-
return c2.json({ error: message2 }, 500);
|
|
123882
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123192
123883
|
}
|
|
123193
123884
|
});
|
|
123194
123885
|
itemsRouter.patch("/:itemId", async (c2) => {
|
|
@@ -123204,11 +123895,10 @@ itemsRouter.patch("/:itemId", async (c2) => {
|
|
|
123204
123895
|
return c2.json(result);
|
|
123205
123896
|
} catch (error2) {
|
|
123206
123897
|
if (error2 instanceof ApiError) {
|
|
123207
|
-
return c2.json(
|
|
123898
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123208
123899
|
}
|
|
123209
123900
|
console.error("Error in updateItem:", error2);
|
|
123210
|
-
|
|
123211
|
-
return c2.json({ error: message2 }, 500);
|
|
123901
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123212
123902
|
}
|
|
123213
123903
|
});
|
|
123214
123904
|
itemsRouter.delete("/:itemId", async (c2) => {
|
|
@@ -123224,13 +123914,16 @@ itemsRouter.delete("/:itemId", async (c2) => {
|
|
|
123224
123914
|
return c2.body(null, 204);
|
|
123225
123915
|
} catch (error2) {
|
|
123226
123916
|
if (error2 instanceof ApiError) {
|
|
123227
|
-
return c2.json(
|
|
123917
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123228
123918
|
}
|
|
123229
123919
|
console.error("Error in deleteItem:", error2);
|
|
123230
|
-
|
|
123231
|
-
return c2.json({ error: message2 }, 500);
|
|
123920
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123232
123921
|
}
|
|
123233
123922
|
});
|
|
123923
|
+
itemsRouter.all("/", async (c2) => {
|
|
123924
|
+
const error2 = ApiError.methodNotAllowed("Method not allowed");
|
|
123925
|
+
return c2.json(createErrorResponse(error2), 405);
|
|
123926
|
+
});
|
|
123234
123927
|
async function listCurrencies(ctx) {
|
|
123235
123928
|
const user = ctx.user;
|
|
123236
123929
|
log2.debug("[API] listing currencies", { userId: user?.id || "anonymous" });
|
|
@@ -123242,9 +123935,8 @@ async function listCurrencies(ctx) {
|
|
|
123242
123935
|
const allCurrencies = await db.query.currencies.findMany();
|
|
123243
123936
|
return allCurrencies;
|
|
123244
123937
|
} catch (error2) {
|
|
123245
|
-
if (error2 instanceof ApiError)
|
|
123938
|
+
if (error2 instanceof ApiError)
|
|
123246
123939
|
throw error2;
|
|
123247
|
-
}
|
|
123248
123940
|
log2.error("Error fetching currencies:", { error: error2 });
|
|
123249
123941
|
throw ApiError.internal("Internal server error", error2);
|
|
123250
123942
|
}
|
|
@@ -123262,6 +123954,9 @@ async function getCurrencyById(ctx) {
|
|
|
123262
123954
|
if (!currencyId) {
|
|
123263
123955
|
throw ApiError.badRequest("Missing currency ID");
|
|
123264
123956
|
}
|
|
123957
|
+
if (!isValidUUID(currencyId)) {
|
|
123958
|
+
throw ApiError.unprocessableEntity("Invalid UUID format for currency ID");
|
|
123959
|
+
}
|
|
123265
123960
|
try {
|
|
123266
123961
|
const db = getDatabase();
|
|
123267
123962
|
const currency = await db.query.currencies.findFirst({
|
|
@@ -123272,9 +123967,8 @@ async function getCurrencyById(ctx) {
|
|
|
123272
123967
|
}
|
|
123273
123968
|
return currency;
|
|
123274
123969
|
} catch (error2) {
|
|
123275
|
-
if (error2 instanceof ApiError)
|
|
123970
|
+
if (error2 instanceof ApiError)
|
|
123276
123971
|
throw error2;
|
|
123277
|
-
}
|
|
123278
123972
|
log2.error(`Error fetching currency ${currencyId}:`, { error: error2 });
|
|
123279
123973
|
throw ApiError.internal("Internal server error", error2);
|
|
123280
123974
|
}
|
|
@@ -123287,21 +123981,18 @@ async function createCurrency(ctx) {
|
|
|
123287
123981
|
if (!user || user.role !== "admin") {
|
|
123288
123982
|
throw ApiError.forbidden("Admin access required");
|
|
123289
123983
|
}
|
|
123290
|
-
let
|
|
123984
|
+
let requestBody;
|
|
123291
123985
|
try {
|
|
123292
|
-
|
|
123293
|
-
|
|
123294
|
-
|
|
123295
|
-
throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
|
|
123296
|
-
}
|
|
123297
|
-
inputData = validationResult.data;
|
|
123298
|
-
} catch (error2) {
|
|
123299
|
-
if (error2 instanceof ApiError) {
|
|
123300
|
-
throw error2;
|
|
123301
|
-
}
|
|
123302
|
-
log2.error("Failed to parse request body or invalid JSON:", { error: error2 });
|
|
123986
|
+
requestBody = await ctx.request.json();
|
|
123987
|
+
} catch (jsonError) {
|
|
123988
|
+
log2.error("Failed to parse request body as JSON:", { error: jsonError });
|
|
123303
123989
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123304
123990
|
}
|
|
123991
|
+
const validationResult = InsertCurrencySchema.safeParse(requestBody);
|
|
123992
|
+
if (!validationResult.success) {
|
|
123993
|
+
throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
|
|
123994
|
+
}
|
|
123995
|
+
const inputData = validationResult.data;
|
|
123305
123996
|
try {
|
|
123306
123997
|
const db = getDatabase();
|
|
123307
123998
|
const [newCurrency] = await db.insert(currencies).values(inputData).returning();
|
|
@@ -123310,6 +124001,8 @@ async function createCurrency(ctx) {
|
|
|
123310
124001
|
}
|
|
123311
124002
|
return newCurrency;
|
|
123312
124003
|
} catch (error2) {
|
|
124004
|
+
if (error2 instanceof ApiError)
|
|
124005
|
+
throw error2;
|
|
123313
124006
|
if (error2 instanceof Error) {
|
|
123314
124007
|
if (error2.message.includes("duplicate key value violates unique constraint") || error2.message.includes("UNIQUE constraint failed")) {
|
|
123315
124008
|
if (error2.message.includes("currencies_slug_unique")) {
|
|
@@ -123335,21 +124028,21 @@ async function updateCurrency(ctx) {
|
|
|
123335
124028
|
if (!currencyId) {
|
|
123336
124029
|
throw ApiError.badRequest("Missing currency ID");
|
|
123337
124030
|
}
|
|
123338
|
-
|
|
124031
|
+
if (!isValidUUID(currencyId)) {
|
|
124032
|
+
throw ApiError.unprocessableEntity("Invalid UUID format for currency ID");
|
|
124033
|
+
}
|
|
124034
|
+
let requestBody;
|
|
123339
124035
|
try {
|
|
123340
|
-
|
|
123341
|
-
|
|
123342
|
-
|
|
123343
|
-
throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
|
|
123344
|
-
}
|
|
123345
|
-
inputData = validationResult.data;
|
|
123346
|
-
} catch (error2) {
|
|
123347
|
-
if (error2 instanceof ApiError) {
|
|
123348
|
-
throw error2;
|
|
123349
|
-
}
|
|
123350
|
-
log2.error("Failed to parse request body or invalid JSON:", { error: error2 });
|
|
124036
|
+
requestBody = await ctx.request.json();
|
|
124037
|
+
} catch (jsonError) {
|
|
124038
|
+
log2.error("Failed to parse request body as JSON:", { error: jsonError });
|
|
123351
124039
|
throw ApiError.badRequest("Invalid JSON body");
|
|
123352
124040
|
}
|
|
124041
|
+
const validationResult = UpdateCurrencySchema.safeParse(requestBody);
|
|
124042
|
+
if (!validationResult.success) {
|
|
124043
|
+
throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
|
|
124044
|
+
}
|
|
124045
|
+
const inputData = validationResult.data;
|
|
123353
124046
|
if (Object.keys(inputData).length === 0) {
|
|
123354
124047
|
throw ApiError.badRequest("No update data provided");
|
|
123355
124048
|
}
|
|
@@ -123361,6 +124054,8 @@ async function updateCurrency(ctx) {
|
|
|
123361
124054
|
}
|
|
123362
124055
|
return updatedCurrency;
|
|
123363
124056
|
} catch (error2) {
|
|
124057
|
+
if (error2 instanceof ApiError)
|
|
124058
|
+
throw error2;
|
|
123364
124059
|
if (error2 instanceof Error) {
|
|
123365
124060
|
if (error2.message.includes("duplicate key value violates unique constraint") || error2.message.includes("UNIQUE constraint failed")) {
|
|
123366
124061
|
if (error2.message.includes("currencies_slug_unique")) {
|
|
@@ -123386,6 +124081,9 @@ async function deleteCurrency(ctx) {
|
|
|
123386
124081
|
if (!currencyId) {
|
|
123387
124082
|
throw ApiError.badRequest("Missing currency ID");
|
|
123388
124083
|
}
|
|
124084
|
+
if (!isValidUUID(currencyId)) {
|
|
124085
|
+
throw ApiError.unprocessableEntity("Invalid UUID format for currency ID");
|
|
124086
|
+
}
|
|
123389
124087
|
try {
|
|
123390
124088
|
const db = getDatabase();
|
|
123391
124089
|
const result = await db.delete(currencies).where(eq(currencies.id, currencyId)).returning({ id: currencies.id });
|
|
@@ -123393,9 +124091,8 @@ async function deleteCurrency(ctx) {
|
|
|
123393
124091
|
throw ApiError.notFound("Currency not found for deletion");
|
|
123394
124092
|
}
|
|
123395
124093
|
} catch (error2) {
|
|
123396
|
-
if (error2 instanceof ApiError)
|
|
124094
|
+
if (error2 instanceof ApiError)
|
|
123397
124095
|
throw error2;
|
|
123398
|
-
}
|
|
123399
124096
|
log2.error(`Error deleting currency ${currencyId}:`, { error: error2 });
|
|
123400
124097
|
throw ApiError.internal("Internal server error", error2);
|
|
123401
124098
|
}
|
|
@@ -123413,11 +124110,10 @@ currenciesRouter.post("/", async (c2) => {
|
|
|
123413
124110
|
return c2.json(result, 201);
|
|
123414
124111
|
} catch (error2) {
|
|
123415
124112
|
if (error2 instanceof ApiError) {
|
|
123416
|
-
return c2.json(
|
|
124113
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123417
124114
|
}
|
|
123418
124115
|
console.error("Error in createCurrency:", error2);
|
|
123419
|
-
|
|
123420
|
-
return c2.json({ error: message2 }, 500);
|
|
124116
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123421
124117
|
}
|
|
123422
124118
|
});
|
|
123423
124119
|
currenciesRouter.get("/", async (c2) => {
|
|
@@ -123432,11 +124128,10 @@ currenciesRouter.get("/", async (c2) => {
|
|
|
123432
124128
|
return c2.json(result);
|
|
123433
124129
|
} catch (error2) {
|
|
123434
124130
|
if (error2 instanceof ApiError) {
|
|
123435
|
-
return c2.json(
|
|
124131
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123436
124132
|
}
|
|
123437
124133
|
console.error("Error in listCurrencies:", error2);
|
|
123438
|
-
|
|
123439
|
-
return c2.json({ error: message2 }, 500);
|
|
124134
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123440
124135
|
}
|
|
123441
124136
|
});
|
|
123442
124137
|
currenciesRouter.get("/:currencyId", async (c2) => {
|
|
@@ -123452,11 +124147,10 @@ currenciesRouter.get("/:currencyId", async (c2) => {
|
|
|
123452
124147
|
return c2.json(result);
|
|
123453
124148
|
} catch (error2) {
|
|
123454
124149
|
if (error2 instanceof ApiError) {
|
|
123455
|
-
return c2.json(
|
|
124150
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123456
124151
|
}
|
|
123457
124152
|
console.error("Error in getCurrencyById:", error2);
|
|
123458
|
-
|
|
123459
|
-
return c2.json({ error: message2 }, 500);
|
|
124153
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123460
124154
|
}
|
|
123461
124155
|
});
|
|
123462
124156
|
currenciesRouter.patch("/:currencyId", async (c2) => {
|
|
@@ -123472,11 +124166,10 @@ currenciesRouter.patch("/:currencyId", async (c2) => {
|
|
|
123472
124166
|
return c2.json(result);
|
|
123473
124167
|
} catch (error2) {
|
|
123474
124168
|
if (error2 instanceof ApiError) {
|
|
123475
|
-
return c2.json(
|
|
124169
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123476
124170
|
}
|
|
123477
124171
|
console.error("Error in updateCurrency:", error2);
|
|
123478
|
-
|
|
123479
|
-
return c2.json({ error: message2 }, 500);
|
|
124172
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123480
124173
|
}
|
|
123481
124174
|
});
|
|
123482
124175
|
currenciesRouter.delete("/:currencyId", async (c2) => {
|
|
@@ -123492,13 +124185,16 @@ currenciesRouter.delete("/:currencyId", async (c2) => {
|
|
|
123492
124185
|
return c2.body(null, 204);
|
|
123493
124186
|
} catch (error2) {
|
|
123494
124187
|
if (error2 instanceof ApiError) {
|
|
123495
|
-
return c2.json(
|
|
124188
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123496
124189
|
}
|
|
123497
124190
|
console.error("Error in deleteCurrency:", error2);
|
|
123498
|
-
|
|
123499
|
-
return c2.json({ error: message2 }, 500);
|
|
124191
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123500
124192
|
}
|
|
123501
124193
|
});
|
|
124194
|
+
currenciesRouter.all("/", async (c2) => {
|
|
124195
|
+
const error2 = ApiError.methodNotAllowed("Method not allowed");
|
|
124196
|
+
return c2.json(createErrorResponse(error2), 405);
|
|
124197
|
+
});
|
|
123502
124198
|
async function getMapElements(ctx) {
|
|
123503
124199
|
const user = ctx.user;
|
|
123504
124200
|
if (!user) {
|
|
@@ -123512,6 +124208,9 @@ async function getMapElements(ctx) {
|
|
|
123512
124208
|
if (!mapId) {
|
|
123513
124209
|
throw ApiError.badRequest("Missing required query parameter: mapId");
|
|
123514
124210
|
}
|
|
124211
|
+
if (!isValidUUID(mapId)) {
|
|
124212
|
+
throw ApiError.unprocessableEntity("mapId must be a valid UUID format");
|
|
124213
|
+
}
|
|
123515
124214
|
try {
|
|
123516
124215
|
const db = getDatabase();
|
|
123517
124216
|
const elements = await db.query.mapElements.findMany({
|
|
@@ -123527,9 +124226,8 @@ async function getMapElements(ctx) {
|
|
|
123527
124226
|
});
|
|
123528
124227
|
return elements;
|
|
123529
124228
|
} catch (error2) {
|
|
123530
|
-
if (error2 instanceof ApiError)
|
|
124229
|
+
if (error2 instanceof ApiError)
|
|
123531
124230
|
throw error2;
|
|
123532
|
-
}
|
|
123533
124231
|
log2.error("Error fetching map elements:", { error: error2 });
|
|
123534
124232
|
throw ApiError.internal("Internal server error", error2);
|
|
123535
124233
|
}
|
|
@@ -123557,9 +124255,8 @@ async function getMapByIdentifier(ctx) {
|
|
|
123557
124255
|
}
|
|
123558
124256
|
return mapDetails;
|
|
123559
124257
|
} catch (error2) {
|
|
123560
|
-
if (error2 instanceof ApiError)
|
|
124258
|
+
if (error2 instanceof ApiError)
|
|
123561
124259
|
throw error2;
|
|
123562
|
-
}
|
|
123563
124260
|
log2.error(`Error fetching map details for identifier '${mapIdentifier}':`, { error: error2 });
|
|
123564
124261
|
throw ApiError.internal("Internal server error", error2);
|
|
123565
124262
|
}
|
|
@@ -123578,11 +124275,10 @@ mapRouter.get("/elements", async (c2) => {
|
|
|
123578
124275
|
return c2.json(result);
|
|
123579
124276
|
} catch (error2) {
|
|
123580
124277
|
if (error2 instanceof ApiError) {
|
|
123581
|
-
return c2.json(
|
|
124278
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123582
124279
|
}
|
|
123583
124280
|
console.error("Error in getMapElements:", error2);
|
|
123584
|
-
|
|
123585
|
-
return c2.json({ error: message2 }, 500);
|
|
124281
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123586
124282
|
}
|
|
123587
124283
|
});
|
|
123588
124284
|
mapsRouter.get("/:identifier", async (c2) => {
|
|
@@ -123598,13 +124294,16 @@ mapsRouter.get("/:identifier", async (c2) => {
|
|
|
123598
124294
|
return c2.json(result);
|
|
123599
124295
|
} catch (error2) {
|
|
123600
124296
|
if (error2 instanceof ApiError) {
|
|
123601
|
-
return c2.json(
|
|
124297
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123602
124298
|
}
|
|
123603
124299
|
console.error("Error in getMapByIdentifier:", error2);
|
|
123604
|
-
|
|
123605
|
-
return c2.json({ error: message2 }, 500);
|
|
124300
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123606
124301
|
}
|
|
123607
124302
|
});
|
|
124303
|
+
mapsRouter.all("/", async (c2) => {
|
|
124304
|
+
const error2 = ApiError.methodNotAllowed("Method not allowed");
|
|
124305
|
+
return c2.json(createErrorResponse(error2), 405);
|
|
124306
|
+
});
|
|
123608
124307
|
async function createShopListing(ctx) {
|
|
123609
124308
|
const user = ctx.user;
|
|
123610
124309
|
if (!user || user.role !== "admin") {
|
|
@@ -123640,6 +124339,8 @@ async function createShopListing(ctx) {
|
|
|
123640
124339
|
}
|
|
123641
124340
|
return newListing;
|
|
123642
124341
|
} catch (error2) {
|
|
124342
|
+
if (error2 instanceof ApiError)
|
|
124343
|
+
throw error2;
|
|
123643
124344
|
if (error2 instanceof Error) {
|
|
123644
124345
|
if (error2.message.includes("duplicate key value violates unique constraint") || error2.message.includes("UNIQUE constraint failed")) {
|
|
123645
124346
|
throw ApiError.conflict("This item is already listed for sale with this currency");
|
|
@@ -123670,9 +124371,8 @@ async function listShopListings(ctx) {
|
|
|
123670
124371
|
const allListings = await db.query.shopListings.findMany();
|
|
123671
124372
|
return allListings;
|
|
123672
124373
|
} catch (error2) {
|
|
123673
|
-
if (error2 instanceof ApiError)
|
|
124374
|
+
if (error2 instanceof ApiError)
|
|
123674
124375
|
throw error2;
|
|
123675
|
-
}
|
|
123676
124376
|
log2.error("Error fetching shop listings:", { error: error2 });
|
|
123677
124377
|
throw ApiError.internal("Internal server error", error2);
|
|
123678
124378
|
}
|
|
@@ -123690,6 +124390,9 @@ async function getShopListingById(ctx) {
|
|
|
123690
124390
|
if (!listingId) {
|
|
123691
124391
|
throw ApiError.badRequest("Missing listing ID");
|
|
123692
124392
|
}
|
|
124393
|
+
if (!isValidUUID(listingId)) {
|
|
124394
|
+
throw ApiError.unprocessableEntity("Invalid UUID format for listing ID");
|
|
124395
|
+
}
|
|
123693
124396
|
try {
|
|
123694
124397
|
const db = getDatabase();
|
|
123695
124398
|
const listing = await db.query.shopListings.findFirst({
|
|
@@ -123700,9 +124403,8 @@ async function getShopListingById(ctx) {
|
|
|
123700
124403
|
}
|
|
123701
124404
|
return listing;
|
|
123702
124405
|
} catch (error2) {
|
|
123703
|
-
if (error2 instanceof ApiError)
|
|
124406
|
+
if (error2 instanceof ApiError)
|
|
123704
124407
|
throw error2;
|
|
123705
|
-
}
|
|
123706
124408
|
log2.error(`Error fetching shop listing ${listingId}:`, { error: error2 });
|
|
123707
124409
|
throw ApiError.internal("Internal server error", error2);
|
|
123708
124410
|
}
|
|
@@ -123754,6 +124456,8 @@ async function updateShopListing(ctx) {
|
|
|
123754
124456
|
}
|
|
123755
124457
|
return updatedListing;
|
|
123756
124458
|
} catch (error2) {
|
|
124459
|
+
if (error2 instanceof ApiError)
|
|
124460
|
+
throw error2;
|
|
123757
124461
|
if (error2 instanceof Error) {
|
|
123758
124462
|
if (error2.message.includes("duplicate key value violates unique constraint") || error2.message.includes("UNIQUE constraint failed")) {
|
|
123759
124463
|
throw ApiError.conflict("This item is already listed for sale with this currency");
|
|
@@ -123784,6 +124488,9 @@ async function deleteShopListing(ctx) {
|
|
|
123784
124488
|
if (!listingId) {
|
|
123785
124489
|
throw ApiError.badRequest("Missing listing ID");
|
|
123786
124490
|
}
|
|
124491
|
+
if (!isValidUUID(listingId)) {
|
|
124492
|
+
throw ApiError.unprocessableEntity("Invalid UUID format for listing ID");
|
|
124493
|
+
}
|
|
123787
124494
|
try {
|
|
123788
124495
|
const db = getDatabase();
|
|
123789
124496
|
const result = await db.delete(shopListings).where(eq(shopListings.id, listingId)).returning({ id: shopListings.id });
|
|
@@ -123791,9 +124498,8 @@ async function deleteShopListing(ctx) {
|
|
|
123791
124498
|
throw ApiError.notFound("Shop listing not found for deletion");
|
|
123792
124499
|
}
|
|
123793
124500
|
} catch (error2) {
|
|
123794
|
-
if (error2 instanceof ApiError)
|
|
124501
|
+
if (error2 instanceof ApiError)
|
|
123795
124502
|
throw error2;
|
|
123796
|
-
}
|
|
123797
124503
|
log2.error(`Error deleting shop listing ${listingId}:`, { error: error2 });
|
|
123798
124504
|
throw ApiError.internal("Internal server error", error2);
|
|
123799
124505
|
}
|
|
@@ -123811,11 +124517,10 @@ shopListingsRouter.post("/", async (c2) => {
|
|
|
123811
124517
|
return c2.json(result, 201);
|
|
123812
124518
|
} catch (error2) {
|
|
123813
124519
|
if (error2 instanceof ApiError) {
|
|
123814
|
-
return c2.json(
|
|
124520
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123815
124521
|
}
|
|
123816
124522
|
console.error("Error in createShopListing:", error2);
|
|
123817
|
-
|
|
123818
|
-
return c2.json({ error: message2 }, 500);
|
|
124523
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123819
124524
|
}
|
|
123820
124525
|
});
|
|
123821
124526
|
shopListingsRouter.get("/", async (c2) => {
|
|
@@ -123830,11 +124535,10 @@ shopListingsRouter.get("/", async (c2) => {
|
|
|
123830
124535
|
return c2.json(result);
|
|
123831
124536
|
} catch (error2) {
|
|
123832
124537
|
if (error2 instanceof ApiError) {
|
|
123833
|
-
return c2.json(
|
|
124538
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123834
124539
|
}
|
|
123835
124540
|
console.error("Error in listShopListings:", error2);
|
|
123836
|
-
|
|
123837
|
-
return c2.json({ error: message2 }, 500);
|
|
124541
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123838
124542
|
}
|
|
123839
124543
|
});
|
|
123840
124544
|
shopListingsRouter.get("/:listingId", async (c2) => {
|
|
@@ -123850,11 +124554,10 @@ shopListingsRouter.get("/:listingId", async (c2) => {
|
|
|
123850
124554
|
return c2.json(result);
|
|
123851
124555
|
} catch (error2) {
|
|
123852
124556
|
if (error2 instanceof ApiError) {
|
|
123853
|
-
return c2.json(
|
|
124557
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123854
124558
|
}
|
|
123855
124559
|
console.error("Error in getShopListingById:", error2);
|
|
123856
|
-
|
|
123857
|
-
return c2.json({ error: message2 }, 500);
|
|
124560
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123858
124561
|
}
|
|
123859
124562
|
});
|
|
123860
124563
|
shopListingsRouter.patch("/:listingId", async (c2) => {
|
|
@@ -123870,11 +124573,10 @@ shopListingsRouter.patch("/:listingId", async (c2) => {
|
|
|
123870
124573
|
return c2.json(result);
|
|
123871
124574
|
} catch (error2) {
|
|
123872
124575
|
if (error2 instanceof ApiError) {
|
|
123873
|
-
return c2.json(
|
|
124576
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123874
124577
|
}
|
|
123875
124578
|
console.error("Error in updateShopListing:", error2);
|
|
123876
|
-
|
|
123877
|
-
return c2.json({ error: message2 }, 500);
|
|
124579
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123878
124580
|
}
|
|
123879
124581
|
});
|
|
123880
124582
|
shopListingsRouter.delete("/:listingId", async (c2) => {
|
|
@@ -123890,13 +124592,16 @@ shopListingsRouter.delete("/:listingId", async (c2) => {
|
|
|
123890
124592
|
return c2.body(null, 204);
|
|
123891
124593
|
} catch (error2) {
|
|
123892
124594
|
if (error2 instanceof ApiError) {
|
|
123893
|
-
return c2.json(
|
|
124595
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
123894
124596
|
}
|
|
123895
124597
|
console.error("Error in deleteShopListing:", error2);
|
|
123896
|
-
|
|
123897
|
-
return c2.json({ error: message2 }, 500);
|
|
124598
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
123898
124599
|
}
|
|
123899
124600
|
});
|
|
124601
|
+
shopListingsRouter.all("/", async (c2) => {
|
|
124602
|
+
const error2 = ApiError.methodNotAllowed("Method not allowed");
|
|
124603
|
+
return c2.json(createErrorResponse(error2), 405);
|
|
124604
|
+
});
|
|
123900
124605
|
async function applyForDeveloperStatus(ctx) {
|
|
123901
124606
|
const user = ctx.user;
|
|
123902
124607
|
log2.debug("[API] applying for developer status", {
|
|
@@ -123943,7 +124648,7 @@ async function listDeveloperKeys(ctx) {
|
|
|
123943
124648
|
if (!user) {
|
|
123944
124649
|
throw ApiError.unauthorized("Must be logged in to view API keys");
|
|
123945
124650
|
}
|
|
123946
|
-
if (user.
|
|
124651
|
+
if (user.developerStatus !== "approved") {
|
|
123947
124652
|
throw ApiError.forbidden("User does not have developer privileges");
|
|
123948
124653
|
}
|
|
123949
124654
|
try {
|
|
@@ -123963,6 +124668,46 @@ async function listDeveloperKeys(ctx) {
|
|
|
123963
124668
|
throw ApiError.internal("Internal server error", error2);
|
|
123964
124669
|
}
|
|
123965
124670
|
}
|
|
124671
|
+
async function parseCreateKeyInput(request) {
|
|
124672
|
+
if (request.headers.get("content-length") === "0") {
|
|
124673
|
+
return {};
|
|
124674
|
+
}
|
|
124675
|
+
try {
|
|
124676
|
+
const requestBody = await request.json();
|
|
124677
|
+
const validationResult = CreateDeveloperKeyInputSchema.safeParse(requestBody);
|
|
124678
|
+
if (!validationResult.success) {
|
|
124679
|
+
throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
|
|
124680
|
+
}
|
|
124681
|
+
return validationResult.data;
|
|
124682
|
+
} catch (error2) {
|
|
124683
|
+
if (error2 instanceof ApiError)
|
|
124684
|
+
throw error2;
|
|
124685
|
+
log2.error("Failed to parse request body or invalid JSON", { error: error2 });
|
|
124686
|
+
throw ApiError.badRequest("Invalid JSON body");
|
|
124687
|
+
}
|
|
124688
|
+
}
|
|
124689
|
+
async function createDeveloperKeyCore(userId, label) {
|
|
124690
|
+
const db = getDatabase();
|
|
124691
|
+
const apiKey2 = generateApiKey();
|
|
124692
|
+
const keyHash = await hashApiKey(apiKey2);
|
|
124693
|
+
const keyData = {
|
|
124694
|
+
userId,
|
|
124695
|
+
keyHash,
|
|
124696
|
+
label: label ?? null
|
|
124697
|
+
};
|
|
124698
|
+
const [newKeyMeta] = await db.insert(developerKeys).values(keyData).returning({
|
|
124699
|
+
id: developerKeys.id,
|
|
124700
|
+
label: developerKeys.label,
|
|
124701
|
+
createdAt: developerKeys.createdAt
|
|
124702
|
+
});
|
|
124703
|
+
if (!newKeyMeta) {
|
|
124704
|
+
throw ApiError.internal("Failed to create API key in database");
|
|
124705
|
+
}
|
|
124706
|
+
return {
|
|
124707
|
+
...newKeyMeta,
|
|
124708
|
+
apiKey: apiKey2
|
|
124709
|
+
};
|
|
124710
|
+
}
|
|
123966
124711
|
async function createDeveloperKey(ctx) {
|
|
123967
124712
|
const user = ctx.user;
|
|
123968
124713
|
log2.debug("[API] creating developer key", {
|
|
@@ -123971,51 +124716,15 @@ async function createDeveloperKey(ctx) {
|
|
|
123971
124716
|
if (!user) {
|
|
123972
124717
|
throw ApiError.unauthorized("Must be logged in to create API keys");
|
|
123973
124718
|
}
|
|
123974
|
-
if (user.
|
|
124719
|
+
if (user.developerStatus !== "approved") {
|
|
123975
124720
|
throw ApiError.forbidden("User does not have developer privileges");
|
|
123976
124721
|
}
|
|
123977
|
-
let inputData = {};
|
|
123978
|
-
try {
|
|
123979
|
-
if (ctx.request.headers.get("content-length") !== "0") {
|
|
123980
|
-
const requestBody = await ctx.request.json();
|
|
123981
|
-
const validationResult = CreateDeveloperKeyInputSchema.safeParse(requestBody);
|
|
123982
|
-
if (!validationResult.success) {
|
|
123983
|
-
throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
|
|
123984
|
-
}
|
|
123985
|
-
inputData = validationResult.data;
|
|
123986
|
-
}
|
|
123987
|
-
} catch (error2) {
|
|
123988
|
-
if (error2 instanceof ApiError) {
|
|
123989
|
-
throw error2;
|
|
123990
|
-
}
|
|
123991
|
-
log2.error("Failed to parse request body or invalid JSON", { error: error2 });
|
|
123992
|
-
throw ApiError.badRequest("Invalid JSON body");
|
|
123993
|
-
}
|
|
123994
124722
|
try {
|
|
123995
|
-
const
|
|
123996
|
-
|
|
123997
|
-
const keyHash = await hashApiKey(apiKey2);
|
|
123998
|
-
const keyData = {
|
|
123999
|
-
userId: user.id,
|
|
124000
|
-
keyHash,
|
|
124001
|
-
label: inputData.label ?? null
|
|
124002
|
-
};
|
|
124003
|
-
const [newKeyMeta] = await db.insert(developerKeys).values(keyData).returning({
|
|
124004
|
-
id: developerKeys.id,
|
|
124005
|
-
label: developerKeys.label,
|
|
124006
|
-
createdAt: developerKeys.createdAt
|
|
124007
|
-
});
|
|
124008
|
-
if (!newKeyMeta) {
|
|
124009
|
-
throw ApiError.internal("Failed to create API key in database");
|
|
124010
|
-
}
|
|
124011
|
-
return {
|
|
124012
|
-
...newKeyMeta,
|
|
124013
|
-
apiKey: apiKey2
|
|
124014
|
-
};
|
|
124723
|
+
const inputData = await parseCreateKeyInput(ctx.request);
|
|
124724
|
+
return await createDeveloperKeyCore(user.id, inputData.label);
|
|
124015
124725
|
} catch (error2) {
|
|
124016
|
-
if (error2 instanceof ApiError)
|
|
124726
|
+
if (error2 instanceof ApiError)
|
|
124017
124727
|
throw error2;
|
|
124018
|
-
}
|
|
124019
124728
|
log2.error("Error creating API key", { error: error2 });
|
|
124020
124729
|
throw ApiError.internal("Internal server error", error2);
|
|
124021
124730
|
}
|
|
@@ -124030,7 +124739,7 @@ async function deleteDeveloperKey(ctx) {
|
|
|
124030
124739
|
if (!user) {
|
|
124031
124740
|
throw ApiError.unauthorized("Must be logged in to delete API keys");
|
|
124032
124741
|
}
|
|
124033
|
-
if (user.
|
|
124742
|
+
if (user.developerStatus !== "approved") {
|
|
124034
124743
|
throw ApiError.forbidden("User does not have developer privileges");
|
|
124035
124744
|
}
|
|
124036
124745
|
if (!keyId) {
|
|
@@ -124051,9 +124760,8 @@ async function deleteDeveloperKey(ctx) {
|
|
|
124051
124760
|
throw ApiError.notFound("API Key not found during delete operation");
|
|
124052
124761
|
}
|
|
124053
124762
|
} catch (error2) {
|
|
124054
|
-
if (error2 instanceof ApiError)
|
|
124763
|
+
if (error2 instanceof ApiError)
|
|
124055
124764
|
throw error2;
|
|
124056
|
-
}
|
|
124057
124765
|
log2.error(`Error revoking API key ${keyId}:`, { error: error2 });
|
|
124058
124766
|
throw ApiError.internal("Internal server error", error2);
|
|
124059
124767
|
}
|
|
@@ -124071,11 +124779,10 @@ devRouter.post("/apply", async (c2) => {
|
|
|
124071
124779
|
return c2.body(null, 204);
|
|
124072
124780
|
} catch (error2) {
|
|
124073
124781
|
if (error2 instanceof ApiError) {
|
|
124074
|
-
return c2.json(
|
|
124782
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
124075
124783
|
}
|
|
124076
124784
|
console.error("Error in applyForDeveloperStatus:", error2);
|
|
124077
|
-
|
|
124078
|
-
return c2.json({ error: message2 }, 500);
|
|
124785
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
124079
124786
|
}
|
|
124080
124787
|
});
|
|
124081
124788
|
devRouter.get("/status", async (c2) => {
|
|
@@ -124090,11 +124797,10 @@ devRouter.get("/status", async (c2) => {
|
|
|
124090
124797
|
return c2.json(result);
|
|
124091
124798
|
} catch (error2) {
|
|
124092
124799
|
if (error2 instanceof ApiError) {
|
|
124093
|
-
return c2.json(
|
|
124800
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
124094
124801
|
}
|
|
124095
124802
|
console.error("Error in getDeveloperStatus:", error2);
|
|
124096
|
-
|
|
124097
|
-
return c2.json({ error: message2 }, 500);
|
|
124803
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
124098
124804
|
}
|
|
124099
124805
|
});
|
|
124100
124806
|
devRouter.get("/keys", async (c2) => {
|
|
@@ -124109,11 +124815,10 @@ devRouter.get("/keys", async (c2) => {
|
|
|
124109
124815
|
return c2.json(result);
|
|
124110
124816
|
} catch (error2) {
|
|
124111
124817
|
if (error2 instanceof ApiError) {
|
|
124112
|
-
return c2.json(
|
|
124818
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
124113
124819
|
}
|
|
124114
124820
|
console.error("Error in listDeveloperKeys:", error2);
|
|
124115
|
-
|
|
124116
|
-
return c2.json({ error: message2 }, 500);
|
|
124821
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
124117
124822
|
}
|
|
124118
124823
|
});
|
|
124119
124824
|
devRouter.post("/keys", async (c2) => {
|
|
@@ -124128,11 +124833,10 @@ devRouter.post("/keys", async (c2) => {
|
|
|
124128
124833
|
return c2.json(result, 201);
|
|
124129
124834
|
} catch (error2) {
|
|
124130
124835
|
if (error2 instanceof ApiError) {
|
|
124131
|
-
return c2.json(
|
|
124836
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
124132
124837
|
}
|
|
124133
124838
|
console.error("Error in createDeveloperKey:", error2);
|
|
124134
|
-
|
|
124135
|
-
return c2.json({ error: message2 }, 500);
|
|
124839
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
124136
124840
|
}
|
|
124137
124841
|
});
|
|
124138
124842
|
devRouter.delete("/keys/:keyId", async (c2) => {
|
|
@@ -124148,13 +124852,16 @@ devRouter.delete("/keys/:keyId", async (c2) => {
|
|
|
124148
124852
|
return c2.body(null, 204);
|
|
124149
124853
|
} catch (error2) {
|
|
124150
124854
|
if (error2 instanceof ApiError) {
|
|
124151
|
-
return c2.json(
|
|
124855
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
124152
124856
|
}
|
|
124153
124857
|
console.error("Error in deleteDeveloperKey:", error2);
|
|
124154
|
-
|
|
124155
|
-
return c2.json({ error: message2 }, 500);
|
|
124858
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
124156
124859
|
}
|
|
124157
124860
|
});
|
|
124861
|
+
devRouter.all("/", async (c2) => {
|
|
124862
|
+
const error2 = ApiError.methodNotAllowed("Method not allowed");
|
|
124863
|
+
return c2.json(createErrorResponse(error2), 405);
|
|
124864
|
+
});
|
|
124158
124865
|
var levelsRouter = new Hono2;
|
|
124159
124866
|
levelsRouter.get("/config", async (c2) => {
|
|
124160
124867
|
const ctx = {
|
|
@@ -124168,11 +124875,10 @@ levelsRouter.get("/config", async (c2) => {
|
|
|
124168
124875
|
return c2.json(configs);
|
|
124169
124876
|
} catch (error2) {
|
|
124170
124877
|
if (error2 instanceof ApiError) {
|
|
124171
|
-
return c2.json(
|
|
124878
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
124172
124879
|
}
|
|
124173
124880
|
console.error("Error in getAllLevelConfigs:", error2);
|
|
124174
|
-
|
|
124175
|
-
return c2.json({ error: message2 }, 500);
|
|
124881
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
124176
124882
|
}
|
|
124177
124883
|
});
|
|
124178
124884
|
levelsRouter.get("/config/:level", async (c2) => {
|
|
@@ -124187,24 +124893,33 @@ levelsRouter.get("/config/:level", async (c2) => {
|
|
|
124187
124893
|
return c2.json(config);
|
|
124188
124894
|
} catch (error2) {
|
|
124189
124895
|
if (error2 instanceof ApiError) {
|
|
124190
|
-
return c2.json(
|
|
124896
|
+
return c2.json(createErrorResponse(error2), error2.statusCode);
|
|
124191
124897
|
}
|
|
124192
124898
|
console.error("Error in getLevelConfigByPath:", error2);
|
|
124193
|
-
|
|
124194
|
-
return c2.json({ error: message2 }, 500);
|
|
124899
|
+
return c2.json(createUnknownErrorResponse(error2), 500);
|
|
124195
124900
|
}
|
|
124196
124901
|
});
|
|
124902
|
+
levelsRouter.all("/", async (c2) => {
|
|
124903
|
+
const error2 = ApiError.methodNotAllowed("Method not allowed");
|
|
124904
|
+
return c2.json(createErrorResponse(error2), 405);
|
|
124905
|
+
});
|
|
124197
124906
|
async function startServer(options) {
|
|
124198
|
-
const { port, verbose, project } = options;
|
|
124199
|
-
const db = await setupDatabase();
|
|
124200
|
-
|
|
124201
|
-
|
|
124202
|
-
|
|
124907
|
+
const { port, verbose = false, project, memoryOnly = false, seed = true } = options;
|
|
124908
|
+
const db = await setupDatabase(memoryOnly ? ":memory:" : undefined);
|
|
124909
|
+
if (seed) {
|
|
124910
|
+
await seedDemoData(db);
|
|
124911
|
+
if (project) {
|
|
124912
|
+
await seedCurrentProjectGame(db, project);
|
|
124913
|
+
}
|
|
124203
124914
|
}
|
|
124204
124915
|
const app = new Hono2;
|
|
124205
124916
|
app.use("*", cors({ origin: "*", credentials: true }));
|
|
124206
124917
|
if (verbose)
|
|
124207
124918
|
app.use("*", logger());
|
|
124919
|
+
app.use("/api/*", async (c2, next) => {
|
|
124920
|
+
c2.set("db", db);
|
|
124921
|
+
await next();
|
|
124922
|
+
});
|
|
124208
124923
|
app.route("/health", healthRouter);
|
|
124209
124924
|
app.route("/api", manifestRouter);
|
|
124210
124925
|
app.use("/api/*", setupAuth());
|