deepsource-mcp-server
Version:
Model Context Protocol server for DeepSource
150 lines • 5.21 kB
JavaScript
/**
* @fileoverview Base handler factory implementation for standardized handler creation
* @packageDocumentation
*/
import { createLogger } from '../../utils/logging/logger.js';
import { DeepSourceClientFactory } from '../../client/factory.js';
import { getApiKey } from '../../config/index.js';
/**
* Creates a base handler factory with common functionality
* @template TParams - The handler parameters type
* @template TResult - The handler result type
* @param handlerName - The name of the handler for logging
* @param handlerLogic - The actual handler implementation
* @returns A handler factory function
*/
export function createBaseHandlerFactory(handlerName, handlerLogic) {
return (deps) => {
/**
* The actual handler function that processes the request
* @param params - The parameters passed to the handler
* @returns Promise resolving to the handler result
*/
const handler = async (params) => {
const startTime = Date.now();
try {
// Log handler invocation
deps.logger.info(`Handler ${handlerName} invoked`, {
hasParams: params !== undefined && params !== null,
...(params && typeof params === 'object' ? { params } : {}),
});
// Execute the handler logic
const result = await handlerLogic(deps, params);
// Log successful completion
const duration = Date.now() - startTime;
deps.logger.info(`Handler ${handlerName} completed successfully`, {
duration,
...(result && typeof result === 'object' && 'data' in result
? {
resultCount: Array.isArray(result.data)
? result.data.length
: 1,
}
: {}),
});
return result;
}
catch (error) {
// Log error details
const duration = Date.now() - startTime;
deps.logger.error(`Handler ${handlerName} failed`, {
duration,
errorType: error instanceof Error ? error.constructor.name : typeof error,
errorMessage: error instanceof Error ? error.message : String(error),
errorStack: error instanceof Error ? error.stack : undefined,
});
// Re-throw the error for upstream handling
throw error;
}
};
return handler;
};
}
/**
* Creates default handler dependencies
* @param overrides - Optional overrides for specific dependencies
* @returns The complete handler dependencies
*/
export function createDefaultHandlerDeps(overrides) {
const apiKey = getApiKey();
return {
clientFactory: new DeepSourceClientFactory(apiKey),
logger: createLogger('Handler'),
getApiKey,
...overrides,
};
}
/**
* Wraps a handler result in an ApiResponse format
* @param data - The data to wrap
* @returns An ApiResponse with the data as JSON text
*/
export function wrapInApiResponse(data) {
return {
content: [
{
type: 'text',
text: JSON.stringify(data, null, 2),
},
],
};
}
/**
* Creates an error ApiResponse
* @param error - The error to convert
* @param defaultMessage - Default message if error parsing fails
* @returns An ApiResponse with error information
*/
export function createErrorResponse(error, defaultMessage = 'An unexpected error occurred') {
let errorData;
if (error instanceof Error) {
// Check if it's a structured error with code
if ('code' in error && typeof error.code === 'string') {
errorData = {
code: error.code,
message: error.message,
};
if ('details' in error && error.details) {
errorData.details = error.details;
}
if ('suggestions' in error && error.suggestions) {
errorData.suggestions = error.suggestions;
}
}
else {
// Generic error
errorData = {
code: 'HANDLER_ERROR',
message: error.message || defaultMessage,
};
}
}
else {
// Unknown error type
errorData = {
code: 'UNKNOWN_ERROR',
message: String(error) || defaultMessage,
};
}
return {
isError: true,
content: [
{
type: 'text',
text: JSON.stringify(errorData),
},
],
};
}
/**
* Type guard to check if a value is an ApiResponse
* @param value - The value to check
* @returns True if the value is an ApiResponse
*/
export function isApiResponse(value) {
return (value !== null &&
typeof value === 'object' &&
'content' in value &&
Array.isArray(value.content));
}
//# sourceMappingURL=handler.factory.js.map