ws-dottie
Version:
Your friendly TypeScript companion for Washington State transportation APIs - WSDOT and WSF data with smart caching and React Query integration
154 lines (152 loc) • 5.8 kB
JavaScript
/**
* UI and output utilities
*/
import chalk from "chalk";
import { discoverEndpoints } from "@/shared/endpoints";
import { WsdotApiError } from "@/shared/fetching/handleErrors";
/**
* Handle errors with consistent formatting and helpful context
* @param error - The error to handle (can be any type)
* @param functionName - Name of the function that caused the error
* @throws Never returns, always exits process with code 1
*/
export const handleError = (error, functionName) => {
// Extract message based on error type
const message = error instanceof WsdotApiError
? error.userMessage
: error instanceof Error
? error.message
: String(error);
console.error(chalk.red(`❌ Error calling ${functionName}:`));
console.error(chalk.yellow(message));
// Add context based on error type
addErrorContext(error);
// Add stack trace in debug mode for generic errors
if (error instanceof Error &&
!(error instanceof WsdotApiError) &&
error.stack &&
process.env.NODE_ENV === "development") {
console.error(chalk.gray(error.stack));
}
process.exit(1);
};
/**
* Add helpful context based on error type
* @param error - The error to add context for
*/
const addErrorContext = (error) => {
if (error instanceof WsdotApiError) {
if (error.code === "API_ERROR") {
console.error(chalk.gray("💡 Tip: Check your API key and parameters"));
}
else if (error.code === "NETWORK_ERROR") {
console.error(chalk.gray("💡 Tip: Check your internet connection"));
}
else if (error.code === "TRANSFORM_ERROR") {
console.error(chalk.gray("💡 Tip: Check the function documentation for required parameters"));
}
return;
}
// Generic error context
const message = error instanceof Error ? error.message : String(error);
if (message.includes("Invalid JSON parameters")) {
console.error(chalk.gray("💡 Tip: Ensure your parameters are valid JSON"));
}
else if (message.includes("Parameter validation failed")) {
console.error(chalk.gray("💡 Tip: Check the function documentation for required parameters"));
}
else if (message.includes("not found")) {
console.error(chalk.gray("💡 Tip: Use --help to see available functions"));
}
};
/**
* Display function not found error with list of available functions
* @param functionName - The function name that was not found
*/
export const displayFunctionNotFound = (functionName) => {
const endpoints = discoverEndpoints();
const availableFunctions = endpoints.map((ep) => ep.functionName);
console.error(chalk.red(`❌ Function '${functionName}' not found`));
console.error(chalk.yellow("Available functions:"));
availableFunctions.forEach((func) => {
console.error(chalk.gray(` ${func}`));
});
};
/**
* Output result with formatting based on CLI options
* @param result - The result data to output
* @param options - CLI options controlling output format (pretty, head, etc.)
*/
export const outputResult = (result, options) => {
const jsonString = JSON.stringify(result, null, options.pretty ? 2 : undefined);
if (options.head && options.head > 0) {
const lines = jsonString.split("\n");
const truncatedLines = lines.slice(0, options.head);
console.log(truncatedLines.join("\n"));
}
else {
console.log(jsonString);
}
};
/**
* Setup console suppression for quiet modes
* @param isQuiet - Whether to suppress console output
* @returns Object with restore method to re-enable console output
*/
export const setupConsoleSuppression = (isQuiet) => {
if (!isQuiet)
return { restore: () => { } };
const originalLog = console.log;
const originalError = console.error;
// Suppress all console output
console.log = console.error = () => { };
return {
restore: () => {
console.log = originalLog;
console.error = originalError;
},
};
};
/**
* Generate default CLI examples for a given tool name
* @param toolName - Name of the CLI tool
* @param additionalExamples - Additional examples to include
* @returns Array of example command strings
*/
export const generateDefaultExamples = (toolName, additionalExamples = []) => {
const baseExamples = [
`${toolName} getBorderCrossings`,
`${toolName} getBridgeClearances '{"route": "005"}'`,
`${toolName} getFareLineItems '{"originTerminalId": 7, "destinationTerminalId": 3, "date": "2025-01-27"}'`,
`${toolName} getVesselLocationsByVesselId # Uses default vesselId: 1`,
`${toolName} getBorderCrossings --raw`,
];
return [...baseExamples, ...additionalExamples];
};
/**
* Generate help text with examples and available functions
* @param toolName - Name of the CLI tool
* @param examples - Array of example commands to include
* @returns Formatted help text string
*/
export const generateHelpText = (toolName, examples = []) => {
const endpoints = discoverEndpoints();
const functionList = endpoints
.map((endpointDef) => {
const functionName = endpointDef.functionName;
const api = endpointDef.api;
const description = `${api} - ${functionName}`;
return ` ${chalk.cyan(functionName)} - ${description}`;
})
.join("\n");
const defaultExamples = generateDefaultExamples(toolName);
const exampleList = examples.length > 0 ? examples : defaultExamples;
return `
Examples:
${exampleList.map((ex) => ` ${ex}`).join("\n")}
Available functions:
${functionList}
For more information about parameters, see the ws-dottie documentation.
`;
};
//# sourceMappingURL=ui.js.map