wp-host
Version:
Automated WordPress hosting deployment tool for bulk site creation with MySQL database management
379 lines (365 loc) โข 14.9 kB
JavaScript
;
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 });
exports.ConfigManager = void 0;
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const crypto = __importStar(require("crypto"));
class ConfigManager {
constructor(config) {
this.config = config;
}
/**
* Generate wp-config.php files for all sites
*/
async generateAllConfigs() {
console.log(`\nโ๏ธ Generating wp-config.php files for ${this.config.sites.length} site(s)...`);
const results = [];
for (let i = 0; i < this.config.sites.length; i++) {
const site = this.config.sites[i];
console.log(`\n๐ [${i + 1}/${this.config.sites.length}] Generating config: ${site.site_name}`);
try {
const result = await this.generateSiteConfig(site);
results.push(result);
if (result.status === 'success') {
console.log(`โ
${site.site_name}: wp-config.php generated successfully`);
}
else {
console.log(`โ ๏ธ ${site.site_name}: wp-config.php generation completed with warnings`);
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error(`โ ${site.site_name}: wp-config.php generation failed - ${errorMessage}`);
results.push({
site_name: site.site_name,
status: 'failed',
errors: [errorMessage]
});
}
}
return results;
}
/**
* Generate wp-config.php for a single site
*/
async generateSiteConfig(site) {
const targetDir = path.resolve(site.directory_path);
const configPath = path.join(targetDir, 'wp-config.php');
console.log(` Target: ${configPath}`);
try {
// Step 1: Verify WordPress installation exists
await this.verifyWordPressInstallation(targetDir);
// Step 2: Check if wp-config.php already exists
if (await fs.pathExists(configPath)) {
console.log(` โ ๏ธ wp-config.php already exists`);
// Backup existing config
const backupPath = `${configPath}.backup.${Date.now()}`;
await fs.copy(configPath, backupPath);
console.log(` ๐ Backed up to ${path.basename(backupPath)}`);
}
// Step 3: Generate wp-config.php content
const configContent = await this.generateConfigContent(site);
// Step 4: Write wp-config.php file
await fs.writeFile(configPath, configContent, 'utf8');
// Step 5: Set appropriate permissions (644)
await fs.chmod(configPath, 0o644);
console.log(` โ
wp-config.php generated successfully`);
return {
site_name: site.site_name,
status: 'success',
wordpress_path: targetDir,
wordpress_info: {
site_url: this.generateSiteUrl(targetDir),
admin_user: 'admin',
admin_password: this.config.wordpress.adminPassword,
admin_email: this.config.wordpress.adminEmail
}
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
throw new Error(`Config generation failed: ${errorMessage}`);
}
}
/**
* Verify that WordPress is installed in the target directory
*/
async verifyWordPressInstallation(targetDir) {
const requiredFiles = [
'wp-blog-header.php',
'wp-config-sample.php',
'wp-includes/version.php'
];
for (const file of requiredFiles) {
const filePath = path.join(targetDir, file);
if (!await fs.pathExists(filePath)) {
throw new Error(`WordPress not properly installed - missing ${file}`);
}
}
}
/**
* Generate wp-config.php content with database credentials and security keys
*/
async generateConfigContent(site) {
const databaseName = site.database_name;
const username = site.db_user;
const password = this.config.mysql.sharedDbPassword;
const host = this.config.mysql.host;
const port = this.config.mysql.port;
// Generate security keys and salts
const securityKeys = this.generateSecurityKeys();
// Generate table prefix (use site name for uniqueness if multiple sites share a database)
const tablePrefix = this.generateTablePrefix(site.site_name);
// Database host with port (if not default)
const dbHost = port === 3306 ? host : `${host}:${port}`;
const configTemplate = `<?php
/**
* The base configuration for WordPress
*
* This file is generated by wp-hosting-automation tool
* Generated on: ${new Date().toISOString()}
* Site: ${site.site_name}
*
* @link https://wordpress.org/support/article/editing-wp-config-php/
*
* @package WordPress
*/
// ** Database settings - Generated automatically ** //
/** The name of the database for WordPress */
define( 'DB_NAME', '${databaseName}' );
/** Database username */
define( 'DB_USER', '${username}' );
/** Database password */
define( 'DB_PASSWORD', '${password}' );
/** Database hostname */
define( 'DB_HOST', '${dbHost}' );
/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8mb4' );
/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
/**#@+
* Authentication unique keys and salts.
*
* Change these to different unique phrases! You can generate these using
* the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
*
* You can change these at any point in time to invalidate all existing cookies.
* This will force all users to have to log in again.
*
* @since 2.6.0
*/
${securityKeys}
/**#@-*/
/**
* WordPress database table prefix.
*
* You can have multiple installations in one database if you give each
* a unique prefix. Only numbers, letters, and underscores please!
*/
$table_prefix = '${tablePrefix}';
/**
* For developers: WordPress debugging mode.
*
* Change this to true to enable the display of notices during development.
* It is strongly recommended that plugin and theme developers use WP_DEBUG
* in their development environments.
*
* For information on other constants that can be used for debugging,
* visit the documentation.
*
* @link https://wordpress.org/support/article/debugging-in-wordpress/
*/
define( 'WP_DEBUG', false );
/* Add any custom values between this line and the "stop editing" comment. */
/* That's all, stop editing! Happy publishing. */
/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';
`;
return configTemplate;
}
/**
* Generate WordPress security keys and salts
*/
generateSecurityKeys() {
const keyNames = [
'AUTH_KEY',
'SECURE_AUTH_KEY',
'LOGGED_IN_KEY',
'NONCE_KEY',
'AUTH_SALT',
'SECURE_AUTH_SALT',
'LOGGED_IN_SALT',
'NONCE_SALT'
];
return keyNames.map(keyName => {
const key = crypto.randomBytes(32).toString('base64');
return `define( '${keyName}', '${key}' );`;
}).join('\n');
}
/**
* Generate a unique table prefix based on site name
*/
generateTablePrefix(siteName) {
// Clean site name to only contain letters and numbers
const cleanName = siteName.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
// Take first 6 characters and add underscore
const prefix = cleanName.substring(0, 6) + '_';
// Ensure it starts with a letter
return prefix.match(/^[a-z]/) ? prefix : `wp${prefix}`;
}
/**
* Generate site URL based on directory path
*/
generateSiteUrl(targetDir) {
const resolvedPath = path.resolve(targetDir);
// Check if it's in common web directories
if (resolvedPath.includes('/var/www/html')) {
const relativePath = resolvedPath.replace('/var/www/html', '');
return `http://localhost${relativePath}`;
}
else if (resolvedPath.includes('/var/www')) {
const relativePath = resolvedPath.replace('/var/www', '');
return `http://localhost${relativePath}`;
}
else {
// Local development directory
return `http://localhost:8080`;
}
}
/**
* Check wp-config.php status for all sites
*/
async checkAllConfigs() {
console.log('\n๐ wp-config.php Status Report');
console.log('==============================');
for (let i = 0; i < this.config.sites.length; i++) {
const site = this.config.sites[i];
console.log(`\n${i + 1}. ${site.site_name}`);
try {
const status = await this.checkSiteConfig(site);
console.log(` wp-config.php: ${status.exists ? 'โ
Exists' : 'โ Missing'}`);
console.log(` WordPress: ${status.hasWordPress ? 'โ
Installed' : 'โ Not found'}`);
if (status.exists && status.isValid) {
console.log(` Database Config: โ
Valid`);
console.log(` Security Keys: โ
Present`);
console.log(` Status: ๐ข Ready`);
}
else if (status.exists) {
console.log(` Status: ๐ก Invalid configuration`);
}
else if (status.hasWordPress) {
console.log(` Status: ๐ก WordPress installed, needs configuration`);
}
else {
console.log(` Status: ๐ด WordPress not installed`);
}
}
catch (error) {
console.log(` Status: โ Error checking status`);
console.log(` Error: ${error instanceof Error ? error.message : String(error)}`);
}
}
}
/**
* Check wp-config.php status for a single site
*/
async checkSiteConfig(site) {
const targetDir = path.resolve(site.directory_path);
const configPath = path.join(targetDir, 'wp-config.php');
try {
const exists = await fs.pathExists(configPath);
// Check if WordPress is installed
const hasWordPress = await fs.pathExists(path.join(targetDir, 'wp-includes'));
let isValid = false;
if (exists) {
// Check if config contains required database settings
const configContent = await fs.readFile(configPath, 'utf8');
const hasDbName = configContent.includes("define( 'DB_NAME'");
const hasDbUser = configContent.includes("define( 'DB_USER'");
const hasDbPassword = configContent.includes("define( 'DB_PASSWORD'");
const hasDbHost = configContent.includes("define( 'DB_HOST'");
isValid = hasDbName && hasDbUser && hasDbPassword && hasDbHost;
}
return { exists, hasWordPress, isValid };
}
catch (error) {
console.error(`Error checking config: ${error instanceof Error ? error.message : String(error)}`);
return { exists: false, hasWordPress: false, isValid: false };
}
}
/**
* Clean up wp-config.php files
* WARNING: This will delete all wp-config.php files!
*/
async cleanupAllConfigs() {
console.log('\n๐งน Cleaning up wp-config.php files...');
console.log('โ ๏ธ WARNING: This will permanently delete all wp-config.php files!');
for (const site of this.config.sites) {
const targetDir = path.resolve(site.directory_path);
const configPath = path.join(targetDir, 'wp-config.php');
try {
console.log(`\n๐๏ธ Cleaning up ${site.site_name}:`);
if (await fs.pathExists(configPath)) {
await fs.remove(configPath);
console.log(` โ
wp-config.php removed`);
}
else {
console.log(` โน๏ธ wp-config.php doesn't exist`);
}
}
catch (error) {
console.error(` โ Error cleaning up ${site.site_name}: ${error instanceof Error ? error.message : String(error)}`);
}
}
console.log('\nโ
Cleanup completed.');
}
/**
* Get configuration generation summary
*/
getSummary(results) {
const total = results.length;
const successful = results.filter(r => r.status === 'success').length;
const failed = results.filter(r => r.status === 'failed').length;
const skipped = results.filter(r => r.status === 'skipped').length;
return { total, successful, failed, skipped };
}
}
exports.ConfigManager = ConfigManager;
//# sourceMappingURL=config-manager.js.map