@zhanghongping/json-sage-workflow-cli
Version:
An intelligent JSON processing workflow system with improved error handling and configuration
122 lines (109 loc) • 3.32 kB
text/typescript
import chalk from 'chalk';
export class ApiError extends Error {
constructor(
public statusCode: number,
message: string
) {
super(message);
this.name = 'ApiError';
}
}
export class RetryableError extends Error {
constructor(message: string) {
super(message);
this.name = 'RetryableError';
}
}
export class JsonSageError extends Error {
constructor(
message: string,
public code: string,
public details?: any
) {
super(message);
this.name = 'JsonSageError';
}
}
export function safeJsonParse(data: string): { success: boolean; data?: any; error?: Error } {
try {
const parsed = JSON.parse(data);
return { success: true, data: parsed };
} catch (error) {
return {
success: false,
error: new JsonSageError(
'Error parsing JSON data. Please ensure the input is valid JSON.',
'INVALID_JSON',
error
)
};
}
}
export async function safeExecute<T>(
fn: () => Promise<T> | T,
errorMessage: string = 'An unexpected error occurred'
): Promise<{ success: boolean; data?: T; error?: Error }> {
try {
const result = await fn();
return { success: true, data: result };
} catch (error) {
return {
success: false,
error: new JsonSageError(
errorMessage,
'EXECUTION_ERROR',
error
)
};
}
}
export async function retryWithBackoff<T>(
operation: () => Promise<T>,
options: {
maxRetries?: number;
initialDelay?: number;
maxDelay?: number;
shouldRetry?: (error: any) => boolean;
} = {}
): Promise<T> {
const {
maxRetries = 3,
initialDelay = 1000,
maxDelay = 10000,
shouldRetry = (error) => {
if (error instanceof ApiError) {
return [502, 503, 504].includes(error.statusCode);
}
return error instanceof RetryableError;
}
} = options;
let lastError: Error;
let delay = initialDelay;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error;
if (!shouldRetry(error) || attempt === maxRetries) {
break;
}
console.log(chalk.yellow(`Attempt ${attempt} failed, retrying in ${delay}ms...`));
await new Promise(resolve => setTimeout(resolve, delay));
delay = Math.min(delay * 2, maxDelay);
}
}
throw lastError;
}
export function handleApiError(error: any): never {
if (error instanceof ApiError) {
throw new Error(`API Error (${error.statusCode}): ${error.message}`);
} else if (error instanceof RetryableError) {
throw new Error(`Retryable Error: ${error.message}`);
} else if (error instanceof JsonSageError) {
throw new Error(`JSON Sage Error (${error.code}): ${error.message}`);
} else if (error instanceof Error) {
throw new Error(`Unexpected Error: ${error.message}`);
} else {
throw new Error('An unknown error occurred');
}
}