@meyje/meyje-setup
Version:
🪄 MEYJE Setup: produtividade e organização desde o primeiro comando. Automatiza a criação de projetos Next.js 14 com as melhores práticas do mercado.
183 lines (153 loc) • 6.42 kB
JavaScript
import path from 'path';
import fs from 'fs';
import chalk from 'chalk';
import { displayWelcome, promptUser } from './utils/prompts.js';
import { runCommand } from './utils/fileSystem.js';
import { normalizeProjectName } from './utils/slugify.js';
import { getDependencies } from './config/dependencies.js';
import { messages } from './config/constants.js';
import { createNextApp, runPackageManagerCommand } from './utils/packageManager.js';
// Importar módulos
import {
createEnvExampleFile,
createDocumentationTemplates,
createQuickstartGuide,
createDefaultFoldersAndFiles,
ensureGlobalsCssExists,
updatePackageJsonWithScripts,
initializeGitRepository,
configureShadcn,
createSwaggerExampleFiles,
createDbFiles,
createJestConfig
} from './modules/index.js';
/**
* Cria a estrutura base do projeto Next.js
* @param {string} projectPath - Caminho do projeto
*/
const createNextAppWrapper = async (projectPath) => {
console.log(chalk.hex('#4f46e5').bold('\n[1/7] Estruturando seu projeto Next.js com as melhores práticas do mercado.'));
console.log(chalk.yellow(messages.nextjsCreated));
console.log(chalk.yellow(messages.nextjsTip));
return createNextApp(projectPath);
};
/**
* Instala as dependências selecionadas
* @param {string} projectPath - Caminho do projeto
* @param {Object} answers - Respostas do usuário
*/
const installDependencies = async (projectPath, answers) => {
console.log(chalk.hex('#4f46e5').bold('\n[3/7] Instalando dependências essenciais para um stack moderno e escalável.'));
const { dependencies, devDependencies } = getDependencies(answers);
if (dependencies.length > 0) {
await runPackageManagerCommand('add', dependencies, { cwd: projectPath });
console.log(chalk.yellow(messages.dependenciesInstalled));
console.log(chalk.yellow(messages.dependenciesTip));
}
if (devDependencies.length > 0) {
console.log(chalk.hex('#4f46e5').bold('\n[4/7] Preparando ambiente de testes e documentação.'));
await runPackageManagerCommand('add-dev', devDependencies, { cwd: projectPath });
console.log(chalk.yellow(messages.devDependenciesInstalled));
console.log(chalk.yellow(messages.devDependenciesTip));
}
};
/**
* Exibe a mensagem final de sucesso
* @param {string} projectPath - Caminho do projeto
*/
const printSuccessMessage = (projectPath) => {
console.log(chalk.yellow('\n' + messages.setupComplete));
console.log(chalk.yellow(messages.setupCompleteTip));
console.log(chalk.hex('#4f46e5').bold('\n' + messages.usefulCommands));
console.log(chalk.hex('#4f46e5')(` cd "${projectPath}"`));
console.log(chalk.hex('#4f46e5')(' pnpm dev'));
console.log(chalk.hex('#4f46e5')(' pnpm test'));
console.log(chalk.hex('#4f46e5')(' pnpm db:studio'));
console.log(chalk.hex('#4f46e5')(' pnpm docs:gen\n'));
console.log(chalk.gray(messages.envReminder));
console.log(chalk.gray('📖 Leia o QUICKSTART.md para mais informações'));
// Beep sonoro
process.stdout.write('\x07');
};
/**
* Função principal do CLI
*/
const main = async () => {
let projectPath = '';
try {
// Exibir banner de boas-vindas
displayWelcome();
// Coletar preferências do usuário
const answers = await promptUser();
// Verificar se answers foi obtido corretamente
if (!answers) {
throw new Error('Não foi possível obter as preferências do usuário. Tente novamente.');
}
// Normalizar nome do projeto
const normalizedProjectName = normalizeProjectName(answers.projectName);
projectPath = path.resolve(answers.basePath, normalizedProjectName);
// Verificar se o diretório já existe
if (fs.existsSync(projectPath)) {
throw new Error(`O diretório "${projectPath}" já existe. Por favor, escolha outro nome ou local.`);
}
// Criar projeto Next.js
await createNextAppWrapper(projectPath);
// Criar arquivos de configuração e documentação
createEnvExampleFile(projectPath);
createQuickstartGuide(projectPath, answers);
console.log(chalk.yellow(messages.quickstartCreated));
console.log(chalk.yellow(messages.quickstartTip));
if (answers && answers.useSwagger === true) {
createDocumentationTemplates(projectPath);
createSwaggerExampleFiles(projectPath);
console.log(chalk.yellow(messages.swaggerConfigured));
console.log(chalk.yellow(messages.swaggerTip));
} else {
createDocumentationTemplates(projectPath);
}
// Criar estrutura de pastas
createDefaultFoldersAndFiles(projectPath);
// Atualizar package.json com scripts
await updatePackageJsonWithScripts(projectPath, answers);
// Configurar banco de dados se solicitado
if (answers && answers.useDb === true) {
await createDbFiles(projectPath);
console.log(chalk.yellow(messages.databaseConfigured));
console.log(chalk.yellow(messages.databaseTip));
}
// Configurar testes se solicitado
if (answers && answers.useTesting === true) {
await createJestConfig(projectPath);
console.log(chalk.yellow(messages.testsConfigured));
console.log(chalk.yellow(messages.testsTip));
}
// Instalar dependências
await installDependencies(projectPath, answers);
// Configurar ShadCN se solicitado
if (answers && answers.useShadcn === true) {
await configureShadcn(projectPath);
}
// Inicializar Git
if (answers && answers.useGit === true) {
await initializeGitRepository(projectPath);
}
// Garantir que o globals.css exista
await ensureGlobalsCssExists(projectPath);
// Exibir mensagem de sucesso
printSuccessMessage(projectPath);
} catch (error) {
console.error(chalk.bold.red('\n❌ Ocorreu um erro durante a execução do script.'));
if (error.exitCode) {
console.error(chalk.red(`O comando "${error.command}" falhou com o código de saída ${error.exitCode}.`));
} else {
console.error(chalk.red(error.message));
}
if (projectPath && fs.existsSync(projectPath)) {
console.log(chalk.yellow(`\nA pasta do projeto "${projectPath}" foi criada, mas pode estar em um estado inconsistente.`));
console.log(chalk.yellow(`É recomendado removê-la ('rm -rf ${projectPath}' ou manualmente) e tentar novamente.`));
}
process.exit(1);
}
};
// Executar o CLI
main();