Skip to main content
Glama
searchapi.controller.ts7.99 kB
import searchApiService from '../services/vendor.searchapi.site.service.js'; import { Logger } from '../utils/logger.util.js'; import { ControllerResponse } from '../types/common.types.js'; import { formatGoogleSearchResults, formatGoogleImageResults, formatYouTubeResults, } from './searchapi.formatter.js'; import { handleControllerError } from '../utils/error-handler.util.js'; import { applyDefaults } from '../utils/defaults.util.js'; import { GoogleSearchOptions, GoogleImageSearchOptions, YouTubeSearchOptions, } from './searchapi.types.js'; import { config } from '../utils/config.util.js'; /** * @namespace SearchApiController * @description Controller responsible for handling SearchAPI.site search operations. * It orchestrates calls to the SearchAPI.site service, applies defaults, * maps options, and formats the response using the formatter. */ /** * @function googleSearch * @description Performs a Google search using SearchAPI.site * @memberof SearchApiController * @param {GoogleSearchOptions} options - Search options including query and API key * @returns {Promise<ControllerResponse>} A promise that resolves to the standard controller response containing the formatted search results in Markdown * @throws {McpError} Throws an McpError (handled by `handleControllerError`) if the service call fails or returns an error */ async function googleSearch( options: GoogleSearchOptions, ): Promise<ControllerResponse> { const methodLogger = Logger.forContext( 'controllers/searchapi.controller.ts', 'googleSearch', ); methodLogger.debug(`Performing Google search for query: ${options.query}`); try { // Validate required parameters if (!options.query) { throw new Error('Query is required for Google search'); } const apiKey = config.get('SEARCHAPI_API_KEY'); if (!apiKey) { throw new Error('API key is required for SearchAPI.site'); } // Define controller defaults const defaults: Partial<GoogleSearchOptions> = { limit: 10, offset: 0, sort: 'date:d', }; // Apply defaults to provided options const mergedOptions = applyDefaults<GoogleSearchOptions>( options, defaults, ); methodLogger.debug('Using options after defaults:', mergedOptions); // Call the service with the options const searchResponse = await searchApiService.googleSearch( { query: mergedOptions.query, limit: mergedOptions.limit, offset: mergedOptions.offset, sort: mergedOptions.sort, from_date: mergedOptions.from_date, to_date: mergedOptions.to_date, }, apiKey, ); methodLogger.debug(`Got the response from the service`, searchResponse); // Format the data using the formatter const formattedContent = formatGoogleSearchResults(searchResponse.data); // Return the standard ControllerResponse structure return { content: formattedContent }; } catch (error) { // Use the standardized error handler with return return handleControllerError(error, { entityType: 'Google Search Results', operation: 'searching', source: 'controllers/searchapi.controller.ts@googleSearch', additionalInfo: { query: options.query }, }); } } /** * @function googleImageSearch * @description Performs a Google image search using SearchAPI.site * @memberof SearchApiController * @param {GoogleImageSearchOptions} options - Search options including query and API key * @returns {Promise<ControllerResponse>} A promise that resolves to the standard controller response containing the formatted image search results in Markdown * @throws {McpError} Throws an McpError (handled by `handleControllerError`) if the service call fails or returns an error */ async function googleImageSearch( options: GoogleImageSearchOptions, ): Promise<ControllerResponse> { const methodLogger = Logger.forContext( 'controllers/searchapi.controller.ts', 'googleImageSearch', ); methodLogger.debug( `Performing Google image search for query: ${options.query}`, ); try { // Validate required parameters if (!options.query) { throw new Error('Query is required for Google image search'); } const apiKey = config.get('SEARCHAPI_API_KEY'); if (!apiKey) { throw new Error('API key is required for SearchAPI.site'); } // Define controller defaults const defaults: Partial<GoogleImageSearchOptions> = { limit: 10, offset: 0, sort: 'date:d', }; // Apply defaults to provided options const mergedOptions = applyDefaults<GoogleImageSearchOptions>( options, defaults, ); methodLogger.debug('Using options after defaults:', mergedOptions); // Call the service with the options const searchResponse = await searchApiService.googleImageSearch( { query: mergedOptions.query, limit: mergedOptions.limit, offset: mergedOptions.offset, sort: mergedOptions.sort, from_date: mergedOptions.from_date, to_date: mergedOptions.to_date, }, apiKey, ); methodLogger.debug(`Got the response from the service`, searchResponse); // Format the data using the formatter const formattedContent = formatGoogleImageResults(searchResponse.data); // Return the standard ControllerResponse structure return { content: formattedContent }; } catch (error) { // Use the standardized error handler with return return handleControllerError(error, { entityType: 'Google Image Search Results', operation: 'searching', source: 'controllers/searchapi.controller.ts@googleImageSearch', additionalInfo: { query: options.query }, }); } } /** * @function youtubeSearch * @description Performs a YouTube search using SearchAPI.site * @memberof SearchApiController * @param {YouTubeSearchOptions} options - Search options including query, API key, and optional parameters * @returns {Promise<ControllerResponse>} A promise that resolves to the standard controller response containing the formatted YouTube search results in Markdown * @throws {McpError} Throws an McpError (handled by `handleControllerError`) if the service call fails or returns an error */ async function youtubeSearch( options: YouTubeSearchOptions, ): Promise<ControllerResponse> { const methodLogger = Logger.forContext( 'controllers/searchapi.controller.ts', 'youtubeSearch', ); methodLogger.debug(`Performing YouTube search for query: ${options.query}`); try { // Validate required parameters if (!options.query) { throw new Error('Query is required for YouTube search'); } const apiKey = config.get('SEARCHAPI_API_KEY'); if (!apiKey) { throw new Error('API key is required for SearchAPI.site'); } // Define controller defaults const defaults: Partial<YouTubeSearchOptions> = { maxResults: 10, order: 'relevance', videoDuration: 'any', }; // Apply defaults to provided options const mergedOptions = applyDefaults<YouTubeSearchOptions>( options, defaults, ); methodLogger.debug('Using options after defaults:', mergedOptions); // Call the service with the options const searchResponse = await searchApiService.youtubeSearch( { query: mergedOptions.query, maxResults: mergedOptions.maxResults, pageToken: mergedOptions.pageToken, order: mergedOptions.order, publishedAfter: mergedOptions.publishedAfter, videoDuration: mergedOptions.videoDuration, }, apiKey, ); methodLogger.debug(`Got the response from the service`, searchResponse); // Format the data using the formatter const formattedContent = formatYouTubeResults(searchResponse); // Return the standard ControllerResponse structure return { content: formattedContent }; } catch (error) { // Use the standardized error handler with return return handleControllerError(error, { entityType: 'YouTube Search Results', operation: 'searching', source: 'controllers/searchapi.controller.ts@youtubeSearch', additionalInfo: { query: options.query }, }); } } export default { googleSearch, googleImageSearch, youtubeSearch, };

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mrgoonie/searchapi-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server