UNPKG

@nutrient-sdk/document-engine-mcp-server

Version:
174 lines (173 loc) 6.8 kB
import multer from 'multer'; import basicAuth from 'express-basic-auth'; import { getEnvironment } from '../utils/Environment.js'; import { logger } from '../utils/Logger.js'; import { dashboardTemplate } from './templates/dashboard.js'; import { uploadResultsTemplate } from './templates/uploadResults.js'; import { errorTemplate } from './templates/error.js'; import { formatFileSize } from '../utils/Common.js'; // Set up multer for file uploads export const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 50 * 1024 * 1024 }, // 50MB limit }); /** * Create basic auth middleware for dashboard routes */ export function createAuthMiddleware() { const env = getEnvironment(); if (!env.DASHBOARD_USERNAME || !env.DASHBOARD_PASSWORD) { throw new Error('DASHBOARD_USERNAME and DASHBOARD_PASSWORD must be provided to enable dashboard'); } return basicAuth({ users: { [env.DASHBOARD_USERNAME]: env.DASHBOARD_PASSWORD }, challenge: true, realm: 'Document Engine Dashboard', }); } /** * Dashboard home page handler */ export async function dashboardHandler(client, req, res) { try { // Get list of documents const response = await client['list-documents']({ page_size: 100, order_by: 'created_at', order_direction: 'desc', }); const documents = response.data.data || []; // Get message from query parameters if present const message = req.query.message; // Render HTML dashboard res.send(dashboardTemplate(documents, formatFileSize, message)); } catch (error) { logger.error('Dashboard error', { error }); res .status(500) .send(errorTemplate(`An error occurred while loading the dashboard: ${error instanceof Error ? error.message : 'Unknown error'}`)); } } /** * File upload handler */ export async function uploadHandler(client, req, res) { try { if (!req.files || req.files.length === 0) { return res.status(400).send(errorTemplate('No files were uploaded.')); } const results = []; const files = Array.isArray(req.files) ? req.files : Object.values(req.files).flat(); for (const file of files) { try { // Create FormData for file upload const formData = new FormData(); const blob = new Blob([file.buffer], { type: 'application/octet-stream' }); formData.append('file', blob, file.originalname); // Upload file to Document Engine with proper content type // @ts-expect-error We can pass FormData to this endpoint. const response = await client['upload-document']({}, formData, { headers: { 'Content-Type': 'multipart/form-data', }, }); const documentId = response.data.data?.document_id; if (!documentId) { throw new Error('No document ID returned from upload'); } results.push({ filename: file.originalname, success: true, documentId: documentId, }); } catch (fileError) { results.push({ filename: file.originalname, success: false, error: fileError instanceof Error ? fileError.message : 'Upload failed', }); } } // Transform results to match the expected type for the template const templateResults = results.map(result => { if ('documentId' in result) { return { filename: result.filename, success: result.success, }; } else { return { filename: result.filename, success: result.success, error: result.error, }; } }); // Render upload results res.send(uploadResultsTemplate(templateResults)); } catch (error) { logger.error('File upload error', { error }); res .status(500) .send(errorTemplate(`An error occurred during file upload: ${error instanceof Error ? error.message : 'Unknown error'}`)); } } /** * File download handler */ export async function downloadHandler(client, req, res) { try { const documentId = req.params.id; if (!documentId) { return res.status(400).send(errorTemplate('Document ID is required')); } // Get document info to get the title for the filename const documentInfo = await client['fetch-document-info']({ documentId }); // Check if document info exists and has title const documentData = documentInfo.data.data; if (!documentData) { throw new Error(`No document data returned for document ID: ${documentId}`); } const documentTitle = documentData.title || 'document'; const safeFilename = documentTitle.replace(/[^a-z0-9]/gi, '_').toLowerCase() + '.pdf'; // Download the document as PDF with proper binary response handling const response = await client['download-document-pdf']({ documentId }, undefined, { responseType: 'arraybuffer', }); // Set headers for file download res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `attachment; filename="${safeFilename}"`); res.send(Buffer.from(response.data)); } catch (error) { logger.error('Document download error', { error }); res .status(500) .send(errorTemplate(`An error occurred while downloading the document: ${error instanceof Error ? error.message : 'Unknown error'}`)); } } /** * File delete handler */ export async function deleteHandler(client, req, res) { try { const documentId = req.params.id; if (!documentId) { return res.status(400).send(errorTemplate('Document ID is required')); } // Delete the document await client['delete-document']({ documentId }); // Redirect back to dashboard with success message res.redirect('/dashboard?message=Document+deleted+successfully'); } catch (error) { logger.error('Document delete error', { error }); res .status(500) .send(errorTemplate(`An error occurred while deleting the document: ${error instanceof Error ? error.message : 'Unknown error'}`)); } }