@playcademy/vite-plugin 0.0.1-beta.12 → 0.0.1-beta.13

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 +1035 -425
  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.9",
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
  ];
@@ -114489,6 +114585,7 @@ async function seedDemoData(db) {
114489
114585
  for (const item of SAMPLE_ITEMS) {
114490
114586
  await db.insert(items).values(item);
114491
114587
  }
114588
+ await seedCurrencies(db);
114492
114589
  for (const inventory of SAMPLE_INVENTORY) {
114493
114590
  await db.insert(inventoryItems).values(inventory);
114494
114591
  }
@@ -114496,12 +114593,90 @@ async function seedDemoData(db) {
114496
114593
  for (const config of levelConfigsData) {
114497
114594
  await db.insert(levelConfigs).values(config);
114498
114595
  }
114596
+ await seedCoreGames(db);
114499
114597
  } catch (error2) {
114500
114598
  console.error("❌ Error seeding demo data:", error2);
114501
114599
  throw error2;
114502
114600
  }
114503
114601
  return DEMO_USER;
114504
114602
  }
114603
+ async function seedCurrencies(db) {
114604
+ const currencyItems = SAMPLE_ITEMS.filter((item) => item.type === "currency");
114605
+ for (const currencyItem of currencyItems) {
114606
+ const symbol = getCurrencySymbol(currencyItem.slug);
114607
+ const isPrimary = currencyItem.slug === ITEM_SLUGS.PLAYCADEMY_CREDITS;
114608
+ await db.insert(currencies).values({
114609
+ id: crypto.randomUUID(),
114610
+ itemId: currencyItem.id,
114611
+ symbol,
114612
+ isPrimary,
114613
+ createdAt: new Date,
114614
+ updatedAt: new Date
114615
+ });
114616
+ }
114617
+ }
114618
+ function getCurrencySymbol(slug) {
114619
+ switch (slug) {
114620
+ case ITEM_SLUGS.PLAYCADEMY_CREDITS:
114621
+ return CURRENCY_SYMBOLS.PLAYCADEMY_CREDITS;
114622
+ case ITEM_SLUGS.PLAYCADEMY_XP:
114623
+ return CURRENCY_SYMBOLS.PLAYCADEMY_XP;
114624
+ default:
114625
+ return CURRENCY_SYMBOLS.DEFAULT;
114626
+ }
114627
+ }
114628
+ async function seedCoreGames(db) {
114629
+ const now2 = new Date;
114630
+ const coreGames = [
114631
+ {
114632
+ id: CORE_GAME_UUIDS.PLAYGROUND,
114633
+ developerId: DEMO_USER.id,
114634
+ slug: "playground",
114635
+ displayName: "Playground",
114636
+ version: "local",
114637
+ platform: "web",
114638
+ assetBundleBase: "https://cdn.test.playcademy.net/games/01/internal",
114639
+ metadata: { description: "A playground environment for internal testing." },
114640
+ mapElementId: null,
114641
+ createdAt: now2,
114642
+ updatedAt: now2
114643
+ },
114644
+ {
114645
+ id: CORE_GAME_UUIDS.EQUATION_ARENA,
114646
+ developerId: DEMO_USER.id,
114647
+ slug: "equation-arena",
114648
+ displayName: "Equation Arena",
114649
+ version: "local",
114650
+ platform: "web",
114651
+ assetBundleBase: "https://cdn.test.playcademy.net/games/02/internal",
114652
+ metadata: { description: "Solve math problems to defeat the dragon!" },
114653
+ mapElementId: null,
114654
+ createdAt: now2,
114655
+ updatedAt: now2
114656
+ },
114657
+ {
114658
+ id: CORE_GAME_UUIDS.BAMBOO,
114659
+ developerId: DEMO_USER.id,
114660
+ slug: "bamboo",
114661
+ displayName: "Bamboo",
114662
+ version: "local",
114663
+ platform: "web",
114664
+ assetBundleBase: "https://cdn.test.playcademy.net/games/03/internal",
114665
+ metadata: { description: "A relaxing game with bamboo and pandas." },
114666
+ mapElementId: null,
114667
+ createdAt: now2,
114668
+ updatedAt: now2
114669
+ }
114670
+ ];
114671
+ for (const gameData of coreGames) {
114672
+ try {
114673
+ await db.insert(games).values(gameData).onConflictDoNothing();
114674
+ console.log(`-> Seeded core game: ${gameData.displayName} (${gameData.slug})`);
114675
+ } catch (error2) {
114676
+ console.error(`Error seeding core game '${gameData.slug}':`, error2);
114677
+ }
114678
+ }
114679
+ }
114505
114680
  function generateLevelConfigs() {
114506
114681
  const configs = [];
114507
114682
  for (let level = 1;level <= 100; level++) {
@@ -114550,7 +114725,7 @@ async function seedCurrentProjectGame(db, project) {
114550
114725
  displayName: project.displayName,
114551
114726
  version: project.version,
114552
114727
  platform: "web",
114553
- assetBundleBase: "",
114728
+ assetBundleBase: "https://localhost",
114554
114729
  metadata: {
114555
114730
  description: project.description || `Auto-generated game for ${project.displayName}`
114556
114731
  },
@@ -114567,7 +114742,17 @@ async function seedCurrentProjectGame(db, project) {
114567
114742
  }
114568
114743
  function setupAuth() {
114569
114744
  return async (c2, next) => {
114570
- c2.set("user", DEMO_USER);
114745
+ const authHeader = c2.req.header("Authorization");
114746
+ if (authHeader?.startsWith("Bearer ")) {
114747
+ const token = authHeader.substring(7);
114748
+ const demoUser = DEMO_TOKENS[token];
114749
+ if (demoUser) {
114750
+ c2.set("user", demoUser);
114751
+ await next();
114752
+ return;
114753
+ }
114754
+ }
114755
+ c2.set("user", DEMO_USERS.admin);
114571
114756
  await next();
114572
114757
  };
114573
114758
  }
@@ -114595,6 +114780,9 @@ class ApiError extends Error {
114595
114780
  static badRequest(message = "Bad request", details) {
114596
114781
  return new ApiError(400, "BAD_REQUEST", message, details);
114597
114782
  }
114783
+ static unprocessableEntity(message = "Unprocessable entity", details) {
114784
+ return new ApiError(422, "UNPROCESSABLE_ENTITY", message, details);
114785
+ }
114598
114786
  static conflict(message = "Conflict") {
114599
114787
  return new ApiError(409, "CONFLICT", message);
114600
114788
  }
@@ -115064,8 +115252,8 @@ function getErrorMap2() {
115064
115252
  return overrideErrorMap2;
115065
115253
  }
115066
115254
  var makeIssue2 = (params) => {
115067
- const { data: data2, path: path22, errorMaps, issueData } = params;
115068
- const fullPath = [...path22, ...issueData.path || []];
115255
+ const { data: data2, path: path23, errorMaps, issueData } = params;
115256
+ const fullPath = [...path23, ...issueData.path || []];
115069
115257
  const fullIssue = {
115070
115258
  ...issueData,
115071
115259
  path: fullPath
@@ -115175,11 +115363,11 @@ var errorUtil2;
115175
115363
  })(errorUtil2 || (errorUtil2 = {}));
115176
115364
 
115177
115365
  class ParseInputLazyPath2 {
115178
- constructor(parent, value, path22, key) {
115366
+ constructor(parent, value, path23, key) {
115179
115367
  this._cachedPath = [];
115180
115368
  this.parent = parent;
115181
115369
  this.data = value;
115182
- this._path = path22;
115370
+ this._path = path23;
115183
115371
  this._key = key;
115184
115372
  }
115185
115373
  get path() {
@@ -118559,27 +118747,6 @@ var coerce2 = {
118559
118747
  date: (arg) => ZodDate2.create({ ...arg, coerce: true })
118560
118748
  };
118561
118749
  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
118750
  var CONSTANTS = {
118584
118751
  INT8_MIN: -128,
118585
118752
  INT8_MAX: 127,
@@ -118879,10 +119046,10 @@ var CreateDeveloperKeyInputSchema = InsertDeveloperKeySchema.pick({
118879
119046
  });
118880
119047
  var safeRelativePathRegex = /^(?!.*\.\.)(?!\/)[\w\-./]+$/;
118881
119048
  var invalidPathMessage = "Path must be relative, contain only alphanumeric, -, _, ., / characters, and not contain .. segments.";
118882
- var validateRelativePath = (path22, fieldName) => {
118883
- if (path22 == null)
119049
+ var validateRelativePath = (path23, fieldName) => {
119050
+ if (path23 == null)
118884
119051
  return true;
118885
- if (typeof path22 !== "string" || !safeRelativePathRegex.test(path22)) {
119052
+ if (typeof path23 !== "string" || !safeRelativePathRegex.test(path23)) {
118886
119053
  throw new exports_external.ZodError([
118887
119054
  {
118888
119055
  code: exports_external.ZodIssueCode.custom,
@@ -118994,10 +119161,10 @@ var ManifestV1Schema = exports_external.object({
118994
119161
  });
118995
119162
  var safeRelativePathRegex2 = /^(?!.*\.\.)(?!\/)[\w\-./]+$/;
118996
119163
  var invalidPathMessage2 = "Path must be relative, contain only alphanumeric, -, _, ., / characters, and not contain .. segments.";
118997
- var validateRelativePath2 = (path22, fieldName) => {
118998
- if (path22 == null)
119164
+ var validateRelativePath2 = (path23, fieldName) => {
119165
+ if (path23 == null)
118999
119166
  return true;
119000
- if (typeof path22 !== "string" || !safeRelativePathRegex2.test(path22)) {
119167
+ if (typeof path23 !== "string" || !safeRelativePathRegex2.test(path23)) {
119001
119168
  throw new exports_external.ZodError([
119002
119169
  {
119003
119170
  code: exports_external.ZodIssueCode.custom,
@@ -119276,9 +119443,8 @@ async function getUserLevel(ctx) {
119276
119443
  }
119277
119444
  return userLevel;
119278
119445
  } catch (error2) {
119279
- if (error2 instanceof ApiError) {
119446
+ if (error2 instanceof ApiError)
119280
119447
  throw error2;
119281
- }
119282
119448
  log2.error(`Error fetching user level for user ${user.id}:`, { error: error2 });
119283
119449
  throw ApiError.internal("Internal server error", error2);
119284
119450
  }
@@ -119365,9 +119531,8 @@ async function addXP(ctx, amount) {
119365
119531
  });
119366
119532
  return result;
119367
119533
  } catch (error2) {
119368
- if (error2 instanceof ApiError) {
119534
+ if (error2 instanceof ApiError)
119369
119535
  throw error2;
119370
- }
119371
119536
  log2.error(`Error adding XP for user ${user.id}:`, { error: error2 });
119372
119537
  throw ApiError.internal("Internal server error", error2);
119373
119538
  }
@@ -119414,9 +119579,8 @@ async function getUserLevelProgress(ctx) {
119414
119579
  totalXP: userLevel.totalXP
119415
119580
  };
119416
119581
  } catch (error2) {
119417
- if (error2 instanceof ApiError) {
119582
+ if (error2 instanceof ApiError)
119418
119583
  throw error2;
119419
- }
119420
119584
  log2.error(`Error fetching user level progress:`, { error: error2 });
119421
119585
  throw ApiError.internal("Internal server error", error2);
119422
119586
  }
@@ -119435,9 +119599,8 @@ async function getLevelConfigByPath(ctx) {
119435
119599
  const db = getDatabase();
119436
119600
  return await getLevelConfig(db, level);
119437
119601
  } catch (error2) {
119438
- if (error2 instanceof ApiError) {
119602
+ if (error2 instanceof ApiError)
119439
119603
  throw error2;
119440
- }
119441
119604
  log2.error(`Error fetching level config for level ${level}:`, { error: error2 });
119442
119605
  throw ApiError.internal("Internal server error", error2);
119443
119606
  }
@@ -119459,13 +119622,34 @@ async function getUserMe(ctx) {
119459
119622
  }
119460
119623
  return userData;
119461
119624
  } catch (error2) {
119462
- if (error2 instanceof ApiError) {
119625
+ if (error2 instanceof ApiError)
119463
119626
  throw error2;
119464
- }
119465
119627
  log2.error("[API /users/me] Database error fetching user:", { error: error2 });
119466
119628
  throw ApiError.internal("Internal server error", error2);
119467
119629
  }
119468
119630
  }
119631
+ function createErrorResponse(error2) {
119632
+ const errorResponse = {
119633
+ error: {
119634
+ code: error2.code,
119635
+ message: error2.message,
119636
+ details: error2.details
119637
+ }
119638
+ };
119639
+ if (errorResponse.error.details === undefined) {
119640
+ delete errorResponse.error.details;
119641
+ }
119642
+ return errorResponse;
119643
+ }
119644
+ function createUnknownErrorResponse(error2) {
119645
+ const message = error2 instanceof Error ? error2.message : "Internal server error";
119646
+ return {
119647
+ error: {
119648
+ code: "INTERNAL_ERROR",
119649
+ message
119650
+ }
119651
+ };
119652
+ }
119469
119653
  var usersRouter = new Hono2;
119470
119654
  usersRouter.get("/me", async (c2) => {
119471
119655
  const ctx = {
@@ -119479,11 +119663,10 @@ usersRouter.get("/me", async (c2) => {
119479
119663
  return c2.json(userData);
119480
119664
  } catch (error2) {
119481
119665
  if (error2 instanceof ApiError) {
119482
- return c2.json({ error: error2.message }, error2.statusCode);
119666
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119483
119667
  }
119484
119668
  console.error("Error in getUserMe:", error2);
119485
- const message = error2 instanceof Error ? error2.message : "Internal server error";
119486
- return c2.json({ error: message }, 500);
119669
+ return c2.json(createUnknownErrorResponse(error2), 500);
119487
119670
  }
119488
119671
  });
119489
119672
  usersRouter.get("/level", async (c2) => {
@@ -119498,11 +119681,10 @@ usersRouter.get("/level", async (c2) => {
119498
119681
  return c2.json(levelData);
119499
119682
  } catch (error2) {
119500
119683
  if (error2 instanceof ApiError) {
119501
- return c2.json({ error: error2.message }, error2.statusCode);
119684
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119502
119685
  }
119503
119686
  console.error("Error in getUserLevel:", error2);
119504
- const message = error2 instanceof Error ? error2.message : "Internal server error";
119505
- return c2.json({ error: message }, 500);
119687
+ return c2.json(createUnknownErrorResponse(error2), 500);
119506
119688
  }
119507
119689
  });
119508
119690
  usersRouter.get("/level/progress", async (c2) => {
@@ -119517,11 +119699,10 @@ usersRouter.get("/level/progress", async (c2) => {
119517
119699
  return c2.json(progressData);
119518
119700
  } catch (error2) {
119519
119701
  if (error2 instanceof ApiError) {
119520
- return c2.json({ error: error2.message }, error2.statusCode);
119702
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119521
119703
  }
119522
119704
  console.error("Error in getUserLevelProgress:", error2);
119523
- const message = error2 instanceof Error ? error2.message : "Internal server error";
119524
- return c2.json({ error: message }, 500);
119705
+ return c2.json(createUnknownErrorResponse(error2), 500);
119525
119706
  }
119526
119707
  });
119527
119708
  usersRouter.post("/xp/add", async (c2) => {
@@ -119536,11 +119717,10 @@ usersRouter.post("/xp/add", async (c2) => {
119536
119717
  return c2.json(result);
119537
119718
  } catch (error2) {
119538
119719
  if (error2 instanceof ApiError) {
119539
- return c2.json({ error: error2.message }, error2.statusCode);
119720
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119540
119721
  }
119541
119722
  console.error("Error in addXPFromRequest:", error2);
119542
- const message = error2 instanceof Error ? error2.message : "Internal server error";
119543
- return c2.json({ error: message }, 500);
119723
+ return c2.json(createUnknownErrorResponse(error2), 500);
119544
119724
  }
119545
119725
  });
119546
119726
  var healthRouter = new Hono2;
@@ -119704,11 +119884,10 @@ inventoryRouter.get("/", async (c2) => {
119704
119884
  return c2.json(inventory);
119705
119885
  } catch (error2) {
119706
119886
  if (error2 instanceof ApiError) {
119707
- return c2.json({ error: error2.message }, error2.statusCode);
119887
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119708
119888
  }
119709
119889
  console.error("Error in getUserInventory:", error2);
119710
- const message = error2 instanceof Error ? error2.message : "Internal server error";
119711
- return c2.json({ error: message }, 500);
119890
+ return c2.json(createUnknownErrorResponse(error2), 500);
119712
119891
  }
119713
119892
  });
119714
119893
  inventoryRouter.post("/add", async (c2) => {
@@ -119723,11 +119902,10 @@ inventoryRouter.post("/add", async (c2) => {
119723
119902
  return c2.json(result);
119724
119903
  } catch (error2) {
119725
119904
  if (error2 instanceof ApiError) {
119726
- return c2.json({ error: error2.message }, error2.statusCode);
119905
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119727
119906
  }
119728
119907
  console.error("Error in addInventoryItem:", error2);
119729
- const message = error2 instanceof Error ? error2.message : "Internal server error";
119730
- return c2.json({ error: message }, 500);
119908
+ return c2.json(createUnknownErrorResponse(error2), 500);
119731
119909
  }
119732
119910
  });
119733
119911
  inventoryRouter.post("/remove", async (c2) => {
@@ -119742,11 +119920,10 @@ inventoryRouter.post("/remove", async (c2) => {
119742
119920
  return c2.json(result);
119743
119921
  } catch (error2) {
119744
119922
  if (error2 instanceof ApiError) {
119745
- return c2.json({ error: error2.message }, error2.statusCode);
119923
+ return c2.json(createErrorResponse(error2), error2.statusCode);
119746
119924
  }
119747
119925
  console.error("Error in removeInventoryItem:", error2);
119748
- const message = error2 instanceof Error ? error2.message : "Internal server error";
119749
- return c2.json({ error: message }, 500);
119926
+ return c2.json(createUnknownErrorResponse(error2), 500);
119750
119927
  }
119751
119928
  });
119752
119929
  function assertError(err2) {
@@ -119961,9 +120138,6 @@ async function initiateUpload(ctx) {
119961
120138
  if (!user) {
119962
120139
  throw ApiError.unauthorized("Must be logged in to initiate uploads");
119963
120140
  }
119964
- if (!uploadDeps) {
119965
- throw ApiError.internal("Upload dependencies not configured");
119966
- }
119967
120141
  let inputData;
119968
120142
  try {
119969
120143
  const requestBody = await ctx.request.json();
@@ -119980,6 +120154,9 @@ async function initiateUpload(ctx) {
119980
120154
  throw ApiError.badRequest("Invalid JSON body");
119981
120155
  }
119982
120156
  const { fileName, gameId } = inputData;
120157
+ if (!uploadDeps) {
120158
+ throw ApiError.internal("Upload dependencies not configured");
120159
+ }
119983
120160
  try {
119984
120161
  const version3 = ulid();
119985
120162
  const tempS3Key = `uploads-temp/${gameId}/${version3}/${fileName}`;
@@ -120000,9 +120177,6 @@ async function* finalizeUpload(ctx) {
120000
120177
  if (!user) {
120001
120178
  throw ApiError.unauthorized("Must be logged in to finalize uploads");
120002
120179
  }
120003
- if (!uploadDeps) {
120004
- throw ApiError.internal("Upload dependencies not configured");
120005
- }
120006
120180
  let inputData;
120007
120181
  try {
120008
120182
  const requestBody = await ctx.request.json();
@@ -120019,6 +120193,9 @@ async function* finalizeUpload(ctx) {
120019
120193
  throw ApiError.badRequest("Invalid JSON body");
120020
120194
  }
120021
120195
  const { tempS3Key, gameId, version: version3, slug, metadata: metadata2 } = inputData;
120196
+ if (!uploadDeps) {
120197
+ throw ApiError.internal("Upload dependencies not configured");
120198
+ }
120022
120199
  try {
120023
120200
  yield {
120024
120201
  type: "status",
@@ -121358,6 +121535,13 @@ async function loadGameState(ctx) {
121358
121535
  }
121359
121536
  try {
121360
121537
  const db = getDatabase();
121538
+ const game = await db.query.games.findFirst({
121539
+ where: eq(games.id, gameId),
121540
+ columns: { id: true }
121541
+ });
121542
+ if (!game) {
121543
+ throw ApiError.notFound("Game not found");
121544
+ }
121361
121545
  const gameState = await db.query.gameStates.findFirst({
121362
121546
  where: and(eq(gameStates.userId, user.id), eq(gameStates.gameId, gameId)),
121363
121547
  columns: { data: true }
@@ -121389,20 +121573,27 @@ async function saveGameState(ctx) {
121389
121573
  if (!gameId) {
121390
121574
  throw ApiError.badRequest("Missing game ID");
121391
121575
  }
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
121576
  try {
121405
121577
  const db = getDatabase();
121578
+ const game = await db.query.games.findFirst({
121579
+ where: eq(games.id, gameId),
121580
+ columns: { id: true }
121581
+ });
121582
+ if (!game) {
121583
+ throw ApiError.notFound("Game not found");
121584
+ }
121585
+ let inputData;
121586
+ try {
121587
+ const requestBody = await ctx.request.json();
121588
+ if (typeof requestBody === "object" && requestBody !== null) {
121589
+ inputData = requestBody;
121590
+ } else {
121591
+ throw new Error("Request body must be an object");
121592
+ }
121593
+ } catch (error2) {
121594
+ log2.error("Failed to parse request body or invalid JSON:", { error: error2 });
121595
+ throw ApiError.badRequest("Invalid JSON body");
121596
+ }
121406
121597
  await db.insert(gameStates).values({
121407
121598
  userId: user.id,
121408
121599
  gameId,
@@ -121421,6 +121612,44 @@ async function saveGameState(ctx) {
121421
121612
  throw ApiError.internal("Internal server error", error2);
121422
121613
  }
121423
121614
  }
121615
+ function findMonorepoRootInternal(startDir) {
121616
+ let currentDir = startDir;
121617
+ while (true) {
121618
+ const packageJsonPath = path22.join(currentDir, "package.json");
121619
+ if (fs32.existsSync(packageJsonPath)) {
121620
+ try {
121621
+ const packageJsonContent = fs32.readFileSync(packageJsonPath, "utf-8");
121622
+ const packageJson = JSON.parse(packageJsonContent);
121623
+ if (packageJson && typeof packageJson === "object" && "workspaces" in packageJson) {
121624
+ return currentDir;
121625
+ }
121626
+ } catch (parseError) {
121627
+ log2.warn(`[utils/paths] Error parsing ${packageJsonPath}:`, {
121628
+ error: parseError
121629
+ });
121630
+ }
121631
+ }
121632
+ const parentDir = path22.dirname(currentDir);
121633
+ if (parentDir === currentDir) {
121634
+ throw new Error("Could not find monorepo root (package.json with workspaces) starting from " + startDir);
121635
+ }
121636
+ currentDir = parentDir;
121637
+ }
121638
+ }
121639
+ var determinedRoot;
121640
+ try {
121641
+ determinedRoot = findMonorepoRootInternal(process.cwd());
121642
+ } catch (error2) {
121643
+ determinedRoot = process.cwd();
121644
+ log2.warn("[utils/paths] Could not locate monorepo root via workspace package.json scan. Falling back to process.cwd() (", { root: determinedRoot, error: error2 });
121645
+ }
121646
+ 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}$/;
121647
+ function isValidUUID(value) {
121648
+ if (!value || typeof value !== "string") {
121649
+ return false;
121650
+ }
121651
+ return UUID_REGEX.test(value);
121652
+ }
121424
121653
  async function validateGameOwnership(user, gameId) {
121425
121654
  if (user.role === "admin") {
121426
121655
  return;
@@ -121492,6 +121721,9 @@ async function getItemById(ctx) {
121492
121721
  if (!itemId) {
121493
121722
  throw ApiError.badRequest("Missing item ID");
121494
121723
  }
121724
+ if (!isValidUUID(itemId)) {
121725
+ throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
121726
+ }
121495
121727
  try {
121496
121728
  const db = getDatabase();
121497
121729
  const item = await db.query.items.findFirst({
@@ -121563,6 +121795,9 @@ async function updateItem(ctx) {
121563
121795
  if (!itemId) {
121564
121796
  throw ApiError.badRequest("Missing item ID");
121565
121797
  }
121798
+ if (!isValidUUID(itemId)) {
121799
+ throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
121800
+ }
121566
121801
  let inputData;
121567
121802
  try {
121568
121803
  const requestBody = await ctx.request.json();
@@ -121589,6 +121824,8 @@ async function updateItem(ctx) {
121589
121824
  }
121590
121825
  return updatedItem;
121591
121826
  } catch (error2) {
121827
+ if (error2 instanceof ApiError)
121828
+ throw error2;
121592
121829
  if (error2 instanceof Error) {
121593
121830
  if (error2.message.includes("duplicate key value violates unique constraint")) {
121594
121831
  throw ApiError.conflict("An item with this slug already exists within the same scope (platform or game)");
@@ -121611,6 +121848,9 @@ async function deleteItem(ctx) {
121611
121848
  if (!itemId) {
121612
121849
  throw ApiError.badRequest("Missing item ID");
121613
121850
  }
121851
+ if (!isValidUUID(itemId)) {
121852
+ throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
121853
+ }
121614
121854
  try {
121615
121855
  const db = getDatabase();
121616
121856
  const result = await db.delete(items).where(eq(items.id, itemId)).returning({ id: items.id });
@@ -121641,6 +121881,9 @@ async function resolveItem(ctx) {
121641
121881
  if (!slug) {
121642
121882
  throw ApiError.badRequest("Missing slug parameter");
121643
121883
  }
121884
+ if (gameId && !isValidUUID(gameId)) {
121885
+ throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
121886
+ }
121644
121887
  try {
121645
121888
  const db = getDatabase();
121646
121889
  if (gameId) {
@@ -121679,6 +121922,9 @@ async function listGameItems(ctx) {
121679
121922
  if (!gameId) {
121680
121923
  throw ApiError.badRequest("Missing game ID");
121681
121924
  }
121925
+ if (!isValidUUID(gameId)) {
121926
+ throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
121927
+ }
121682
121928
  try {
121683
121929
  const db = getDatabase();
121684
121930
  const gameItems = await db.query.items.findMany({
@@ -121706,6 +121952,9 @@ async function createGameItem(ctx) {
121706
121952
  if (!gameId) {
121707
121953
  throw ApiError.badRequest("Missing game ID");
121708
121954
  }
121955
+ if (!isValidUUID(gameId)) {
121956
+ throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
121957
+ }
121709
121958
  await validateGameOwnership(user, gameId);
121710
121959
  let inputData;
121711
121960
  try {
@@ -121758,6 +122007,12 @@ async function updateGameItem(ctx) {
121758
122007
  if (!gameId || !itemId) {
121759
122008
  throw ApiError.badRequest("Missing game ID or item ID");
121760
122009
  }
122010
+ if (!isValidUUID(gameId)) {
122011
+ throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
122012
+ }
122013
+ if (!isValidUUID(itemId)) {
122014
+ throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
122015
+ }
121761
122016
  await validateGameOwnership(user, gameId);
121762
122017
  let inputData;
121763
122018
  try {
@@ -121791,6 +122046,9 @@ async function updateGameItem(ctx) {
121791
122046
  }
121792
122047
  return updatedItem;
121793
122048
  } catch (error2) {
122049
+ if (error2 instanceof ApiError) {
122050
+ throw error2;
122051
+ }
121794
122052
  if (error2 instanceof Error) {
121795
122053
  if (error2.message.includes("duplicate key value violates unique constraint")) {
121796
122054
  throw ApiError.conflict("An item with this slug already exists for this game");
@@ -121815,6 +122073,12 @@ async function deleteGameItem(ctx) {
121815
122073
  if (!gameId || !itemId) {
121816
122074
  throw ApiError.badRequest("Missing game ID or item ID");
121817
122075
  }
122076
+ if (!isValidUUID(gameId)) {
122077
+ throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
122078
+ }
122079
+ if (!isValidUUID(itemId)) {
122080
+ throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
122081
+ }
121818
122082
  await validateGameOwnership(user, gameId);
121819
122083
  try {
121820
122084
  const db = getDatabase();
@@ -121830,6 +122094,288 @@ async function deleteGameItem(ctx) {
121830
122094
  throw ApiError.internal("Internal server error", error2);
121831
122095
  }
121832
122096
  }
122097
+ async function createGameItemShopListing(ctx) {
122098
+ const user = ctx.user;
122099
+ const gameId = ctx.params.gameId;
122100
+ const itemId = ctx.params.itemId;
122101
+ log2.debug("[API] creating game item shop listing", {
122102
+ userId: user?.id || "anonymous",
122103
+ gameId,
122104
+ itemId
122105
+ });
122106
+ if (!user) {
122107
+ throw ApiError.unauthorized("Must be logged in to create shop listings");
122108
+ }
122109
+ if (!gameId || !itemId) {
122110
+ throw ApiError.badRequest("Missing game ID or item ID");
122111
+ }
122112
+ if (!isValidUUID(gameId)) {
122113
+ throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
122114
+ }
122115
+ if (!isValidUUID(itemId)) {
122116
+ throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
122117
+ }
122118
+ await validateGameOwnershipAndItemAccess(user.id, gameId, itemId);
122119
+ let inputData;
122120
+ try {
122121
+ const requestBody = await ctx.request.json();
122122
+ const validationResult = InsertShopListingSchema.omit({
122123
+ itemId: true
122124
+ }).safeParse(requestBody);
122125
+ if (!validationResult.success) {
122126
+ throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
122127
+ }
122128
+ inputData = validationResult.data;
122129
+ } catch (error2) {
122130
+ if (error2 instanceof ApiError) {
122131
+ throw error2;
122132
+ }
122133
+ log2.error("Failed to parse request body", { error: error2 });
122134
+ throw ApiError.badRequest("Invalid JSON body");
122135
+ }
122136
+ try {
122137
+ const db = getDatabase();
122138
+ const currency = await db.query.currencies.findFirst({
122139
+ where: eq(currencies.itemId, inputData.currencyId)
122140
+ });
122141
+ if (!currency) {
122142
+ throw ApiError.badRequest("Invalid currency: currency not found for the provided item ID");
122143
+ }
122144
+ const [newListing] = await db.insert(shopListings).values({
122145
+ ...inputData,
122146
+ itemId,
122147
+ currencyId: currency.id
122148
+ }).returning();
122149
+ if (!newListing) {
122150
+ throw ApiError.internal("Failed to create shop listing in database");
122151
+ }
122152
+ return newListing;
122153
+ } catch (error2) {
122154
+ if (error2 instanceof ApiError)
122155
+ throw error2;
122156
+ if (error2 instanceof Error) {
122157
+ if (error2.message.includes("duplicate key value violates unique constraint")) {
122158
+ throw ApiError.conflict("A shop listing already exists for this item with the specified currency");
122159
+ }
122160
+ if (error2.message.includes("violates foreign key constraint")) {
122161
+ if (error2.message.includes("shop_listings_currency_id_fkey")) {
122162
+ throw ApiError.badRequest("Invalid currency ID");
122163
+ }
122164
+ }
122165
+ }
122166
+ log2.error("Error creating shop listing", { error: error2 });
122167
+ throw ApiError.internal("Internal server error", error2);
122168
+ }
122169
+ }
122170
+ async function getGameItemShopListing(ctx) {
122171
+ const user = ctx.user;
122172
+ const gameId = ctx.params.gameId;
122173
+ const itemId = ctx.params.itemId;
122174
+ log2.debug("[API] fetching game item shop listing", {
122175
+ userId: user?.id || "anonymous",
122176
+ gameId,
122177
+ itemId
122178
+ });
122179
+ if (!user) {
122180
+ throw ApiError.unauthorized("Must be logged in to view shop listings");
122181
+ }
122182
+ if (!gameId || !itemId) {
122183
+ throw ApiError.badRequest("Missing game ID or item ID");
122184
+ }
122185
+ if (!isValidUUID(gameId)) {
122186
+ throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
122187
+ }
122188
+ if (!isValidUUID(itemId)) {
122189
+ throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
122190
+ }
122191
+ await validateGameOwnershipAndItemAccess(user.id, gameId, itemId);
122192
+ try {
122193
+ const db = getDatabase();
122194
+ const shopListing = await db.query.shopListings.findFirst({
122195
+ where: eq(shopListings.itemId, itemId)
122196
+ });
122197
+ return shopListing || null;
122198
+ } catch (error2) {
122199
+ log2.error(`Error fetching shop listing for item ${itemId}:`, { error: error2 });
122200
+ throw ApiError.internal("Internal server error", error2);
122201
+ }
122202
+ }
122203
+ async function updateGameItemShopListing(ctx) {
122204
+ const user = ctx.user;
122205
+ const gameId = ctx.params.gameId;
122206
+ const itemId = ctx.params.itemId;
122207
+ log2.debug("[API] updating game item shop listing", {
122208
+ userId: user?.id || "anonymous",
122209
+ gameId,
122210
+ itemId
122211
+ });
122212
+ if (!user) {
122213
+ throw ApiError.unauthorized("Must be logged in to update shop listings");
122214
+ }
122215
+ if (!gameId || !itemId) {
122216
+ throw ApiError.badRequest("Missing game ID or item ID");
122217
+ }
122218
+ if (!isValidUUID(gameId)) {
122219
+ throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
122220
+ }
122221
+ if (!isValidUUID(itemId)) {
122222
+ throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
122223
+ }
122224
+ await validateGameOwnershipAndItemAccess(user.id, gameId, itemId);
122225
+ let inputData;
122226
+ try {
122227
+ const requestBody = await ctx.request.json();
122228
+ const validationResult = UpdateShopListingSchema.safeParse(requestBody);
122229
+ if (!validationResult.success) {
122230
+ throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
122231
+ }
122232
+ inputData = validationResult.data;
122233
+ } catch (error2) {
122234
+ if (error2 instanceof ApiError) {
122235
+ throw error2;
122236
+ }
122237
+ log2.error("Failed to parse request body", { error: error2 });
122238
+ throw ApiError.badRequest("Invalid JSON body");
122239
+ }
122240
+ try {
122241
+ const db = getDatabase();
122242
+ let resolvedCurrencyId = inputData.currencyId;
122243
+ if (inputData.currencyId) {
122244
+ const currency = await db.query.currencies.findFirst({
122245
+ where: eq(currencies.itemId, inputData.currencyId)
122246
+ });
122247
+ if (!currency) {
122248
+ throw ApiError.badRequest("Invalid currency: currency not found for the provided item ID");
122249
+ }
122250
+ resolvedCurrencyId = currency.id;
122251
+ }
122252
+ const [updatedListing] = await db.update(shopListings).set({
122253
+ ...inputData,
122254
+ currencyId: resolvedCurrencyId,
122255
+ updatedAt: new Date
122256
+ }).where(eq(shopListings.itemId, itemId)).returning();
122257
+ if (!updatedListing) {
122258
+ throw ApiError.notFound("Shop listing not found for this item");
122259
+ }
122260
+ return updatedListing;
122261
+ } catch (error2) {
122262
+ if (error2 instanceof ApiError)
122263
+ throw error2;
122264
+ if (error2 instanceof Error) {
122265
+ if (error2.message.includes("duplicate key value violates unique constraint")) {
122266
+ throw ApiError.conflict("A shop listing already exists for this item with the specified currency");
122267
+ }
122268
+ if (error2.message.includes("violates foreign key constraint")) {
122269
+ if (error2.message.includes("shop_listings_currency_id_fkey")) {
122270
+ throw ApiError.badRequest("Invalid currency ID");
122271
+ }
122272
+ }
122273
+ }
122274
+ log2.error(`Error updating shop listing for item ${itemId}:`, { error: error2 });
122275
+ throw ApiError.internal("Internal server error", error2);
122276
+ }
122277
+ }
122278
+ async function deleteGameItemShopListing(ctx) {
122279
+ const user = ctx.user;
122280
+ const gameId = ctx.params.gameId;
122281
+ const itemId = ctx.params.itemId;
122282
+ log2.debug("[API] deleting game item shop listing", {
122283
+ userId: user?.id || "anonymous",
122284
+ gameId,
122285
+ itemId
122286
+ });
122287
+ if (!user) {
122288
+ throw ApiError.unauthorized("Must be logged in to delete shop listings");
122289
+ }
122290
+ if (!gameId || !itemId) {
122291
+ throw ApiError.badRequest("Missing game ID or item ID");
122292
+ }
122293
+ if (!isValidUUID(gameId)) {
122294
+ throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
122295
+ }
122296
+ if (!isValidUUID(itemId)) {
122297
+ throw ApiError.unprocessableEntity("itemId must be a valid UUID format");
122298
+ }
122299
+ await validateGameOwnershipAndItemAccess(user.id, gameId, itemId);
122300
+ try {
122301
+ const db = getDatabase();
122302
+ const result = await db.delete(shopListings).where(eq(shopListings.itemId, itemId)).returning();
122303
+ if (result.length === 0) {
122304
+ throw ApiError.notFound("Shop listing not found for this item");
122305
+ }
122306
+ log2.info(`Shop listing deleted for item ${itemId} by user ${user.id}`);
122307
+ } catch (error2) {
122308
+ if (error2 instanceof ApiError) {
122309
+ throw error2;
122310
+ }
122311
+ log2.error(`Error deleting shop listing for item ${itemId}:`, { error: error2 });
122312
+ throw ApiError.internal("Internal server error", error2);
122313
+ }
122314
+ }
122315
+ async function listGameShopListings(ctx) {
122316
+ const user = ctx.user;
122317
+ const gameId = ctx.params.gameId;
122318
+ log2.debug("[API] listing game shop listings", {
122319
+ userId: user?.id || "anonymous",
122320
+ gameId
122321
+ });
122322
+ if (!user) {
122323
+ throw ApiError.unauthorized("Must be logged in to view shop listings");
122324
+ }
122325
+ if (!gameId) {
122326
+ throw ApiError.badRequest("Missing game ID");
122327
+ }
122328
+ if (!isValidUUID(gameId)) {
122329
+ throw ApiError.unprocessableEntity("gameId must be a valid UUID format");
122330
+ }
122331
+ await validateGameOwnership(user, gameId);
122332
+ try {
122333
+ const db = getDatabase();
122334
+ const gameItems = await db.query.items.findMany({
122335
+ where: eq(items.gameId, gameId)
122336
+ });
122337
+ if (gameItems.length === 0) {
122338
+ return [];
122339
+ }
122340
+ const itemIds = gameItems.map((item) => item.id);
122341
+ const gameShopListings = await db.query.shopListings.findMany({
122342
+ where: inArray(shopListings.itemId, itemIds),
122343
+ with: {
122344
+ item: true
122345
+ }
122346
+ });
122347
+ return gameShopListings;
122348
+ } catch (error2) {
122349
+ if (error2 instanceof ApiError) {
122350
+ throw error2;
122351
+ }
122352
+ log2.error(`Error fetching shop listings for game ${gameId}:`, { error: error2 });
122353
+ throw ApiError.internal("Internal server error", error2);
122354
+ }
122355
+ }
122356
+ async function validateGameOwnershipAndItemAccess(userId, gameId, itemId) {
122357
+ try {
122358
+ const db = getDatabase();
122359
+ const game = await db.query.games.findFirst({
122360
+ where: and(eq(games.id, gameId), eq(games.developerId, userId))
122361
+ });
122362
+ if (!game) {
122363
+ throw ApiError.forbidden("You do not own this game");
122364
+ }
122365
+ const item = await db.query.items.findFirst({
122366
+ where: and(eq(items.id, itemId), eq(items.gameId, gameId))
122367
+ });
122368
+ if (!item) {
122369
+ throw ApiError.notFound("Item not found in this game");
122370
+ }
122371
+ } catch (error2) {
122372
+ if (error2 instanceof ApiError) {
122373
+ throw error2;
122374
+ }
122375
+ log2.error(`Error validating game ownership and item access:`, { error: error2 });
122376
+ throw ApiError.internal("Internal server error", error2);
122377
+ }
122378
+ }
121833
122379
 
121834
122380
  class BigEndian {
121835
122381
  uint8(data2, offset) {
@@ -122650,11 +123196,10 @@ gamesRouter.get("/", async (c2) => {
122650
123196
  return c2.json(result);
122651
123197
  } catch (error2) {
122652
123198
  if (error2 instanceof ApiError) {
122653
- return c2.json({ error: error2.message }, error2.statusCode);
123199
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122654
123200
  }
122655
123201
  console.error("Error in listGames:", error2);
122656
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122657
- return c2.json({ error: message2 }, 500);
123202
+ return c2.json(createUnknownErrorResponse(error2), 500);
122658
123203
  }
122659
123204
  });
122660
123205
  gamesRouter.get("/:slug", async (c2) => {
@@ -122671,11 +123216,10 @@ gamesRouter.get("/:slug", async (c2) => {
122671
123216
  return c2.json(result);
122672
123217
  } catch (error2) {
122673
123218
  if (error2 instanceof ApiError) {
122674
- return c2.json({ error: error2.message }, error2.statusCode);
123219
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122675
123220
  }
122676
123221
  console.error("Error in getGame:", error2);
122677
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122678
- return c2.json({ error: message2 }, 500);
123222
+ return c2.json(createUnknownErrorResponse(error2), 500);
122679
123223
  }
122680
123224
  });
122681
123225
  gamesRouter.put("/:slug", async (c2) => {
@@ -122691,11 +123235,10 @@ gamesRouter.put("/:slug", async (c2) => {
122691
123235
  return c2.json(result);
122692
123236
  } catch (error2) {
122693
123237
  if (error2 instanceof ApiError) {
122694
- return c2.json({ error: error2.message }, error2.statusCode);
123238
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122695
123239
  }
122696
123240
  console.error("Error in upsertGameBySlug:", error2);
122697
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122698
- return c2.json({ error: message2 }, 500);
123241
+ return c2.json(createUnknownErrorResponse(error2), 500);
122699
123242
  }
122700
123243
  });
122701
123244
  gamesRouter.patch("/:gameId", async (c2) => {
@@ -122711,11 +123254,10 @@ gamesRouter.patch("/:gameId", async (c2) => {
122711
123254
  return c2.json(result);
122712
123255
  } catch (error2) {
122713
123256
  if (error2 instanceof ApiError) {
122714
- return c2.json({ error: error2.message }, error2.statusCode);
123257
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122715
123258
  }
122716
123259
  console.error("Error in updateGame:", error2);
122717
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122718
- return c2.json({ error: message2 }, 500);
123260
+ return c2.json(createUnknownErrorResponse(error2), 500);
122719
123261
  }
122720
123262
  });
122721
123263
  gamesRouter.delete("/:gameId", async (c2) => {
@@ -122731,11 +123273,10 @@ gamesRouter.delete("/:gameId", async (c2) => {
122731
123273
  return c2.body(null, 204);
122732
123274
  } catch (error2) {
122733
123275
  if (error2 instanceof ApiError) {
122734
- return c2.json({ error: error2.message }, error2.statusCode);
123276
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122735
123277
  }
122736
123278
  console.error("Error in deleteGame:", error2);
122737
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122738
- return c2.json({ error: message2 }, 500);
123279
+ return c2.json(createUnknownErrorResponse(error2), 500);
122739
123280
  }
122740
123281
  });
122741
123282
  gamesRouter.post("/:gameId/sessions", async (c2) => {
@@ -122751,11 +123292,10 @@ gamesRouter.post("/:gameId/sessions", async (c2) => {
122751
123292
  return c2.json(result);
122752
123293
  } catch (error2) {
122753
123294
  if (error2 instanceof ApiError) {
122754
- return c2.json({ error: error2.message }, error2.statusCode);
123295
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122755
123296
  }
122756
123297
  console.error("Error in startGameSession:", error2);
122757
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122758
- return c2.json({ error: message2 }, 500);
123298
+ return c2.json(createUnknownErrorResponse(error2), 500);
122759
123299
  }
122760
123300
  });
122761
123301
  gamesRouter.post("/:gameId/sessions/:sessionId/end", async (c2) => {
@@ -122772,14 +123312,13 @@ gamesRouter.post("/:gameId/sessions/:sessionId/end", async (c2) => {
122772
123312
  return c2.json(result);
122773
123313
  } catch (error2) {
122774
123314
  if (error2 instanceof ApiError) {
122775
- return c2.json({ error: error2.message }, error2.statusCode);
123315
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122776
123316
  }
122777
123317
  console.error("Error in endGameSession:", error2);
122778
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122779
- return c2.json({ error: message2 }, 500);
123318
+ return c2.json(createUnknownErrorResponse(error2), 500);
122780
123319
  }
122781
123320
  });
122782
- gamesRouter.post("/:gameId/sessions/token", async (c2) => {
123321
+ gamesRouter.post("/:gameId/token", async (c2) => {
122783
123322
  const gameId = c2.req.param("gameId");
122784
123323
  const ctx = {
122785
123324
  user: c2.get("user"),
@@ -122792,14 +123331,13 @@ gamesRouter.post("/:gameId/sessions/token", async (c2) => {
122792
123331
  return c2.json(result);
122793
123332
  } catch (error2) {
122794
123333
  if (error2 instanceof ApiError) {
122795
- return c2.json({ error: error2.message }, error2.statusCode);
123334
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122796
123335
  }
122797
123336
  console.error("Error in mintGameToken:", error2);
122798
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122799
- return c2.json({ error: message2 }, 500);
123337
+ return c2.json(createUnknownErrorResponse(error2), 500);
122800
123338
  }
122801
123339
  });
122802
- gamesRouter.get("/:gameId/sessions/state", async (c2) => {
123340
+ gamesRouter.get("/:gameId/state", async (c2) => {
122803
123341
  const gameId = c2.req.param("gameId");
122804
123342
  const ctx = {
122805
123343
  user: c2.get("user"),
@@ -122812,14 +123350,13 @@ gamesRouter.get("/:gameId/sessions/state", async (c2) => {
122812
123350
  return c2.json(result);
122813
123351
  } catch (error2) {
122814
123352
  if (error2 instanceof ApiError) {
122815
- return c2.json({ error: error2.message }, error2.statusCode);
123353
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122816
123354
  }
122817
123355
  console.error("Error in loadGameState:", error2);
122818
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122819
- return c2.json({ error: message2 }, 500);
123356
+ return c2.json(createUnknownErrorResponse(error2), 500);
122820
123357
  }
122821
123358
  });
122822
- gamesRouter.post("/:gameId/sessions/state", async (c2) => {
123359
+ gamesRouter.post("/:gameId/state", async (c2) => {
122823
123360
  const gameId = c2.req.param("gameId");
122824
123361
  const ctx = {
122825
123362
  user: c2.get("user"),
@@ -122829,14 +123366,13 @@ gamesRouter.post("/:gameId/sessions/state", async (c2) => {
122829
123366
  };
122830
123367
  try {
122831
123368
  await saveGameState(ctx);
122832
- return c2.json({ success: true });
123369
+ return c2.body(null, 204);
122833
123370
  } catch (error2) {
122834
123371
  if (error2 instanceof ApiError) {
122835
- return c2.json({ error: error2.message }, error2.statusCode);
123372
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122836
123373
  }
122837
123374
  console.error("Error in saveGameState:", error2);
122838
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122839
- return c2.json({ error: message2 }, 500);
123375
+ return c2.json(createUnknownErrorResponse(error2), 500);
122840
123376
  }
122841
123377
  });
122842
123378
  gamesRouter.post("/uploads/initiate", async (c2) => {
@@ -122851,11 +123387,10 @@ gamesRouter.post("/uploads/initiate", async (c2) => {
122851
123387
  return c2.json(result);
122852
123388
  } catch (error2) {
122853
123389
  if (error2 instanceof ApiError) {
122854
- return c2.json({ error: error2.message }, error2.statusCode);
123390
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122855
123391
  }
122856
123392
  console.error("Error in initiateUpload:", error2);
122857
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122858
- return c2.json({ error: message2 }, 500);
123393
+ return c2.json(createUnknownErrorResponse(error2), 500);
122859
123394
  }
122860
123395
  });
122861
123396
  gamesRouter.post("/uploads/finalize", async (c2) => {
@@ -122876,12 +123411,12 @@ gamesRouter.post("/uploads/finalize", async (c2) => {
122876
123411
  controller.close();
122877
123412
  } catch (error2) {
122878
123413
  if (error2 instanceof ApiError) {
122879
- controller.enqueue(formatSSEData("error", { message: error2.message }));
123414
+ const errorResponse = createErrorResponse(error2);
123415
+ controller.enqueue(formatSSEData("error", errorResponse.error));
122880
123416
  } else {
122881
123417
  console.error("Error in finalize upload stream:", error2);
122882
- controller.enqueue(formatSSEData("error", {
122883
- message: "Internal server error"
122884
- }));
123418
+ const errorResponse = createUnknownErrorResponse(error2);
123419
+ controller.enqueue(formatSSEData("error", errorResponse.error));
122885
123420
  }
122886
123421
  controller.close();
122887
123422
  }
@@ -122896,11 +123431,10 @@ gamesRouter.post("/uploads/finalize", async (c2) => {
122896
123431
  });
122897
123432
  } catch (error2) {
122898
123433
  if (error2 instanceof ApiError) {
122899
- return c2.json({ error: error2.message }, error2.statusCode);
123434
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122900
123435
  }
122901
123436
  console.error("Error in finalizeUpload:", error2);
122902
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122903
- return c2.json({ error: message2 }, 500);
123437
+ return c2.json(createUnknownErrorResponse(error2), 500);
122904
123438
  }
122905
123439
  });
122906
123440
  gamesRouter.get("/:gameId/items", async (c2) => {
@@ -122916,11 +123450,10 @@ gamesRouter.get("/:gameId/items", async (c2) => {
122916
123450
  return c2.json(result);
122917
123451
  } catch (error2) {
122918
123452
  if (error2 instanceof ApiError) {
122919
- return c2.json({ error: error2.message }, error2.statusCode);
123453
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122920
123454
  }
122921
123455
  console.error("Error in listGameItems:", error2);
122922
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122923
- return c2.json({ error: message2 }, 500);
123456
+ return c2.json(createUnknownErrorResponse(error2), 500);
122924
123457
  }
122925
123458
  });
122926
123459
  gamesRouter.post("/:gameId/items", async (c2) => {
@@ -122936,11 +123469,10 @@ gamesRouter.post("/:gameId/items", async (c2) => {
122936
123469
  return c2.json(result, 201);
122937
123470
  } catch (error2) {
122938
123471
  if (error2 instanceof ApiError) {
122939
- return c2.json({ error: error2.message }, error2.statusCode);
123472
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122940
123473
  }
122941
123474
  console.error("Error in createGameItem:", error2);
122942
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122943
- return c2.json({ error: message2 }, 500);
123475
+ return c2.json(createUnknownErrorResponse(error2), 500);
122944
123476
  }
122945
123477
  });
122946
123478
  gamesRouter.patch("/:gameId/items/:itemId", async (c2) => {
@@ -122957,11 +123489,10 @@ gamesRouter.patch("/:gameId/items/:itemId", async (c2) => {
122957
123489
  return c2.json(result);
122958
123490
  } catch (error2) {
122959
123491
  if (error2 instanceof ApiError) {
122960
- return c2.json({ error: error2.message }, error2.statusCode);
123492
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122961
123493
  }
122962
123494
  console.error("Error in updateGameItem:", error2);
122963
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122964
- return c2.json({ error: message2 }, 500);
123495
+ return c2.json(createUnknownErrorResponse(error2), 500);
122965
123496
  }
122966
123497
  });
122967
123498
  gamesRouter.delete("/:gameId/items/:itemId", async (c2) => {
@@ -122978,11 +123509,109 @@ gamesRouter.delete("/:gameId/items/:itemId", async (c2) => {
122978
123509
  return c2.body(null, 204);
122979
123510
  } catch (error2) {
122980
123511
  if (error2 instanceof ApiError) {
122981
- return c2.json({ error: error2.message }, error2.statusCode);
123512
+ return c2.json(createErrorResponse(error2), error2.statusCode);
122982
123513
  }
122983
123514
  console.error("Error in deleteGameItem:", error2);
122984
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
122985
- return c2.json({ error: message2 }, 500);
123515
+ return c2.json(createUnknownErrorResponse(error2), 500);
123516
+ }
123517
+ });
123518
+ gamesRouter.get("/:gameId/shop-listings", async (c2) => {
123519
+ const gameId = c2.req.param("gameId");
123520
+ const ctx = {
123521
+ user: c2.get("user"),
123522
+ params: { gameId },
123523
+ url: new URL(c2.req.url),
123524
+ request: c2.req.raw
123525
+ };
123526
+ try {
123527
+ const result = await listGameShopListings(ctx);
123528
+ return c2.json(result);
123529
+ } catch (error2) {
123530
+ if (error2 instanceof ApiError) {
123531
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123532
+ }
123533
+ console.error("Error in listGameShopListings:", error2);
123534
+ return c2.json(createUnknownErrorResponse(error2), 500);
123535
+ }
123536
+ });
123537
+ gamesRouter.post("/:gameId/items/:itemId/shop-listing", async (c2) => {
123538
+ const gameId = c2.req.param("gameId");
123539
+ const itemId = c2.req.param("itemId");
123540
+ const ctx = {
123541
+ user: c2.get("user"),
123542
+ params: { gameId, itemId },
123543
+ url: new URL(c2.req.url),
123544
+ request: c2.req.raw
123545
+ };
123546
+ try {
123547
+ const result = await createGameItemShopListing(ctx);
123548
+ return c2.json(result, 201);
123549
+ } catch (error2) {
123550
+ if (error2 instanceof ApiError) {
123551
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123552
+ }
123553
+ console.error("Error in createGameItemShopListing:", error2);
123554
+ return c2.json(createUnknownErrorResponse(error2), 500);
123555
+ }
123556
+ });
123557
+ gamesRouter.get("/:gameId/items/:itemId/shop-listing", async (c2) => {
123558
+ const gameId = c2.req.param("gameId");
123559
+ const itemId = c2.req.param("itemId");
123560
+ const ctx = {
123561
+ user: c2.get("user"),
123562
+ params: { gameId, itemId },
123563
+ url: new URL(c2.req.url),
123564
+ request: c2.req.raw
123565
+ };
123566
+ try {
123567
+ const result = await getGameItemShopListing(ctx);
123568
+ return c2.json(result);
123569
+ } catch (error2) {
123570
+ if (error2 instanceof ApiError) {
123571
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123572
+ }
123573
+ console.error("Error in getGameItemShopListing:", error2);
123574
+ return c2.json(createUnknownErrorResponse(error2), 500);
123575
+ }
123576
+ });
123577
+ gamesRouter.patch("/:gameId/items/:itemId/shop-listing", async (c2) => {
123578
+ const gameId = c2.req.param("gameId");
123579
+ const itemId = c2.req.param("itemId");
123580
+ const ctx = {
123581
+ user: c2.get("user"),
123582
+ params: { gameId, itemId },
123583
+ url: new URL(c2.req.url),
123584
+ request: c2.req.raw
123585
+ };
123586
+ try {
123587
+ const result = await updateGameItemShopListing(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 updateGameItemShopListing:", error2);
123594
+ return c2.json(createUnknownErrorResponse(error2), 500);
123595
+ }
123596
+ });
123597
+ gamesRouter.delete("/: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
+ await deleteGameItemShopListing(ctx);
123608
+ return c2.body(null, 204);
123609
+ } catch (error2) {
123610
+ if (error2 instanceof ApiError) {
123611
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123612
+ }
123613
+ console.error("Error in deleteGameItemShopListing:", error2);
123614
+ return c2.json(createUnknownErrorResponse(error2), 500);
122986
123615
  }
122987
123616
  });
122988
123617
  var manifestRouter = new Hono2;
@@ -123006,15 +123635,15 @@ manifestRouter.get("/", async (c2) => {
123006
123635
  },
123007
123636
  {
123008
123637
  method: "POST",
123009
- url: `${baseUrl}/api/games/:gameId/sessions/token`
123638
+ url: `${baseUrl}/api/games/:gameId/token`
123010
123639
  },
123011
123640
  {
123012
123641
  method: "GET",
123013
- url: `${baseUrl}/api/games/:gameId/sessions/state`
123642
+ url: `${baseUrl}/api/games/:gameId/state`
123014
123643
  },
123015
123644
  {
123016
123645
  method: "POST",
123017
- url: `${baseUrl}/api/games/:gameId/sessions/state`
123646
+ url: `${baseUrl}/api/games/:gameId/state`
123018
123647
  }
123019
123648
  ],
123020
123649
  documentation: "https://docs.playcademy.dev"
@@ -123086,9 +123715,8 @@ async function getShopView(ctx) {
123086
123715
  currencies: shopCurrencies
123087
123716
  };
123088
123717
  } catch (error2) {
123089
- if (error2 instanceof ApiError) {
123718
+ if (error2 instanceof ApiError)
123090
123719
  throw error2;
123091
- }
123092
123720
  log2.error("Error fetching shop view data:", { error: error2 });
123093
123721
  throw ApiError.internal("Internal server error", error2);
123094
123722
  }
@@ -123106,11 +123734,10 @@ shopRouter.get("/view", async (c2) => {
123106
123734
  return c2.json(result);
123107
123735
  } catch (error2) {
123108
123736
  if (error2 instanceof ApiError) {
123109
- return c2.json({ error: error2.message }, error2.statusCode);
123737
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123110
123738
  }
123111
123739
  console.error("Error in getShopView:", error2);
123112
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123113
- return c2.json({ error: message2 }, 500);
123740
+ return c2.json(createUnknownErrorResponse(error2), 500);
123114
123741
  }
123115
123742
  });
123116
123743
  var itemsRouter = new Hono2;
@@ -123126,11 +123753,10 @@ itemsRouter.get("/resolve", async (c2) => {
123126
123753
  return c2.json(result);
123127
123754
  } catch (error2) {
123128
123755
  if (error2 instanceof ApiError) {
123129
- return c2.json({ error: error2.message }, error2.statusCode);
123756
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123130
123757
  }
123131
123758
  console.error("Error in resolveItem:", error2);
123132
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123133
- return c2.json({ error: message2 }, 500);
123759
+ return c2.json(createUnknownErrorResponse(error2), 500);
123134
123760
  }
123135
123761
  });
123136
123762
  itemsRouter.post("/", async (c2) => {
@@ -123145,11 +123771,10 @@ itemsRouter.post("/", async (c2) => {
123145
123771
  return c2.json(result, 201);
123146
123772
  } catch (error2) {
123147
123773
  if (error2 instanceof ApiError) {
123148
- return c2.json({ error: error2.message }, error2.statusCode);
123774
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123149
123775
  }
123150
123776
  console.error("Error in createItem:", error2);
123151
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123152
- return c2.json({ error: message2 }, 500);
123777
+ return c2.json(createUnknownErrorResponse(error2), 500);
123153
123778
  }
123154
123779
  });
123155
123780
  itemsRouter.get("/", async (c2) => {
@@ -123164,11 +123789,10 @@ itemsRouter.get("/", async (c2) => {
123164
123789
  return c2.json(result);
123165
123790
  } catch (error2) {
123166
123791
  if (error2 instanceof ApiError) {
123167
- return c2.json({ error: error2.message }, error2.statusCode);
123792
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123168
123793
  }
123169
123794
  console.error("Error in listItems:", error2);
123170
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123171
- return c2.json({ error: message2 }, 500);
123795
+ return c2.json(createUnknownErrorResponse(error2), 500);
123172
123796
  }
123173
123797
  });
123174
123798
  itemsRouter.get("/:itemId", async (c2) => {
@@ -123184,11 +123808,10 @@ itemsRouter.get("/:itemId", async (c2) => {
123184
123808
  return c2.json(result);
123185
123809
  } catch (error2) {
123186
123810
  if (error2 instanceof ApiError) {
123187
- return c2.json({ error: error2.message }, error2.statusCode);
123811
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123188
123812
  }
123189
123813
  console.error("Error in getItemById:", error2);
123190
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123191
- return c2.json({ error: message2 }, 500);
123814
+ return c2.json(createUnknownErrorResponse(error2), 500);
123192
123815
  }
123193
123816
  });
123194
123817
  itemsRouter.patch("/:itemId", async (c2) => {
@@ -123204,11 +123827,10 @@ itemsRouter.patch("/:itemId", async (c2) => {
123204
123827
  return c2.json(result);
123205
123828
  } catch (error2) {
123206
123829
  if (error2 instanceof ApiError) {
123207
- return c2.json({ error: error2.message }, error2.statusCode);
123830
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123208
123831
  }
123209
123832
  console.error("Error in updateItem:", error2);
123210
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123211
- return c2.json({ error: message2 }, 500);
123833
+ return c2.json(createUnknownErrorResponse(error2), 500);
123212
123834
  }
123213
123835
  });
123214
123836
  itemsRouter.delete("/:itemId", async (c2) => {
@@ -123224,11 +123846,10 @@ itemsRouter.delete("/:itemId", async (c2) => {
123224
123846
  return c2.body(null, 204);
123225
123847
  } catch (error2) {
123226
123848
  if (error2 instanceof ApiError) {
123227
- return c2.json({ error: error2.message }, error2.statusCode);
123849
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123228
123850
  }
123229
123851
  console.error("Error in deleteItem:", error2);
123230
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123231
- return c2.json({ error: message2 }, 500);
123852
+ return c2.json(createUnknownErrorResponse(error2), 500);
123232
123853
  }
123233
123854
  });
123234
123855
  async function listCurrencies(ctx) {
@@ -123242,9 +123863,8 @@ async function listCurrencies(ctx) {
123242
123863
  const allCurrencies = await db.query.currencies.findMany();
123243
123864
  return allCurrencies;
123244
123865
  } catch (error2) {
123245
- if (error2 instanceof ApiError) {
123866
+ if (error2 instanceof ApiError)
123246
123867
  throw error2;
123247
- }
123248
123868
  log2.error("Error fetching currencies:", { error: error2 });
123249
123869
  throw ApiError.internal("Internal server error", error2);
123250
123870
  }
@@ -123272,9 +123892,8 @@ async function getCurrencyById(ctx) {
123272
123892
  }
123273
123893
  return currency;
123274
123894
  } catch (error2) {
123275
- if (error2 instanceof ApiError) {
123895
+ if (error2 instanceof ApiError)
123276
123896
  throw error2;
123277
- }
123278
123897
  log2.error(`Error fetching currency ${currencyId}:`, { error: error2 });
123279
123898
  throw ApiError.internal("Internal server error", error2);
123280
123899
  }
@@ -123287,21 +123906,18 @@ async function createCurrency(ctx) {
123287
123906
  if (!user || user.role !== "admin") {
123288
123907
  throw ApiError.forbidden("Admin access required");
123289
123908
  }
123290
- let inputData;
123909
+ let requestBody;
123291
123910
  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 });
123911
+ requestBody = await ctx.request.json();
123912
+ } catch (jsonError) {
123913
+ log2.error("Failed to parse request body as JSON:", { error: jsonError });
123303
123914
  throw ApiError.badRequest("Invalid JSON body");
123304
123915
  }
123916
+ const validationResult = InsertCurrencySchema.safeParse(requestBody);
123917
+ if (!validationResult.success) {
123918
+ throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
123919
+ }
123920
+ const inputData = validationResult.data;
123305
123921
  try {
123306
123922
  const db = getDatabase();
123307
123923
  const [newCurrency] = await db.insert(currencies).values(inputData).returning();
@@ -123310,6 +123926,8 @@ async function createCurrency(ctx) {
123310
123926
  }
123311
123927
  return newCurrency;
123312
123928
  } catch (error2) {
123929
+ if (error2 instanceof ApiError)
123930
+ throw error2;
123313
123931
  if (error2 instanceof Error) {
123314
123932
  if (error2.message.includes("duplicate key value violates unique constraint") || error2.message.includes("UNIQUE constraint failed")) {
123315
123933
  if (error2.message.includes("currencies_slug_unique")) {
@@ -123335,21 +123953,18 @@ async function updateCurrency(ctx) {
123335
123953
  if (!currencyId) {
123336
123954
  throw ApiError.badRequest("Missing currency ID");
123337
123955
  }
123338
- let inputData;
123956
+ let requestBody;
123339
123957
  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 });
123958
+ requestBody = await ctx.request.json();
123959
+ } catch (jsonError) {
123960
+ log2.error("Failed to parse request body as JSON:", { error: jsonError });
123351
123961
  throw ApiError.badRequest("Invalid JSON body");
123352
123962
  }
123963
+ const validationResult = UpdateCurrencySchema.safeParse(requestBody);
123964
+ if (!validationResult.success) {
123965
+ throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
123966
+ }
123967
+ const inputData = validationResult.data;
123353
123968
  if (Object.keys(inputData).length === 0) {
123354
123969
  throw ApiError.badRequest("No update data provided");
123355
123970
  }
@@ -123361,6 +123976,8 @@ async function updateCurrency(ctx) {
123361
123976
  }
123362
123977
  return updatedCurrency;
123363
123978
  } catch (error2) {
123979
+ if (error2 instanceof ApiError)
123980
+ throw error2;
123364
123981
  if (error2 instanceof Error) {
123365
123982
  if (error2.message.includes("duplicate key value violates unique constraint") || error2.message.includes("UNIQUE constraint failed")) {
123366
123983
  if (error2.message.includes("currencies_slug_unique")) {
@@ -123393,9 +124010,8 @@ async function deleteCurrency(ctx) {
123393
124010
  throw ApiError.notFound("Currency not found for deletion");
123394
124011
  }
123395
124012
  } catch (error2) {
123396
- if (error2 instanceof ApiError) {
124013
+ if (error2 instanceof ApiError)
123397
124014
  throw error2;
123398
- }
123399
124015
  log2.error(`Error deleting currency ${currencyId}:`, { error: error2 });
123400
124016
  throw ApiError.internal("Internal server error", error2);
123401
124017
  }
@@ -123413,11 +124029,10 @@ currenciesRouter.post("/", async (c2) => {
123413
124029
  return c2.json(result, 201);
123414
124030
  } catch (error2) {
123415
124031
  if (error2 instanceof ApiError) {
123416
- return c2.json({ error: error2.message }, error2.statusCode);
124032
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123417
124033
  }
123418
124034
  console.error("Error in createCurrency:", error2);
123419
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123420
- return c2.json({ error: message2 }, 500);
124035
+ return c2.json(createUnknownErrorResponse(error2), 500);
123421
124036
  }
123422
124037
  });
123423
124038
  currenciesRouter.get("/", async (c2) => {
@@ -123432,11 +124047,10 @@ currenciesRouter.get("/", async (c2) => {
123432
124047
  return c2.json(result);
123433
124048
  } catch (error2) {
123434
124049
  if (error2 instanceof ApiError) {
123435
- return c2.json({ error: error2.message }, error2.statusCode);
124050
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123436
124051
  }
123437
124052
  console.error("Error in listCurrencies:", error2);
123438
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123439
- return c2.json({ error: message2 }, 500);
124053
+ return c2.json(createUnknownErrorResponse(error2), 500);
123440
124054
  }
123441
124055
  });
123442
124056
  currenciesRouter.get("/:currencyId", async (c2) => {
@@ -123452,11 +124066,10 @@ currenciesRouter.get("/:currencyId", async (c2) => {
123452
124066
  return c2.json(result);
123453
124067
  } catch (error2) {
123454
124068
  if (error2 instanceof ApiError) {
123455
- return c2.json({ error: error2.message }, error2.statusCode);
124069
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123456
124070
  }
123457
124071
  console.error("Error in getCurrencyById:", error2);
123458
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123459
- return c2.json({ error: message2 }, 500);
124072
+ return c2.json(createUnknownErrorResponse(error2), 500);
123460
124073
  }
123461
124074
  });
123462
124075
  currenciesRouter.patch("/:currencyId", async (c2) => {
@@ -123472,11 +124085,10 @@ currenciesRouter.patch("/:currencyId", async (c2) => {
123472
124085
  return c2.json(result);
123473
124086
  } catch (error2) {
123474
124087
  if (error2 instanceof ApiError) {
123475
- return c2.json({ error: error2.message }, error2.statusCode);
124088
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123476
124089
  }
123477
124090
  console.error("Error in updateCurrency:", error2);
123478
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123479
- return c2.json({ error: message2 }, 500);
124091
+ return c2.json(createUnknownErrorResponse(error2), 500);
123480
124092
  }
123481
124093
  });
123482
124094
  currenciesRouter.delete("/:currencyId", async (c2) => {
@@ -123492,11 +124104,10 @@ currenciesRouter.delete("/:currencyId", async (c2) => {
123492
124104
  return c2.body(null, 204);
123493
124105
  } catch (error2) {
123494
124106
  if (error2 instanceof ApiError) {
123495
- return c2.json({ error: error2.message }, error2.statusCode);
124107
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123496
124108
  }
123497
124109
  console.error("Error in deleteCurrency:", error2);
123498
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123499
- return c2.json({ error: message2 }, 500);
124110
+ return c2.json(createUnknownErrorResponse(error2), 500);
123500
124111
  }
123501
124112
  });
123502
124113
  async function getMapElements(ctx) {
@@ -123512,6 +124123,9 @@ async function getMapElements(ctx) {
123512
124123
  if (!mapId) {
123513
124124
  throw ApiError.badRequest("Missing required query parameter: mapId");
123514
124125
  }
124126
+ if (!isValidUUID(mapId)) {
124127
+ throw ApiError.unprocessableEntity("mapId must be a valid UUID format");
124128
+ }
123515
124129
  try {
123516
124130
  const db = getDatabase();
123517
124131
  const elements = await db.query.mapElements.findMany({
@@ -123527,9 +124141,8 @@ async function getMapElements(ctx) {
123527
124141
  });
123528
124142
  return elements;
123529
124143
  } catch (error2) {
123530
- if (error2 instanceof ApiError) {
124144
+ if (error2 instanceof ApiError)
123531
124145
  throw error2;
123532
- }
123533
124146
  log2.error("Error fetching map elements:", { error: error2 });
123534
124147
  throw ApiError.internal("Internal server error", error2);
123535
124148
  }
@@ -123557,9 +124170,8 @@ async function getMapByIdentifier(ctx) {
123557
124170
  }
123558
124171
  return mapDetails;
123559
124172
  } catch (error2) {
123560
- if (error2 instanceof ApiError) {
124173
+ if (error2 instanceof ApiError)
123561
124174
  throw error2;
123562
- }
123563
124175
  log2.error(`Error fetching map details for identifier '${mapIdentifier}':`, { error: error2 });
123564
124176
  throw ApiError.internal("Internal server error", error2);
123565
124177
  }
@@ -123578,11 +124190,10 @@ mapRouter.get("/elements", async (c2) => {
123578
124190
  return c2.json(result);
123579
124191
  } catch (error2) {
123580
124192
  if (error2 instanceof ApiError) {
123581
- return c2.json({ error: error2.message }, error2.statusCode);
124193
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123582
124194
  }
123583
124195
  console.error("Error in getMapElements:", error2);
123584
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123585
- return c2.json({ error: message2 }, 500);
124196
+ return c2.json(createUnknownErrorResponse(error2), 500);
123586
124197
  }
123587
124198
  });
123588
124199
  mapsRouter.get("/:identifier", async (c2) => {
@@ -123598,11 +124209,10 @@ mapsRouter.get("/:identifier", async (c2) => {
123598
124209
  return c2.json(result);
123599
124210
  } catch (error2) {
123600
124211
  if (error2 instanceof ApiError) {
123601
- return c2.json({ error: error2.message }, error2.statusCode);
124212
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123602
124213
  }
123603
124214
  console.error("Error in getMapByIdentifier:", error2);
123604
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123605
- return c2.json({ error: message2 }, 500);
124215
+ return c2.json(createUnknownErrorResponse(error2), 500);
123606
124216
  }
123607
124217
  });
123608
124218
  async function createShopListing(ctx) {
@@ -123640,6 +124250,8 @@ async function createShopListing(ctx) {
123640
124250
  }
123641
124251
  return newListing;
123642
124252
  } catch (error2) {
124253
+ if (error2 instanceof ApiError)
124254
+ throw error2;
123643
124255
  if (error2 instanceof Error) {
123644
124256
  if (error2.message.includes("duplicate key value violates unique constraint") || error2.message.includes("UNIQUE constraint failed")) {
123645
124257
  throw ApiError.conflict("This item is already listed for sale with this currency");
@@ -123670,9 +124282,8 @@ async function listShopListings(ctx) {
123670
124282
  const allListings = await db.query.shopListings.findMany();
123671
124283
  return allListings;
123672
124284
  } catch (error2) {
123673
- if (error2 instanceof ApiError) {
124285
+ if (error2 instanceof ApiError)
123674
124286
  throw error2;
123675
- }
123676
124287
  log2.error("Error fetching shop listings:", { error: error2 });
123677
124288
  throw ApiError.internal("Internal server error", error2);
123678
124289
  }
@@ -123690,6 +124301,9 @@ async function getShopListingById(ctx) {
123690
124301
  if (!listingId) {
123691
124302
  throw ApiError.badRequest("Missing listing ID");
123692
124303
  }
124304
+ if (!isValidUUID(listingId)) {
124305
+ throw ApiError.unprocessableEntity("Invalid UUID format for listing ID");
124306
+ }
123693
124307
  try {
123694
124308
  const db = getDatabase();
123695
124309
  const listing = await db.query.shopListings.findFirst({
@@ -123700,9 +124314,8 @@ async function getShopListingById(ctx) {
123700
124314
  }
123701
124315
  return listing;
123702
124316
  } catch (error2) {
123703
- if (error2 instanceof ApiError) {
124317
+ if (error2 instanceof ApiError)
123704
124318
  throw error2;
123705
- }
123706
124319
  log2.error(`Error fetching shop listing ${listingId}:`, { error: error2 });
123707
124320
  throw ApiError.internal("Internal server error", error2);
123708
124321
  }
@@ -123754,6 +124367,8 @@ async function updateShopListing(ctx) {
123754
124367
  }
123755
124368
  return updatedListing;
123756
124369
  } catch (error2) {
124370
+ if (error2 instanceof ApiError)
124371
+ throw error2;
123757
124372
  if (error2 instanceof Error) {
123758
124373
  if (error2.message.includes("duplicate key value violates unique constraint") || error2.message.includes("UNIQUE constraint failed")) {
123759
124374
  throw ApiError.conflict("This item is already listed for sale with this currency");
@@ -123784,6 +124399,9 @@ async function deleteShopListing(ctx) {
123784
124399
  if (!listingId) {
123785
124400
  throw ApiError.badRequest("Missing listing ID");
123786
124401
  }
124402
+ if (!isValidUUID(listingId)) {
124403
+ throw ApiError.unprocessableEntity("Invalid UUID format for listing ID");
124404
+ }
123787
124405
  try {
123788
124406
  const db = getDatabase();
123789
124407
  const result = await db.delete(shopListings).where(eq(shopListings.id, listingId)).returning({ id: shopListings.id });
@@ -123791,9 +124409,8 @@ async function deleteShopListing(ctx) {
123791
124409
  throw ApiError.notFound("Shop listing not found for deletion");
123792
124410
  }
123793
124411
  } catch (error2) {
123794
- if (error2 instanceof ApiError) {
124412
+ if (error2 instanceof ApiError)
123795
124413
  throw error2;
123796
- }
123797
124414
  log2.error(`Error deleting shop listing ${listingId}:`, { error: error2 });
123798
124415
  throw ApiError.internal("Internal server error", error2);
123799
124416
  }
@@ -123811,11 +124428,10 @@ shopListingsRouter.post("/", async (c2) => {
123811
124428
  return c2.json(result, 201);
123812
124429
  } catch (error2) {
123813
124430
  if (error2 instanceof ApiError) {
123814
- return c2.json({ error: error2.message }, error2.statusCode);
124431
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123815
124432
  }
123816
124433
  console.error("Error in createShopListing:", error2);
123817
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123818
- return c2.json({ error: message2 }, 500);
124434
+ return c2.json(createUnknownErrorResponse(error2), 500);
123819
124435
  }
123820
124436
  });
123821
124437
  shopListingsRouter.get("/", async (c2) => {
@@ -123830,11 +124446,10 @@ shopListingsRouter.get("/", async (c2) => {
123830
124446
  return c2.json(result);
123831
124447
  } catch (error2) {
123832
124448
  if (error2 instanceof ApiError) {
123833
- return c2.json({ error: error2.message }, error2.statusCode);
124449
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123834
124450
  }
123835
124451
  console.error("Error in listShopListings:", error2);
123836
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123837
- return c2.json({ error: message2 }, 500);
124452
+ return c2.json(createUnknownErrorResponse(error2), 500);
123838
124453
  }
123839
124454
  });
123840
124455
  shopListingsRouter.get("/:listingId", async (c2) => {
@@ -123850,11 +124465,10 @@ shopListingsRouter.get("/:listingId", async (c2) => {
123850
124465
  return c2.json(result);
123851
124466
  } catch (error2) {
123852
124467
  if (error2 instanceof ApiError) {
123853
- return c2.json({ error: error2.message }, error2.statusCode);
124468
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123854
124469
  }
123855
124470
  console.error("Error in getShopListingById:", error2);
123856
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123857
- return c2.json({ error: message2 }, 500);
124471
+ return c2.json(createUnknownErrorResponse(error2), 500);
123858
124472
  }
123859
124473
  });
123860
124474
  shopListingsRouter.patch("/:listingId", async (c2) => {
@@ -123870,11 +124484,10 @@ shopListingsRouter.patch("/:listingId", async (c2) => {
123870
124484
  return c2.json(result);
123871
124485
  } catch (error2) {
123872
124486
  if (error2 instanceof ApiError) {
123873
- return c2.json({ error: error2.message }, error2.statusCode);
124487
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123874
124488
  }
123875
124489
  console.error("Error in updateShopListing:", error2);
123876
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123877
- return c2.json({ error: message2 }, 500);
124490
+ return c2.json(createUnknownErrorResponse(error2), 500);
123878
124491
  }
123879
124492
  });
123880
124493
  shopListingsRouter.delete("/:listingId", async (c2) => {
@@ -123890,11 +124503,10 @@ shopListingsRouter.delete("/:listingId", async (c2) => {
123890
124503
  return c2.body(null, 204);
123891
124504
  } catch (error2) {
123892
124505
  if (error2 instanceof ApiError) {
123893
- return c2.json({ error: error2.message }, error2.statusCode);
124506
+ return c2.json(createErrorResponse(error2), error2.statusCode);
123894
124507
  }
123895
124508
  console.error("Error in deleteShopListing:", error2);
123896
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
123897
- return c2.json({ error: message2 }, 500);
124509
+ return c2.json(createUnknownErrorResponse(error2), 500);
123898
124510
  }
123899
124511
  });
123900
124512
  async function applyForDeveloperStatus(ctx) {
@@ -123943,7 +124555,7 @@ async function listDeveloperKeys(ctx) {
123943
124555
  if (!user) {
123944
124556
  throw ApiError.unauthorized("Must be logged in to view API keys");
123945
124557
  }
123946
- if (user.role !== "developer" || user.developerStatus !== "approved") {
124558
+ if (user.developerStatus !== "approved") {
123947
124559
  throw ApiError.forbidden("User does not have developer privileges");
123948
124560
  }
123949
124561
  try {
@@ -123963,6 +124575,46 @@ async function listDeveloperKeys(ctx) {
123963
124575
  throw ApiError.internal("Internal server error", error2);
123964
124576
  }
123965
124577
  }
124578
+ async function parseCreateKeyInput(request) {
124579
+ if (request.headers.get("content-length") === "0") {
124580
+ return {};
124581
+ }
124582
+ try {
124583
+ const requestBody = await request.json();
124584
+ const validationResult = CreateDeveloperKeyInputSchema.safeParse(requestBody);
124585
+ if (!validationResult.success) {
124586
+ throw ApiError.badRequest(`Validation failed: ${formatValidationErrors(validationResult.error)}`);
124587
+ }
124588
+ return validationResult.data;
124589
+ } catch (error2) {
124590
+ if (error2 instanceof ApiError)
124591
+ throw error2;
124592
+ log2.error("Failed to parse request body or invalid JSON", { error: error2 });
124593
+ throw ApiError.badRequest("Invalid JSON body");
124594
+ }
124595
+ }
124596
+ async function createDeveloperKeyCore(userId, label) {
124597
+ const db = getDatabase();
124598
+ const apiKey2 = generateApiKey();
124599
+ const keyHash = await hashApiKey(apiKey2);
124600
+ const keyData = {
124601
+ userId,
124602
+ keyHash,
124603
+ label: label ?? null
124604
+ };
124605
+ const [newKeyMeta] = await db.insert(developerKeys).values(keyData).returning({
124606
+ id: developerKeys.id,
124607
+ label: developerKeys.label,
124608
+ createdAt: developerKeys.createdAt
124609
+ });
124610
+ if (!newKeyMeta) {
124611
+ throw ApiError.internal("Failed to create API key in database");
124612
+ }
124613
+ return {
124614
+ ...newKeyMeta,
124615
+ apiKey: apiKey2
124616
+ };
124617
+ }
123966
124618
  async function createDeveloperKey(ctx) {
123967
124619
  const user = ctx.user;
123968
124620
  log2.debug("[API] creating developer key", {
@@ -123971,51 +124623,15 @@ async function createDeveloperKey(ctx) {
123971
124623
  if (!user) {
123972
124624
  throw ApiError.unauthorized("Must be logged in to create API keys");
123973
124625
  }
123974
- if (user.role !== "developer" || user.developerStatus !== "approved") {
124626
+ if (user.developerStatus !== "approved") {
123975
124627
  throw ApiError.forbidden("User does not have developer privileges");
123976
124628
  }
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
124629
  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
- };
124630
+ const inputData = await parseCreateKeyInput(ctx.request);
124631
+ return await createDeveloperKeyCore(user.id, inputData.label);
124015
124632
  } catch (error2) {
124016
- if (error2 instanceof ApiError) {
124633
+ if (error2 instanceof ApiError)
124017
124634
  throw error2;
124018
- }
124019
124635
  log2.error("Error creating API key", { error: error2 });
124020
124636
  throw ApiError.internal("Internal server error", error2);
124021
124637
  }
@@ -124030,7 +124646,7 @@ async function deleteDeveloperKey(ctx) {
124030
124646
  if (!user) {
124031
124647
  throw ApiError.unauthorized("Must be logged in to delete API keys");
124032
124648
  }
124033
- if (user.role !== "developer" || user.developerStatus !== "approved") {
124649
+ if (user.developerStatus !== "approved") {
124034
124650
  throw ApiError.forbidden("User does not have developer privileges");
124035
124651
  }
124036
124652
  if (!keyId) {
@@ -124051,9 +124667,8 @@ async function deleteDeveloperKey(ctx) {
124051
124667
  throw ApiError.notFound("API Key not found during delete operation");
124052
124668
  }
124053
124669
  } catch (error2) {
124054
- if (error2 instanceof ApiError) {
124670
+ if (error2 instanceof ApiError)
124055
124671
  throw error2;
124056
- }
124057
124672
  log2.error(`Error revoking API key ${keyId}:`, { error: error2 });
124058
124673
  throw ApiError.internal("Internal server error", error2);
124059
124674
  }
@@ -124071,11 +124686,10 @@ devRouter.post("/apply", async (c2) => {
124071
124686
  return c2.body(null, 204);
124072
124687
  } catch (error2) {
124073
124688
  if (error2 instanceof ApiError) {
124074
- return c2.json({ error: error2.message }, error2.statusCode);
124689
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124075
124690
  }
124076
124691
  console.error("Error in applyForDeveloperStatus:", error2);
124077
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
124078
- return c2.json({ error: message2 }, 500);
124692
+ return c2.json(createUnknownErrorResponse(error2), 500);
124079
124693
  }
124080
124694
  });
124081
124695
  devRouter.get("/status", async (c2) => {
@@ -124090,11 +124704,10 @@ devRouter.get("/status", async (c2) => {
124090
124704
  return c2.json(result);
124091
124705
  } catch (error2) {
124092
124706
  if (error2 instanceof ApiError) {
124093
- return c2.json({ error: error2.message }, error2.statusCode);
124707
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124094
124708
  }
124095
124709
  console.error("Error in getDeveloperStatus:", error2);
124096
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
124097
- return c2.json({ error: message2 }, 500);
124710
+ return c2.json(createUnknownErrorResponse(error2), 500);
124098
124711
  }
124099
124712
  });
124100
124713
  devRouter.get("/keys", async (c2) => {
@@ -124109,11 +124722,10 @@ devRouter.get("/keys", async (c2) => {
124109
124722
  return c2.json(result);
124110
124723
  } catch (error2) {
124111
124724
  if (error2 instanceof ApiError) {
124112
- return c2.json({ error: error2.message }, error2.statusCode);
124725
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124113
124726
  }
124114
124727
  console.error("Error in listDeveloperKeys:", error2);
124115
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
124116
- return c2.json({ error: message2 }, 500);
124728
+ return c2.json(createUnknownErrorResponse(error2), 500);
124117
124729
  }
124118
124730
  });
124119
124731
  devRouter.post("/keys", async (c2) => {
@@ -124128,11 +124740,10 @@ devRouter.post("/keys", async (c2) => {
124128
124740
  return c2.json(result, 201);
124129
124741
  } catch (error2) {
124130
124742
  if (error2 instanceof ApiError) {
124131
- return c2.json({ error: error2.message }, error2.statusCode);
124743
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124132
124744
  }
124133
124745
  console.error("Error in createDeveloperKey:", error2);
124134
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
124135
- return c2.json({ error: message2 }, 500);
124746
+ return c2.json(createUnknownErrorResponse(error2), 500);
124136
124747
  }
124137
124748
  });
124138
124749
  devRouter.delete("/keys/:keyId", async (c2) => {
@@ -124148,11 +124759,10 @@ devRouter.delete("/keys/:keyId", async (c2) => {
124148
124759
  return c2.body(null, 204);
124149
124760
  } catch (error2) {
124150
124761
  if (error2 instanceof ApiError) {
124151
- return c2.json({ error: error2.message }, error2.statusCode);
124762
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124152
124763
  }
124153
124764
  console.error("Error in deleteDeveloperKey:", error2);
124154
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
124155
- return c2.json({ error: message2 }, 500);
124765
+ return c2.json(createUnknownErrorResponse(error2), 500);
124156
124766
  }
124157
124767
  });
124158
124768
  var levelsRouter = new Hono2;
@@ -124168,11 +124778,10 @@ levelsRouter.get("/config", async (c2) => {
124168
124778
  return c2.json(configs);
124169
124779
  } catch (error2) {
124170
124780
  if (error2 instanceof ApiError) {
124171
- return c2.json({ error: error2.message }, error2.statusCode);
124781
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124172
124782
  }
124173
124783
  console.error("Error in getAllLevelConfigs:", error2);
124174
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
124175
- return c2.json({ error: message2 }, 500);
124784
+ return c2.json(createUnknownErrorResponse(error2), 500);
124176
124785
  }
124177
124786
  });
124178
124787
  levelsRouter.get("/config/:level", async (c2) => {
@@ -124187,19 +124796,20 @@ levelsRouter.get("/config/:level", async (c2) => {
124187
124796
  return c2.json(config);
124188
124797
  } catch (error2) {
124189
124798
  if (error2 instanceof ApiError) {
124190
- return c2.json({ error: error2.message }, error2.statusCode);
124799
+ return c2.json(createErrorResponse(error2), error2.statusCode);
124191
124800
  }
124192
124801
  console.error("Error in getLevelConfigByPath:", error2);
124193
- const message2 = error2 instanceof Error ? error2.message : "Internal server error";
124194
- return c2.json({ error: message2 }, 500);
124802
+ return c2.json(createUnknownErrorResponse(error2), 500);
124195
124803
  }
124196
124804
  });
124197
124805
  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);
124806
+ const { port, verbose = false, project, memoryOnly = false, seed = true } = options;
124807
+ const db = await setupDatabase(memoryOnly ? ":memory:" : undefined);
124808
+ if (seed) {
124809
+ await seedDemoData(db);
124810
+ if (project) {
124811
+ await seedCurrentProjectGame(db, project);
124812
+ }
124203
124813
  }
124204
124814
  const app = new Hono2;
124205
124815
  app.use("*", cors({ origin: "*", credentials: true }));