@stackmemoryai/stackmemory 0.3.21 → 0.3.22

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/integrations/mcp/tool-definitions-code.ts"],
4
+ "sourcesContent": ["/**\n * Code Execution Tool Definitions for MCP Server\n */\n\nexport const codeExecutionTools = [\n {\n name: 'code.execute',\n description: 'Execute Python, JavaScript, or TypeScript code in a sandboxed environment',\n inputSchema: {\n type: 'object',\n properties: {\n language: {\n type: 'string',\n enum: ['python', 'javascript', 'typescript'],\n description: 'Programming language to execute',\n },\n code: {\n type: 'string',\n description: 'Code to execute',\n },\n workingDirectory: {\n type: 'string',\n description: 'Optional working directory for execution',\n },\n timeout: {\n type: 'number',\n description: 'Execution timeout in milliseconds (default: 30000)',\n },\n force: {\n type: 'boolean',\n description: 'Force execution even if code validation fails',\n },\n },\n required: ['language', 'code'],\n },\n },\n {\n name: 'code.validate',\n description: 'Validate code for potential security issues',\n inputSchema: {\n type: 'object',\n properties: {\n code: {\n type: 'string',\n description: 'Code to validate',\n },\n },\n required: ['code'],\n },\n },\n {\n name: 'code.sandbox_status',\n description: 'Get status of the code execution sandbox',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'code.clean_sandbox',\n description: 'Clean temporary files from the sandbox',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n];\n\n/**\n * Example of using code execution in restricted mode\n */\nexport const codeOnlyModeExample = `\n# When in code_only mode, Claude can ONLY execute code\n\n## Example Python execution:\n\\`\\`\\`python\nimport numpy as np\nimport matplotlib.pyplot as plt\n\n# Generate data\nx = np.linspace(0, 10, 100)\ny = np.sin(x)\n\n# Create visualization (won't display but will execute)\nplt.plot(x, y)\nplt.title('Sine Wave')\nplt.xlabel('X')\nplt.ylabel('Y')\n\n# Calculate statistics\nmean_y = np.mean(y)\nstd_y = np.std(y)\nprint(f\"Mean: {mean_y:.4f}\")\nprint(f\"Std: {std_y:.4f}\")\n\\`\\`\\`\n\n## Example JavaScript execution:\n\\`\\`\\`javascript\n// Process data\nconst data = Array.from({length: 10}, (_, i) => i ** 2);\n\n// Calculate sum\nconst sum = data.reduce((a, b) => a + b, 0);\nconsole.log('Sum of squares:', sum);\n\n// Async operation\nasync function fetchData() {\n // Simulate API call\n await new Promise(resolve => setTimeout(resolve, 100));\n return { status: 'success', data: [1, 2, 3] };\n}\n\nfetchData().then(result => {\n console.log('Async result:', result);\n});\n\\`\\`\\`\n\n## Benefits of code_only mode:\n1. Safe computational environment\n2. No file system modifications\n3. No network access\n4. Pure problem-solving focus\n5. Ideal for algorithms, data analysis, and mathematical computations\n`;"],
5
+ "mappings": "AAIO,MAAM,qBAAqB;AAAA,EAChC;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,UAAU;AAAA,UACR,MAAM;AAAA,UACN,MAAM,CAAC,UAAU,cAAc,YAAY;AAAA,UAC3C,aAAa;AAAA,QACf;AAAA,QACA,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,kBAAkB;AAAA,UAChB,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,SAAS;AAAA,UACP,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,OAAO;AAAA,UACL,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,YAAY,MAAM;AAAA,IAC/B;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,MAAM;AAAA,IACnB;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAC;AAAA,IACf;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY,CAAC;AAAA,IACf;AAAA,EACF;AACF;AAKO,MAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
6
+ "names": []
7
+ }
@@ -248,7 +248,7 @@ class RailwayMCPServer {
248
248
  for (const q of queries) {
249
249
  try {
250
250
  await this.pgPool.query(q);
251
- } catch (e2) {
251
+ } catch (e) {
252
252
  }
253
253
  }
254
254
  await this.pgPool.query("INSERT INTO railway_schema_version (version, description) VALUES ($1, $2) ON CONFLICT (version) DO NOTHING", [version, description]);
@@ -331,10 +331,13 @@ class RailwayMCPServer {
331
331
  if (this.pgPool) {
332
332
  await this.pgPool.query("DELETE FROM admin_sessions WHERE expires_at <= NOW()");
333
333
  } else if (this.db) {
334
- this.db.prepare('DELETE FROM admin_sessions WHERE datetime(expires_at) <= datetime("now")').run();
334
+ const tableExists = this.db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='admin_sessions'`).get();
335
+ if (tableExists) {
336
+ this.db.prepare('DELETE FROM admin_sessions WHERE datetime(expires_at) <= datetime("now")').run();
337
+ }
335
338
  }
336
- } catch {
337
- console.warn("Admin session cleanup failed:", e);
339
+ } catch (error) {
340
+ console.warn("Admin session cleanup failed:", error);
338
341
  }
339
342
  };
340
343
  run();
@@ -359,7 +362,7 @@ class RailwayMCPServer {
359
362
  }
360
363
  }
361
364
  async authenticate(req, res, next) {
362
- if (req.path === "/health" || req.path === "/health/db") {
365
+ if (req.path === "/health" || req.path === "/api/health" || req.path === "/health/db") {
363
366
  return next();
364
367
  }
365
368
  const authHeader = req.headers.authorization;
@@ -375,8 +378,8 @@ class RailwayMCPServer {
375
378
  }
376
379
  req.user = valid;
377
380
  return next();
378
- } catch (e2) {
379
- return res.status(500).json({ error: e2.message || "Auth error" });
381
+ } catch (e) {
382
+ return res.status(500).json({ error: e.message || "Auth error" });
380
383
  }
381
384
  }
382
385
  if (config.authMode === "jwt" && process.env["AUTH0_DOMAIN"]) {
@@ -448,7 +451,7 @@ class RailwayMCPServer {
448
451
  next();
449
452
  }
450
453
  setupRoutes() {
451
- this.app.get("/health", (req, res) => {
454
+ const healthHandler = (req, res) => {
452
455
  const health = {
453
456
  status: "healthy",
454
457
  version: "1.0.0",
@@ -457,7 +460,9 @@ class RailwayMCPServer {
457
460
  environment: config.environment
458
461
  };
459
462
  res.json(health);
460
- });
463
+ };
464
+ this.app.get("/health", healthHandler);
465
+ this.app.get("/api/health", healthHandler);
461
466
  this.app.get("/", (req, res) => {
462
467
  res.json({
463
468
  name: "StackMemory Railway Server",
@@ -599,7 +604,6 @@ class RailwayMCPServer {
599
604
  [apiKeyHash, keyResult.rows[0].id]
600
605
  );
601
606
  }
602
- const databaseUrl = process.env.DATABASE_URL;
603
607
  } else {
604
608
  const keyRow = this.db.prepare(
605
609
  "SELECT id FROM api_keys WHERE user_id = ? AND revoked = 0 LIMIT 1"
@@ -691,7 +695,7 @@ class RailwayMCPServer {
691
695
  res.status(500).json({ error: error.message });
692
696
  }
693
697
  });
694
- const parseCookies2 = (cookieHeader) => {
698
+ const parseCookies = (cookieHeader) => {
695
699
  const out = {};
696
700
  if (!cookieHeader) return out;
697
701
  cookieHeader.split(";").forEach((p) => {
@@ -700,15 +704,15 @@ class RailwayMCPServer {
700
704
  });
701
705
  return out;
702
706
  };
703
- const setJwtCookie2 = (res, token) => {
707
+ const setJwtCookie = (res, token) => {
704
708
  const flags = ["Path=/", "HttpOnly", "SameSite=Lax"];
705
709
  if (process.env["NODE_ENV"] === "production") flags.push("Secure");
706
710
  res.setHeader("Set-Cookie", `sm_admin_jwt=${encodeURIComponent(token)}; ${flags.join("; ")}`);
707
711
  };
708
- const clearJwtCookie2 = (res) => {
712
+ const clearJwtCookie = (res) => {
709
713
  res.setHeader("Set-Cookie", "sm_admin_jwt=; Path=/; HttpOnly; Max-Age=0; SameSite=Lax");
710
714
  };
711
- const verifyAdminJwt2 = (token) => {
715
+ const verifyAdminJwt = (token) => {
712
716
  try {
713
717
  const secret = process.env["ADMIN_JWT_SECRET"] || "dev-admin-secret";
714
718
  const payload = jwt.verify(token, secret);
@@ -728,10 +732,10 @@ class RailwayMCPServer {
728
732
  const requireAdmin = (req, res, next) => {
729
733
  const user = req.user || {};
730
734
  if (user.role === "admin") return next();
731
- const cookies = parseCookies2(req.headers.cookie);
735
+ const cookies = parseCookies(req.headers.cookie);
732
736
  const t = cookies["sm_admin_jwt"];
733
737
  if (t) {
734
- const verified = verifyAdminJwt2(t);
738
+ const verified = verifyAdminJwt(t);
735
739
  if (verified) {
736
740
  checkDbSession(verified.jti).then((ok) => {
737
741
  if (ok) return next();
@@ -764,8 +768,8 @@ class RailwayMCPServer {
764
768
  }
765
769
  const rows = this.db.prepare("SELECT id, name, is_public, created_at, updated_at FROM projects ORDER BY updated_at DESC").all();
766
770
  return res.json({ projects: rows });
767
- } catch (e2) {
768
- res.status(500).json({ error: e2.message });
771
+ } catch (e) {
772
+ res.status(500).json({ error: e.message });
769
773
  }
770
774
  });
771
775
  this.app.post("/admin/api/projects", requireAdmin, async (req, res) => {
@@ -778,8 +782,8 @@ class RailwayMCPServer {
778
782
  }
779
783
  this.db.prepare("INSERT OR IGNORE INTO projects (id, name, is_public) VALUES (?, ?, ?)").run(id, name || id, isPublic ? 1 : 0);
780
784
  return res.json({ success: true });
781
- } catch (e2) {
782
- res.status(500).json({ error: e2.message });
785
+ } catch (e) {
786
+ res.status(500).json({ error: e.message });
783
787
  }
784
788
  });
785
789
  this.app.patch("/admin/api/projects/:id/visibility", requireAdmin, async (req, res) => {
@@ -793,8 +797,8 @@ class RailwayMCPServer {
793
797
  }
794
798
  this.db.prepare("UPDATE projects SET is_public = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?").run(isPublic ? 1 : 0, pid);
795
799
  return res.json({ success: true });
796
- } catch (e2) {
797
- res.status(500).json({ error: e2.message });
800
+ } catch (e) {
801
+ res.status(500).json({ error: e.message });
798
802
  }
799
803
  });
800
804
  this.app.get("/admin/api/projects/:id/members", requireAdmin, async (req, res) => {
@@ -809,8 +813,8 @@ class RailwayMCPServer {
809
813
  }
810
814
  const stmt = this.db.prepare("SELECT pm.user_id, pm.role, u.email, u.name FROM project_members pm LEFT JOIN users u ON u.id = pm.user_id WHERE pm.project_id = ? ORDER BY pm.role");
811
815
  return res.json({ members: stmt.all(pid) });
812
- } catch (e2) {
813
- res.status(500).json({ error: e2.message });
816
+ } catch (e) {
817
+ res.status(500).json({ error: e.message });
814
818
  }
815
819
  });
816
820
  this.app.put("/admin/api/projects/:id/members", requireAdmin, async (req, res) => {
@@ -829,8 +833,8 @@ class RailwayMCPServer {
829
833
  }
830
834
  this.db.prepare("INSERT INTO project_members (project_id, user_id, role) VALUES (?, ?, ?) ON CONFLICT(project_id, user_id) DO UPDATE SET role = ?").run(pid, userId, role, role);
831
835
  return res.json({ success: true });
832
- } catch (e2) {
833
- res.status(500).json({ error: e2.message });
836
+ } catch (e) {
837
+ res.status(500).json({ error: e.message });
834
838
  }
835
839
  });
836
840
  this.app.delete("/admin/api/projects/:id/members/:userId", requireAdmin, async (req, res) => {
@@ -843,8 +847,8 @@ class RailwayMCPServer {
843
847
  }
844
848
  this.db.prepare("DELETE FROM project_members WHERE project_id = ? AND user_id = ?").run(pid, uid);
845
849
  return res.json({ success: true });
846
- } catch (e2) {
847
- res.status(500).json({ error: e2.message });
850
+ } catch (e) {
851
+ res.status(500).json({ error: e.message });
848
852
  }
849
853
  });
850
854
  this.app.get("/admin/api/sessions", requireAdmin, async (_req, res) => {
@@ -855,8 +859,8 @@ class RailwayMCPServer {
855
859
  }
856
860
  const rows = this.db.prepare("SELECT id, user_id, created_at, expires_at, user_agent, ip FROM admin_sessions ORDER BY created_at DESC").all();
857
861
  return res.json({ sessions: rows });
858
- } catch (e2) {
859
- res.status(500).json({ error: e2.message });
862
+ } catch (e) {
863
+ res.status(500).json({ error: e.message });
860
864
  }
861
865
  });
862
866
  this.app.delete("/admin/api/sessions/:id", requireAdmin, async (req, res) => {
@@ -868,13 +872,13 @@ class RailwayMCPServer {
868
872
  this.db.prepare("DELETE FROM admin_sessions WHERE id = ?").run(id);
869
873
  }
870
874
  res.json({ success: true });
871
- } catch (e2) {
872
- res.status(500).json({ error: e2.message });
875
+ } catch (e) {
876
+ res.status(500).json({ error: e.message });
873
877
  }
874
878
  });
875
879
  this.app.post("/admin/api/sessions/refresh", requireAdmin, async (req, res) => {
876
880
  try {
877
- const cookies = parseCookies2(req.headers.cookie);
881
+ const cookies = parseCookies(req.headers.cookie);
878
882
  const t = cookies["sm_admin_jwt"];
879
883
  if (!t) return res.status(400).json({ error: "No session" });
880
884
  const secret = process.env["ADMIN_JWT_SECRET"] || "dev-admin-secret";
@@ -892,7 +896,8 @@ class RailwayMCPServer {
892
896
  } else {
893
897
  this.db.prepare("DELETE FROM admin_sessions WHERE id = ?").run(oldJti);
894
898
  }
895
- } catch {
899
+ } catch (error) {
900
+ console.warn("Failed to delete session during refresh:", error);
896
901
  }
897
902
  const jti = Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2);
898
903
  const hours = parseInt(process.env["ADMIN_SESSION_HOURS"] || "8", 10);
@@ -910,8 +915,8 @@ class RailwayMCPServer {
910
915
  if (process.env["NODE_ENV"] === "production") flags.push("Secure");
911
916
  res.setHeader("Set-Cookie", `sm_admin_jwt=${encodeURIComponent(token)}; ${flags.join("; ")}`);
912
917
  return res.json({ success: true });
913
- } catch (e2) {
914
- res.status(500).json({ error: e2.message });
918
+ } catch (e) {
919
+ res.status(500).json({ error: e.message });
915
920
  }
916
921
  });
917
922
  this.app.get("/admin", requireAdmin, (req, res) => {
@@ -1063,6 +1068,63 @@ loadSessions();
1063
1068
  }
1064
1069
  });
1065
1070
  }
1071
+ this.app.get("/admin/login", (_req, res) => {
1072
+ res.setHeader("Content-Type", "text/html");
1073
+ res.send(`<!doctype html><html><head><meta charset="utf-8"/><title>Admin Login</title>
1074
+ <style>body{font-family:system-ui;margin:40px} input{padding:8px;margin:4px} button{padding:8px}</style></head>
1075
+ <body><h3>Admin Login</h3>
1076
+ <p>Paste an admin API key to manage projects and members.</p>
1077
+ <form method="POST" action="/admin/login">
1078
+ <input type="password" name="apiKey" placeholder="sk-..." style="min-width:360px" required/>
1079
+ <div><button type="submit">Login</button></div>
1080
+ <p style="color:#666">Your key is validated server-side and not stored in the browser; a short-lived session cookie is created.</p>
1081
+ </form>
1082
+ </body></html>`);
1083
+ });
1084
+ this.app.post("/admin/login", express.urlencoded({ extended: false }), async (req, res) => {
1085
+ try {
1086
+ const apiKey = req.body?.apiKey || "";
1087
+ if (!apiKey) return res.status(400).send("Missing API key");
1088
+ const u = await this.validateApiKey(apiKey);
1089
+ if (!u || u.role !== "admin") return res.status(403).send("Not an admin API key");
1090
+ const jti = Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2);
1091
+ const hours = parseInt(process.env["ADMIN_SESSION_HOURS"] || "8", 10);
1092
+ const expMs = Date.now() + hours * 3600 * 1e3;
1093
+ const expDateIso = new Date(expMs).toISOString();
1094
+ const ua = req.headers["user-agent"] || "";
1095
+ const ip = req.headers["x-forwarded-for"] || req.socket.remoteAddress || "";
1096
+ if (this.pgPool) {
1097
+ await this.pgPool.query("INSERT INTO admin_sessions (id, user_id, expires_at, user_agent, ip) VALUES ($1, $2, $3, $4, $5)", [jti, u.id, expDateIso, ua, ip]);
1098
+ } else {
1099
+ this.db.prepare("INSERT INTO admin_sessions (id, user_id, expires_at, user_agent, ip) VALUES (?, ?, ?, ?, ?)").run(jti, u.id, expDateIso, ua, ip);
1100
+ }
1101
+ const token = jwt.sign({ sub: u.id, role: "admin", jti }, process.env["ADMIN_JWT_SECRET"] || "dev-admin-secret", { expiresIn: hours + "h" });
1102
+ setJwtCookie(res, token);
1103
+ res.redirect("/admin");
1104
+ } catch (e) {
1105
+ res.status(500).send("Login failed");
1106
+ }
1107
+ });
1108
+ this.app.get("/admin/logout", async (req, res) => {
1109
+ const cookies = parseCookies(req.headers.cookie);
1110
+ const t = cookies["sm_admin_jwt"];
1111
+ if (t) {
1112
+ const verified = verifyAdminJwt(t);
1113
+ if (verified) {
1114
+ try {
1115
+ if (this.pgPool) {
1116
+ await this.pgPool.query("DELETE FROM admin_sessions WHERE id = $1", [verified.jti]);
1117
+ } else {
1118
+ this.db.prepare("DELETE FROM admin_sessions WHERE id = ?").run(verified.jti);
1119
+ }
1120
+ } catch (error) {
1121
+ console.warn("Failed to delete session during logout:", error);
1122
+ }
1123
+ }
1124
+ }
1125
+ clearJwtCookie(res);
1126
+ res.redirect("/admin/login");
1127
+ });
1066
1128
  }
1067
1129
  setupWebSocket() {
1068
1130
  this.wss = new WebSocketServer({
@@ -1280,60 +1342,4 @@ process.on("SIGINT", () => {
1280
1342
  console.log("Shutting down...");
1281
1343
  process.exit(0);
1282
1344
  });
1283
- (void 0).app.get("/admin/login", (_req, res) => {
1284
- res.setHeader("Content-Type", "text/html");
1285
- res.send(`<!doctype html><html><head><meta charset="utf-8"/><title>Admin Login</title>
1286
- <style>body{font-family:system-ui;margin:40px} input{padding:8px;margin:4px} button{padding:8px}</style></head>
1287
- <body><h3>Admin Login</h3>
1288
- <p>Paste an admin API key to manage projects and members.</p>
1289
- <form method="POST" action="/admin/login">
1290
- <input type="password" name="apiKey" placeholder="sk-..." style="min-width:360px" required/>
1291
- <div><button type="submit">Login</button></div>
1292
- <p style="color:#666">Your key is validated server-side and not stored in the browser; a short-lived session cookie is created.</p>
1293
- </form>
1294
- </body></html>`);
1295
- });
1296
- (void 0).app.post("/admin/login", express.urlencoded({ extended: false }), async (req, res) => {
1297
- try {
1298
- const apiKey = req.body?.apiKey || "";
1299
- if (!apiKey) return res.status(400).send("Missing API key");
1300
- const u = await (void 0).validateApiKey(apiKey);
1301
- if (!u || u.role !== "admin") return res.status(403).send("Not an admin API key");
1302
- const jti = Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2);
1303
- const hours = parseInt(process.env["ADMIN_SESSION_HOURS"] || "8", 10);
1304
- const expMs = Date.now() + hours * 3600 * 1e3;
1305
- const expDateIso = new Date(expMs).toISOString();
1306
- const ua = req.headers["user-agent"] || "";
1307
- const ip = req.headers["x-forwarded-for"] || req.socket.remoteAddress || "";
1308
- if ((void 0).pgPool) {
1309
- await (void 0).pgPool.query("INSERT INTO admin_sessions (id, user_id, expires_at, user_agent, ip) VALUES ($1, $2, $3, $4, $5)", [jti, u.id, expDateIso, ua, ip]);
1310
- } else {
1311
- (void 0).db.prepare("INSERT INTO admin_sessions (id, user_id, expires_at, user_agent, ip) VALUES (?, ?, ?, ?, ?)").run(jti, u.id, expDateIso, ua, ip);
1312
- }
1313
- const token = jwt.sign({ sub: u.id, role: "admin", jti }, process.env["ADMIN_JWT_SECRET"] || "dev-admin-secret", { expiresIn: hours + "h" });
1314
- setJwtCookie(res, token);
1315
- res.redirect("/admin");
1316
- } catch (e2) {
1317
- res.status(500).send("Login failed");
1318
- }
1319
- });
1320
- (void 0).app.get("/admin/logout", async (req, res) => {
1321
- const cookies = parseCookies(req.headers.cookie);
1322
- const t = cookies["sm_admin_jwt"];
1323
- if (t) {
1324
- const verified = verifyAdminJwt(t);
1325
- if (verified) {
1326
- try {
1327
- if ((void 0).pgPool) {
1328
- await (void 0).pgPool.query("DELETE FROM admin_sessions WHERE id = $1", [verified.jti]);
1329
- } else {
1330
- (void 0).db.prepare("DELETE FROM admin_sessions WHERE id = ?").run(verified.jti);
1331
- }
1332
- } catch {
1333
- }
1334
- }
1335
- }
1336
- clearJwtCookie(res);
1337
- res.redirect("/admin/login");
1338
- });
1339
1345
  //# sourceMappingURL=index.js.map