php-universal-mcp-server
Version:
Servidor MCP universal para desenvolvimento PHP e criação de sites em qualquer provedor de hospedagem
297 lines (265 loc) • 8.65 kB
JavaScript
/**
* Site Creator - Módulo para criação de sites a partir de templates
*/
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
class SiteCreator {
/**
* Inicializa o criador de sites
* @param {Object} config - Configurações
*/
constructor(config = {}) {
this.config = {
templatesDir: path.join(__dirname, '../templates'),
sitesDir: config.sitesDir || path.join(process.cwd(), 'sites'),
...config
};
// Criar diretório de sites se não existir
if (!fs.existsSync(this.config.sitesDir)) {
fs.mkdirSync(this.config.sitesDir, { recursive: true });
}
}
/**
* Lista os templates disponíveis
* @returns {Array<string>} Lista de nomes de templates
*/
listTemplates() {
try {
return fs.readdirSync(this.config.templatesDir)
.filter(item => {
const stats = fs.statSync(path.join(this.config.templatesDir, item));
return stats.isDirectory();
});
} catch (error) {
console.error('Erro ao listar templates:', error.message);
return [];
}
}
/**
* Verifica se um template existe
* @param {string} templateName - Nome do template
* @returns {boolean} Verdadeiro se o template existir
*/
templateExists(templateName) {
const templatePath = path.join(this.config.templatesDir, templateName);
return fs.existsSync(templatePath) && fs.statSync(templatePath).isDirectory();
}
/**
* Cria um novo site a partir de um template
* @param {Object} options - Opções de criação
* @param {string} options.domain - Nome do domínio
* @param {string} options.template - Nome do template
* @param {string} options.siteName - Nome do site
* @param {Object} options.variables - Variáveis para substituir no template
* @returns {Object} Resultado da criação
*/
createSite(options) {
const { domain, template = 'default', siteName, variables = {} } = options;
// Validações
if (!domain) {
return {
success: false,
error: 'Domínio não especificado',
timestamp: new Date().toISOString()
};
}
if (!this.templateExists(template)) {
return {
success: false,
error: `Template '${template}' não encontrado`,
timestamp: new Date().toISOString()
};
}
const siteDir = path.join(this.config.sitesDir, domain);
// Verifica se o site já existe
if (fs.existsSync(siteDir)) {
return {
success: false,
error: `Site '${domain}' já existe`,
timestamp: new Date().toISOString()
};
}
try {
// Cria o diretório do site
fs.mkdirSync(siteDir, { recursive: true });
// Copia o template para o diretório do site
this._copyTemplate(template, siteDir, {
siteName: siteName || domain,
...variables
});
// Cria o arquivo de configuração do site
const configFile = path.join(siteDir, 'site-config.json');
fs.writeFileSync(configFile, JSON.stringify({
domain,
template,
siteName: siteName || domain,
createdAt: new Date().toISOString(),
variables: {
siteName: siteName || domain,
...variables
}
}, null, 2), 'utf8');
// Retorna sucesso
return {
success: true,
domain,
template,
siteName: siteName || domain,
siteDir,
message: `Site '${domain}' criado com sucesso!`,
timestamp: new Date().toISOString()
};
} catch (error) {
// Remove o diretório do site em caso de erro
if (fs.existsSync(siteDir)) {
this._removeDirectory(siteDir);
}
return {
success: false,
error: `Erro ao criar site: ${error.message}`,
timestamp: new Date().toISOString()
};
}
}
/**
* Copia um template para o diretório do site
* @param {string} templateName - Nome do template
* @param {string} siteDir - Diretório do site
* @param {Object} variables - Variáveis para substituir no template
* @private
*/
_copyTemplate(templateName, siteDir, variables) {
const templateDir = path.join(this.config.templatesDir, templateName);
this._copyDirectory(templateDir, siteDir, variables);
}
/**
* Copia um diretório recursivamente
* @param {string} sourceDir - Diretório fonte
* @param {string} targetDir - Diretório destino
* @param {Object} variables - Variáveis para substituir no conteúdo
* @private
*/
_copyDirectory(sourceDir, targetDir, variables) {
// Cria o diretório destino se não existir
if (!fs.existsSync(targetDir)) {
fs.mkdirSync(targetDir, { recursive: true });
}
// Lista os arquivos e diretórios
const items = fs.readdirSync(sourceDir);
// Copia cada item
for (const item of items) {
const sourcePath = path.join(sourceDir, item);
const targetPath = path.join(targetDir, item);
const stats = fs.statSync(sourcePath);
if (stats.isDirectory()) {
// Se for diretório, copia recursivamente
this._copyDirectory(sourcePath, targetPath, variables);
} else {
// Se for arquivo, copia com substituição de variáveis
this._copyFile(sourcePath, targetPath, variables);
}
}
}
/**
* Copia um arquivo com substituição de variáveis
* @param {string} sourcePath - Caminho do arquivo fonte
* @param {string} targetPath - Caminho do arquivo destino
* @param {Object} variables - Variáveis para substituir no conteúdo
* @private
*/
_copyFile(sourcePath, targetPath, variables) {
let content = fs.readFileSync(sourcePath, 'utf8');
// Substitui as variáveis no conteúdo
for (const [key, value] of Object.entries(variables)) {
content = content.replace(new RegExp(`\\{\\{\\s*${key}\\s*\\}\\}`, 'g'), value);
}
// Escreve o arquivo com as substituições
fs.writeFileSync(targetPath, content, 'utf8');
}
/**
* Remove um diretório recursivamente
* @param {string} dir - Diretório a ser removido
* @private
*/
_removeDirectory(dir) {
if (fs.existsSync(dir)) {
fs.rmSync(dir, { recursive: true, force: true });
}
}
/**
* Lista os sites criados
* @returns {Array<Object>} Lista de sites
*/
listSites() {
try {
return fs.readdirSync(this.config.sitesDir)
.filter(item => {
const stats = fs.statSync(path.join(this.config.sitesDir, item));
return stats.isDirectory();
})
.map(domain => {
const configPath = path.join(this.config.sitesDir, domain, 'site-config.json');
if (fs.existsSync(configPath)) {
try {
return JSON.parse(fs.readFileSync(configPath, 'utf8'));
} catch (e) {
return { domain };
}
}
return { domain };
});
} catch (error) {
console.error('Erro ao listar sites:', error.message);
return [];
}
}
/**
* Inicia um servidor local para o site
* @param {string} domain - Nome do domínio
* @param {number} port - Porta do servidor
* @returns {Object} Resultado da operação
*/
startServer(domain, port = 8000) {
const siteDir = path.join(this.config.sitesDir, domain);
if (!fs.existsSync(siteDir)) {
return {
success: false,
error: `Site '${domain}' não encontrado`,
timestamp: new Date().toISOString()
};
}
try {
// Verifica se o PHP está instalado
try {
execSync('php -v', { stdio: 'ignore' });
} catch (e) {
return {
success: false,
error: 'PHP não disponível no sistema. Instale o PHP para iniciar o servidor.',
timestamp: new Date().toISOString()
};
}
// Inicia o servidor PHP
const serverProcess = execSync(
`php -S localhost:${port} -t "${siteDir}"`,
{ stdio: 'pipe', detached: true }
);
return {
success: true,
domain,
port,
url: `http://localhost:${port}`,
message: `Servidor iniciado para '${domain}' em http://localhost:${port}`,
timestamp: new Date().toISOString()
};
} catch (error) {
return {
success: false,
error: `Erro ao iniciar servidor: ${error.message}`,
timestamp: new Date().toISOString()
};
}
}
}
module.exports = SiteCreator;