minor refactor, cleanup

This commit is contained in:
Nystik
2026-03-11 22:08:30 +01:00
parent 2b9ebf1fbd
commit 9789be6d70
38 changed files with 259 additions and 379 deletions

View File

@@ -7,7 +7,6 @@ const app = express();
app.use(express.json({ limit: "50mb" }));
// --- Request logging ---
app.use((req, res, next) => {
const start = Date.now();
const origEnd = res.end;
@@ -29,7 +28,6 @@ app.use((req, res, next) => {
next();
});
// --- Routes ---
const fsRoutes = require("./routes/fs");
const vaultRoutes = require("./routes/vault");
@@ -51,15 +49,10 @@ app.use("/vault-files", (req, res, next) => {
express.static(vaultPath)(req, res, next);
});
// --- Static serving ---
// dist/ has shim-loader.js + patched index.html (dev mode).
// In Docker, these live inside the obsidian assets dir instead.
app.use(express.static(path.join(__dirname, "..", "dist")));
// Serve obsidian assets (app.js, app.css, libs, fonts, etc.)
app.use(express.static(config.obsidianAssetsPath));
// --- Start ---
const server = app.listen(config.port, () => {
console.log(
`[obsidian-bridge] Server running on http://localhost:${config.port}`,

View File

@@ -17,8 +17,7 @@ function getVaultRoot(req, res) {
}
// Resolve a client-provided path to an absolute path within a vault.
// Strips leading slashes so paths from the client are always treated as
// relative to the vault root. Rejects path traversal attempts.
// Strips leading slashes so paths from the client are always treated as relative to the vault root.
function resolveVaultPath(vaultRoot, relativePath) {
const cleaned = (relativePath || "").replace(/^\/+/, "");
const resolved = path.resolve(vaultRoot, cleaned);
@@ -46,6 +45,19 @@ function guardPath(req, res) {
return resolved;
}
// Same as guardPath but reads path from req.body (POST routes)
function guardBodyPath(req, res) {
const vaultRoot = getVaultRoot(req, res);
if (!vaultRoot) return null;
const resolved = resolveVaultPath(vaultRoot, req.body?.path);
if (!resolved) {
res.status(403).json({ error: "Invalid path" });
return null;
}
req._vaultRoot = vaultRoot;
return resolved;
}
// GET /api/fs/stat?path=...
router.get("/stat", async (req, res) => {
const resolved = guardPath(req, res);
@@ -70,7 +82,7 @@ router.get("/readdir", async (req, res) => {
const resolved = guardPath(req, res);
if (!resolved) return;
try {
// Check if path is a file - return ENOTDIR instead of crashing
// Check if path is a file. return ENOTDIR instead of crashing
const stat = await fs.promises.stat(resolved);
if (!stat.isDirectory()) {
return res
@@ -123,10 +135,8 @@ router.get("/readFile", async (req, res) => {
// POST /api/fs/writeFile { path, content, encoding?, vault? }
router.post("/writeFile", async (req, res) => {
const vaultRoot = getVaultRoot(req, res);
if (!vaultRoot) return;
const resolved = resolveVaultPath(vaultRoot, req.body?.path);
if (!resolved) return res.status(403).json({ error: "Invalid path" });
const resolved = guardBodyPath(req, res);
if (!resolved) return;
try {
// Ensure parent directory exists
const dir = path.dirname(resolved);
@@ -151,10 +161,8 @@ router.post("/writeFile", async (req, res) => {
// POST /api/fs/appendFile { path, content, vault? }
router.post("/appendFile", async (req, res) => {
const vaultRoot = getVaultRoot(req, res);
if (!vaultRoot) return;
const resolved = resolveVaultPath(vaultRoot, req.body?.path);
if (!resolved) return res.status(403).json({ error: "Invalid path" });
const resolved = guardBodyPath(req, res);
if (!resolved) return;
try {
await fs.promises.appendFile(resolved, req.body.content, "utf-8");
res.json({ ok: true });
@@ -165,10 +173,8 @@ router.post("/appendFile", async (req, res) => {
// POST /api/fs/mkdir { path, recursive?, vault? }
router.post("/mkdir", async (req, res) => {
const vaultRoot = getVaultRoot(req, res);
if (!vaultRoot) return;
const resolved = resolveVaultPath(vaultRoot, req.body?.path);
if (!resolved) return res.status(403).json({ error: "Invalid path" });
const resolved = guardBodyPath(req, res);
if (!resolved) return;
try {
await fs.promises.mkdir(resolved, { recursive: !!req.body.recursive });
res.json({ ok: true });
@@ -277,10 +283,8 @@ router.get("/realpath", async (req, res) => {
// POST /api/fs/utimes { path, atime, mtime, vault? }
router.post("/utimes", async (req, res) => {
const vaultRoot = getVaultRoot(req, res);
if (!vaultRoot) return;
const resolved = resolveVaultPath(vaultRoot, req.body?.path);
if (!resolved) return res.status(403).json({ error: "Invalid path" });
const resolved = guardBodyPath(req, res);
if (!resolved) return;
try {
await fs.promises.utimes(
resolved,
@@ -293,7 +297,7 @@ router.post("/utimes", async (req, res) => {
}
});
// GET /api/fs/tree?path=...&vault=... - returns full recursive file tree with metadata
// GET /api/fs/tree?path=...&vault=... returns full recursive file tree with metadata
router.get("/tree", async (req, res) => {
const vaultRoot = getVaultRoot(req, res);
if (!vaultRoot) return;

View File

@@ -5,7 +5,7 @@ const path = require("path");
const router = express.Router();
// GET /api/vault/list - returns all discovered vaults (re-scans on each call)
// GET /api/vault/list - returns all discovered vaults (re-scans on each call)
router.get("/list", (req, res) => {
config.refreshVaults();
const list = Object.entries(config.vaults).map(([id, vaultPath]) => ({
@@ -16,7 +16,7 @@ router.get("/list", (req, res) => {
res.json(list);
});
// GET /api/vault/info?vault=<id> - returns info for a specific vault
// GET /api/vault/info?vault=<id> - returns info for a specific vault
router.get("/info", (req, res) => {
const vaultId = req.query.vault || config.defaultVaultId;
const vaultPath = config.getVaultPath(vaultId);
@@ -32,7 +32,7 @@ router.get("/info", (req, res) => {
});
});
// POST /api/vault/create { name } - create a new vault in VAULT_ROOT
// POST /api/vault/create { name } - create a new vault in VAULT_ROOT
router.post("/create", async (req, res) => {
const name = req.body?.name;
if (!name || /[\/\\:*?"<>|]/.test(name)) {
@@ -54,7 +54,7 @@ router.post("/create", async (req, res) => {
}
});
// DELETE /api/vault/remove?vault=<id> - remove a vault from disk
// DELETE /api/vault/remove?vault=<id> - remove a vault from disk
router.delete("/remove", async (req, res) => {
const vaultId = req.query.vault;
const vaultPath = config.getVaultPath(vaultId);