/**
* Analyze controller
*
* Implements document and RFP analysis endpoints
*/
import { analyzeService } from '../services/analyze.service.js';
import { APIError } from '../middleware/errorHandler.js';
import { logger } from '../utils/logger.js';
export const analyzeController = {
/**
* Analyze a document
*/
analyzeDocument: async (req, res, next) => {
try {
const { document, options } = req.body;
if (!document || !document.content) {
return next(new APIError('Missing required document content', 400, 'MISSING_DOCUMENT_CONTENT'));
}
const startTime = Date.now();
const analysis = await analyzeService.analyzeDocument(document, options);
const duration = Date.now() - startTime;
logger.info(`Document analysis completed in ${duration}ms`);
res.json({
analysisId: analysis.id,
results: analysis.results,
metadata: {
processingTime: duration,
timestamp: new Date().toISOString()
}
});
} catch (error) {
next(new APIError(`Document analysis failed: ${error.message}`, 500));
}
},
/**
* Analyze multiple documents in batch
*/
analyzeDocumentBatch: async (req, res, next) => {
try {
const { documents, options } = req.body;
if (!documents || !Array.isArray(documents) || documents.length === 0) {
return next(new APIError('Missing or invalid documents', 400, 'INVALID_DOCUMENTS'));
}
const startTime = Date.now();
const batchResults = await analyzeService.analyzeDocumentBatch(documents, options);
const duration = Date.now() - startTime;
logger.info(`Batch document analysis completed in ${duration}ms, processed ${documents.length} documents`);
res.json({
batchId: batchResults.batchId,
results: batchResults.results,
metadata: {
processingTime: duration,
timestamp: new Date().toISOString(),
documentsProcessed: documents.length
}
});
} catch (error) {
next(new APIError(`Batch document analysis failed: ${error.message}`, 500));
}
},
/**
* Get document analysis results
*/
getDocumentAnalysisResults: async (req, res, next) => {
try {
const { analysisId } = req.params;
const analysis = await analyzeService.getDocumentAnalysisResults(analysisId);
if (!analysis) {
return next(new APIError(`Analysis not found: ${analysisId}`, 404, 'ANALYSIS_NOT_FOUND'));
}
res.json(analysis);
} catch (error) {
next(new APIError(`Failed to retrieve analysis results: ${error.message}`, 500));
}
},
/**
* Analyze an RFP document
*/
analyzeRFP: async (req, res, next) => {
try {
const { rfpDocument, options } = req.body;
if (!rfpDocument || !rfpDocument.content) {
return next(new APIError('Missing required RFP document content', 400, 'MISSING_RFP_CONTENT'));
}
const startTime = Date.now();
const analysis = await analyzeService.analyzeRFP(rfpDocument, options);
const duration = Date.now() - startTime;
logger.info(`RFP analysis completed in ${duration}ms`);
res.json({
analysisId: analysis.id,
results: analysis.results,
metadata: {
processingTime: duration,
timestamp: new Date().toISOString()
}
});
} catch (error) {
next(new APIError(`RFP analysis failed: ${error.message}`, 500));
}
},
/**
* Get RFP analysis results
*/
getRFPAnalysisResults: async (req, res, next) => {
try {
const { analysisId } = req.params;
const analysis = await analyzeService.getRFPAnalysisResults(analysisId);
if (!analysis) {
return next(new APIError(`RFP analysis not found: ${analysisId}`, 404, 'ANALYSIS_NOT_FOUND'));
}
res.json(analysis);
} catch (error) {
next(new APIError(`Failed to retrieve RFP analysis results: ${error.message}`, 500));
}
},
/**
* Generate RFP response
*/
generateRFPResponse: async (req, res, next) => {
try {
const { analysisId } = req.params;
const { sections, template, options } = req.body;
if (!sections || !Array.isArray(sections) || sections.length === 0) {
return next(new APIError('Missing or invalid response sections', 400, 'INVALID_SECTIONS'));
}
const startTime = Date.now();
const response = await analyzeService.generateRFPResponse(analysisId, sections, template, options);
const duration = Date.now() - startTime;
logger.info(`RFP response generation completed in ${duration}ms`);
res.json({
responseId: response.id,
content: response.content,
sections: response.sections,
metadata: {
processingTime: duration,
analysisId,
timestamp: new Date().toISOString()
}
});
} catch (error) {
next(new APIError(`RFP response generation failed: ${error.message}`, 500));
}
},
/**
* Extract entities from text
*/
extractEntities: async (req, res, next) => {
try {
const { text, entityTypes, options } = req.body;
if (!text) {
return next(new APIError('Missing required text for entity extraction', 400, 'MISSING_TEXT'));
}
const startTime = Date.now();
const entities = await analyzeService.extractEntities(text, entityTypes, options);
const duration = Date.now() - startTime;
res.json({
entities,
metadata: {
processingTime: duration,
timestamp: new Date().toISOString()
}
});
} catch (error) {
next(new APIError(`Entity extraction failed: ${error.message}`, 500));
}
},
/**
* Extract topics from text
*/
extractTopics: async (req, res, next) => {
try {
const { text, options } = req.body;
if (!text) {
return next(new APIError('Missing required text for topic extraction', 400, 'MISSING_TEXT'));
}
const startTime = Date.now();
const topics = await analyzeService.extractTopics(text, options);
const duration = Date.now() - startTime;
res.json({
topics,
metadata: {
processingTime: duration,
timestamp: new Date().toISOString()
}
});
} catch (error) {
next(new APIError(`Topic extraction failed: ${error.message}`, 500));
}
},
/**
* Extract sections from document
*/
extractSections: async (req, res, next) => {
try {
const { document, options } = req.body;
if (!document || !document.content) {
return next(new APIError('Missing required document content', 400, 'MISSING_DOCUMENT_CONTENT'));
}
const startTime = Date.now();
const sections = await analyzeService.extractSections(document, options);
const duration = Date.now() - startTime;
res.json({
sections,
metadata: {
processingTime: duration,
timestamp: new Date().toISOString()
}
});
} catch (error) {
next(new APIError(`Section extraction failed: ${error.message}`, 500));
}
},
/**
* Summarize content
*/
summarizeContent: async (req, res, next) => {
try {
const { text, maxLength, options } = req.body;
if (!text) {
return next(new APIError('Missing required text for summarization', 400, 'MISSING_TEXT'));
}
const startTime = Date.now();
const summary = await analyzeService.summarizeContent(text, maxLength, options);
const duration = Date.now() - startTime;
res.json({
summary,
metadata: {
processingTime: duration,
timestamp: new Date().toISOString(),
originalLength: text.length,
summaryLength: summary.length
}
});
} catch (error) {
next(new APIError(`Summarization failed: ${error.message}`, 500));
}
},
/**
* Classify content
*/
classifyContent: async (req, res, next) => {
try {
const { text, categories, options } = req.body;
if (!text) {
return next(new APIError('Missing required text for classification', 400, 'MISSING_TEXT'));
}
const startTime = Date.now();
const classification = await analyzeService.classifyContent(text, categories, options);
const duration = Date.now() - startTime;
res.json({
classification,
metadata: {
processingTime: duration,
timestamp: new Date().toISOString()
}
});
} catch (error) {
next(new APIError(`Classification failed: ${error.message}`, 500));
}
},
/**
* Get analysis history
*/
getAnalysisHistory: async (req, res, next) => {
try {
const history = await analyzeService.getAnalysisHistory(req.query);
res.json(history);
} catch (error) {
next(new APIError(`Failed to retrieve analysis history: ${error.message}`, 500));
}
},
/**
* Get analysis history details
*/
getAnalysisHistoryDetails: async (req, res, next) => {
try {
const { analysisId } = req.params;
const historyDetails = await analyzeService.getAnalysisHistoryDetails(analysisId);
if (!historyDetails) {
return next(new APIError(`Analysis history not found: ${analysisId}`, 404, 'HISTORY_NOT_FOUND'));
}
res.json(historyDetails);
} catch (error) {
next(new APIError(`Failed to retrieve analysis history details: ${error.message}`, 500));
}
},
/**
* Delete analysis history
*/
deleteAnalysisHistory: async (req, res, next) => {
try {
const { analysisId } = req.params;
const success = await analyzeService.deleteAnalysisHistory(analysisId);
if (!success) {
return next(new APIError(`Analysis history not found: ${analysisId}`, 404, 'HISTORY_NOT_FOUND'));
}
res.status(204).end();
} catch (error) {
next(new APIError(`Failed to delete analysis history: ${error.message}`, 500));
}
}
};
export default analyzeController;