appwrite-utils-cli
Version:
Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.
153 lines (152 loc) • 7.11 kB
JavaScript
import chalk from "chalk";
import { logger } from "./logging.js";
export class MessageFormatter {
static success(message, options = {}) {
const formatted = `${chalk.green("✅")} ${options.prefix ? `${options.prefix}: ` : ""}${message}`;
console.log(formatted);
if (!options.skipLogging) {
logger.info(`SUCCESS: ${options.prefix ? `${options.prefix}: ` : ""}${message}`);
}
}
static error(message, error, options = {}) {
const errorDetails = error instanceof Error ? error.message : error;
const formatted = `${chalk.red("❌")} ${options.prefix ? `${options.prefix}: ` : ""}${message}${errorDetails ? `\n ${chalk.gray(errorDetails)}` : ""}`;
console.error(formatted);
if (!options.skipLogging) {
logger.error(`ERROR: ${options.prefix ? `${options.prefix}: ` : ""}${message}`, {
error: errorDetails,
stack: error instanceof Error ? error.stack : undefined,
});
}
}
static warning(message, options = {}) {
const formatted = `${chalk.yellow("⚠️")} ${options.prefix ? `${options.prefix}: ` : ""}${message}`;
console.log(formatted);
if (!options.skipLogging) {
logger.warn(`WARNING: ${options.prefix ? `${options.prefix}: ` : ""}${message}`);
}
}
static info(message, options = {}) {
const formatted = `${chalk.blue("ℹ️")} ${options.prefix ? `${options.prefix}: ` : ""}${message}`;
console.log(formatted);
if (!options.skipLogging) {
logger.info(`INFO: ${options.prefix ? `${options.prefix}: ` : ""}${message}`);
}
}
static step(step, total, message, options = {}) {
const formatted = `${chalk.cyan(`[${step}/${total}]`)} ${options.prefix ? `${options.prefix}: ` : ""}${message}`;
console.log(formatted);
if (!options.skipLogging) {
logger.info(`STEP ${step}/${total}: ${options.prefix ? `${options.prefix}: ` : ""}${message}`);
}
}
static progress(message, options = {}) {
const formatted = `${chalk.gray("⏳")} ${options.prefix ? `${options.prefix}: ` : ""}${message}`;
console.log(formatted);
if (!options.skipLogging) {
logger.debug(`PROGRESS: ${options.prefix ? `${options.prefix}: ` : ""}${message}`);
}
}
static debug(message, data, options = {}) {
if (process.env.NODE_ENV === "development" || process.env.DEBUG) {
const formatted = `${chalk.magenta("🔍")} ${options.prefix ? `${options.prefix}: ` : ""}${message}`;
console.log(formatted);
if (data) {
console.log(chalk.gray(JSON.stringify(data, null, 2)));
}
}
if (!options.skipLogging) {
logger.debug(`DEBUG: ${options.prefix ? `${options.prefix}: ` : ""}${message}`, data);
}
}
static banner(title, subtitle) {
const divider = chalk.cyan("═".repeat(60));
console.log(`\n${divider}`);
console.log(chalk.cyan.bold(` ${title}`));
if (subtitle) {
console.log(chalk.gray(` ${subtitle}`));
}
console.log(`${divider}\n`);
}
static section(title) {
console.log(`\n${chalk.bold.underline(title)}`);
}
static list(items, title) {
if (title) {
console.log(chalk.bold(title));
}
items.forEach((item, index) => {
console.log(`${chalk.gray(` ${index + 1}.`)} ${item}`);
});
}
static table(data, headers) {
if (data.length === 0)
return;
const keys = headers || Object.keys(data[0]);
const maxWidths = keys.map(key => Math.max(key.length, ...data.map(row => String(row[key]).length)));
// Header
const headerRow = keys.map((key, i) => chalk.bold(key.padEnd(maxWidths[i]))).join(" │ ");
console.log(`┌─${keys.map((_, i) => "─".repeat(maxWidths[i])).join("─┼─")}─┐`);
console.log(`│ ${headerRow} │`);
console.log(`├─${keys.map((_, i) => "─".repeat(maxWidths[i])).join("─┼─")}─┤`);
// Rows
data.forEach(row => {
const dataRow = keys.map((key, i) => String(row[key]).padEnd(maxWidths[i])).join(" │ ");
console.log(`│ ${dataRow} │`);
});
console.log(`└─${keys.map((_, i) => "─".repeat(maxWidths[i])).join("─┴─")}─┘`);
}
static operationSummary(title, stats, duration) {
this.section(`${title} Summary`);
Object.entries(stats).forEach(([key, value]) => {
const formattedKey = key.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase());
console.log(`${chalk.gray("●")} ${formattedKey}: ${chalk.cyan(String(value))}`);
});
if (duration) {
console.log(`${chalk.gray("●")} Duration: ${chalk.cyan(this.formatDuration(duration))}`);
}
console.log();
}
static formatBytes(bytes) {
const units = ['B', 'KB', 'MB', 'GB', 'TB'];
let size = bytes;
let unitIndex = 0;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
unitIndex++;
}
return `${size.toFixed(1)} ${units[unitIndex]}`;
}
static formatDuration(ms) {
const seconds = Math.floor(ms / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
if (hours > 0) {
return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
}
else if (minutes > 0) {
return `${minutes}m ${seconds % 60}s`;
}
else {
return `${seconds}s`;
}
}
static formatNumber(num) {
return num.toLocaleString();
}
}
export const Messages = {
CONFIG_NOT_FOUND: "Appwrite configuration not found. Run 'appwrite-migrate setup' first.",
CONFIG_LOADED: (type, path) => `Loaded ${type} configuration from ${path}`,
DATABASE_CONNECTION_FAILED: "Failed to connect to Appwrite. Check your endpoint and API key.",
OPERATION_CANCELLED: "Operation cancelled by user.",
OPERATION_COMPLETED: (operation) => `${operation} completed successfully`,
BACKUP_STARTED: (database) => `Starting backup for database: ${database}`,
BACKUP_COMPLETED: (database, size) => `Backup completed for ${database} (${MessageFormatter.formatBytes(size)})`,
IMPORT_STARTED: (collections) => `Starting import process for ${collections} collection(s)`,
IMPORT_COMPLETED: (documents) => `Import completed. Processed ${MessageFormatter.formatNumber(documents)} documents`,
FUNCTION_DEPLOYED: (name) => `Function '${name}' deployed successfully`,
FUNCTION_DEPLOYMENT_FAILED: (name, error) => `Function '${name}' deployment failed: ${error}`,
TRANSFER_STARTED: (source, target) => `Starting transfer from ${source} to ${target}`,
TRANSFER_COMPLETED: (items) => `Transfer completed. Moved ${MessageFormatter.formatNumber(items)} items`,
};