More udpates to documentation generation
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { readdir, readFile, writeFile, mkdir, rm, rename, stat } from 'fs/promises';
|
||||
import { readdir, readFile, writeFile, mkdir, rm, rename, stat, copyFile } from 'fs/promises';
|
||||
import { resolve as pathResolve, join, normalize, dirname, extname } from 'path';
|
||||
import crypto from 'crypto';
|
||||
import { env } from '../../config/env';
|
||||
@@ -250,6 +250,29 @@ function isEditableFile(relativePath: string): boolean {
|
||||
return ['.md', '.txt', '.yml', '.yaml', '.json', '.css', '.html', '.js'].includes(ext);
|
||||
}
|
||||
|
||||
const ALLOWED_UPLOAD_EXTENSIONS = new Set([
|
||||
'.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico',
|
||||
'.pdf', '.zip',
|
||||
]);
|
||||
|
||||
async function uploadFile(relativePath: string, sourcePath: string): Promise<void> {
|
||||
const ext = extname(relativePath).toLowerCase();
|
||||
if (!ALLOWED_UPLOAD_EXTENSIONS.has(ext)) {
|
||||
throw new Error(`File type not allowed: ${ext}`);
|
||||
}
|
||||
|
||||
const fullPath = safeResolve(relativePath);
|
||||
await mkdir(dirname(fullPath), { recursive: true });
|
||||
await copyFile(sourcePath, fullPath);
|
||||
|
||||
// Invalidate tree cache (structure changed)
|
||||
try {
|
||||
await redis.del(TREE_CACHE_KEY);
|
||||
} catch (err) {
|
||||
logger.warn('Failed to invalidate tree cache after upload:', err);
|
||||
}
|
||||
}
|
||||
|
||||
async function invalidateTreeCache(): Promise<void> {
|
||||
try {
|
||||
await redis.del(TREE_CACHE_KEY);
|
||||
@@ -265,6 +288,7 @@ export const docsFilesService = {
|
||||
createFile,
|
||||
deleteFile,
|
||||
renameFile,
|
||||
uploadFile,
|
||||
safeResolve,
|
||||
isEditableFile,
|
||||
invalidateTreeCache,
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { Router, Request, Response, NextFunction } from 'express';
|
||||
import multer from 'multer';
|
||||
import { rm } from 'fs/promises';
|
||||
import { extname } from 'path';
|
||||
import { authenticate } from '../../middleware/auth.middleware';
|
||||
import { requireNonTemp, requireRole } from '../../middleware/rbac.middleware';
|
||||
import { env } from '../../config/env';
|
||||
@@ -104,6 +107,57 @@ router.post(
|
||||
},
|
||||
);
|
||||
|
||||
// --- File Upload ---
|
||||
|
||||
const ALLOWED_UPLOAD_EXTENSIONS = new Set([
|
||||
'.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico',
|
||||
'.pdf', '.zip',
|
||||
]);
|
||||
|
||||
const upload = multer({
|
||||
storage: multer.diskStorage({}), // temp dir
|
||||
limits: { fileSize: 20 * 1024 * 1024 }, // 20MB
|
||||
fileFilter: (_req, file, cb) => {
|
||||
const ext = extname(file.originalname).toLowerCase();
|
||||
if (ALLOWED_UPLOAD_EXTENSIONS.has(ext)) {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(new Error(`File type not allowed: ${ext}`));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// POST /api/docs/upload — upload binary file (image, pdf, etc.)
|
||||
router.post(
|
||||
'/upload',
|
||||
upload.single('file'),
|
||||
async (req: Request, res: Response, next: NextFunction) => {
|
||||
const tempPath = req.file?.path;
|
||||
try {
|
||||
cm_docs_operations.inc({ operation: 'upload' });
|
||||
if (!req.file) {
|
||||
res.status(400).json({ error: { message: 'No file provided', code: 'VALIDATION_ERROR' } });
|
||||
return;
|
||||
}
|
||||
|
||||
const targetDir = (req.body as { path?: string }).path || '';
|
||||
const fileName = req.file.originalname;
|
||||
const relativePath = targetDir ? `${targetDir}/${fileName}` : fileName;
|
||||
|
||||
await docsFilesService.uploadFile(relativePath, req.file.path);
|
||||
|
||||
// Clean up temp file
|
||||
try { await rm(req.file.path); } catch { /* ignore */ }
|
||||
|
||||
res.json({ success: true, path: relativePath });
|
||||
} catch (err) {
|
||||
// Clean up temp file on error
|
||||
if (tempPath) { try { await rm(tempPath); } catch { /* ignore */ } }
|
||||
handleFileError(err, res, next);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// --- File Management Endpoints ---
|
||||
|
||||
// GET /api/docs/files — list file tree
|
||||
|
||||
Reference in New Issue
Block a user