UNPKG

puter-cli

Version:

Command line interface for Puter cloud platform

195 lines (178 loc) 6.94 kB
import chalk from 'chalk'; import Conf from 'conf'; import ora from 'ora'; import { PROJECT_NAME, } from '../commons.js' import { getProfileModule } from '../modules/ProfileModule.js'; import { getPuter } from '../modules/PuterModule.js'; const config = new Conf({ projectName: PROJECT_NAME }); /** * Login user * @param {Object} options - Login options * @param {boolean} options.save - Save token to .env file * @param {boolean} options.web - Use browser-based login (default) * @param {boolean} options.withCredentials - Use username/password login * @param {string} options.host - Puter host URL * @returns void */ export async function login(options = {}) { const profileAPI = getProfileModule(); await profileAPI.switchProfileWizard(options); } /** * Logout user * @returns void */ export async function logout() { let spinner; try { spinner = ora('Logging out from Puter...').start(); const token = config.get('auth_token'); const selected_profile = config.get('selected_profile'); if (token) { // legacy auth config.clear(); spinner.succeed(chalk.green('Successfully logged out from Puter!')); } else if (selected_profile) { // multi profile auth config.delete('selected_profile'); config.delete('username'); config.delete('cwd'); const profiles = config.get('profiles'); config.set('profiles', profiles.filter(profile => profile.uuid != selected_profile)); spinner.succeed(chalk.green('Successfully logged out from Puter!')); } else { spinner.info(chalk.yellow('Already logged out')); } } catch (error) { if (spinner) { spinner.fail(chalk.red('Failed to logout')); } console.error(chalk.red(`Error: ${error.message}`)); } } export async function getUserInfo() { console.log(chalk.green('Getting user info...\n')); const puter = getPuter(); try { const data = await puter.auth.getUser(); if (data) { console.log(chalk.cyan('User Information:')); console.log(chalk.dim('----------------------------------------')); console.log(chalk.cyan(`Username: `) + chalk.white(data.username)); console.log(chalk.cyan(`UUID: `) + chalk.white(data.uuid)); console.log(chalk.cyan(`Email: `) + chalk.white(data.email)); console.log(chalk.cyan(`Email Confirmed: `) + chalk.white(data.email_confirmed ? 'Yes' : 'No')); console.log(chalk.cyan(`Temporary Account: `) + chalk.white(data.is_temp ? 'Yes' : 'No')); console.log(chalk.cyan(`Account Age: `) + chalk.white(data.human_readable_age)); console.log(chalk.dim('----------------------------------------')); console.log(chalk.cyan('Feature Flags:')); for (const [flag, enabled] of Object.entries(data.feature_flags)) { console.log(chalk.cyan(` - ${flag}: `) + chalk.white(enabled ? 'Enabled' : 'Disabled')); } console.log(chalk.dim('----------------------------------------')); console.log(chalk.green('Done.')); } else { console.error(chalk.red('Unable to get your info. Please check your credentials.')); } } catch (error) { console.error(chalk.red(`Failed to get user info.\nError: ${error.message}`)); console.log(error); } } export function isAuthenticated() { return !!config.get('auth_token'); } export function getAuthToken() { const profileAPI = getProfileModule();; return profileAPI.getAuthToken(); } export function getCurrentUserName() { const profileAPI = getProfileModule();; return profileAPI.getCurrentProfile()?.username; } export function getCurrentDirectory() { return config.get('cwd'); } /** * Fetch usage information */ export async function getUsageInfo() { console.log(chalk.green('Fetching usage information...\n')); const puter = getPuter(); try { const data = await puter.auth.getMonthlyUsage(); if (data) { // Display allowance information if (data.allowanceInfo) { console.log(chalk.cyan('Allowance Information:')); console.log(chalk.dim('='.repeat(100))); console.log(chalk.cyan(`Month Usage Allowance: `) + chalk.white(data.allowanceInfo.monthUsageAllowance.toLocaleString())); console.log(chalk.cyan(`Remaining: `) + chalk.white(data.allowanceInfo.remaining.toLocaleString())); const usedPercentage = ((data.allowanceInfo.monthUsageAllowance - data.allowanceInfo.remaining) / data.allowanceInfo.monthUsageAllowance * 100).toFixed(2); console.log(chalk.cyan(`Used: `) + chalk.white(`${usedPercentage}%`)); console.log(chalk.dim('='.repeat(100))); } // Display usage information per API if (data.usage) { console.log(chalk.cyan('\nAPI Usage:')); console.log(chalk.dim('='.repeat(100))); console.log( chalk.bold('API'.padEnd(50)) + chalk.bold('Count'.padEnd(15)) + chalk.bold('Cost'.padEnd(20)) + chalk.bold('Units') ); console.log(chalk.dim('='.repeat(100))); // Filter out 'total' and sort entries by cost (descending) const usageEntries = Object.entries(data.usage) .filter(([key]) => key !== 'total') .sort(([, a], [, b]) => b.cost - a.cost); usageEntries.forEach(([api, details]) => { console.log( api.padEnd(50) + details.count.toString().padEnd(15) + details.cost.toLocaleString().padEnd(20) + details.units.toLocaleString() ); }); // Display total if available if (data.usage.total !== undefined) { console.log(chalk.dim('='.repeat(100))); console.log( chalk.bold('TOTAL'.padEnd(50)) + ''.padEnd(15) + chalk.bold(data.usage.total.toLocaleString()) ); } console.log(chalk.dim('='.repeat(100))); } // Display app totals if (data.appTotals && Object.keys(data.appTotals).length > 0) { console.log(chalk.cyan('\nApp Totals:')); console.log(chalk.dim('='.repeat(100))); console.log( chalk.bold('App'.padEnd(50)) + chalk.bold('Count'.padEnd(15)) + chalk.bold('Total') ); console.log(chalk.dim('='.repeat(100))); // Sort by total (descending) const appEntries = Object.entries(data.appTotals) .sort(([, a], [, b]) => b.total - a.total); appEntries.forEach(([app, details]) => { console.log( app.padEnd(50) + details.count.toString().padEnd(15) + details.total.toLocaleString() ); }); console.log(chalk.dim('='.repeat(100))); } console.log(chalk.green('Done.')); } else { console.error(chalk.red('Unable to fetch usage information.')); } } catch (error) { console.error(chalk.red(`Failed to fetch usage information.\nError: ${error.message}`)); } }