wp-host
Version:
Automated WordPress hosting deployment tool for bulk site creation with MySQL database management
1,045 lines โข 50.8 kB
JavaScript
#!/usr/bin/env node
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const commander_1 = require("commander");
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const config_parser_1 = require("./config-parser");
const mysql_manager_1 = require("./mysql-manager");
const database_manager_1 = require("./database-manager");
const wordpress_manager_1 = require("./wordpress-manager");
const config_manager_1 = require("./config-manager");
const permissions_manager_1 = require("./permissions-manager");
const app_password_manager_1 = require("./app-password-manager");
const export_manager_1 = require("./export-manager");
const prompt_service_1 = require("./prompt-service");
const program = new commander_1.Command();
program
.name("wp-hosting-automation")
.description("WordPress Batch Hosting Tool - Deploy multiple WordPress sites with MySQL databases")
.version("1.0.0");
program
.command("deploy")
.description("Deploy WordPress sites with interactive options")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("-v, --verbose", "Enable verbose logging")
.option("--skip-prompts", "Skip interactive prompts (non-interactive mode)")
.option("--app-passwords", "Generate application passwords automatically")
.option("--export [path]", "Export deployment results to CSV")
.option("--no-db-suffix", "Use site names as database names without _db suffix")
.option("--use-existing-databases", "Use existing databases instead of dropping and recreating them")
.action(async (options) => {
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
console.log("\n๐ก Create a configuration file with your site details:");
console.log(" - JSON format: sites.json");
console.log(" - CSV format: sites.csv");
process.exit(1);
}
try {
// Set database suffix preference
if (options.noDbSuffix) {
config_parser_1.ConfigParser.setNoDbSuffix(true);
}
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
if (options.verbose) {
console.log(`โ
Configuration loaded successfully:`);
console.log(` - Found ${config.sites.length} site(s) to deploy`);
console.log(` - MySQL: ${config.mysql.host}:${config.mysql.port}`);
console.log(` - WordPress Admin: ${config.wordpress.adminEmail}`);
}
// Initialize prompt service
const promptService = new prompt_service_1.PromptService();
// Get deployment options (interactive or from CLI flags)
let deploymentOptions;
if (options.skipPrompts) {
deploymentOptions = {
cleanAllDirectories: false, // Default to false for non-interactive mode
generateAppPasswords: !!options.appPasswords,
generateExport: !!options.export,
exportPath: typeof options.export === "string" ? options.export : undefined,
};
}
else {
deploymentOptions = await promptService.promptDeploymentOptions();
}
// Show deployment preview and get confirmation
if (!options.skipPrompts) {
const confirmed = await promptService.promptDeploymentPreview(config.sites.length, deploymentOptions);
if (!confirmed) {
console.log("โ Deployment cancelled by user");
process.exit(0);
}
}
console.log("\n๐ Starting deployment process...");
// Step 1: Create databases
console.log("\n๐ Step 1: Creating databases and users...");
const databaseManager = new database_manager_1.DatabaseManager(config);
await databaseManager.initialize();
const dbResults = await databaseManager.createAllDatabases(options.useExistingDatabases);
const dbSummary = databaseManager.getSummary(dbResults);
if (dbSummary.failed > 0) {
console.error(`โ Database creation failed for ${dbSummary.failed} sites. Aborting deployment.`);
await databaseManager.close();
process.exit(1);
}
console.log(`โ
Databases created successfully (${dbSummary.successful}/${dbSummary.total})`);
await databaseManager.close();
// Step 2: WordPress installation and setup
console.log("\n๐ Step 2: Installing and configuring WordPress...");
const wordpressManager = new wordpress_manager_1.WordPressManager(config);
const wpResults = await wordpressManager.installAllSites(deploymentOptions.cleanAllDirectories);
const wpSummary = wordpressManager.getSummary(wpResults);
if (wpSummary.failed > 0) {
console.error(`โ WordPress installation failed for ${wpSummary.failed} sites. Deployment incomplete.`);
process.exit(1);
}
console.log(`โ
WordPress installed and configured successfully (${wpSummary.successful}/${wpSummary.total})`);
// Step 3: Set file permissions
console.log("\n๐ Step 3: Setting file permissions...");
const permissionsManager = new permissions_manager_1.PermissionsManager(config);
const permissionResults = await permissionsManager.setAllPermissions();
const permissionSummary = permissionsManager.getSummary(permissionResults);
if (permissionSummary.failed > 0) {
console.error(`โ Permission setting failed for ${permissionSummary.failed} sites. Deployment incomplete.`);
process.exit(1);
}
console.log(`โ
File permissions set successfully (${permissionSummary.successful}/${permissionSummary.total})`);
// Step 4: Generate application passwords (optional)
let appPasswordResults;
if (deploymentOptions.generateAppPasswords) {
console.log("\n๐ Step 4: Generating application passwords...");
const appPasswordManager = new app_password_manager_1.AppPasswordManager(config);
appPasswordResults = await appPasswordManager.generateAllAppPasswords();
appPasswordManager.displaySummary(appPasswordResults);
}
// Step 5: Export deployment results (optional)
let exportPath;
if (deploymentOptions.generateExport) {
console.log("\n๐ Step 5: Exporting deployment results...");
const exportManager = new export_manager_1.ExportManager(config);
exportPath = await exportManager.generateDeploymentExport(wpResults, appPasswordResults, deploymentOptions.exportPath);
}
// Show completion summary
const totalSuccessful = Math.min(dbSummary.successful, wpSummary.successful, permissionSummary.successful);
promptService.displayCompletionSummary(totalSuccessful, config.sites.length, !!appPasswordResults, !!exportPath, exportPath);
if (options.verbose) {
console.log("\n๐ Detailed Results:");
for (const site of config.sites) {
const siteResult = wpResults.find((r) => r.site_name === site.site_name);
console.log(`\n๐ฆ Site: ${site.site_name}`);
console.log(` Directory: ${site.directory_path}`);
console.log(` Database: ${site.database_name}`);
console.log(` DB User: ${site.db_user}`);
console.log(` Admin User: ${site.wordpress_admin_username || "admin"}`);
console.log(` Admin Email: ${config.wordpress.adminEmail}`);
if (siteResult?.wordpress_info) {
console.log(` Site URL: ${siteResult.wordpress_info.site_url}`);
}
if (appPasswordResults) {
const appResult = appPasswordResults.find((r) => r.site_name === site.site_name);
if (appResult) {
console.log(` App Password: ${appResult.app_password}`);
}
}
}
}
}
catch (error) {
console.error(`โ Configuration error: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("validate")
.description("Validate configuration file without deploying")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("-v, --verbose", "Enable verbose logging")
.option("--no-db-suffix", "Use site names as database names without _db suffix")
.action(async (options) => {
console.log("๐ WordPress Configuration Validator");
console.log("===================================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
// Set database suffix preference
if (options.noDbSuffix) {
config_parser_1.ConfigParser.setNoDbSuffix(true);
}
console.log(`๐ Validating configuration: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
console.log("โ
Configuration is valid!");
console.log(`\n๐ Summary:`);
console.log(` - Sites to deploy: ${config.sites.length}`);
console.log(` - MySQL: ${config.mysql.host}:${config.mysql.port}`);
console.log(` - WordPress Admin: ${config.wordpress.adminEmail}`);
if (options.verbose) {
console.log("\n๐ Site Details:");
config.sites.forEach((site, index) => {
console.log(` ${index + 1}. ${site.site_name}`);
console.log(` Path: ${site.directory_path}`);
console.log(` Database: ${site.database_name}`);
if (site.db_user)
console.log(` DB User: ${site.db_user}`);
});
console.log("\n๐๏ธ MySQL Configuration:");
console.log(` Host: ${config.mysql.host}`);
console.log(` Port: ${config.mysql.port}`);
console.log(` Root User: ${config.mysql.rootUser}`);
console.log(` Root Password: ${"*".repeat(config.mysql.rootPassword.length)}`);
console.log(` Shared DB Password: ${"*".repeat(config.mysql.sharedDbPassword.length)}`);
console.log("\n๐ WordPress Configuration:");
console.log(` Admin Email: ${config.wordpress.adminEmail}`);
console.log(` Admin Password: ${"*".repeat(config.wordpress.adminPassword.length)}`);
}
}
catch (error) {
console.error(`โ Validation failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("test-connection")
.description("Test MySQL connection using configuration file")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.action(async (options) => {
console.log("๐งช MySQL Connection Tester");
console.log("==========================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
console.log(`๐ Reading MySQL configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
const mysqlManager = new mysql_manager_1.MySQLManager(config.mysql);
// Test connection
const isConnected = await mysqlManager.testConnection();
if (isConnected) {
// Get server info if connection successful
await mysqlManager.connect();
const serverInfo = await mysqlManager.getServerInfo();
await mysqlManager.disconnect();
console.log("\n๐ MySQL Server Information:");
console.log(` Version: ${serverInfo.version}`);
console.log(` Host: ${serverInfo.host}:${serverInfo.port}`);
console.log("\nโ
MySQL connection is working correctly!");
console.log("๐ You can now run deployment commands.");
}
else {
console.log("\nโ MySQL connection failed!");
console.log("๐ก Please check:");
console.log(" - MySQL server is running");
console.log(" - Host and port are correct");
console.log(" - Root username and password are correct");
process.exit(1);
}
}
catch (error) {
console.error(`โ Connection test failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("create-databases")
.description("Create MySQL databases and users for all sites")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("-v, --verbose", "Enable verbose logging")
.option("--no-db-suffix", "Use site names as database names without _db suffix")
.option("--use-existing-databases", "Use existing databases instead of dropping and recreating them")
.action(async (options) => {
console.log("๐๏ธ WordPress Database Creator");
console.log("==============================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
let databaseManager = null;
try {
// Set database suffix preference
if (options.noDbSuffix) {
config_parser_1.ConfigParser.setNoDbSuffix(true);
}
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
if (options.verbose) {
console.log(`โ
Configuration loaded: ${config.sites.length} site(s) found`);
}
// Initialize database manager
databaseManager = new database_manager_1.DatabaseManager(config);
await databaseManager.initialize();
// Create all databases
const results = await databaseManager.createAllDatabases(options.useExistingDatabases);
// Show summary
const summary = databaseManager.getSummary(results);
console.log("\n๐ Database Creation Summary");
console.log("============================");
console.log(`Total Sites: ${summary.total}`);
console.log(`โ
Successful: ${summary.successful}`);
console.log(`โ Failed: ${summary.failed}`);
console.log(`โญ๏ธ Skipped: ${summary.skipped}`);
if (summary.failed > 0) {
console.log("\nโ ๏ธ Some databases failed to create. Check the errors above.");
process.exit(1);
}
else {
console.log("\n๐ All databases created successfully!");
console.log("โ
Ready for WordPress installation.");
}
}
catch (error) {
console.error(`โ Database creation failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
finally {
if (databaseManager) {
await databaseManager.close();
}
}
});
program
.command("check-databases")
.description("Check status of databases and users for all sites")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("--no-db-suffix", "Use site names as database names without _db suffix")
.action(async (options) => {
console.log("๐ WordPress Database Status Checker");
console.log("====================================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
let databaseManager = null;
try {
// Set database suffix preference
if (options.noDbSuffix) {
config_parser_1.ConfigParser.setNoDbSuffix(true);
}
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize database manager
databaseManager = new database_manager_1.DatabaseManager(config);
await databaseManager.initialize();
// Generate report
await databaseManager.generateReport();
}
catch (error) {
console.error(`โ Database check failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
finally {
if (databaseManager) {
await databaseManager.close();
}
}
});
program
.command("reset-wordpress")
.description("Reset WordPress tables in databases (keeps databases and users intact)")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("--confirm", "Skip confirmation prompt")
.action(async (options) => {
console.log("๐ WordPress Table Reset");
console.log("========================");
console.log("โ ๏ธ WARNING: This will delete all WordPress data but keep databases and users!");
if (!options.confirm) {
console.log("\nโ This is a destructive operation. Use --confirm flag to proceed.");
console.log("Example: wp-hosting-automation reset-wordpress --confirm");
process.exit(1);
}
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
let databaseManager = null;
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize database manager
databaseManager = new database_manager_1.DatabaseManager(config);
await databaseManager.initialize();
// Reset WordPress tables
await databaseManager.resetWordPressTables();
console.log("\nโ
WordPress reset completed successfully!");
console.log("๐ You can now run deployment again for a fresh WordPress setup.");
}
catch (error) {
console.error(`โ WordPress reset failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
finally {
if (databaseManager) {
await databaseManager.close();
}
}
});
program
.command("cleanup-databases")
.description("Remove all databases and users (WARNING: DESTRUCTIVE!)")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("--confirm", "Skip confirmation prompt")
.option("--no-db-suffix", "Use site names as database names without _db suffix")
.action(async (options) => {
console.log("๐งน WordPress Database Cleanup");
console.log("=============================");
console.log("โ ๏ธ WARNING: This will permanently delete all databases and users!");
if (!options.confirm) {
console.log("\nโ This is a destructive operation. Use --confirm flag to proceed.");
console.log("Example: wp-hosting-automation cleanup-databases --confirm");
process.exit(1);
}
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
let databaseManager = null;
try {
// Set database suffix preference
if (options.noDbSuffix) {
config_parser_1.ConfigParser.setNoDbSuffix(true);
}
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize database manager
databaseManager = new database_manager_1.DatabaseManager(config);
await databaseManager.initialize();
// Cleanup all databases
await databaseManager.cleanupAllDatabases();
}
catch (error) {
console.error(`โ Database cleanup failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
finally {
if (databaseManager) {
await databaseManager.close();
}
}
});
program
.command("install-wordpress")
.description("Download and install WordPress for all sites")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("-v, --verbose", "Enable verbose logging")
.action(async (options) => {
console.log("๐ WordPress Installer");
console.log("======================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
let wordpressManager = null;
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
if (options.verbose) {
console.log(`โ
Configuration loaded: ${config.sites.length} site(s) found`);
}
// Initialize WordPress manager
wordpressManager = new wordpress_manager_1.WordPressManager(config);
// Install WordPress for all sites
const results = await wordpressManager.installAllSites();
// Show summary
const summary = wordpressManager.getSummary(results);
console.log("\n๐ WordPress Installation Summary");
console.log("==================================");
console.log(`Total Sites: ${summary.total}`);
console.log(`โ
Successful: ${summary.successful}`);
console.log(`โ Failed: ${summary.failed}`);
console.log(`โญ๏ธ Skipped: ${summary.skipped}`);
if (summary.failed > 0) {
console.log("\nโ ๏ธ Some WordPress installations failed. Check the errors above.");
process.exit(1);
}
else {
console.log("\n๐ All WordPress installations completed successfully!");
console.log("โ
Ready for configuration.");
}
}
catch (error) {
console.error(`โ WordPress installation failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("check-wordpress")
.description("Check status of WordPress installations for all sites")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.action(async (options) => {
console.log("๐ WordPress Status Checker");
console.log("===========================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize WordPress manager
const wordpressManager = new wordpress_manager_1.WordPressManager(config);
// Generate report
await wordpressManager.generateReport();
}
catch (error) {
console.error(`โ WordPress check failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("cleanup-wordpress")
.description("Remove all WordPress installations (WARNING: DESTRUCTIVE!)")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("--confirm", "Skip confirmation prompt")
.action(async (options) => {
console.log("๐งน WordPress Cleanup");
console.log("====================");
console.log("โ ๏ธ WARNING: This will permanently delete all WordPress installations!");
if (!options.confirm) {
console.log("\nโ This is a destructive operation. Use --confirm flag to proceed.");
console.log("Example: wp-hosting-automation cleanup-wordpress --confirm");
process.exit(1);
}
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize WordPress manager
const wordpressManager = new wordpress_manager_1.WordPressManager(config);
// Cleanup all installations
await wordpressManager.cleanupAllInstallations();
}
catch (error) {
console.error(`โ WordPress cleanup failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("generate-config")
.description("Generate wp-config.php files for all sites")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("-v, --verbose", "Enable verbose logging")
.action(async (options) => {
console.log("โ๏ธ WordPress Configuration Generator");
console.log("====================================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
if (options.verbose) {
console.log(`โ
Configuration loaded: ${config.sites.length} site(s) found`);
}
// Initialize config manager
const configManager = new config_manager_1.ConfigManager(config);
// Generate wp-config.php for all sites
const results = await configManager.generateAllConfigs();
// Show summary
const summary = configManager.getSummary(results);
console.log("\n๐ wp-config.php Generation Summary");
console.log("===================================");
console.log(`Total Sites: ${summary.total}`);
console.log(`โ
Successful: ${summary.successful}`);
console.log(`โ Failed: ${summary.failed}`);
console.log(`โญ๏ธ Skipped: ${summary.skipped}`);
if (summary.failed > 0) {
console.log("\nโ ๏ธ Some wp-config.php files failed to generate. Check the errors above.");
process.exit(1);
}
else {
console.log("\n๐ All wp-config.php files generated successfully!");
console.log("โ
WordPress sites are ready to use.");
}
}
catch (error) {
console.error(`โ Configuration generation failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("check-config")
.description("Check status of wp-config.php files for all sites")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.action(async (options) => {
console.log("๐ wp-config.php Status Checker");
console.log("=================================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize config manager
const configManager = new config_manager_1.ConfigManager(config);
// Generate report
await configManager.checkAllConfigs();
}
catch (error) {
console.error(`โ Configuration check failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("cleanup-config")
.description("Remove all wp-config.php files (WARNING: DESTRUCTIVE!)")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("--confirm", "Skip confirmation prompt")
.action(async (options) => {
console.log("๐งน wp-config.php Cleanup");
console.log("=========================");
console.log("โ ๏ธ WARNING: This will permanently delete all wp-config.php files!");
if (!options.confirm) {
console.log("\nโ This is a destructive operation. Use --confirm flag to proceed.");
console.log("Example: wp-hosting-automation cleanup-config --confirm");
process.exit(1);
}
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize config manager
const configManager = new config_manager_1.ConfigManager(config);
// Cleanup all configurations
await configManager.cleanupAllConfigs();
}
catch (error) {
console.error(`โ Configuration cleanup failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("set-permissions")
.description("Set appropriate file permissions for all WordPress sites")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("-v, --verbose", "Enable verbose logging")
.action(async (options) => {
console.log("๐ WordPress Permissions Manager");
console.log("================================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
if (options.verbose) {
console.log(`โ
Configuration loaded: ${config.sites.length} site(s) found`);
}
// Initialize permissions manager
const permissionsManager = new permissions_manager_1.PermissionsManager(config);
// Set permissions for all sites
const results = await permissionsManager.setAllPermissions();
// Show summary
const summary = permissionsManager.getSummary(results);
console.log("\n๐ Permissions Setting Summary");
console.log("==============================");
console.log(`Total Sites: ${summary.total}`);
console.log(`โ
Successful: ${summary.successful}`);
console.log(`โ Failed: ${summary.failed}`);
if (summary.failed > 0) {
console.log("\nโ ๏ธ Some sites failed permission setting. Check the errors above.");
process.exit(1);
}
else {
console.log("\n๐ All file permissions set successfully!");
console.log("โ
WordPress sites are properly secured.");
}
}
catch (error) {
console.error(`โ Permission setting failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("check-permissions")
.description("Check file permissions status for all WordPress sites")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.action(async (options) => {
console.log("๐ WordPress Permissions Checker");
console.log("=================================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize permissions manager
const permissionsManager = new permissions_manager_1.PermissionsManager(config);
// Generate report
await permissionsManager.checkAllPermissions();
}
catch (error) {
console.error(`โ Permission check failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("fix-permissions")
.description("Fix file permissions for all WordPress sites")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.action(async (options) => {
console.log("๐ง WordPress Permissions Fixer");
console.log("===============================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize permissions manager
const permissionsManager = new permissions_manager_1.PermissionsManager(config);
// Fix all permissions
await permissionsManager.fixAllPermissions();
}
catch (error) {
console.error(`โ Permission fix failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("generate-app-passwords")
.description("Generate WordPress application passwords for API access")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.action(async (options) => {
console.log("๐ WordPress Application Password Generator");
console.log("===========================================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize app password manager
const appPasswordManager = new app_password_manager_1.AppPasswordManager(config);
// Generate application passwords
const results = await appPasswordManager.generateAllAppPasswords();
appPasswordManager.displaySummary(results);
}
catch (error) {
console.error(`โ Application password generation failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("export-deployment")
.description("Export deployment information to CSV spreadsheet")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("-o, --output <file>", "Export file path (must end with .csv)")
.option("--include-app-passwords", "Include application passwords in export")
.action(async (options) => {
console.log("๐ Deployment Export Generator");
console.log("==============================");
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize export manager
const exportManager = new export_manager_1.ExportManager(config);
// Mock deployment results (since this is a standalone export)
const mockResults = config.sites.map((site) => ({
site_name: site.site_name,
status: "success",
wordpress_path: site.directory_path,
wordpress_info: {
site_url: exportManager["generateSiteUrl"](site.directory_path),
admin_user: site.wordpress_admin_username || "admin",
admin_password: config.wordpress.adminPassword,
admin_email: config.wordpress.adminEmail,
},
}));
// Generate app passwords if requested
let appPasswordResults;
if (options.includeAppPasswords) {
console.log("\n๐ Generating application passwords for export...");
const appPasswordManager = new app_password_manager_1.AppPasswordManager(config);
appPasswordResults = await appPasswordManager.generateAllAppPasswords();
}
// Generate export
const exportPath = await exportManager.generateDeploymentExport(mockResults, appPasswordResults, options.output);
console.log("\nโ
Export completed successfully!");
console.log(`๐ File saved to: ${exportPath}`);
}
catch (error) {
console.error(`โ Export failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("update-permalinks")
.description("Update permalink structure for existing WordPress sites (for wp-json API support)")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)")
.option("-s, --structure <structure>", "Permalink structure pattern", "/%postname%/")
.option("--confirm", "Skip confirmation prompt")
.action(async (options) => {
console.log("๐ WordPress Permalink Structure Updater");
console.log("========================================");
console.log(`๐ New structure: ${options.structure}`);
// Auto-detect configuration file if not specified
let configPath;
if (options.config) {
configPath = path.resolve(options.config);
}
else {
// CSV-first approach: look for CSV files first, then JSON
const possibleFiles = ["sites.csv", "template.csv", "sites.json"];
let foundFile = null;
for (const file of possibleFiles) {
if (await fs.pathExists(file)) {
foundFile = file;
break;
}
}
if (!foundFile) {
console.error("โ No configuration file found.");
console.error("๐ก Please create sites.csv or specify a file with -c flag");
console.error(" Example: wp-host update-permalinks -c my-sites.csv");
process.exit(1);
}
configPath = path.resolve(foundFile);
}
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
console.error("๐ก Make sure the file exists or use -c flag to specify a different file");
process.exit(1);
}
try {
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Interactive confirmation if --confirm flag not provided
if (!options.confirm) {
console.log("\nโ ๏ธ This will update the permalink structure for all sites in your configuration.");
console.log(" This operation is designed for existing WordPress installations.");
console.log(" It uses WP-CLI to safely update permalinks and flush rewrite rules.");
console.log(`\n๐ Sites to update: ${config.sites.length}`);
console.log(`๐ New permalink structure: ${options.structure}`);
const { PromptService } = await Promise.resolve().then(() => __importStar(require("./prompt-service")));
const promptService = new PromptService();
const shouldProceed = await promptService.promptConfirmation("Do you want to proceed with updating permalinks?", [
"Update permalink structure for all configured sites",
"Use WP-CLI to safely modify WordPress settings",
"Flush rewrite rules to ensure changes take effect",
], false);
if (!shouldProceed) {
console.log("\nโ Operation cancelled by user.");
process.exit(0);
}
}
// Initialize WordPress manager
const wordpressManager = new wordpress_manager_1.WordPressManager(config);
// Update permalinks for all sites
const results = await wordpressManager.updateAllPermalinks(options.structure);
const summary = wordpressManager.getSummary(results);
if (summary.failed > 0) {
console.log("\nโ ๏ธ Some sites failed to update. Check the errors above.");
console.log("๐ก Note: This only works on existing WordPress installations with WP-CLI.");
process.exit(1);
}
else if (summary.successful === 0) {
console.log("\nโ ๏ธ No sites were updated.");
console.log("๐ก Make sure your sites have WordPress installed and configured.");
process.exit(1);
}
else {
console.log("\n๐ Permalink structure updated successfully!");
console.log(`โ
${summary.successful} sites now use: ${options.structure}`);
console.log("\n๐ก Your wp-json API endpoints should now work properly.");
console.log(" Example: https://yoursite.com/wp-json/wp/v2/posts");
}
}
catch (error) {
console.error(`โ Permalink update failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
});
program
.command("cleanup-nosuffix-databases")
.description("Remove databases created without _db suffix (for fixing accidental creation)")
.option("-c, --config <file>", "Configuration file path (JSON or CSV)", "sites.json")
.option("--confirm", "Skip confirmation prompt")
.action(async (options) => {
console.log("๐งน WordPress Database Cleanup (No Suffix)");
console.log("=========================================");
console.log("โ ๏ธ WARNING: This will remove databases created WITHOUT _db suffix!");
console.log(" This is for cleaning up accidentally created databases.");
console.log(" Your actual databases with _db suffix will NOT be touched.");
if (!options.confirm) {
console.log("\nโ This is a destructive operation. Use --confirm flag to proceed.");
console.log("Example: wp-host cleanup-nosuffix-databases --confirm");
process.exit(1);
}
const configPath = path.resolve(options.config);
if (!(await fs.pathExists(configPath))) {
console.error(`โ Configuration file not found: ${configPath}`);
process.exit(1);
}
let mysqlManager = null;
try {
// IMPORTANT: Set no-db-suffix to true to target databases without suffix
config_parser_1.ConfigParser.setNoDbSuffix(true);
console.log(`๐ Reading configuration from: ${configPath}`);
const config = await config_parser_1.ConfigParser.parseConfig(configPath);
// Initialize MySQL manager directly
mysqlManager = new mysql_manager_1.MySQLManager(config.mysql);
await mysqlManager.connect();
console.log("\n๐ Cleaning up databases without _db suffix...");
let cleanedCount = 0;
for (const site of config.sites) {
const databaseName = site.site_name; // This should NOT have _db suffix
try {
// Check if database exists (without _db suffix)
const dbExists = await mysqlManager.databaseExists(databaseName);
if (dbExists) {
console.log(`\n๐๏ธ Found database without suffix: ${databaseName}`);
// Drop the database
await mysqlManager.executeQuery(`DROP DATABASE IF EXISTS \`${databaseName}\``);
console.log(` โ
Dropped database: ${databaseName}`);
// Also try to drop associated user
const username = `${site.site_name}_user`;
await mysqlManager.executeQuery(`DROP USER IF EXISTS \`${username}\`@\`localhost\``);
console.log(` โ
Dropped user: ${username}@localhost`);
cleanedCount++;
}
}
catch (error) {
console.error(` โ Error cleaning up ${site.site_name}: ${error instanceof Error ? error.message : String(error)}`);
}
}
// Flush privileges after cleanup
await mysqlManager.executeQuery("FLUSH PRIVILEGES");
if (cleanedCount > 0) {
console.log(`\nโ
Cleanup completed. Removed ${cleanedCount} databases without _db suffix.`);
console.log("๐ You can now use regular commands to work with your _db suffixed databases.");
}
else {
console.log("\nโ
No databases without _db suffix found. Nothing to clean up.");
}
}
catch (error) {
console.error(`โ Database cleanup failed: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
finally {
if (mysqlManager) {
await mysqlManager.disconnect();
}
}
});
// Add help examples
program.on("--help", () => {
console.log("");
console.log("Examples:");
console.log(" # Validation and testing");
console.log(" $ wp-hosting-automation validate");
console.log(" $ wp-hosting-automation test-connection");
console.log("");
console.log(" # Full deployment (interactive)");
console.log(" $ wp-hosting-automation deploy");
console.log(" $ wp-hosting-automation deploy -c my-sites.csv -v");
console.log("");
console.log(" # Non-interactive deployment with options");
console.log(" $ wp-hosting-automation deploy --skip-prompts --app-passwords --export");
console.log(" $ wp-hosting-automation deploy --skip-prompts --export /path/to/results.csv");
console.log("");
console.log(" # Individual operations");
console.log(" $ wp-hosting-automation create-databases");
console.log(" $ wp-hosting-automation install-wordpress");
console.log(" $ wp-hosting-automation generate-config");
console.log(" $ wp-hosting-automation set-permissions");
console.log("");
console.log(" # Optional features");
console.log(" $ wp-hosting-automation generate-app-passwords");
console.log(" $ wp-hosting-automation export-deployment --include-app-passwords");
console.log(" $ wp-hosting-automation export-deployment -o my-deployment.csv");
console.log("");
console.log(" # Update existing sites");
console.log(" $ wp-hosting-automation update-permalinks --confirm");
console.log(' $ wp-hosting-automation update-permalinks --structure="/%year%/%postname%/" --confirm');
console.log("");
console.log(" # Status checking");
console.log(" $ wp-hosting-automation check-databases");
console.log(" $ wp-hosting-automation check-wordpress");
console.log(" $ wp-hosting-automation check-config");
console.log(" $ wp-hosting-automation check-permissions");
console.log("");
console.log(" # Database suffix management");
console.log(" $ wp-hosting-automation deploy --no-db-suffix # Use site names without _db suffix");
console.log(" $ wp-hosting-automation cleanup-nosuffix-databases --confirm # Clean up databases without _db suffix");
console.log("");
console.log(" # Using existing databases (for migrations)");
console.log(" $ wp-hosting-automation deploy --use-existing-databases # Use existing databases without dropping");
console.log(" $ wp-hosting-automation create-databases --use-existing-databases # Setup users for existing DBs");
console.log("");
console.log("Configuration file formats:");
console.log(" ๐ CSV (recommended): Use template.csv for user-friendly column headers");
console.log(' ๐ JSON: { "mysql": {...}, "wordpress": {...}, "sites": [...] }');
console.log("");
console.log("Features:");
console.log(" ๐ง Complete WordPress automation (databases + installation + con