avocavo 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/bin/avocavo.js +61 -15
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the Avocavo CLI will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.0.4] - 2025-08-04
|
|
6
|
+
|
|
7
|
+
### 🔧 Login Experience Fixes
|
|
8
|
+
- **FIXED**: Login no longer incorrectly reports "no API keys" when user has existing keys
|
|
9
|
+
- **IMPROVED**: Smart API key detection after login - checks server for all user keys
|
|
10
|
+
- **ADDED**: Auto-selection of single API key for seamless experience
|
|
11
|
+
- **ENHANCED**: Better messaging for users with multiple API keys
|
|
12
|
+
|
|
13
|
+
### 🎯 Key Management Improvements
|
|
14
|
+
- **SMART**: If user has exactly 1 API key, it's automatically selected and activated
|
|
15
|
+
- **GUIDANCE**: Users with multiple keys get clear instructions to run `avocavo keys switch`
|
|
16
|
+
- **ACCURATE**: Login now correctly identifies users with 0, 1, or multiple API keys
|
|
17
|
+
- **RELIABLE**: Fallback handling if API key check fails
|
|
18
|
+
|
|
19
|
+
### 🛠️ Technical Changes
|
|
20
|
+
- Enhanced post-login API key detection logic
|
|
21
|
+
- Added server-side key enumeration via `/api/keys` endpoint
|
|
22
|
+
- Improved error handling and user guidance messages
|
|
23
|
+
- Better integration between authentication and key management systems
|
|
24
|
+
|
|
5
25
|
## [1.0.3] - 2025-08-04
|
|
6
26
|
|
|
7
27
|
### 🔐 Authentication Fixes
|
package/bin/avocavo.js
CHANGED
|
@@ -4,6 +4,7 @@ const { program } = require('commander');
|
|
|
4
4
|
const chalk = require('chalk');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const fs = require('fs');
|
|
7
|
+
const axios = require('axios');
|
|
7
8
|
const { NutritionAPI } = require('../lib/api');
|
|
8
9
|
const { AuthManager } = require('../lib/auth');
|
|
9
10
|
const { formatNutrition, formatPerformanceMetrics, formatUSDAMatch, formatTable } = require('../lib/formatters');
|
|
@@ -77,11 +78,13 @@ program
|
|
|
77
78
|
if (success) {
|
|
78
79
|
console.log(chalk.green('✅ Successfully logged in!'));
|
|
79
80
|
|
|
80
|
-
//
|
|
81
|
-
|
|
81
|
+
// Check for API keys - first check if user has a selected key
|
|
82
|
+
let apiKey = await auth.getApiKey();
|
|
83
|
+
|
|
82
84
|
if (apiKey) {
|
|
85
|
+
// User has a selected API key, test it
|
|
83
86
|
if (program.opts().verbose) {
|
|
84
|
-
console.log(chalk.gray(`Debug: API key
|
|
87
|
+
console.log(chalk.gray(`Debug: Using selected API key: ${apiKey.substring(0, 12)}...`));
|
|
85
88
|
}
|
|
86
89
|
const api = new NutritionAPI(apiKey, program.opts().baseUrl, 30000, auth);
|
|
87
90
|
try {
|
|
@@ -89,23 +92,66 @@ program
|
|
|
89
92
|
console.log(chalk.cyan(`📊 Account: ${account.email} (${account.api_tier} tier)`));
|
|
90
93
|
console.log(chalk.cyan(`📈 Usage: ${account.usage.current_month}/${account.usage.monthly_limit || 'unlimited'}`));
|
|
91
94
|
} catch (err) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
console.log(chalk.yellow('⚠️ You don\'t have any API keys yet'));
|
|
95
|
-
console.log(chalk.cyan('💡 Create your first API key to start using the nutrition API:'));
|
|
96
|
-
console.log(chalk.cyan(' avocavo keys create'));
|
|
95
|
+
console.log(chalk.yellow('⚠️ Selected API key appears invalid'));
|
|
96
|
+
console.log(chalk.cyan('💡 Try selecting a different key with: avocavo keys switch'));
|
|
97
97
|
if (program.opts().verbose) {
|
|
98
98
|
console.log(chalk.gray(`Debug: ${err.message}`));
|
|
99
|
-
console.log(chalk.gray(`Debug: Status ${err.statusCode || 'unknown'}`));
|
|
100
|
-
if (err.response?.data) {
|
|
101
|
-
console.log(chalk.gray(`Response: ${JSON.stringify(err.response.data, null, 2)}`));
|
|
102
|
-
}
|
|
103
99
|
}
|
|
104
100
|
}
|
|
105
101
|
} else {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
102
|
+
// No selected API key, check if user has any keys at all
|
|
103
|
+
try {
|
|
104
|
+
const KeyManager = require('../lib/keys');
|
|
105
|
+
const keyManager = new KeyManager(auth, program.opts().baseUrl);
|
|
106
|
+
|
|
107
|
+
// Get user's API keys from server
|
|
108
|
+
const headers = await keyManager.getAuthHeaders();
|
|
109
|
+
const response = await axios.get(`${program.opts().baseUrl}/api/keys`, { headers });
|
|
110
|
+
|
|
111
|
+
if (response.data.keys && response.data.keys.length > 0) {
|
|
112
|
+
const keyCount = response.data.keys.length;
|
|
113
|
+
|
|
114
|
+
if (keyCount === 1) {
|
|
115
|
+
// Auto-select the single key
|
|
116
|
+
console.log(chalk.cyan('🔄 You have 1 API key. Auto-selecting it...'));
|
|
117
|
+
const singleKey = response.data.keys[0];
|
|
118
|
+
|
|
119
|
+
// Store the key as selected (simplified approach)
|
|
120
|
+
await auth.storeApiKeySecurely(auth.getUserInfo().email, singleKey.api_key);
|
|
121
|
+
|
|
122
|
+
// Test the auto-selected key
|
|
123
|
+
const api = new NutritionAPI(singleKey.api_key, program.opts().baseUrl, 30000, auth);
|
|
124
|
+
try {
|
|
125
|
+
const account = await api.getAccountUsage();
|
|
126
|
+
console.log(chalk.green('✅ API key activated!'));
|
|
127
|
+
console.log(chalk.cyan(`📊 Account: ${account.email} (${account.api_tier} tier)`));
|
|
128
|
+
console.log(chalk.cyan(`📈 Usage: ${account.usage.current_month}/${account.usage.monthly_limit || 'unlimited'}`));
|
|
129
|
+
} catch (err) {
|
|
130
|
+
console.log(chalk.yellow('⚠️ Auto-selected API key appears invalid'));
|
|
131
|
+
console.log(chalk.cyan('💡 Check your keys with: avocavo keys list'));
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
// Multiple keys - prompt user to select one
|
|
135
|
+
console.log(chalk.cyan(`💡 You have ${keyCount} API keys but none selected. Choose one to activate:`));
|
|
136
|
+
console.log(chalk.cyan(' avocavo keys switch'));
|
|
137
|
+
console.log(chalk.gray(' or'));
|
|
138
|
+
console.log(chalk.cyan(' avocavo keys list'));
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
// No API keys at all
|
|
142
|
+
console.log(chalk.yellow('⚠️ You don\'t have any API keys yet'));
|
|
143
|
+
console.log(chalk.cyan('💡 Create your first API key to start using the nutrition API:'));
|
|
144
|
+
console.log(chalk.cyan(' avocavo keys create'));
|
|
145
|
+
}
|
|
146
|
+
} catch (keyCheckError) {
|
|
147
|
+
// Fallback to create message if we can't check existing keys
|
|
148
|
+
console.log(chalk.yellow('⚠️ Unable to check for existing API keys'));
|
|
149
|
+
console.log(chalk.cyan('💡 Create an API key to start using the nutrition API:'));
|
|
150
|
+
console.log(chalk.cyan(' avocavo keys create'));
|
|
151
|
+
if (program.opts().verbose) {
|
|
152
|
+
console.log(chalk.gray(`Debug: ${keyCheckError.message}`));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
109
155
|
}
|
|
110
156
|
} else {
|
|
111
157
|
console.log(chalk.red('❌ Login failed'));
|