Split monolithic kernel_commands.rs (2185 lines) and pipeline_commands.rs (1391 lines) into focused sub-modules under kernel_commands/ and pipeline_commands/ directories. Add gateway module (commands, config, io, runtime), health_check, and 15 new TypeScript client libraries for SaaS relay, auth, admin, telemetry, and kernel sub-systems (a2a, agent, chat, hands, skills, triggers). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
174 lines
5.2 KiB
TypeScript
174 lines
5.2 KiB
TypeScript
/**
|
|
* Safe JSON Parsing Utilities
|
|
*
|
|
* Provides try-catch protected JSON parsing with optional default values
|
|
* and context-aware error messages.
|
|
*
|
|
* Usage:
|
|
* - safeJsonParse: Returns result object with success/failure status
|
|
* - parseJsonOrDefault: Returns parsed value or default on failure
|
|
* - parseJsonOrThrow: Returns parsed value or throws friendly error
|
|
*/
|
|
|
|
export interface SafeJsonParseResult<T> {
|
|
success: boolean;
|
|
data?: T;
|
|
error?: string;
|
|
}
|
|
|
|
/**
|
|
* Safely parse a JSON string with error handling
|
|
*
|
|
* @param text - The JSON string to parse
|
|
* @param defaultValue - Optional default value to return on parse failure
|
|
* @returns Result object with success status, data, and optional error message
|
|
*
|
|
* @example
|
|
* const result = safeJsonParse<UserData>(jsonString);
|
|
* if (result.success) {
|
|
* console.log(result.data);
|
|
* } else {
|
|
* console.error(result.error);
|
|
* }
|
|
*/
|
|
export function safeJsonParse<T>(text: string, defaultValue?: T): SafeJsonParseResult<T> {
|
|
try {
|
|
const data = JSON.parse(text) as T;
|
|
return { success: true, data };
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : 'Unknown JSON parse error';
|
|
// Log truncated input for debugging
|
|
const truncatedInput = text.length > 100 ? `${text.substring(0, 100)}...` : text;
|
|
console.warn('[json-utils] Parse failed:', errorMessage, 'Input:', truncatedInput);
|
|
return {
|
|
success: false,
|
|
error: errorMessage,
|
|
data: defaultValue,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Safely parse JSON and return default value on failure
|
|
*
|
|
* Use this when you have a sensible default and don't need to know
|
|
* about parse failures.
|
|
*
|
|
* @param text - The JSON string to parse
|
|
* @param defaultValue - The value to return if parsing fails
|
|
* @returns The parsed data or the default value
|
|
*
|
|
* @example
|
|
* const config = parseJsonOrDefault(rawConfig, defaultConfig);
|
|
*/
|
|
export function parseJsonOrDefault<T>(text: string, defaultValue: T): T {
|
|
const result = safeJsonParse<T>(text, defaultValue);
|
|
return result.data!;
|
|
}
|
|
|
|
/**
|
|
* Safely parse JSON or throw a friendly error with context
|
|
*
|
|
* Use this when JSON parsing is required and failures should halt execution
|
|
* with a clear error message.
|
|
*
|
|
* @param text - The JSON string to parse
|
|
* @param context - Optional context for the error message (e.g., "loading config")
|
|
* @returns The parsed data
|
|
* @throws Error with context-aware message if parsing fails
|
|
*
|
|
* @example
|
|
* try {
|
|
* const data = parseJsonOrThrow<UserConfig>(rawJson, 'parsing user config');
|
|
* } catch (error) {
|
|
* showToast(error.message); // "JSON parse failed (parsing user config): Unexpected token..."
|
|
* }
|
|
*/
|
|
export function parseJsonOrThrow<T>(text: string, context?: string): T {
|
|
const result = safeJsonParse<T>(text);
|
|
if (!result.success) {
|
|
throw new Error(`JSON parse failed${context ? ` (${context})` : ''}: ${result.error}`);
|
|
}
|
|
return result.data!;
|
|
}
|
|
|
|
/**
|
|
* Type guard to check if a value is a valid JSON-compatible object
|
|
*
|
|
* @param value - The value to check
|
|
* @returns True if the value can be safely serialized to JSON
|
|
*/
|
|
export function isJsonSerializable(value: unknown): boolean {
|
|
try {
|
|
JSON.stringify(value);
|
|
return true;
|
|
} catch (_e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Safely stringify a value to JSON
|
|
*
|
|
* @param value - The value to stringify
|
|
* @param fallback - Fallback string if stringification fails
|
|
* @returns JSON string or fallback
|
|
*/
|
|
export function safeJsonStringify(value: unknown, fallback = '{}'): string {
|
|
try {
|
|
return JSON.stringify(value);
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : 'Unknown stringify error';
|
|
console.warn('[json-utils] Stringify failed:', errorMessage);
|
|
return fallback;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Safely stringify with pretty formatting
|
|
*
|
|
* @param value - The value to stringify
|
|
* @param indent - Number of spaces for indentation (default: 2)
|
|
* @param fallback - Fallback string if stringification fails
|
|
* @returns Formatted JSON string or fallback
|
|
*/
|
|
export function safeJsonStringifyPretty(value: unknown, indent = 2, fallback = '{}'): string {
|
|
try {
|
|
return JSON.stringify(value, null, indent);
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : 'Unknown stringify error';
|
|
console.warn('[json-utils] Pretty stringify failed:', errorMessage);
|
|
return fallback;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deep clone an object using JSON serialization
|
|
*
|
|
* Note: This only works for JSON-serializable data (no functions, undefined, symbols, etc.)
|
|
*
|
|
* @param value - The value to clone
|
|
* @returns A deep clone of the value
|
|
* @throws Error if the value cannot be serialized
|
|
*/
|
|
export function deepClone<T>(value: T): T {
|
|
return JSON.parse(JSON.stringify(value)) as T;
|
|
}
|
|
|
|
/**
|
|
* Safely deep clone an object with fallback
|
|
*
|
|
* @param value - The value to clone
|
|
* @param fallback - Fallback value if cloning fails
|
|
* @returns A deep clone of the value or the fallback
|
|
*/
|
|
export function safeDeepClone<T>(value: T, fallback: T): T {
|
|
try {
|
|
return JSON.parse(JSON.stringify(value)) as T;
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : 'Unknown clone error';
|
|
console.warn('[json-utils] Deep clone failed:', errorMessage);
|
|
return fallback;
|
|
}
|
|
}
|