import { ToolResponse } from '../types/stateData.js';
export class GamblingRegulationsError extends Error {
constructor(
message: string,
public code: string,
public statusCode: number = 500,
public details?: Record<string, any>
) {
super(message);
this.name = 'GamblingRegulationsError';
Error.captureStackTrace(this, this.constructor);
}
}
export enum ErrorCode {
STATE_NOT_FOUND = 'STATE_NOT_FOUND',
INVALID_INPUT = 'INVALID_INPUT',
DATA_VALIDATION_ERROR = 'DATA_VALIDATION_ERROR',
FILE_READ_ERROR = 'FILE_READ_ERROR',
CALCULATION_ERROR = 'CALCULATION_ERROR',
INTERNAL_ERROR = 'INTERNAL_ERROR',
LICENSE_TYPE_NOT_FOUND = 'LICENSE_TYPE_NOT_FOUND',
INSUFFICIENT_DATA = 'INSUFFICIENT_DATA',
}
export function createErrorResponse(
error: Error | GamblingRegulationsError,
includeStack: boolean = false
): ToolResponse {
if (error instanceof GamblingRegulationsError) {
return {
content: [{
type: "text",
text: JSON.stringify({
error: error.message,
code: error.code,
details: error.details,
...(includeStack && { stack: error.stack })
}, null, 2)
}],
isError: true
};
}
return {
content: [{
type: "text",
text: JSON.stringify({
error: error.message,
code: ErrorCode.INTERNAL_ERROR,
...(includeStack && { stack: error.stack })
}, null, 2)
}],
isError: true
};
}
export function validateStateName(stateName: string): void {
if (!stateName || typeof stateName !== 'string') {
throw new GamblingRegulationsError(
'State name is required and must be a string',
ErrorCode.INVALID_INPUT,
400,
{ provided: stateName }
);
}
const trimmed = stateName.trim();
if (trimmed.length === 0) {
throw new GamblingRegulationsError(
'State name cannot be empty',
ErrorCode.INVALID_INPUT,
400
);
}
}
export function validateProjectedRevenue(revenue: number): void {
if (typeof revenue !== 'number' || isNaN(revenue)) {
throw new GamblingRegulationsError(
'Projected revenue must be a valid number',
ErrorCode.INVALID_INPUT,
400,
{ provided: revenue }
);
}
if (revenue < 0) {
throw new GamblingRegulationsError(
'Projected revenue cannot be negative',
ErrorCode.INVALID_INPUT,
400,
{ provided: revenue }
);
}
if (revenue > 1000000000000) {
throw new GamblingRegulationsError(
'Projected revenue exceeds maximum allowed value',
ErrorCode.INVALID_INPUT,
400,
{ provided: revenue, max: 1000000000000 }
);
}
}
export function validateLicenseType(licenseType: string): void {
if (!licenseType || typeof licenseType !== 'string') {
throw new GamblingRegulationsError(
'License type is required and must be a string',
ErrorCode.INVALID_INPUT,
400,
{ provided: licenseType }
);
}
}
export function validateStateList(states: string[]): void {
if (!Array.isArray(states)) {
throw new GamblingRegulationsError(
'States must be provided as an array',
ErrorCode.INVALID_INPUT,
400,
{ provided: typeof states }
);
}
if (states.length === 0) {
throw new GamblingRegulationsError(
'At least one state must be provided',
ErrorCode.INVALID_INPUT,
400
);
}
if (states.length > 33) {
throw new GamblingRegulationsError(
'Cannot compare more than 33 states',
ErrorCode.INVALID_INPUT,
400,
{ provided: states.length, max: 33 }
);
}
states.forEach(state => validateStateName(state));
}
export function validateComparisonAspect(aspect: string): void {
const validAspects = ['licensing', 'fees', 'compliance', 'taxes', 'all'];
if (!validAspects.includes(aspect)) {
throw new GamblingRegulationsError(
`Invalid comparison aspect. Must be one of: ${validAspects.join(', ')}`,
ErrorCode.INVALID_INPUT,
400,
{ provided: aspect, valid: validAspects }
);
}
}
export function validateTimeframe(timeframe: string): void {
const validTimeframes = ['30-days', '90-days', '1-year', 'all'];
if (!validTimeframes.includes(timeframe)) {
throw new GamblingRegulationsError(
`Invalid timeframe. Must be one of: ${validTimeframes.join(', ')}`,
ErrorCode.INVALID_INPUT,
400,
{ provided: timeframe, valid: validTimeframes }
);
}
}
export function handleToolError(error: unknown): ToolResponse {
console.error('Tool execution error:', error);
if (error instanceof GamblingRegulationsError) {
return createErrorResponse(error);
}
if (error instanceof Error) {
return createErrorResponse(
new GamblingRegulationsError(
error.message,
ErrorCode.INTERNAL_ERROR,
500
)
);
}
return createErrorResponse(
new GamblingRegulationsError(
'An unexpected error occurred',
ErrorCode.INTERNAL_ERROR,
500
)
);
}
export const logger = {
info: (message: string, data?: any) => {
console.error(`[INFO] ${message}`, data || '');
},
error: (message: string, error?: any) => {
console.error(`[ERROR] ${message}`, error || '');
},
warn: (message: string, data?: any) => {
console.error(`[WARN] ${message}`, data || '');
},
debug: (message: string, data?: any) => {
if (process.env.DEBUG === 'true') {
console.error(`[DEBUG] ${message}`, data || '');
}
}
};