@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.
Files changed (2) hide show
  1. package/dist/index.js +1141 -426
  2. 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 fs32 = __require2("fs");
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 (fs32.existsSync(path3.join(nodeModulesDirectory, pkg)))
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 (fs32.existsSync(path3.join(nodeModulesDirectory, pkg)))
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 (!fs32.existsSync(ESBUILD_BINARY_PATH)) {
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 (!fs32.existsSync(binPath)) {
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 (!fs32.existsSync(binTargetPath)) {
44008
- fs32.mkdirSync(path3.dirname(binTargetPath), { recursive: true });
44009
- fs32.copyFileSync(binPath, binTargetPath);
44010
- fs32.chmodSync(binTargetPath, 493);
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 path22 = __require2("path");
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) && (path22.basename(__filename2) !== "main.js" || path22.basename(__dirname2) !== "lib")) {
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 path22.join(os22.tmpdir(), `esbuild-${crypto32.randomBytes(32).toString("hex")}`);
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 fs32;
46913
+ var fs33;
46912
46914
  try {
46913
- fs32 = __require2("fs");
46914
- if (!fs32.existsSync || !fs32.readFileSync) {
46915
- fs32 = null;
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(path22) {
46954
- path22 = path22.trim();
46955
- if (/^file:/.test(path22)) {
46956
- path22 = path22.replace(/file:\/\/\/(\w:)?/, function(protocol, drive) {
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 (path22 in fileContentsCache) {
46961
- return fileContentsCache[path22];
46962
+ if (path23 in fileContentsCache) {
46963
+ return fileContentsCache[path23];
46962
46964
  }
46963
46965
  var contents = "";
46964
46966
  try {
46965
- if (!fs32) {
46967
+ if (!fs33) {
46966
46968
  var xhr = new XMLHttpRequest;
46967
- xhr.open("GET", path22, false);
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 (fs32.existsSync(path22)) {
46973
- contents = fs32.readFileSync(path22, "utf8");
46974
+ } else if (fs33.existsSync(path23)) {
46975
+ contents = fs33.readFileSync(path23, "utf8");
46974
46976
  }
46975
46977
  } catch (er2) {}
46976
- return fileContentsCache[path22] = contents;
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 && fs32 && fs32.existsSync(source)) {
47239
+ if (!contents && fs33 && fs33.existsSync(source)) {
47238
47240
  try {
47239
- contents = fs32.readFileSync(source, "utf8");
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 fs32 = __require2("fs");
47785
+ var fs33 = __require2("fs");
47784
47786
  function fileExistsSync(path3) {
47785
- if (!fs32.existsSync(path3)) {
47787
+ if (!fs33.existsSync(path3)) {
47786
47788
  return false;
47787
47789
  }
47788
47790
  try {
47789
- var stats = fs32.statSync(path3);
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 (!fs32.existsSync(packageJsonPath)) {
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
- fs32.readFile(path3, "utf8", function(err2, result) {
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(path22, callback2) {
47814
- fs32.stat(path22, function(err2, stats) {
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 fs32 = __require2("fs");
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 = fs32.lstatSync(filename).isDirectory() ? path3.resolve(filename, "./tsconfig.json") : path3.resolve(cwd, filename);
49288
+ var absolutePath = fs33.lstatSync(filename).isDirectory() ? path3.resolve(filename, "./tsconfig.json") : path3.resolve(cwd, filename);
49287
49289
  return absolutePath;
49288
49290
  }
49289
- if (fs32.statSync(cwd).isFile()) {
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 = fs32.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 = fs32.existsSync;
49318
+ existsSync2 = fs33.existsSync;
49317
49319
  }
49318
49320
  if (readFileSync === undefined) {
49319
49321
  readFileSync = function(filename) {
49320
- return fs32.readFileSync(filename, "utf8");
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: path22, field }, columnIndex) => {
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 path22.entries()) {
50961
- if (pathChunkIndex < path22.length - 1) {
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) && path22.length === 2) {
50970
- const objectName = path22[0];
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 fs32 = __require22("fs");
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
- fs32.lstatSync(base);
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 = fs32.lstatSync(base);
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
- fs32.statSync(base);
55881
- linkTarget = fs32.readlinkSync(base);
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
- fs32.lstat(base, function(err2) {
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 fs32.lstat(base, gotStat);
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
- fs32.stat(base, function(err22) {
55965
+ fs33.stat(base, function(err22) {
55964
55966
  if (err22)
55965
55967
  return cb(err22);
55966
- fs32.readlink(base, function(err3, target) {
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 fs32 = __require22("fs");
55997
- var origRealpath = fs32.realpath;
55998
- var origRealpathSync = fs32.realpathSync;
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
- fs32.realpath = realpath;
56037
- fs32.realpathSync = realpathSync;
56038
+ fs33.realpath = realpath;
56039
+ fs33.realpathSync = realpathSync;
56038
56040
  }
56039
56041
  function unmonkeypatch() {
56040
- fs32.realpath = origRealpath;
56041
- fs32.realpathSync = origRealpathSync;
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 path22 = require_path2();
56268
- minimatch2.sep = path22.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 (path22.sep !== "/") {
56782
- f3 = f3.split(path22.sep).join("/");
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 fs32 = __require22("fs");
56873
- var path22 = __require22("path");
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 || fs32;
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 = path22.resolve(cwd);
56942
+ self2.cwd = path23.resolve(cwd);
56941
56943
  else {
56942
- self2.cwd = path22.resolve(options.cwd);
56944
+ self2.cwd = path23.resolve(options.cwd);
56943
56945
  self2.changedCwd = self2.cwd !== cwd;
56944
56946
  }
56945
- self2.root = options.root || path22.resolve(self2.cwd, "/");
56946
- self2.root = path22.resolve(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 = path22.join(self2.root, f3);
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 = path22.resolve(self2.cwd, f3);
57034
+ abs = path23.resolve(self2.cwd, f3);
57033
57035
  } else {
57034
- abs = path22.resolve(f3);
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 path22 = __require22("path");
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 = path22.join(this.root, 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 = path22.join(this.root, prefix2);
57346
+ prefix2 = path23.join(this.root, prefix2);
57345
57347
  } else {
57346
- prefix2 = path22.resolve(this.root, 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 path22 = __require22("path");
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 = path22.join(this.root, 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 = path22.join(this.root, prefix2);
58005
+ prefix2 = path23.join(this.root, prefix2);
58004
58006
  } else {
58005
- prefix2 = path22.resolve(this.root, 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: path22, errorMaps, issueData } = params;
58969
- const fullPath = [...path22, ...issueData.path || []];
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, path22, key) {
59062
+ constructor(parent, value, path23, key) {
59061
59063
  this._cachedPath = [];
59062
59064
  this.parent = parent;
59063
59065
  this.data = value;
59064
- this._path = path22;
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 path22 = paths[i22];
93944
+ const path23 = paths[i22];
93943
93945
  Object.keys(routes).forEach((m) => {
93944
93946
  if (method === METHOD_NAME_ALL || method === m) {
93945
- routes[m][path22] ||= [
93946
- ...findMiddleware(middleware[m], path22) || findMiddleware(middleware[METHOD_NAME_ALL], path22) || []
93947
+ routes[m][path23] ||= [
93948
+ ...findMiddleware(middleware[m], path23) || findMiddleware(middleware[METHOD_NAME_ALL], path23) || []
93947
93949
  ];
93948
- routes[m][path22].push([handler, paramCount - len2 + i22 + 1]);
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, path22) => {
93958
+ this.match = (method2, path23) => {
93957
93959
  const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
93958
- const staticMatch = matcher[2][path22];
93960
+ const staticMatch = matcher[2][path23];
93959
93961
  if (staticMatch) {
93960
93962
  return staticMatch;
93961
93963
  }
93962
- const match2 = path22.match(matcher[0]);
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.8",
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 DEMO_USER = {
114386
- id: crypto.randomUUID(),
114387
- name: "Demo User",
114388
- username: "demo_user",
114389
- email: "demo@playcademy.com",
114390
- emailVerified: true,
114391
- image: null,
114392
- role: "developer",
114393
- developerStatus: "approved",
114394
- createdAt: now,
114395
- updatedAt: now
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
- await db.insert(users).values(DEMO_USER);
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.set("user", DEMO_USER);
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: path22, errorMaps, issueData } = params;
115068
- const fullPath = [...path22, ...issueData.path || []];
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, path22, key) {
115418
+ constructor(parent, value, path23, key) {
115179
115419
  this._cachedPath = [];
115180
115420
  this.parent = parent;
115181
115421
  this.data = value;
115182
- this._path = path22;
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 = (path22, fieldName) => {
118883
- if (path22 == null)
119101
+ var validateRelativePath = (path23, fieldName) => {
119102
+ if (path23 == null)
118884
119103
  return true;
118885
- if (typeof path22 !== "string" || !safeRelativePathRegex.test(path22)) {
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 = (path22, fieldName) => {
118998
- if (path22 == null)
119216
+ var validateRelativePath2 = (path23, fieldName) => {
119217
+ if (path23 == null)
118999
119218
  return true;
119000
- if (typeof path22 !== "string" || !safeRelativePathRegex2.test(path22)) {
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({ error: error2.message }, error2.statusCode);
119718
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119483
119719
  }
119484
119720
  console.error("Error in getUserMe:", error2);
119485
- const message = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
119736
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119502
119737
  }
119503
119738
  console.error("Error in getUserLevel:", error2);
119504
- const message = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
119754
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119521
119755
  }
119522
119756
  console.error("Error in getUserLevelProgress:", error2);
119523
- const message = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
119772
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119540
119773
  }
119541
119774
  console.error("Error in addXPFromRequest:", error2);
119542
- const message = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
119943
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119708
119944
  }
119709
119945
  console.error("Error in getUserInventory:", error2);
119710
- const message = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
119961
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119727
119962
  }
119728
119963
  console.error("Error in addInventoryItem:", error2);
119729
- const message = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
119979
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119746
119980
  }
119747
119981
  console.error("Error in removeInventoryItem:", error2);
119748
- const message = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123259
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122654
123260
  }
122655
123261
  console.error("Error in listGames:", error2);
122656
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123279
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122675
123280
  }
122676
123281
  console.error("Error in getGame:", error2);
122677
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123298
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122695
123299
  }
122696
123300
  console.error("Error in upsertGameBySlug:", error2);
122697
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123317
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122715
123318
  }
122716
123319
  console.error("Error in updateGame:", error2);
122717
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123336
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122735
123337
  }
122736
123338
  console.error("Error in deleteGame:", error2);
122737
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123355
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122755
123356
  }
122756
123357
  console.error("Error in startGameSession:", error2);
122757
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123375
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122776
123376
  }
122777
123377
  console.error("Error in endGameSession:", error2);
122778
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122779
- return c2.json({ error: message2 }, 500);
123378
+ return c2.json(createUnknownErrorResponse(error2), 500);
122780
123379
  }
122781
123380
  });
122782
- gamesRouter.post("/:gameId/sessions/token", async (c2) => {
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({ error: error2.message }, error2.statusCode);
123394
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122796
123395
  }
122797
123396
  console.error("Error in mintGameToken:", error2);
122798
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122799
- return c2.json({ error: message2 }, 500);
123397
+ return c2.json(createUnknownErrorResponse(error2), 500);
122800
123398
  }
122801
123399
  });
122802
- gamesRouter.get("/:gameId/sessions/state", async (c2) => {
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({ error: error2.message }, error2.statusCode);
123413
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122816
123414
  }
122817
123415
  console.error("Error in loadGameState:", error2);
122818
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122819
- return c2.json({ error: message2 }, 500);
123416
+ return c2.json(createUnknownErrorResponse(error2), 500);
122820
123417
  }
122821
123418
  });
122822
- gamesRouter.post("/:gameId/sessions/state", async (c2) => {
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.json({ success: true });
123429
+ return c2.body(null, 204);
122833
123430
  } catch (error2) {
122834
123431
  if (error2 instanceof ApiError) {
122835
- return c2.json({ error: error2.message }, error2.statusCode);
123432
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122836
123433
  }
122837
123434
  console.error("Error in saveGameState:", error2);
122838
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123450
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122855
123451
  }
122856
123452
  console.error("Error in initiateUpload:", error2);
122857
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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
- controller.enqueue(formatSSEData("error", { message: error2.message }));
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
- controller.enqueue(formatSSEData("error", {
122883
- message: "Internal server error"
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({ error: error2.message }, error2.statusCode);
123494
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122900
123495
  }
122901
123496
  console.error("Error in finalizeUpload:", error2);
122902
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123513
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122920
123514
  }
122921
123515
  console.error("Error in listGameItems:", error2);
122922
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123532
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122940
123533
  }
122941
123534
  console.error("Error in createGameItem:", error2);
122942
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123552
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122961
123553
  }
122962
123554
  console.error("Error in updateGameItem:", error2);
122963
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123572
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122982
123573
  }
122983
123574
  console.error("Error in deleteGameItem:", error2);
122984
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122985
- return c2.json({ error: message2 }, 500);
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/sessions/token`
123702
+ url: `${baseUrl}/api/games/:gameId/token`
123010
123703
  },
123011
123704
  {
123012
123705
  method: "GET",
123013
- url: `${baseUrl}/api/games/:gameId/sessions/state`
123706
+ url: `${baseUrl}/api/games/:gameId/state`
123014
123707
  },
123015
123708
  {
123016
123709
  method: "POST",
123017
- url: `${baseUrl}/api/games/:gameId/sessions/state`
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({ error: error2.message }, error2.statusCode);
123801
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123110
123802
  }
123111
123803
  console.error("Error in getShopView:", error2);
123112
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123824
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123130
123825
  }
123131
123826
  console.error("Error in resolveItem:", error2);
123132
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123842
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123149
123843
  }
123150
123844
  console.error("Error in createItem:", error2);
123151
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123860
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123168
123861
  }
123169
123862
  console.error("Error in listItems:", error2);
123170
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123879
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123188
123880
  }
123189
123881
  console.error("Error in getItemById:", error2);
123190
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123898
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123208
123899
  }
123209
123900
  console.error("Error in updateItem:", error2);
123210
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
123917
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123228
123918
  }
123229
123919
  console.error("Error in deleteItem:", error2);
123230
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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 inputData;
123984
+ let requestBody;
123291
123985
  try {
123292
- const requestBody = await ctx.request.json();
123293
- const validationResult = InsertCurrencySchema.safeParse(requestBody);
123294
- if (!validationResult.success) {
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
- let inputData;
124031
+ if (!isValidUUID(currencyId)) {
124032
+ throw ApiError.unprocessableEntity("Invalid UUID format for currency ID");
124033
+ }
124034
+ let requestBody;
123339
124035
  try {
123340
- const requestBody = await ctx.request.json();
123341
- const validationResult = UpdateCurrencySchema.safeParse(requestBody);
123342
- if (!validationResult.success) {
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({ error: error2.message }, error2.statusCode);
124113
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123417
124114
  }
123418
124115
  console.error("Error in createCurrency:", error2);
123419
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124131
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123436
124132
  }
123437
124133
  console.error("Error in listCurrencies:", error2);
123438
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124150
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123456
124151
  }
123457
124152
  console.error("Error in getCurrencyById:", error2);
123458
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124169
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123476
124170
  }
123477
124171
  console.error("Error in updateCurrency:", error2);
123478
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124188
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123496
124189
  }
123497
124190
  console.error("Error in deleteCurrency:", error2);
123498
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124278
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123582
124279
  }
123583
124280
  console.error("Error in getMapElements:", error2);
123584
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124297
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123602
124298
  }
123603
124299
  console.error("Error in getMapByIdentifier:", error2);
123604
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124520
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123815
124521
  }
123816
124522
  console.error("Error in createShopListing:", error2);
123817
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124538
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123834
124539
  }
123835
124540
  console.error("Error in listShopListings:", error2);
123836
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124557
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123854
124558
  }
123855
124559
  console.error("Error in getShopListingById:", error2);
123856
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124576
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123874
124577
  }
123875
124578
  console.error("Error in updateShopListing:", error2);
123876
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124595
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123894
124596
  }
123895
124597
  console.error("Error in deleteShopListing:", error2);
123896
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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.role !== "developer" || user.developerStatus !== "approved") {
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.role !== "developer" || user.developerStatus !== "approved") {
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 db = getDatabase();
123996
- const apiKey2 = generateApiKey();
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.role !== "developer" || user.developerStatus !== "approved") {
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({ error: error2.message }, error2.statusCode);
124782
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124075
124783
  }
124076
124784
  console.error("Error in applyForDeveloperStatus:", error2);
124077
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124800
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124094
124801
  }
124095
124802
  console.error("Error in getDeveloperStatus:", error2);
124096
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124818
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124113
124819
  }
124114
124820
  console.error("Error in listDeveloperKeys:", error2);
124115
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124836
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124132
124837
  }
124133
124838
  console.error("Error in createDeveloperKey:", error2);
124134
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124855
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124152
124856
  }
124153
124857
  console.error("Error in deleteDeveloperKey:", error2);
124154
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124878
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124172
124879
  }
124173
124880
  console.error("Error in getAllLevelConfigs:", error2);
124174
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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({ error: error2.message }, error2.statusCode);
124896
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124191
124897
  }
124192
124898
  console.error("Error in getLevelConfigByPath:", error2);
124193
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
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
- await seedDemoData(db);
124201
- if (project) {
124202
- await seedCurrentProjectGame(db, project);
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());