56 lines
1.7 KiB
JavaScript
56 lines
1.7 KiB
JavaScript
'use strict';
|
|
const { Router } = require('express');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const router = Router();
|
|
|
|
/** Return available drive letters on Windows. */
|
|
function getWindowsRoots() {
|
|
const roots = [];
|
|
for (let code = 65; code <= 90; code++) {
|
|
const drive = `${String.fromCharCode(code)}:\\`;
|
|
try { fs.accessSync(drive); roots.push({ name: drive, path: drive }); } catch { /* skip */ }
|
|
}
|
|
return roots;
|
|
}
|
|
|
|
router.get('/', (req, res) => {
|
|
const reqPath = req.query.path ? String(req.query.path) : null;
|
|
|
|
// No path → return filesystem roots
|
|
if (!reqPath) {
|
|
const isWindows = process.platform === 'win32';
|
|
const dirs = isWindows ? getWindowsRoots() : [{ name: '/', path: '/' }];
|
|
return res.json({ path: null, parent: null, dirs });
|
|
}
|
|
|
|
// Validate: must exist and be a directory
|
|
let stat;
|
|
try { stat = fs.statSync(reqPath); }
|
|
catch { return res.status(400).json({ error: 'Path does not exist' }); }
|
|
|
|
if (!stat.isDirectory()) {
|
|
return res.status(400).json({ error: 'Path is not a directory' });
|
|
}
|
|
|
|
// List subdirectories, excluding hidden entries
|
|
let dirs;
|
|
try {
|
|
dirs = fs.readdirSync(reqPath, { withFileTypes: true })
|
|
.filter(e => e.isDirectory() && !e.name.startsWith('.'))
|
|
.map(e => ({ name: e.name, path: path.join(reqPath, e.name) }))
|
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
} catch {
|
|
return res.status(403).json({ error: 'Cannot read directory' });
|
|
}
|
|
|
|
// Compute parent; at a drive root on Windows dirname === reqPath
|
|
const parent = path.dirname(reqPath);
|
|
const atRoot = parent === reqPath;
|
|
|
|
res.json({ path: reqPath, parent: atRoot ? null : parent, dirs });
|
|
});
|
|
|
|
module.exports = router;
|