const express = require("express"); const path = require("path"); const config = require("./config"); const { setupWebSocket } = require("./ws"); const app = express(); app.use(express.json({ limit: "50mb" })); app.use((req, res, next) => { const start = Date.now(); const origEnd = res.end; res.end = function (...args) { const duration = Date.now() - start; const status = res.statusCode; const color = status >= 500 ? "\x1b[31m" : status >= 400 ? "\x1b[33m" : "\x1b[32m"; const reset = "\x1b[0m"; const path = req.originalUrl.length > 80 ? req.originalUrl.slice(0, 80) + "..." : req.originalUrl; console.log( `${color}${req.method} ${status}${reset} ${path} (${duration}ms)`, ); origEnd.apply(this, args); }; next(); }); const fsRoutes = require("./routes/fs"); const vaultRoutes = require("./routes/vault"); const proxyRoutes = require("./routes/proxy"); app.use("/api/fs", fsRoutes); app.use("/api/vault", vaultRoutes); app.use("/api/proxy", proxyRoutes); // Serve vault files for resource URLs (images, attachments, etc.) // Vault ID is the first path segment: /vault-files//path/to/file app.use("/vault-files", (req, res, next) => { // Extract vault ID from the first path segment const parts = req.path.split("/").filter(Boolean); if (parts.length === 0) return res.status(400).json({ error: "Missing vault ID" }); const vaultId = decodeURIComponent(parts[0]); const vaultPath = config.getVaultPath(vaultId); if (!vaultPath) return res.status(404).json({ error: "Vault not found" }); // Rewrite req.url to strip the vault ID prefix, then serve statically req.url = "/" + parts.slice(1).join("/"); express.static(vaultPath)(req, res, next); }); app.use(express.static(path.join(__dirname, "..", "dist"))); app.use(express.static(config.obsidianAssetsPath)); const server = app.listen(config.port, () => { console.log(`[ignis] Server running on http://localhost:${config.port}`); console.log(`[ignis] Vault root: ${config.vaultRoot}`); console.log(`[ignis] Vaults: ${Object.keys(config.vaults).join(", ")}`); }); setupWebSocket(server);