/**
* Shared utilities for MCP2 Tools
* Common helper functions used across modules
*/
/**
* Validation utilities
*/
export class ValidationUtils {
/**
* Validate required fields
*/
static validateRequired(data, requiredFields) {
const errors = [];
for (const field of requiredFields) {
if (!data[field]) {
errors.push({
field,
message: `${field} is required`,
value: data[field]
});
}
}
return errors;
}
/**
* Validate URL format
*/
static validateUrl(url) {
try {
new URL(url);
return true;
}
catch {
return false;
}
}
/**
* Validate HTTP method
*/
static validateHttpMethod(method) {
const validMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'];
return validMethods.includes(method.toUpperCase());
}
/**
* Validate timeout value
*/
static validateTimeout(timeout) {
const num = Number(timeout);
return !isNaN(num) && num > 0 && num <= 300000; // Max 5 minutes
}
}
/**
* String interpolation utilities
*/
export class StringUtils {
/**
* Simple template interpolation
*/
static interpolate(template, variables) {
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
return variables[key] !== undefined ? String(variables[key]) : match;
});
}
/**
* Convert object to query string
*/
static toQueryString(obj) {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(obj)) {
if (value !== null && value !== undefined) {
params.append(key, String(value));
}
}
return params.toString();
}
/**
* Generate random ID
*/
static generateId(length = 8) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
/**
* Truncate string with ellipsis
*/
static truncate(str, maxLength) {
if (str.length <= maxLength)
return str;
return str.substring(0, maxLength - 3) + '...';
}
}
/**
* Time utilities
*/
export class TimeUtils {
/**
* Format milliseconds to human readable format
*/
static formatDuration(ms) {
if (ms < 1000)
return `${ms}ms`;
if (ms < 60000)
return `${(ms / 1000).toFixed(2)}s`;
return `${(ms / 60000).toFixed(2)}m`;
}
/**
* Get current timestamp in ISO format
*/
static now() {
return new Date().toISOString();
}
/**
* Parse timeout value with default
*/
static parseTimeout(value, defaultValue = 30000) {
if (!value)
return defaultValue;
const parsed = Number(value);
return isNaN(parsed) ? defaultValue : Math.max(1000, Math.min(300000, parsed));
}
}
/**
* Object utilities
*/
export class ObjectUtils {
/**
* Deep merge objects
*/
static deepMerge(target, source) {
const result = { ...target };
for (const key in source) {
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
result[key] = this.deepMerge(result[key] || {}, source[key]);
}
else {
result[key] = source[key];
}
}
return result;
}
/**
* Remove undefined values from object
*/
static removeUndefined(obj) {
if (obj === null || typeof obj !== 'object')
return obj;
if (Array.isArray(obj))
return obj.filter(item => item !== undefined).map(item => this.removeUndefined(item));
const result = {};
for (const [key, value] of Object.entries(obj)) {
if (value !== undefined) {
result[key] = this.removeUndefined(value);
}
}
return result;
}
/**
* Pick specific keys from object
*/
static pick(obj, keys) {
const result = {};
for (const key of keys) {
if (key in obj) {
result[key] = obj[key];
}
}
return result;
}
}
/**
* Error utilities
*/
export class ErrorUtils {
/**
* Create standardized error response
*/
static createErrorResponse(message, code, details) {
return {
success: false,
error: message,
code: code || 'UNKNOWN_ERROR',
details,
timestamp: TimeUtils.now()
};
}
/**
* Extract meaningful error message from error object
*/
static extractMessage(error) {
if (typeof error === 'string')
return error;
if (error?.message)
return error.message;
if (error?.error)
return error.error;
return 'Unknown error occurred';
}
/**
* Check if error is network related
*/
static isNetworkError(error) {
const message = this.extractMessage(error).toLowerCase();
return message.includes('network') ||
message.includes('fetch') ||
message.includes('timeout') ||
message.includes('connection');
}
}
/**
* Async utilities
*/
export class AsyncUtils {
/**
* Sleep for specified milliseconds
*/
static sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Execute with timeout
*/
static async withTimeout(promise, timeoutMs) {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error(`Operation timed out after ${timeoutMs}ms`)), timeoutMs);
});
return Promise.race([promise, timeoutPromise]);
}
/**
* Retry async function
*/
static async retry(fn, maxAttempts = 3, delayMs = 1000) {
let lastError;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await fn();
}
catch (error) {
lastError = error;
if (attempt < maxAttempts) {
await this.sleep(delayMs * attempt); // Exponential backoff
}
}
}
throw lastError;
}
}
//# sourceMappingURL=index.js.map