/**
* SearchData Controller Layer
*
* This controller handles HTTP requests and responses for search operations.
* It serves as the interface between the HTTP layer and the search service,
* managing request validation, response formatting, and error handling.
*
* Key responsibilities:
* - HTTP request/response handling
* - Input validation and sanitization
* - Error response formatting
* - Service layer coordination
* - Status code management
*
* Authentication requirements:
* - All endpoints require authenticated session
* - Visibility is enforced at service layer
*
* @module SearchDataController
*/
// @ts-check
/**
* @import {ExpressRequestAuthorized, ExpressResponse} from './../../types.js'
*/
import { HEX2uuid } from '@commtool/sql-query';
import { errorLoggerRead } from '../../utils/requestLogger.js';
import * as searchService from './service.js';
/**
* Search all entity types with fulltext search
*
* This endpoint performs a comprehensive search across multiple entity types
* using MySQL fulltext search. It supports filtering by type, gender, stage,
* and hierarchy, as well as visibility restrictions based on user permissions.
*
* @param {ExpressRequestAuthorized} req - Express request object
* @param {ExpressResponse} res - Express response object
*
* HTTP Status Codes:
* - 200: Search completed successfully
* - 500: Internal server error
*
* Response format:
* - Array of search results with title, value, key, type, validFrom
* - Or {success: false, message: error} on error
*
* Authentication: Requires authenticated session
* Logging: Uses errorLoggerRead for error tracking
*/
export const searchAll = async (req, res) => {
try {
const searchQuery = req.query.search;
const result = await searchService.searchAllEntities(
searchQuery,
req.session,
req.query
);
res.json(result);
} catch (e) {
errorLoggerRead(e);
res.json({ success: false, message: e });
}
};
/**
* Search specific entity type with fulltext search
*
* This endpoint performs type-specific searches with optimized queries
* for different entity types (member, person, extern, group, list, etc.).
*
* @param {ExpressRequestAuthorized} req - Express request object
* @param {ExpressResponse} res - Express response object
*
* HTTP Status Codes:
* - 200: Search completed successfully
* - 500: Internal server error
*
* Response format:
* - Array of {title, value, key, type} objects
*
* Authentication: Requires authenticated session
* Logging: Uses errorLoggerRead for error tracking
*/
export const searchByType = async (req, res) => {
try {
const searchQuery = req.query.search;
const type = req.params.type;
let result = [];
// Route to appropriate search service based on type
switch (type) {
case 'member':
result = await searchService.searchMembers(searchQuery, req.session, req.query);
break;
case 'extern':
result = await searchService.searchExtern(searchQuery, req.session, req.query);
break;
case 'person':
result = await searchService.searchPersons(searchQuery, req.session, req.query);
break;
case 'group':
result = await searchService.searchGroups(searchQuery, req.session, req.query);
break;
case 'list':
case 'dlist':
case 'email':
if (['list', 'dlist', 'email'].includes(type)) {
result = await searchService.searchLists(searchQuery, type, req.session, req.query);
}
break;
default:
result = await searchService.searchGeneric(searchQuery, type, req.session, req.query);
break;
}
// Format results for API response
if (result) {
res.json(result.map((r, Index) => ({
title: r.title,
value: HEX2uuid(r.value),
key: Index,
type: r.type
})));
} else {
res.json([]);
}
} catch (e) {
errorLoggerRead(e);
res.json({ success: false, message: e });
}
};
/**
* Search entities using semantic vector similarity (AI embeddings)
*
* This endpoint performs semantic search using vector similarity, which finds
* entities that are semantically similar to the search query even if they don't
* contain the exact keywords. This uses AI embeddings stored in the database.
*
* @param {ExpressRequestAuthorized} req - Express request object
* @param {ExpressResponse} res - Express response object
*
* HTTP Status Codes:
* - 200: Search completed successfully
* - 400: Missing or invalid search query
* - 500: Internal server error
*
* Response format:
* - Array of {title, value, key, type, similarity, distance, model} objects
* - Or {success: false, message, error} on error
*
* Authentication: Requires authenticated session
* Logging: Uses errorLoggerRead for error tracking
*/
export const searchEmbedding = async (req, res) => {
try {
const searchQuery = String(req.query.search || '');
if (!searchQuery) {
return res.status(400).json({
success: false,
message: 'Search query is required'
});
}
const formattedResults = await searchService.searchBySemantic(
searchQuery,
req.session,
req.query
);
res.json(formattedResults);
} catch (error) {
errorLoggerRead(error);
res.status(500).json({
success: false,
message: 'Embedding search failed',
error: error.message
});
}
};