1263 lines
39 KiB
JavaScript
1263 lines
39 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
const readline = require('readline');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const { execSync } = require('child_process');
|
||
const https = require('https');
|
||
const http = require('http');
|
||
|
||
const rl = readline.createInterface({
|
||
input: process.stdin,
|
||
output: process.stdout
|
||
});
|
||
|
||
// 🎨 Cores para console
|
||
const colors = {
|
||
reset: '\x1b[0m',
|
||
bright: '\x1b[1m',
|
||
red: '\x1b[31m',
|
||
green: '\x1b[32m',
|
||
yellow: '\x1b[33m',
|
||
blue: '\x1b[34m',
|
||
magenta: '\x1b[35m',
|
||
cyan: '\x1b[36m'
|
||
};
|
||
|
||
const log = {
|
||
info: (msg) => console.log(`${colors.blue}ℹ️ ${msg}${colors.reset}`),
|
||
success: (msg) => console.log(`${colors.green}✅ ${msg}${colors.reset}`),
|
||
warning: (msg) => console.log(`${colors.yellow}⚠️ ${msg}${colors.reset}`),
|
||
error: (msg) => console.log(`${colors.red}❌ ${msg}${colors.reset}`),
|
||
title: (msg) => console.log(`${colors.cyan}${colors.bright}🚀 ${msg}${colors.reset}\n`),
|
||
step: (msg) => console.log(`${colors.bright}🔧 ${msg}${colors.reset}`)
|
||
};
|
||
|
||
// 🔐 Configuração da API PraFrota
|
||
let apiCredentials = {
|
||
token: null,
|
||
tenantId: null,
|
||
baseUrl: 'https://prafrota-be-bff-tenant-api.grupopra.tech'
|
||
};
|
||
|
||
// 📝 Configuração do domínio V2.0 - EXPANDIDA
|
||
let domainConfig = {
|
||
// Básicos
|
||
name: '',
|
||
displayName: '',
|
||
menuPosition: '',
|
||
|
||
// Funcionalidades V1
|
||
hasPhotos: false,
|
||
hasSideCard: false,
|
||
hasKilometer: false,
|
||
hasColor: false,
|
||
hasStatus: false,
|
||
remoteSelects: [],
|
||
|
||
// ✨ NOVOS V2.0 - Core Patterns
|
||
hasFooter: false,
|
||
footerConfig: {
|
||
columns: [] // { field, type, format, label, precision }
|
||
},
|
||
|
||
hasCheckboxGrouped: false,
|
||
checkboxGroupedConfig: {
|
||
fieldName: 'options',
|
||
groups: [] // { id, label, icon, items }
|
||
},
|
||
|
||
hasBulkActions: false,
|
||
bulkActionsConfig: {
|
||
type: 'basic', // 'basic' | 'advanced'
|
||
actions: []
|
||
},
|
||
|
||
// ✨ NOVOS V2.0 - Enhanced Patterns
|
||
hasDateRangeUtils: false,
|
||
|
||
hasAdvancedSideCard: false,
|
||
sideCardConfig: {
|
||
imageField: '',
|
||
statusConfig: {},
|
||
formatFunctions: []
|
||
},
|
||
|
||
hasExtendedSearchOptions: false,
|
||
searchOptionsConfig: {
|
||
useStates: false,
|
||
useVehicleTypes: false,
|
||
useStatusComplex: false,
|
||
customOptions: []
|
||
},
|
||
|
||
// ✨ NOVOS V2.0 - Advanced Patterns
|
||
hasAdvancedSubTabs: false,
|
||
subTabsConfig: {
|
||
enableComponents: false,
|
||
dynamicComponents: []
|
||
}
|
||
};
|
||
|
||
// 🎯 TEMPLATES LIBRARY V2.0
|
||
|
||
// ===== FOOTER CONFIG TEMPLATES =====
|
||
const FooterTemplates = {
|
||
count: {
|
||
type: 'count',
|
||
format: 'default',
|
||
label: 'Total:',
|
||
precision: 0
|
||
},
|
||
sum_currency: {
|
||
type: 'sum',
|
||
format: 'currency',
|
||
label: 'Total:',
|
||
precision: 2
|
||
},
|
||
sum_number: {
|
||
type: 'sum',
|
||
format: 'number',
|
||
label: 'Total:',
|
||
precision: 2
|
||
},
|
||
avg_number: {
|
||
type: 'avg',
|
||
format: 'number',
|
||
label: 'Média:',
|
||
precision: 1
|
||
},
|
||
avg_default: {
|
||
type: 'avg',
|
||
format: 'default',
|
||
label: 'Média:',
|
||
precision: 0
|
||
},
|
||
min_number: {
|
||
type: 'min',
|
||
format: 'number',
|
||
label: 'Mínimo:',
|
||
precision: 2
|
||
},
|
||
max_number: {
|
||
type: 'max',
|
||
format: 'number',
|
||
label: 'Máximo:',
|
||
precision: 2
|
||
}
|
||
};
|
||
|
||
// ===== CHECKBOX GROUPED TEMPLATES =====
|
||
const CheckboxGroupedTemplates = {
|
||
security: {
|
||
id: 'security',
|
||
label: 'Segurança',
|
||
icon: 'fa-shield-alt',
|
||
items: [
|
||
{ id: 1, name: 'Airbag', value: false },
|
||
{ id: 2, name: 'Freios ABS', value: false },
|
||
{ id: 3, name: 'Alarme antifurto', value: false },
|
||
{ id: 4, name: 'Cinto de 3 pontos', value: false },
|
||
{ id: 5, name: 'Controle de tração', value: false }
|
||
]
|
||
},
|
||
comfort: {
|
||
id: 'comfort',
|
||
label: 'Conforto',
|
||
icon: 'fa-couch',
|
||
expanded: false,
|
||
items: [
|
||
{ id: 51, name: 'Ar-condicionado', value: false },
|
||
{ id: 52, name: 'Direção elétrica', value: false },
|
||
{ id: 53, name: 'Vidros elétricos', value: false },
|
||
{ id: 54, name: 'Piloto automático', value: false }
|
||
]
|
||
},
|
||
multimedia: {
|
||
id: 'multimedia',
|
||
label: 'Multimídia',
|
||
icon: 'fa-tv',
|
||
expanded: false,
|
||
items: [
|
||
{ id: 101, name: 'Central multimídia', value: false },
|
||
{ id: 102, name: 'GPS integrado', value: false },
|
||
{ id: 103, name: 'Bluetooth', value: false },
|
||
{ id: 104, name: 'USB', value: false }
|
||
]
|
||
}
|
||
};
|
||
|
||
// ===== BULK ACTIONS TEMPLATES =====
|
||
const BulkActionsTemplates = {
|
||
basic: [
|
||
{
|
||
id: 'delete-selected',
|
||
label: 'Excluir Selecionados',
|
||
icon: 'fas fa-trash',
|
||
action: `(selectedItems) => this.bulkDelete(selectedItems as ${capitalize(domainConfig.name)}[])`
|
||
},
|
||
{
|
||
id: 'export-selected',
|
||
label: 'Exportar Selecionados',
|
||
icon: 'fas fa-download',
|
||
action: `(selectedItems) => this.bulkExport(selectedItems as ${capitalize(domainConfig.name)}[])`
|
||
}
|
||
],
|
||
advanced: [
|
||
{
|
||
id: 'update-data',
|
||
label: 'Atualizar Dados',
|
||
icon: 'fas fa-sync-alt',
|
||
subActions: [
|
||
{
|
||
id: 'update-api-external',
|
||
label: 'Via API Externa',
|
||
icon: 'fas fa-cloud',
|
||
action: `(selectedItems) => this.updateViaExternalAPI(selectedItems as ${capitalize(domainConfig.name)}[])`
|
||
},
|
||
{
|
||
id: 'update-bulk-edit',
|
||
label: 'Edição em Lote',
|
||
icon: 'fas fa-edit',
|
||
action: `(selectedItems) => this.bulkEdit(selectedItems as ${capitalize(domainConfig.name)}[])`
|
||
}
|
||
]
|
||
},
|
||
{
|
||
id: 'status-change',
|
||
label: 'Alterar Status',
|
||
icon: 'fas fa-toggle-on',
|
||
action: `(selectedItems) => this.bulkStatusChange(selectedItems as ${capitalize(domainConfig.name)}[])`
|
||
}
|
||
]
|
||
};
|
||
|
||
// ===== SEARCH OPTIONS LIBRARY =====
|
||
const SearchOptionsLibrary = {
|
||
estados: [
|
||
{ value: "AC", label: "Acre" },
|
||
{ value: "AL", label: "Alagoas" },
|
||
{ value: "AP", label: "Amapá" },
|
||
{ value: "AM", label: "Amazonas" },
|
||
{ value: "BA", label: "Bahia" },
|
||
{ value: "CE", label: "Ceará" },
|
||
{ value: "DF", label: "Distrito Federal" },
|
||
{ value: "ES", label: "Espírito Santo" },
|
||
{ value: "GO", label: "Goiás" },
|
||
{ value: "MA", label: "Maranhão" },
|
||
{ value: "MT", label: "Mato Grosso" },
|
||
{ value: "MS", label: "Mato Grosso do Sul" },
|
||
{ value: "MG", label: "Minas Gerais" },
|
||
{ value: "PA", label: "Pará" },
|
||
{ value: "PB", label: "Paraíba" },
|
||
{ value: "PR", label: "Paraná" },
|
||
{ value: "PE", label: "Pernambuco" },
|
||
{ value: "PI", label: "Piauí" },
|
||
{ value: "RJ", label: "Rio de Janeiro" },
|
||
{ value: "RN", label: "Rio Grande do Norte" },
|
||
{ value: "RS", label: "Rio Grande do Sul" },
|
||
{ value: "RO", label: "Rondônia" },
|
||
{ value: "RR", label: "Roraima" },
|
||
{ value: "SC", label: "Santa Catarina" },
|
||
{ value: "SP", label: "São Paulo" },
|
||
{ value: "SE", label: "Sergipe" },
|
||
{ value: "TO", label: "Tocantins" }
|
||
],
|
||
|
||
vehicleTypes: [
|
||
{ value: 'CAR', label: 'Carro' },
|
||
{ value: 'PICKUP_TRUCK', label: 'Caminhonete' },
|
||
{ value: 'TRUCK', label: 'Caminhão' },
|
||
{ value: 'TRUCK_TRAILER', label: 'Caminhão com Carreta' },
|
||
{ value: 'MOTORCYCLE', label: 'Motocicleta' },
|
||
{ value: 'VAN', label: 'Van' },
|
||
{ value: 'BUS', label: 'Ônibus' },
|
||
{ value: 'TRAILER', label: 'Carreta' },
|
||
{ value: 'SEMI_TRUCK', label: 'Semi-Reboque' },
|
||
{ value: 'MINIBUS', label: 'Micro Ônibus' },
|
||
{ value: 'MOTOR_SCOOTER', label: 'Motoneta' },
|
||
{ value: 'MOPED', label: 'Ciclomotor' },
|
||
{ value: 'TRICYCLE', label: 'Triciclo' },
|
||
{ value: 'UTILITY', label: 'Utilitário' },
|
||
{ value: 'OTHER', label: 'Outro' }
|
||
],
|
||
|
||
statusComplex: [
|
||
{ value: 'active', label: 'Ativo' },
|
||
{ value: 'inactive', label: 'Inativo' },
|
||
{ value: 'pending', label: 'Pendente' },
|
||
{ value: 'processing', label: 'Processando' },
|
||
{ value: 'completed', label: 'Concluído' },
|
||
{ value: 'cancelled', label: 'Cancelado' },
|
||
{ value: 'suspended', label: 'Suspenso' },
|
||
{ value: 'archived', label: 'Arquivado' }
|
||
]
|
||
};
|
||
|
||
// 🔐 FUNÇÕES DE CONSULTA À API REAL
|
||
async function requestAuthCredentials() {
|
||
log.title('🔐 CONFIGURAÇÃO DA API');
|
||
log.info('Para gerar interfaces baseadas em dados reais, precisamos acessar a API PraFrota.');
|
||
log.info('');
|
||
log.info('📋 Como obter as credenciais:');
|
||
log.info('1. Abra a aplicação no navegador (localhost:4200)');
|
||
log.info('2. Faça login normalmente');
|
||
log.info('3. Abra DevTools (F12) → Console');
|
||
log.info('4. Execute: localStorage.getItem("prafrota_auth_token")');
|
||
log.info('5. Execute: localStorage.getItem("tenant_id")');
|
||
log.info('');
|
||
|
||
return new Promise((resolve) => {
|
||
rl.question(`${colors.bright}🔑 Token de autenticação (ou deixe vazio para pular):${colors.reset} `, (token) => {
|
||
if (!token.trim()) {
|
||
log.warning('Token não fornecido. Usando geração de interface padrão.');
|
||
apiCredentials.token = null;
|
||
apiCredentials.tenantId = null;
|
||
resolve();
|
||
return;
|
||
}
|
||
|
||
apiCredentials.token = token.trim();
|
||
|
||
rl.question(`${colors.bright}🏢 Tenant ID:${colors.reset} `, (tenantId) => {
|
||
apiCredentials.tenantId = tenantId.trim();
|
||
log.success('Credenciais configuradas! Tentaremos acessar dados reais da API.');
|
||
resolve();
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
async function analyzeRealAPI(domainName) {
|
||
if (!apiCredentials.token || !apiCredentials.tenantId) {
|
||
log.info('Credenciais não fornecidas. Usando interface padrão.');
|
||
return { success: false, reason: 'no_credentials' };
|
||
}
|
||
|
||
log.step(`🔍 Analisando API real para domínio: ${domainName}`);
|
||
|
||
// Endpoints para testar (singular e plural)
|
||
const endpoints = [
|
||
`${domainName}?page=1&limit=1`,
|
||
`${domainName}s?page=1&limit=1`,
|
||
`api/${domainName}?page=1&limit=1`,
|
||
`api/${domainName}s?page=1&limit=1`
|
||
];
|
||
|
||
for (const endpoint of endpoints) {
|
||
try {
|
||
log.info(`🔍 Testando endpoint: ${endpoint}`);
|
||
|
||
const response = await makeAPIRequest(endpoint);
|
||
|
||
if (response && response.data && Array.isArray(response.data) && response.data.length > 0) {
|
||
const sampleObject = response.data[0];
|
||
log.success(`✅ Dados reais encontrados! ${Object.keys(sampleObject).length} campos detectados`);
|
||
log.info(`📊 Total de registros: ${response.totalCount || 'N/A'}`);
|
||
log.info(`🔗 Endpoint usado: ${endpoint}`);
|
||
|
||
// Mostrar preview dos campos
|
||
log.info('📝 Campos detectados:');
|
||
Object.entries(sampleObject).slice(0, 5).forEach(([key, value]) => {
|
||
const type = typeof value;
|
||
const preview = type === 'string' && value.length > 30
|
||
? value.substring(0, 30) + '...'
|
||
: value;
|
||
log.info(` • ${key} (${type}): ${preview}`);
|
||
});
|
||
|
||
if (Object.keys(sampleObject).length > 5) {
|
||
log.info(` ... e mais ${Object.keys(sampleObject).length - 5} campos`);
|
||
}
|
||
|
||
return {
|
||
success: true,
|
||
strategy: 'real_api_data',
|
||
interface: generateInterfaceFromRealData(domainName, sampleObject),
|
||
fields: extractFieldsFromRealData(sampleObject),
|
||
metadata: {
|
||
source: 'authenticated_api',
|
||
endpoint: endpoint,
|
||
sampleSize: response.data.length,
|
||
totalCount: response.totalCount || 'unknown',
|
||
timestamp: new Date().toISOString()
|
||
}
|
||
};
|
||
} else {
|
||
log.warning(`⚠️ Endpoint ${endpoint} sem dados válidos`);
|
||
}
|
||
|
||
} catch (error) {
|
||
log.warning(`⚠️ Erro no endpoint ${endpoint}: ${error.message}`);
|
||
}
|
||
}
|
||
|
||
log.error('❌ Nenhum endpoint retornou dados válidos');
|
||
return {
|
||
success: false,
|
||
reason: 'no_data_found',
|
||
message: 'Endpoints existem mas não retornaram dados válidos. Verifique se o domínio existe na API.'
|
||
};
|
||
}
|
||
|
||
async function makeAPIRequest(endpoint) {
|
||
const fullUrl = `${apiCredentials.baseUrl}/${endpoint}`;
|
||
|
||
return new Promise((resolve, reject) => {
|
||
const urlParts = new URL(fullUrl);
|
||
|
||
const options = {
|
||
hostname: urlParts.hostname,
|
||
port: urlParts.port || 443,
|
||
path: urlParts.pathname + urlParts.search,
|
||
method: 'GET',
|
||
headers: {
|
||
'Accept': 'application/json',
|
||
'x-tenant-user-auth': apiCredentials.token,
|
||
'x-tenant-uuid': apiCredentials.tenantId,
|
||
'User-Agent': 'Create-Domain-V2.0'
|
||
}
|
||
};
|
||
|
||
const req = https.request(options, (res) => {
|
||
let data = '';
|
||
|
||
res.on('data', chunk => data += chunk);
|
||
res.on('end', () => {
|
||
try {
|
||
resolve(JSON.parse(data));
|
||
} catch (error) {
|
||
reject(new Error('Invalid JSON response'));
|
||
}
|
||
});
|
||
});
|
||
|
||
req.on('error', (error) => {
|
||
reject(error);
|
||
});
|
||
|
||
req.setTimeout(10000, () => {
|
||
req.destroy();
|
||
reject(new Error('Request timeout'));
|
||
});
|
||
|
||
req.end();
|
||
});
|
||
}
|
||
|
||
function generateInterfaceFromRealData(domainName, sampleObject) {
|
||
const className = domainName.charAt(0).toUpperCase() + domainName.slice(1);
|
||
let interfaceCode = `/**
|
||
* 🎯 ${className} Interface - DADOS REAIS DA API PraFrota
|
||
*
|
||
* ✨ Auto-gerado a partir de dados reais da API autenticada
|
||
* 📅 Gerado em: ${new Date().toLocaleString()}
|
||
* 🔗 Fonte: API Response Analysis com autenticação
|
||
*/
|
||
export interface ${className} {\n`;
|
||
|
||
Object.entries(sampleObject).forEach(([key, value]) => {
|
||
const type = detectTypeScriptFromRealData(value);
|
||
const isOptional = value === null || value === undefined;
|
||
const optional = isOptional ? '?' : '';
|
||
const description = inferFieldDescription(key, type);
|
||
|
||
interfaceCode += ` ${key}${optional}: ${type}; // ${description}\n`;
|
||
});
|
||
|
||
interfaceCode += '}';
|
||
return interfaceCode;
|
||
}
|
||
|
||
function detectTypeScriptFromRealData(value) {
|
||
if (value === null || value === undefined) return 'any';
|
||
|
||
const type = typeof value;
|
||
|
||
if (type === 'string') {
|
||
// Detectar datas ISO
|
||
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value)) return 'string';
|
||
// Detectar emails
|
||
if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) return 'string';
|
||
return 'string';
|
||
}
|
||
|
||
if (type === 'number') return 'number';
|
||
if (type === 'boolean') return 'boolean';
|
||
|
||
if (Array.isArray(value)) {
|
||
if (value.length === 0) return 'any[]';
|
||
return `${detectTypeScriptFromRealData(value[0])}[]`;
|
||
}
|
||
|
||
if (type === 'object') return 'any';
|
||
|
||
return 'any';
|
||
}
|
||
|
||
function extractFieldsFromRealData(sampleObject) {
|
||
return Object.entries(sampleObject).map(([name, value]) => ({
|
||
name,
|
||
type: detectTypeScriptFromRealData(value),
|
||
required: value !== null && value !== undefined,
|
||
description: inferFieldDescription(name, detectTypeScriptFromRealData(value)),
|
||
realValue: typeof value === 'string' ? value.substring(0, 50) + '...' : value
|
||
}));
|
||
}
|
||
|
||
function inferFieldDescription(fieldName, type) {
|
||
const descriptions = {
|
||
id: 'Identificador único',
|
||
name: 'Nome do registro',
|
||
email: 'Endereço de email',
|
||
phone: 'Número de telefone',
|
||
address: 'Endereço',
|
||
status: 'Status do registro',
|
||
active: 'Se está ativo',
|
||
created_at: 'Data de criação',
|
||
updated_at: 'Data de atualização',
|
||
deleted_at: 'Data de exclusão',
|
||
description: 'Descrição',
|
||
title: 'Título',
|
||
price: 'Preço',
|
||
amount: 'Valor/Quantia',
|
||
quantity: 'Quantidade',
|
||
user_id: 'ID do usuário',
|
||
company_id: 'ID da empresa',
|
||
tenant_id: 'ID do tenant',
|
||
brand: 'Marca',
|
||
model: 'Modelo',
|
||
year: 'Ano',
|
||
plate: 'Placa'
|
||
};
|
||
|
||
return descriptions[fieldName] || `Campo ${fieldName} (${type})`;
|
||
}
|
||
|
||
// 🎯 Função principal
|
||
async function main() {
|
||
try {
|
||
log.title('CRIADOR DE DOMÍNIOS V2.0 - SISTEMA PRAFROTA');
|
||
log.info('🆕 Versão 2.0 com FooterConfig, CheckboxGrouped, BulkActions e mais!');
|
||
|
||
// Verificar pré-requisitos
|
||
await checkPrerequisites();
|
||
|
||
// 🔐 Solicitar credenciais da API (novo V2.0)
|
||
await requestAuthCredentials();
|
||
|
||
// Coletar informações V2.0
|
||
await gatherDomainInfoV2();
|
||
|
||
// Confirmar configuração
|
||
await confirmConfigurationV2();
|
||
|
||
// Criar branch para o desenvolvimento
|
||
await createBranch();
|
||
|
||
// Gerar domínio V2.0
|
||
await generateDomainV2();
|
||
|
||
// Compilar e testar
|
||
await compileAndTest();
|
||
|
||
// Commit automático
|
||
await autoCommit();
|
||
|
||
log.success('🎉 DOMÍNIO V2.0 CRIADO COM SUCESSO!');
|
||
log.success('🚀 Sistema totalmente integrado com todos os padrões mais recentes!');
|
||
showNewFeaturesV2();
|
||
|
||
} catch (error) {
|
||
log.error(`Erro: ${error.message}`);
|
||
process.exit(1);
|
||
} finally {
|
||
rl.close();
|
||
}
|
||
}
|
||
|
||
// ===== V2.0 SPECIFIC FUNCTIONS =====
|
||
|
||
// 📝 Coletar informações V2.0
|
||
async function gatherDomainInfoV2() {
|
||
log.title('CONFIGURAÇÃO DO DOMÍNIO V2.0');
|
||
|
||
// Básicos
|
||
await gatherBasicInfo();
|
||
|
||
// ✨ NOVO: Footer Configuration
|
||
await gatherFooterConfig();
|
||
|
||
// ✨ NOVO: Checkbox Grouped Configuration
|
||
await gatherCheckboxGroupedConfig();
|
||
|
||
// ✨ NOVO: Bulk Actions Configuration
|
||
await gatherBulkActionsConfig();
|
||
|
||
// ✨ NOVO: Enhanced Features
|
||
await gatherEnhancedFeaturesConfig();
|
||
|
||
// Funcionalidades V1 (legacy)
|
||
await gatherLegacyFeatures();
|
||
}
|
||
|
||
// Helper para perguntas yes/no
|
||
function askYesNo(question) {
|
||
return new Promise((resolve) => {
|
||
rl.question(`${question} (s/N): `, (answer) => {
|
||
resolve(answer.toLowerCase() === 's' || answer.toLowerCase() === 'sim');
|
||
});
|
||
});
|
||
}
|
||
|
||
// Helper para perguntas com opções
|
||
function askOptions(question, options) {
|
||
return new Promise((resolve) => {
|
||
const optionsText = options.map((opt, i) => `${i + 1}. ${opt}`).join('\n');
|
||
rl.question(`${question}\n${optionsText}\nEscolha (1-${options.length}): `, (answer) => {
|
||
const index = parseInt(answer) - 1;
|
||
if (index >= 0 && index < options.length) {
|
||
resolve(options[index]);
|
||
} else {
|
||
log.warning('Opção inválida, usando primeira opção');
|
||
resolve(options[0]);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
// Configuração básica
|
||
async function gatherBasicInfo() {
|
||
domainConfig.name = await ask('Nome do domínio (ex: products): ');
|
||
domainConfig.displayName = await ask('Nome para exibição (ex: Produtos): ');
|
||
domainConfig.menuPosition = await ask('Posição no menu (após qual item): ');
|
||
}
|
||
|
||
// ✨ NOVO: Footer Configuration
|
||
async function gatherFooterConfig() {
|
||
log.info('\n📊 CONFIGURAÇÃO DE FOOTER NAS COLUNAS');
|
||
|
||
domainConfig.hasFooter = await askYesNo('Deseja footer com totalização nas colunas?');
|
||
|
||
if (domainConfig.hasFooter) {
|
||
log.info('Tipos disponíveis: count, sum_currency, sum_number, avg_number, avg_default, min_number, max_number');
|
||
|
||
const numColumns = await askNumber('Quantas colunas terão footer? (1-5): ', 1, 5);
|
||
|
||
for (let i = 0; i < numColumns; i++) {
|
||
log.info(`\n--- Coluna ${i + 1} ---`);
|
||
const field = await ask(`Campo da coluna ${i + 1} (ex: price, quantity): `);
|
||
const type = await askOptions(`Tipo de footer para ${field}:`, [
|
||
'count', 'sum_currency', 'sum_number', 'avg_number', 'avg_default'
|
||
]);
|
||
|
||
domainConfig.footerConfig.columns.push({
|
||
field,
|
||
...FooterTemplates[type]
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
// ✨ NOVO: Checkbox Grouped Configuration
|
||
async function gatherCheckboxGroupedConfig() {
|
||
log.info('\n☑️ CONFIGURAÇÃO DE CHECKBOX AGRUPADO');
|
||
|
||
domainConfig.hasCheckboxGrouped = await askYesNo('Deseja checkbox agrupado (ex: opcionais, características)?');
|
||
|
||
if (domainConfig.hasCheckboxGrouped) {
|
||
domainConfig.checkboxGroupedConfig.fieldName = await ask('Nome do campo (ex: options, features): ') || 'options';
|
||
|
||
const groupTypes = await askOptions('Quais grupos incluir:', [
|
||
'Segurança + Conforto',
|
||
'Segurança + Conforto + Multimídia',
|
||
'Todos os grupos',
|
||
'Customizado'
|
||
]);
|
||
|
||
switch (groupTypes) {
|
||
case 'Segurança + Conforto':
|
||
domainConfig.checkboxGroupedConfig.groups = [
|
||
CheckboxGroupedTemplates.security,
|
||
CheckboxGroupedTemplates.comfort
|
||
];
|
||
break;
|
||
case 'Segurança + Conforto + Multimídia':
|
||
domainConfig.checkboxGroupedConfig.groups = [
|
||
CheckboxGroupedTemplates.security,
|
||
CheckboxGroupedTemplates.comfort,
|
||
CheckboxGroupedTemplates.multimedia
|
||
];
|
||
break;
|
||
case 'Todos os grupos':
|
||
domainConfig.checkboxGroupedConfig.groups = Object.values(CheckboxGroupedTemplates);
|
||
break;
|
||
default:
|
||
log.info('Modo customizado não implementado, usando Segurança + Conforto');
|
||
domainConfig.checkboxGroupedConfig.groups = [
|
||
CheckboxGroupedTemplates.security,
|
||
CheckboxGroupedTemplates.comfort
|
||
];
|
||
}
|
||
}
|
||
}
|
||
|
||
// ✨ NOVO: Bulk Actions Configuration
|
||
async function gatherBulkActionsConfig() {
|
||
log.info('\n⚡ CONFIGURAÇÃO DE AÇÕES EM LOTE');
|
||
|
||
domainConfig.hasBulkActions = await askYesNo('Deseja ações em lote (bulk actions)?');
|
||
|
||
if (domainConfig.hasBulkActions) {
|
||
domainConfig.bulkActionsConfig.type = await askOptions('Tipo de ações:', [
|
||
'basic', 'advanced'
|
||
]);
|
||
|
||
domainConfig.bulkActionsConfig.actions = BulkActionsTemplates[domainConfig.bulkActionsConfig.type];
|
||
}
|
||
}
|
||
|
||
// ✨ NOVO: Enhanced Features Configuration
|
||
async function gatherEnhancedFeaturesConfig() {
|
||
log.info('\n🚀 FUNCIONALIDADES AVANÇADAS');
|
||
|
||
// DateRangeUtils
|
||
domainConfig.hasDateRangeUtils = await askYesNo('Integrar DateRangeUtils automaticamente?');
|
||
|
||
// Advanced SideCard
|
||
if (await askYesNo('Deseja SideCard avançado (com statusConfig e imageField)?')) {
|
||
domainConfig.hasAdvancedSideCard = true;
|
||
domainConfig.sideCardConfig.imageField = await ask('Campo para imagem (ex: photos, images): ') || 'photos';
|
||
}
|
||
|
||
// Extended Search Options
|
||
domainConfig.hasExtendedSearchOptions = await askYesNo('Usar searchOptions pré-definidos (Estados, Status, etc.)?');
|
||
|
||
if (domainConfig.hasExtendedSearchOptions) {
|
||
domainConfig.searchOptionsConfig.useStates = await askYesNo(' • Incluir Estados (UF)?');
|
||
domainConfig.searchOptionsConfig.useVehicleTypes = await askYesNo(' • Incluir Tipos de Veículo?');
|
||
domainConfig.searchOptionsConfig.useStatusComplex = await askYesNo(' • Incluir Status Complexos?');
|
||
}
|
||
|
||
// Advanced SubTabs
|
||
domainConfig.hasAdvancedSubTabs = await askYesNo('Usar SubTabs avançadas (componentes dinâmicos)?');
|
||
}
|
||
|
||
// Legacy features (V1)
|
||
async function gatherLegacyFeatures() {
|
||
log.info('\n📋 FUNCIONALIDADES BÁSICAS');
|
||
|
||
domainConfig.hasPhotos = await askYesNo('Incluir sub-aba de fotos?');
|
||
domainConfig.hasSideCard = await askYesNo('Incluir side card básico?') && !domainConfig.hasAdvancedSideCard;
|
||
domainConfig.hasStatus = await askYesNo('Incluir campo de status?');
|
||
domainConfig.hasKilometer = await askYesNo('Incluir campo de quilometragem?');
|
||
domainConfig.hasColor = await askYesNo('Incluir campo de cor?');
|
||
}
|
||
|
||
// Helper functions
|
||
function ask(question) {
|
||
return new Promise((resolve) => {
|
||
rl.question(question, (answer) => {
|
||
resolve(answer.trim());
|
||
});
|
||
});
|
||
}
|
||
|
||
function askNumber(question, min = 1, max = 10) {
|
||
return new Promise((resolve) => {
|
||
rl.question(question, (answer) => {
|
||
const num = parseInt(answer);
|
||
if (num >= min && num <= max) {
|
||
resolve(num);
|
||
} else {
|
||
log.warning(`Número inválido, usando ${min}`);
|
||
resolve(min);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
function capitalize(str) {
|
||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||
}
|
||
|
||
// Mostrar novas funcionalidades V2.0
|
||
function showNewFeaturesV2() {
|
||
log.info('\n🎯 FUNCIONALIDADES V2.0 IMPLEMENTADAS:');
|
||
|
||
if (domainConfig.hasFooter) {
|
||
log.success(` ✅ FooterConfig: ${domainConfig.footerConfig.columns.length} colunas com totalização`);
|
||
}
|
||
|
||
if (domainConfig.hasCheckboxGrouped) {
|
||
log.success(` ✅ CheckboxGrouped: ${domainConfig.checkboxGroupedConfig.groups.length} grupos configurados`);
|
||
}
|
||
|
||
if (domainConfig.hasBulkActions) {
|
||
log.success(` ✅ BulkActions: Modo ${domainConfig.bulkActionsConfig.type}`);
|
||
}
|
||
|
||
if (domainConfig.hasDateRangeUtils) {
|
||
log.success(` ✅ DateRangeUtils: Integração automática`);
|
||
}
|
||
|
||
if (domainConfig.hasAdvancedSideCard) {
|
||
log.success(` ✅ SideCard Avançado: Com statusConfig e imageField`);
|
||
}
|
||
|
||
if (domainConfig.hasExtendedSearchOptions) {
|
||
log.success(` ✅ SearchOptions Estendidos: Estados, Tipos, Status`);
|
||
}
|
||
|
||
log.info('\n📝 Próximos passos:');
|
||
log.info(` 1. Testar: http://localhost:4200/app/${domainConfig.name}`);
|
||
log.info(` 2. Push: git push origin feature/domain-${domainConfig.name}`);
|
||
log.info(` 3. Documentar: Adicionar no .mcp/config.json`);
|
||
}
|
||
|
||
// Confirmar configuração V2.0
|
||
async function confirmConfigurationV2() {
|
||
log.title('CONFIRMAÇÃO DA CONFIGURAÇÃO V2.0');
|
||
|
||
console.log('📋 Resumo:');
|
||
console.log(` • Domínio: ${domainConfig.name} (${domainConfig.displayName})`);
|
||
console.log(` • Menu: Após "${domainConfig.menuPosition}"`);
|
||
|
||
// V2.0 Features
|
||
console.log('\n🆕 Funcionalidades V2.0:');
|
||
console.log(` • Footer: ${domainConfig.hasFooter ? '✅ ' + domainConfig.footerConfig.columns.length + ' colunas' : '❌'}`);
|
||
console.log(` • CheckboxGrouped: ${domainConfig.hasCheckboxGrouped ? '✅ ' + domainConfig.checkboxGroupedConfig.groups.length + ' grupos' : '❌'}`);
|
||
console.log(` • BulkActions: ${domainConfig.hasBulkActions ? '✅ ' + domainConfig.bulkActionsConfig.type : '❌'}`);
|
||
console.log(` • DateRangeUtils: ${domainConfig.hasDateRangeUtils ? '✅' : '❌'}`);
|
||
console.log(` • SideCard Avançado: ${domainConfig.hasAdvancedSideCard ? '✅' : '❌'}`);
|
||
console.log(` • SearchOptions Estendidos: ${domainConfig.hasExtendedSearchOptions ? '✅' : '❌'}`);
|
||
|
||
// V1 Features
|
||
console.log('\n📋 Funcionalidades Básicas:');
|
||
console.log(` • Fotos: ${domainConfig.hasPhotos ? '✅' : '❌'}`);
|
||
console.log(` • SideCard: ${domainConfig.hasSideCard ? '✅' : '❌'}`);
|
||
console.log(` • Status: ${domainConfig.hasStatus ? '✅' : '❌'}`);
|
||
console.log(` • Quilometragem: ${domainConfig.hasKilometer ? '✅' : '❌'}`);
|
||
console.log(` • Cor: ${domainConfig.hasColor ? '✅' : '❌'}`);
|
||
|
||
const confirm = await askYesNo('\nConfirma a criação do domínio com estas configurações?');
|
||
if (!confirm) {
|
||
throw new Error('Operação cancelada pelo usuário');
|
||
}
|
||
}
|
||
|
||
// ===== GERAÇÃO V2.0 =====
|
||
|
||
// Gerar domínio V2.0
|
||
async function generateDomainV2() {
|
||
log.title('GERANDO DOMÍNIO V2.0');
|
||
|
||
// Criar estrutura de pastas
|
||
await createDirectoryStructure();
|
||
|
||
// Gerar arquivos V2.0
|
||
await generateComponentV2();
|
||
await generateServiceV2();
|
||
await generateInterfaceV2();
|
||
await generateTemplatesV2();
|
||
|
||
// Integrações V2.0
|
||
await updateRoutingV2();
|
||
await updateSidebarV2();
|
||
await updateMCPConfigV2();
|
||
|
||
log.success('Domínio V2.0 gerado com sucesso!');
|
||
}
|
||
|
||
// ===== FUNÇÕES AUXILIARES V2.0 =====
|
||
|
||
// Verificar pré-requisitos
|
||
async function checkPrerequisites() {
|
||
log.info('Verificando pré-requisitos...');
|
||
|
||
// Verificar se está na branch main
|
||
try {
|
||
const currentBranch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();
|
||
if (currentBranch !== 'main') {
|
||
throw new Error(`Você deve estar na branch main. Branch atual: ${currentBranch}`);
|
||
}
|
||
log.success('Branch main ativa');
|
||
} catch (error) {
|
||
throw new Error('Erro ao verificar branch Git');
|
||
}
|
||
|
||
// Verificar se Git está configurado
|
||
try {
|
||
const gitUser = execSync('git config user.name', { encoding: 'utf8' }).trim();
|
||
const gitEmail = execSync('git config user.email', { encoding: 'utf8' }).trim();
|
||
log.success(`Git configurado: ${gitUser} <${gitEmail}>`);
|
||
} catch (error) {
|
||
throw new Error('Git não configurado. Execute: git config --global user.name "Seu Nome" && git config --global user.email "seu@email.com"');
|
||
}
|
||
}
|
||
|
||
// Criar branch para desenvolvimento
|
||
async function createBranch() {
|
||
log.title('CRIANDO BRANCH DE DESENVOLVIMENTO');
|
||
|
||
const branchName = `feature/domain-${domainConfig.name}`;
|
||
|
||
try {
|
||
log.info(`Criando branch: ${branchName}`);
|
||
execSync(`git checkout -b ${branchName}`, { stdio: 'inherit' });
|
||
log.success(`Branch ${branchName} criada e ativada`);
|
||
} catch (error) {
|
||
throw new Error(`Erro ao criar branch: ${error.message}`);
|
||
}
|
||
}
|
||
|
||
// Criar estrutura de diretórios
|
||
async function createDirectoryStructure() {
|
||
const domainPath = `projects/idt_app/src/app/domain/${domainConfig.name}`;
|
||
|
||
log.info('Criando estrutura de diretórios...');
|
||
|
||
if (!fs.existsSync(domainPath)) {
|
||
fs.mkdirSync(domainPath, { recursive: true });
|
||
log.success(`Diretório criado: ${domainPath}`);
|
||
}
|
||
}
|
||
|
||
// Gerar arquivos V2.0
|
||
async function generateComponentV2() {
|
||
try {
|
||
const generators = require('./create-domain-v2-generators.js');
|
||
const componentContent = generators.generateComponentV2(domainConfig);
|
||
|
||
const componentPath = `projects/idt_app/src/app/domain/${domainConfig.name}/${domainConfig.name}.component.ts`;
|
||
fs.writeFileSync(componentPath, componentContent);
|
||
log.success(`Component V2.0 gerado: ${componentPath}`);
|
||
} catch (error) {
|
||
log.error(`Erro ao gerar component: ${error.message}`);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
async function generateServiceV2() {
|
||
try {
|
||
const generators = require('./create-domain-v2-generators.js');
|
||
const serviceContent = generators.generateServiceV2(domainConfig);
|
||
|
||
const servicePath = `projects/idt_app/src/app/domain/${domainConfig.name}/${domainConfig.name}.service.ts`;
|
||
fs.writeFileSync(servicePath, serviceContent);
|
||
log.success(`Service V2.0 gerado: ${servicePath}`);
|
||
} catch (error) {
|
||
log.error(`Erro ao gerar service: ${error.message}`);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
async function generateInterfaceV2() {
|
||
try {
|
||
let interfaceContent;
|
||
|
||
// 🚀 NOVA FUNCIONALIDADE V2.0: Tentar API real primeiro
|
||
log.step('🔍 Tentando gerar interface a partir de dados reais da API...');
|
||
const apiResult = await analyzeRealAPI(domainConfig.name);
|
||
|
||
if (apiResult.success) {
|
||
log.success('✅ Interface gerada a partir de dados REAIS da API!');
|
||
log.info(`📊 Estratégia: ${apiResult.strategy}`);
|
||
log.info(`🔗 Endpoint: ${apiResult.metadata.endpoint}`);
|
||
log.info(`📋 Campos detectados: ${apiResult.fields.length}`);
|
||
|
||
interfaceContent = apiResult.interface;
|
||
} else {
|
||
// Fallback para gerador padrão
|
||
log.warning('⚠️ Não foi possível acessar dados reais da API');
|
||
log.info(`📋 Motivo: ${apiResult.message || 'Credenciais não fornecidas'}`);
|
||
log.info('🔄 Usando geração padrão de interface...');
|
||
|
||
const generators = require('./create-domain-v2-generators.js');
|
||
interfaceContent = await generators.generateInterfaceV2(domainConfig);
|
||
}
|
||
|
||
const interfacePath = `projects/idt_app/src/app/domain/${domainConfig.name}/${domainConfig.name}.interface.ts`;
|
||
fs.writeFileSync(interfacePath, interfaceContent);
|
||
log.success(`Interface V2.0 gerada: ${interfacePath}`);
|
||
|
||
if (apiResult.success) {
|
||
log.success('🎉 INTERFACE BASEADA EM DADOS REAIS DA API!');
|
||
}
|
||
|
||
} catch (error) {
|
||
log.error(`Erro ao gerar interface: ${error.message}`);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
async function generateTemplatesV2() {
|
||
// HTML Template
|
||
const htmlContent = `<div class="domain-container">
|
||
<div class="main-content">
|
||
<app-tab-system
|
||
#tabSystem
|
||
[config]="tabConfig"
|
||
[events]="tabEvents"
|
||
[showDebugInfo]="false"
|
||
(tabSelected)="onTabSelected($event)"
|
||
(tabClosed)="onTabClosed($event)"
|
||
(tabAdded)="onTabAdded($event)"
|
||
(tableEvent)="onTableEvent($event)">
|
||
</app-tab-system>
|
||
</div>
|
||
</div>`;
|
||
|
||
// SCSS Template
|
||
const scssContent = `// 🎨 ${capitalize(domainConfig.name)} Component Styles - V2.0
|
||
// Estilos específicos para o domínio ${domainConfig.displayName}
|
||
|
||
.domain-container {
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
background: var(--background);
|
||
|
||
.main-content {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
padding: 0;
|
||
}
|
||
}
|
||
|
||
// 🆕 V2.0: Estilos específicos para funcionalidades
|
||
${domainConfig.hasBulkActions ? `
|
||
// Bulk Actions específicos
|
||
.bulk-actions {
|
||
margin-bottom: 1rem;
|
||
|
||
.bulk-action-button {
|
||
margin-right: 0.5rem;
|
||
|
||
&.advanced {
|
||
background: var(--idt-primary-color);
|
||
color: white;
|
||
}
|
||
}
|
||
}` : ''}
|
||
|
||
${domainConfig.hasFooter ? `
|
||
// Footer customizations
|
||
.footer-enhanced {
|
||
font-weight: 600;
|
||
|
||
.footer-currency {
|
||
color: var(--success-color);
|
||
}
|
||
|
||
.footer-count {
|
||
color: var(--info-color);
|
||
}
|
||
}` : ''}
|
||
|
||
// 📱 Responsividade
|
||
@media (max-width: 768px) {
|
||
.domain-container {
|
||
.main-content {
|
||
padding: 0.5rem;
|
||
}
|
||
}
|
||
}`;
|
||
|
||
const htmlPath = `projects/idt_app/src/app/domain/${domainConfig.name}/${domainConfig.name}.component.html`;
|
||
const scssPath = `projects/idt_app/src/app/domain/${domainConfig.name}/${domainConfig.name}.component.scss`;
|
||
|
||
fs.writeFileSync(htmlPath, htmlContent);
|
||
fs.writeFileSync(scssPath, scssContent);
|
||
|
||
log.success(`Templates V2.0 gerados: HTML e SCSS`);
|
||
}
|
||
|
||
// Atualizar roteamento V2.0
|
||
async function updateRoutingV2() {
|
||
log.info('Atualizando roteamento...');
|
||
|
||
const routesPath = 'projects/idt_app/src/app/app.routes.ts';
|
||
let routesContent = fs.readFileSync(routesPath, 'utf8');
|
||
|
||
// Adicionar import
|
||
const importLine = `import { ${capitalize(domainConfig.name)}Component } from './domain/${domainConfig.name}/${domainConfig.name}.component';`;
|
||
if (!routesContent.includes(importLine)) {
|
||
routesContent = routesContent.replace(
|
||
/import.*from.*;\n(?=\n)/,
|
||
`$&${importLine}\n`
|
||
);
|
||
}
|
||
|
||
// Adicionar rota
|
||
const routeLine = ` { path: '${domainConfig.name}', component: ${capitalize(domainConfig.name)}Component },`;
|
||
if (!routesContent.includes(routeLine)) {
|
||
routesContent = routesContent.replace(
|
||
/export const routes: Routes = \[\n/,
|
||
`$&${routeLine}\n`
|
||
);
|
||
}
|
||
|
||
fs.writeFileSync(routesPath, routesContent);
|
||
log.success('Roteamento atualizado');
|
||
}
|
||
|
||
// Atualizar sidebar V2.0
|
||
async function updateSidebarV2() {
|
||
log.info('Atualizando menu lateral...');
|
||
|
||
const sidebarPath = 'projects/idt_app/src/app/shared/components/sidebar/sidebar.component.ts';
|
||
let sidebarContent = fs.readFileSync(sidebarPath, 'utf8');
|
||
|
||
// Encontrar posição do menu
|
||
const menuPositionRegex = new RegExp(`title: '${domainConfig.menuPosition}'[\\s\\S]*?},`);
|
||
const match = sidebarContent.match(menuPositionRegex);
|
||
|
||
if (match) {
|
||
const newMenuItem = `{
|
||
title: '${domainConfig.displayName}',
|
||
icon: 'fas fa-cube',
|
||
route: '${domainConfig.name}',
|
||
permissions: ['${domainConfig.name}:read']
|
||
},`;
|
||
|
||
const insertPosition = match.index + match[0].length;
|
||
sidebarContent = sidebarContent.slice(0, insertPosition) + '\n ' + newMenuItem + sidebarContent.slice(insertPosition);
|
||
}
|
||
|
||
fs.writeFileSync(sidebarPath, sidebarContent);
|
||
log.success('Menu lateral atualizado');
|
||
}
|
||
|
||
// Atualizar configuração MCP V2.0
|
||
async function updateMCPConfigV2() {
|
||
log.info('Atualizando configuração MCP...');
|
||
|
||
try {
|
||
const mcpPath = '.mcp/config.json';
|
||
const mcpContent = JSON.parse(fs.readFileSync(mcpPath, 'utf8'));
|
||
|
||
// Adicionar domínio à lista
|
||
if (!mcpContent.projects.idt_app.domains.includes(domainConfig.name)) {
|
||
mcpContent.projects.idt_app.domains.push(domainConfig.name);
|
||
}
|
||
|
||
// Adicionar contexto específico V2.0
|
||
const domainContext = {
|
||
description: `Domínio de ${domainConfig.displayName} - V2.0`,
|
||
files: [
|
||
`projects/idt_app/src/app/domain/${domainConfig.name}/${domainConfig.name}.component.ts`,
|
||
`projects/idt_app/src/app/domain/${domainConfig.name}/${domainConfig.name}.service.ts`,
|
||
`projects/idt_app/src/app/domain/${domainConfig.name}/${domainConfig.name}.interface.ts`
|
||
],
|
||
features: {
|
||
baseDomainComponent: true,
|
||
registryPattern: true,
|
||
apiClientService: true,
|
||
// V2.0 Features
|
||
footerConfig: domainConfig.hasFooter,
|
||
checkboxGrouped: domainConfig.hasCheckboxGrouped,
|
||
bulkActions: domainConfig.hasBulkActions,
|
||
dateRangeUtils: domainConfig.hasDateRangeUtils,
|
||
advancedSideCard: domainConfig.hasAdvancedSideCard,
|
||
extendedSearchOptions: domainConfig.hasExtendedSearchOptions
|
||
}
|
||
};
|
||
|
||
mcpContent.contexts[`domain-${domainConfig.name}`] = domainContext;
|
||
|
||
fs.writeFileSync(mcpPath, JSON.stringify(mcpContent, null, 2));
|
||
log.success('Configuração MCP V2.0 atualizada');
|
||
|
||
} catch (error) {
|
||
log.warning(`Erro ao atualizar MCP: ${error.message} - será atualizado manualmente`);
|
||
}
|
||
}
|
||
|
||
// Compilar e testar automaticamente
|
||
async function compileAndTest() {
|
||
log.title('COMPILAÇÃO E TESTES V2.0');
|
||
|
||
try {
|
||
log.info('Compilando aplicação com funcionalidades V2.0...');
|
||
execSync('ng build idt_app --configuration development', {
|
||
stdio: 'inherit',
|
||
timeout: 120000 // 2 minutos timeout
|
||
});
|
||
log.success('Compilação V2.0 realizada com sucesso! ✨');
|
||
|
||
} catch (error) {
|
||
log.error(`Erro na compilação: ${error.message}`);
|
||
throw new Error('Falha na compilação - verifique os erros acima');
|
||
}
|
||
}
|
||
|
||
// Commit automático V2.0
|
||
async function autoCommit() {
|
||
log.title('COMMIT AUTOMÁTICO V2.0');
|
||
|
||
try {
|
||
const branchName = `feature/domain-${domainConfig.name}`;
|
||
|
||
// Adicionar todos os arquivos
|
||
execSync('git add .', { stdio: 'inherit' });
|
||
|
||
// Criar mensagem de commit V2.0
|
||
const v2Features = [];
|
||
if (domainConfig.hasFooter) v2Features.push(`FooterConfig: ${domainConfig.footerConfig.columns.length} colunas`);
|
||
if (domainConfig.hasCheckboxGrouped) v2Features.push(`CheckboxGrouped: ${domainConfig.checkboxGroupedConfig.groups.length} grupos`);
|
||
if (domainConfig.hasBulkActions) v2Features.push(`BulkActions: ${domainConfig.bulkActionsConfig.type}`);
|
||
if (domainConfig.hasDateRangeUtils) v2Features.push('DateRangeUtils integration');
|
||
if (domainConfig.hasAdvancedSideCard) v2Features.push('Advanced SideCard');
|
||
if (domainConfig.hasExtendedSearchOptions) v2Features.push('Extended SearchOptions');
|
||
|
||
const commitMessage = `feat: add ${domainConfig.displayName} domain (V2.0)
|
||
|
||
✨ Features V2.0 implementadas:
|
||
${v2Features.map(f => `- ${f}`).join('\n')}
|
||
|
||
🔧 Arquivos gerados:
|
||
- Component: ${capitalize(domainConfig.name)}Component (BaseDomainComponent + Registry Pattern)
|
||
- Service: ${capitalize(domainConfig.name)}Service (DomainService + ApiClientService)
|
||
- Interface: ${capitalize(domainConfig.name)} TypeScript
|
||
- Templates: HTML e SCSS com V2.0 features
|
||
|
||
🔗 Integrações:
|
||
- Roteamento: app.routes.ts
|
||
- Menu: sidebar.component.ts (após ${domainConfig.menuPosition})
|
||
- MCP: .mcp/config.json com features V2.0
|
||
|
||
🎯 Gerado automaticamente via create-domain-v2.js`;
|
||
|
||
// Fazer commit
|
||
execSync(`git commit -m "${commitMessage}"`, { stdio: 'inherit' });
|
||
|
||
log.success(`Commit V2.0 realizado na branch ${branchName}! 📝`);
|
||
log.info(`Para fazer push: git push origin ${branchName}`);
|
||
|
||
} catch (error) {
|
||
log.warning(`Erro no commit automático: ${error.message}`);
|
||
log.info('Você pode fazer o commit manualmente depois');
|
||
}
|
||
}
|
||
|
||
function capitalize(str) {
|
||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||
}
|
||
|
||
// ===== EXECUÇÃO =====
|
||
|
||
if (require.main === module) {
|
||
main();
|
||
}
|
||
|
||
module.exports = {
|
||
domainConfig,
|
||
FooterTemplates,
|
||
CheckboxGroupedTemplates,
|
||
BulkActionsTemplates,
|
||
SearchOptionsLibrary,
|
||
generateComponentV2,
|
||
generateServiceV2,
|
||
generateInterfaceV2
|
||
};
|