avocavo
Version:
Avocavo CLI - Nutrition analysis made simple. Get accurate USDA nutrition data with secure authentication.
256 lines (222 loc) โข 8.96 kB
JavaScript
const chalk = require('chalk');
const { table } = require('table');
function formatNutrition(nutrition) {
if (!nutrition) return chalk.gray('No nutrition data available');
const lines = [];
// Helper function to format a value
const formatValue = (value, unit = '', decimals = 1) => {
if (value === null || value === undefined) {
return chalk.gray('null');
}
return chalk.bold(`${Number(value).toFixed(decimals)}${unit}`);
};
// Main macros - use _total format (API standard) with fallback to simple format
const calories = nutrition.calories_total ?? nutrition.calories;
const protein = nutrition.protein_total ?? nutrition.protein;
const fat = nutrition.total_fat_total ?? nutrition.total_fat;
const carbs = nutrition.carbohydrates_total ?? nutrition.carbohydrates;
const fiber = nutrition.fiber_total ?? nutrition.fiber;
const sugar = nutrition.sugar_total ?? nutrition.sugar;
// Primary nutrients
lines.push(` ๐ฅ Calories: ${formatValue(calories, '', 0)}`);
lines.push(` ๐ฅฉ Protein: ${formatValue(protein, 'g')}`);
lines.push(` ๐ง Total Fat: ${formatValue(fat, 'g')}`);
lines.push(` ๐พ Carbohydrates: ${formatValue(carbs, 'g')}`);
lines.push(` ๐ฟ Fiber: ${formatValue(fiber, 'g')}`);
lines.push(` ๐ฏ Sugar: ${formatValue(sugar, 'g')}`);
// Fat breakdown
lines.push(` ๐ Saturated Fat: ${formatValue(nutrition.saturated_fat, 'g')}`);
lines.push(` ๐ Monounsaturated Fat: ${formatValue(nutrition.monounsaturated_fat, 'g')}`);
lines.push(` ๐ Polyunsaturated Fat: ${formatValue(nutrition.polyunsaturated_fat, 'g')}`);
lines.push(` ๐ Trans Fat: ${formatValue(nutrition.trans_fat, 'g')}`);
lines.push(` ๐ Cholesterol: ${formatValue(nutrition.cholesterol, 'mg')}`);
// Minerals
lines.push(` ๐ง Sodium: ${formatValue(nutrition.sodium, 'mg')}`);
lines.push(` ๐ฆด Calcium: ${formatValue(nutrition.calcium, 'mg')}`);
lines.push(` ๐ฉธ Iron: ${formatValue(nutrition.iron, 'mg')}`);
lines.push(` ๐งฒ Magnesium: ${formatValue(nutrition.magnesium, 'mg')}`);
lines.push(` ๐ฆด Phosphorus: ${formatValue(nutrition.phosphorus, 'mg')}`);
lines.push(` ๐ Potassium: ${formatValue(nutrition.potassium, 'mg')}`);
lines.push(` ๐งฌ Zinc: ${formatValue(nutrition.zinc, 'mg')}`);
lines.push(` ๐งฌ Selenium: ${formatValue(nutrition.selenium, 'ยตg')}`);
// Vitamins
lines.push(` ๐ฅ Vitamin A: ${formatValue(nutrition.vitamin_a, 'ยตg')}`);
lines.push(` ๐ Vitamin C: ${formatValue(nutrition.vitamin_c, 'mg')}`);
lines.push(` โ๏ธ Vitamin D: ${formatValue(nutrition.vitamin_d_iu, 'IU')}`);
lines.push(` ๐ฟ Vitamin E: ${formatValue(nutrition.vitamin_e, 'mg')}`);
lines.push(` ๐ฅฌ Vitamin K: ${formatValue(nutrition.vitamin_k, 'ยตg')}`);
lines.push(` ๐ง Thiamin (B1): ${formatValue(nutrition.thiamin, 'mg')}`);
lines.push(` ๐ง Riboflavin (B2): ${formatValue(nutrition.riboflavin, 'mg')}`);
lines.push(` ๐ง Niacin (B3): ${formatValue(nutrition.niacin, 'mg')}`);
lines.push(` ๐ง Vitamin B6: ${formatValue(nutrition.vitamin_b6, 'mg')}`);
lines.push(` ๐ง Vitamin B12: ${formatValue(nutrition.vitamin_b12, 'ยตg')}`);
lines.push(` ๐งฌ Folate: ${formatValue(nutrition.folate, 'ยตg')}`);
return lines.length > 0 ? lines.join('\n') : chalk.gray('No nutrition data available');
}
function formatPerformanceMetrics(result) {
if (!result) return '';
const lines = [];
// Cache information (remove cache_type from user display)
if (result.metadata?.cached !== undefined || result.from_cache !== undefined) {
const cached = result.metadata?.cached ?? result.from_cache;
const cacheIcon = cached ? 'โก' : '๐';
const cacheText = cached ? 'Cached' : 'Fresh';
lines.push(` ${cacheIcon} Cache: ${chalk.cyan(cacheText)}`);
}
// Processing time
const processingTime = result.metadata?.processing_time_ms ?? result.processing_time_ms;
if (processingTime !== undefined) {
lines.push(` โฑ๏ธ Time: ${formatResponseTime(processingTime)}`);
}
// Method used
if (result.metadata?.method_used) {
const methodIcons = {
'sql_exact': '๐ฏ',
'fuzzy_match': '๐',
'llm_driven_search': '๐ค',
'usda_api_fallback': '๐',
'core_mapping_reuse': '๐พ',
'portion_adjusted': '๐',
'modifier_adjusted_conversion': '๐ง',
'small_measurement_fallback': '๐ค',
'small_measurement': '๐ค'
};
const methodDescriptions = {
'sql_exact': 'Direct USDA match',
'fuzzy_match': 'USDA fuzzy search',
'llm_driven_search': 'Smart USDA matching',
'usda_api_fallback': 'USDA API search',
'core_mapping_reuse': 'Cached USDA match',
'portion_adjusted': 'Size-adjusted USDA match',
'modifier_adjusted_conversion': 'Modified USDA match',
'small_measurement_fallback': 'Small portion USDA match',
'small_measurement': 'Micro portion USDA match'
};
const icon = methodIcons[result.metadata.method_used] || '๐ง';
lines.push(` ${icon} Method: ${chalk.blue(result.metadata.method_used)}`);
}
// Parsing tier information
if (result.metadata?.portion_source) {
const tierIcons = {
'tier_1_exact': '1๏ธโฃ',
'tier_2_fuzzy': '2๏ธโฃ',
'tier_3_adjusted': '3๏ธโฃ',
'tier_4_with_modifier': '4๏ธโฃ',
'tier_5_generic': '5๏ธโฃ',
'tier_6_small_measurement': '6๏ธโฃ',
'tier_7_semantic_match': '7๏ธโฃ'
};
const tierIcon = tierIcons[result.metadata.portion_source] || '๐ข';
lines.push(` ${tierIcon} Tier: ${chalk.green(result.metadata.portion_source)}`);
}
// Parsing details
if (result.parsing?.estimated_grams || result.estimated_grams) {
const grams = result.parsing?.estimated_grams ?? result.estimated_grams;
lines.push(` โ๏ธ Weight: ${chalk.magenta(grams + 'g')}`);
}
return lines.length > 0 ? '\n' + chalk.gray('Performance:') + '\n' + lines.join('\n') : '';
}
function formatUSDAMatch(usda, verificationUrl) {
if (!usda) return '';
const lines = [];
lines.push(` ๐ Description: ${chalk.cyan(usda.description)}`);
lines.push(` ๐ข FDC ID: ${chalk.yellow(usda.fdc_id)}`);
lines.push(` ๐ Data Type: ${chalk.blue(usda.data_type)}`);
if (verificationUrl) {
lines.push(` ๐ Verify: ${chalk.underline(verificationUrl)}`);
}
return '\n' + chalk.gray('USDA Verification:') + '\n' + lines.join('\n');
}
function formatTable(data, options = {}) {
const config = {
border: {
topBody: 'โ',
topJoin: 'โฌ',
topLeft: 'โ',
topRight: 'โ',
bottomBody: 'โ',
bottomJoin: 'โด',
bottomLeft: 'โ',
bottomRight: 'โ',
bodyLeft: 'โ',
bodyRight: 'โ',
bodyJoin: 'โ',
joinBody: 'โ',
joinLeft: 'โ',
joinRight: 'โค',
joinJoin: 'โผ'
},
drawHorizontalLine: (index, size) => {
return index === 0 || index === 1 || index === size;
},
...options
};
return table(data, config);
}
function formatBytes(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function formatDuration(ms) {
if (ms < 1000) {
return `${ms.toFixed(1)}ms`;
} else if (ms < 60000) {
return `${(ms / 1000).toFixed(1)}s`;
} else {
const minutes = Math.floor(ms / 60000);
const seconds = ((ms % 60000) / 1000).toFixed(1);
return `${minutes}m ${seconds}s`;
}
}
function formatPercentage(value, total) {
if (!total || total === 0) return '0%';
return `${((value / total) * 100).toFixed(1)}%`;
}
function formatUsage(current, limit) {
if (!limit) return `${current.toLocaleString()}`;
const percentage = (current / limit) * 100;
const color = percentage > 90 ? chalk.red : percentage > 75 ? chalk.yellow : chalk.green;
return `${color(current.toLocaleString())}/${limit.toLocaleString()} (${percentage.toFixed(1)}%)`;
}
function formatResponseTime(ms) {
if (ms < 100) {
return chalk.green(`${ms.toFixed(1)}ms`);
} else if (ms < 300) {
return chalk.yellow(`${ms.toFixed(1)}ms`);
} else {
return chalk.red(`${ms.toFixed(1)}ms`);
}
}
function formatStatus(status) {
switch (status.toLowerCase()) {
case 'ok':
case 'available':
case 'active':
case 'success':
return chalk.green(status);
case 'degraded':
case 'warning':
return chalk.yellow(status);
case 'error':
case 'failed':
case 'unavailable':
return chalk.red(status);
default:
return chalk.gray(status);
}
}
module.exports = {
formatNutrition,
formatPerformanceMetrics,
formatUSDAMatch,
formatTable,
formatBytes,
formatDuration,
formatPercentage,
formatUsage,
formatResponseTime,
formatStatus
};