ae629d1dc2
- Camada de banco unificada (src/database.js): drivers Postgres/Firebird, tradutor de SQL, suporte a schema e pool de conexões - Conexões: novo_local (Postgres externo) e firebird_local (legado) - Tela de rotas da API redesenhada (auth, params, exemplos de body) - Correções de segurança (críticos/altos/médios/baixos): XSS no chat, escalonamento de privilégio, mídia autenticada, SQL restrito a gerente, JWT sem fallback + issuer, IDOR em conversas, CORS por allowlist, rate-limit no login, limites de corpo por rota - Deploy alinhado: install.sh grava .env com PG_*, migracoes.js driver-aware Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
491 lines
16 KiB
JavaScript
491 lines
16 KiB
JavaScript
/**
|
||
* ARQUIVO DE MIGRAÇÕES DO BANCO DE DADOS
|
||
* ========================================
|
||
*
|
||
* Este script contém TODAS as alterações estruturais feitas no banco de dados
|
||
* desde a criação inicial do projeto.
|
||
*
|
||
* USO:
|
||
* node scripts/migracoes.js [alias]
|
||
*
|
||
* Exemplo:
|
||
* node scripts/migracoes.js lajedo
|
||
* node scripts/migracoes.js novo
|
||
*
|
||
* IMPORTANTE:
|
||
* - Cada migração tem um ID único e só executa uma vez
|
||
* - O controle é feito via tabela CHATC2_CONTROLE_MIGRACOES
|
||
* - Para adicionar NOVA migração, adicione um novo objeto no array MIGRACOES
|
||
* - Nunca remova ou altere migrações já existentes (apenas adicione novas)
|
||
*/
|
||
|
||
const db = require('../src/database');
|
||
|
||
// Este script aplica DDL no dialeto Firebird (BLOB SUB_TYPE, etc.).
|
||
// O schema do PostgreSQL é gerenciado externamente (banco externo) — use este
|
||
// script apenas para bancos Firebird. Alias padrão: firebird_local.
|
||
const alias = process.argv[2] || 'firebird_local';
|
||
|
||
// ============================================================
|
||
// CONTROLE DE MIGRAÇÕES
|
||
// ============================================================
|
||
async function garantirControle() {
|
||
try {
|
||
await db.execute(alias, `
|
||
CREATE TABLE CHATC2_CONTROLE_MIGRACOES (
|
||
MIG_ID INTEGER NOT NULL PRIMARY KEY,
|
||
MIG_DESCRICAO VARCHAR(200),
|
||
MIG_DATA_EXECUCAO TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
MIG_STATUS CHAR(1) DEFAULT 'A'
|
||
)
|
||
`);
|
||
console.log('✅ Tabela CHATC2_CONTROLE_MIGRACOES criada');
|
||
} catch(e) {
|
||
if (!e.message.includes('already exists')) {
|
||
console.log('⚠️ CHATC2_CONTROLE_MIGRACOES:', e.message.substring(0, 100));
|
||
}
|
||
}
|
||
}
|
||
|
||
async function migracaoJaExecutada(id) {
|
||
try {
|
||
var r = await db.query(alias,
|
||
'SELECT COUNT(*) AS CT FROM CHATC2_CONTROLE_MIGRACOES WHERE MIG_ID = ?', [id]);
|
||
return r[0]?.CT > 0;
|
||
} catch(e) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
async function registrarMigracao(id, descricao) {
|
||
try {
|
||
await db.execute(alias,
|
||
'INSERT INTO CHATC2_CONTROLE_MIGRACOES (MIG_ID, MIG_DESCRICAO) VALUES (?, ?)',
|
||
[id, descricao]);
|
||
} catch(e) {
|
||
console.log('⚠️ Erro ao registrar migração:', e.message.substring(0, 80));
|
||
}
|
||
}
|
||
|
||
// ============================================================
|
||
// LISTA DE MIGRAÇÕES
|
||
// ============================================================
|
||
// SEMPRE adicione NOVAS migrações no FINAL do array, com ID sequencial.
|
||
// NUNCA remova ou modifique migrações já existentes.
|
||
|
||
const MIGRACOES = [
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 1: Campo USU_TIPO_CHAT em USUARIOS
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 1,
|
||
descricao: 'Adicionar USU_TIPO_CHAT em USUARIOS (A=Atendente, G=Gerente)',
|
||
sql: [
|
||
`ALTER TABLE USUARIOS ADD USU_TIPO_CHAT CHAR(1) DEFAULT 'A'`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 2: Tabela CHATC2_INSTANCIAS (Evolution API)
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 2,
|
||
descricao: 'Criar tabela CHATC2_INSTANCIAS para conexões WhatsApp',
|
||
sql: [
|
||
`CREATE TABLE CHATC2_INSTANCIAS (
|
||
INS_CODIGO_ID INTEGER NOT NULL PRIMARY KEY,
|
||
INS_EMPRESA_ID INTEGER NOT NULL,
|
||
INS_NOME VARCHAR(100),
|
||
INS_URL VARCHAR(500),
|
||
INS_API_KEY VARCHAR(500),
|
||
INS_INSTANCE_NAME VARCHAR(100),
|
||
INS_STATUS CHAR(1) DEFAULT 'D',
|
||
INS_QR_CODE BLOB SUB_TYPE 0,
|
||
INS_DT_CONEXAO TIMESTAMP,
|
||
INS_DT_CADASTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
INS_SITUACAO CHAR(1) DEFAULT 'A'
|
||
)`,
|
||
`CREATE SEQUENCE GEN_INSTANCIAS`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 3: Tabela CHATC2_EQUIPES
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 3,
|
||
descricao: 'Criar tabela CHATC2_EQUIPES',
|
||
sql: [
|
||
`CREATE TABLE CHATC2_EQUIPES (
|
||
EQU_CODIGO_ID INTEGER NOT NULL PRIMARY KEY,
|
||
EQU_EMPRESA_ID INTEGER NOT NULL,
|
||
EQU_NOME VARCHAR(100),
|
||
EQU_ORDEM INTEGER DEFAULT 0,
|
||
EQU_SITUACAO CHAR(1) DEFAULT 'A'
|
||
)`,
|
||
`CREATE SEQUENCE GEN_EQUIPES`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 4: Tabela CHATC2_USU_EQUIPES
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 4,
|
||
descricao: 'Criar tabela CHATC2_USU_EQUIPES (relação N:N)',
|
||
sql: [
|
||
`CREATE TABLE CHATC2_USU_EQUIPES (
|
||
EQU_EQUIPE_ID INTEGER NOT NULL,
|
||
EQU_USUARIO_ID INTEGER NOT NULL,
|
||
PRIMARY KEY (EQU_EQUIPE_ID, EQU_USUARIO_ID)
|
||
)`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 5: Tabela CHATC2_ETIQUETAS
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 5,
|
||
descricao: 'Criar tabela CHATC2_ETIQUETAS',
|
||
sql: [
|
||
`CREATE TABLE CHATC2_ETIQUETAS (
|
||
ETI_CODIGO_ID INTEGER NOT NULL PRIMARY KEY,
|
||
ETI_EMPRESA_ID INTEGER NOT NULL,
|
||
ETI_NOME VARCHAR(50),
|
||
ETI_COR VARCHAR(7) DEFAULT '#667eea',
|
||
ETI_SITUACAO CHAR(1) DEFAULT 'A'
|
||
)`,
|
||
`CREATE SEQUENCE GEN_ETIQUETAS`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 6: Tabela CHATC2_CONVERSAS
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 6,
|
||
descricao: 'Criar tabela CHATC2_CONVERSAS',
|
||
sql: [
|
||
`CREATE TABLE CHATC2_CONVERSAS (
|
||
CON_CODIGO_ID INTEGER NOT NULL PRIMARY KEY,
|
||
CON_EMPRESA_ID INTEGER NOT NULL,
|
||
CON_INSTANCIA_ID INTEGER,
|
||
CON_CLIENTE_ID INTEGER,
|
||
CON_NUMERO VARCHAR(20),
|
||
CON_NOME_CONTATO VARCHAR(100),
|
||
CON_STATUS CHAR(1) DEFAULT 'E',
|
||
CON_USUARIO_ID INTEGER,
|
||
CON_EQUIPE_ID INTEGER,
|
||
CON_DT_INICIO TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
CON_DT_FINAL TIMESTAMP,
|
||
CON_DT_ULTIMA_MSG TIMESTAMP,
|
||
CON_SAUDACAO_ENVIADA CHAR(1) DEFAULT 'N',
|
||
CON_CSAT_ENVIADO CHAR(1) DEFAULT 'N',
|
||
CON_PRIMEIRA_MSG TIMESTAMP,
|
||
CON_ORIGEM VARCHAR(20) DEFAULT 'whatsapp',
|
||
CON_SITUACAO CHAR(1) DEFAULT 'A'
|
||
)`,
|
||
`CREATE SEQUENCE GEN_CONVERSAS`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 7: Tabela CHATC2_CONVERSAS_MENSAGENS
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 7,
|
||
descricao: 'Criar tabela CHATC2_CONVERSAS_MENSAGENS',
|
||
sql: [
|
||
`CREATE TABLE CHATC2_CONVERSAS_MENSAGENS (
|
||
CME_CODIGO_ID INTEGER NOT NULL PRIMARY KEY,
|
||
CME_CONVERSA_ID INTEGER NOT NULL,
|
||
CME_REMETENTE CHAR(1) DEFAULT 'C',
|
||
CME_USUARIO_ID INTEGER,
|
||
CME_MENSAGEM BLOB SUB_TYPE 1,
|
||
CME_TEXTO VARCHAR(4000),
|
||
CME_TIPO VARCHAR(20) DEFAULT 'text',
|
||
CME_DT_ENVIO TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
CME_PRIVADA CHAR(1) DEFAULT 'N',
|
||
CME_LIDA CHAR(1) DEFAULT 'N',
|
||
CME_MIDIA_ID INTEGER,
|
||
CME_SITUACAO CHAR(1) DEFAULT 'A'
|
||
)`,
|
||
`CREATE SEQUENCE GEN_CONVERSAS_MENSAGENS`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 8: Tabela CHATC2_MENSAGENS_ATENDIMENTOS (blob mídias)
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 8,
|
||
descricao: 'Criar tabela CHATC2_MENSAGENS_ATENDIMENTOS para mídias',
|
||
sql: [
|
||
`CREATE TABLE CHATC2_MENSAGENS_ATENDIMENTOS (
|
||
MAT_CODIGO_ID INTEGER NOT NULL PRIMARY KEY,
|
||
MAT_CONVERSA_ID INTEGER,
|
||
MAT_MENSAGEM_ID INTEGER,
|
||
MAT_NOME_ARQUIVO VARCHAR(255),
|
||
MAT_TIPO_ARQUIVO VARCHAR(50),
|
||
MAT_ARQUIVO BLOB SUB_TYPE 0,
|
||
MAT_DT_CADASTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
MAT_SITUACAO CHAR(1) DEFAULT 'A'
|
||
)`,
|
||
`CREATE SEQUENCE GEN_MENSAGENS_ATENDIMENTO`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 9: Tabela CHATC2_CONVERSAS_ETIQUETAS
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 9,
|
||
descricao: 'Criar tabela CHATC2_CONVERSAS_ETIQUETAS',
|
||
sql: [
|
||
`CREATE TABLE CHATC2_CONVERSAS_ETIQUETAS (
|
||
CET_CONVERSA_ID INTEGER NOT NULL,
|
||
CET_ETIQUETA_ID INTEGER NOT NULL,
|
||
PRIMARY KEY (CET_CONVERSA_ID, CET_ETIQUETA_ID)
|
||
)`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 10: Tabela CHATC2_CSAT_AVALIACOES
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 10,
|
||
descricao: 'Criar tabela CHATC2_CSAT_AVALIACOES',
|
||
sql: [
|
||
`CREATE TABLE CHATC2_CSAT_AVALIACOES (
|
||
CSA_CODIGO_ID INTEGER NOT NULL PRIMARY KEY,
|
||
CSA_CONVERSA_ID INTEGER,
|
||
CSA_EMPRESA_ID INTEGER,
|
||
CSA_CLIENTE_ID INTEGER,
|
||
CSA_NOTA INTEGER,
|
||
CSA_COMENTARIO VARCHAR(500),
|
||
CSA_DT_AVALIACAO TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
)`,
|
||
`CREATE SEQUENCE GEN_CSAT_AVALIACOES`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 11: Tabela CHATC2_CONFIGURACOES_EMPRESA (base)
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 11,
|
||
descricao: 'Criar tabela CHATC2_CONFIGURACOES_EMPRESA (base)',
|
||
sql: [
|
||
`CREATE TABLE CHATC2_CONFIGURACOES_EMPRESA (
|
||
CFE_EMPRESA_ID INTEGER NOT NULL PRIMARY KEY,
|
||
CFE_INSTANCIA_PADRAO_ID INTEGER,
|
||
CFE_FOTO_CELULAR CHAR(1) DEFAULT 'N',
|
||
CFE_SAUDACAO_ATIVA CHAR(1) DEFAULT 'S',
|
||
CFE_SAUDACAO_MENSAGEM VARCHAR(500),
|
||
CFE_CSAT_ATIVO CHAR(1) DEFAULT 'N',
|
||
CFE_CSAT_MENSAGEM VARCHAR(500) DEFAULT 'Avalie seu atendimento de 1 a 5 estrelas'
|
||
)`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 12: EQU_ORDEM em CHATC2_EQUIPES
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 12,
|
||
descricao: 'Adicionar EQU_ORDEM em CHATC2_EQUIPES (ordenação)',
|
||
sql: [
|
||
`ALTER TABLE CHATC2_EQUIPES ADD EQU_ORDEM INTEGER DEFAULT 0`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 13: Campos de triagem em CHATC2_CONFIGURACOES_EMPRESA
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 13,
|
||
descricao: 'Adicionar campos de triagem em CHATC2_CONFIGURACOES_EMPRESA',
|
||
sql: [
|
||
`ALTER TABLE CHATC2_CONFIGURACOES_EMPRESA ADD CFE_ENVIAR_NOME_USUARIO CHAR(1) DEFAULT 'N'`,
|
||
`ALTER TABLE CHATC2_CONFIGURACOES_EMPRESA ADD CFE_TRIAGEM_ATIVA CHAR(1) DEFAULT 'N'`,
|
||
`ALTER TABLE CHATC2_CONFIGURACOES_EMPRESA ADD CFE_TRIAGEM_MSG_WELCOME VARCHAR(500)`,
|
||
`ALTER TABLE CHATC2_CONFIGURACOES_EMPRESA ADD CFE_TRIAGEM_MSG_AFTER VARCHAR(500)`,
|
||
`ALTER TABLE CHATC2_CONFIGURACOES_EMPRESA ADD CFE_TRIAGEM_BOLETO_NUMERO VARCHAR(10) DEFAULT '0'`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 14: CON_MENU_ESTADO em CHATC2_CONVERSAS
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 14,
|
||
descricao: 'Adicionar CON_MENU_ESTADO em CHATC2_CONVERSAS (navegação triagem)',
|
||
sql: [
|
||
`ALTER TABLE CHATC2_CONVERSAS ADD CON_MENU_ESTADO VARCHAR(100)`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 15: CON_ETIQUETAS_DESC em CHATC2_CONVERSAS
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 15,
|
||
descricao: 'Adicionar CON_ETIQUETAS_DESC em CHATC2_CONVERSAS (estado legado)',
|
||
sql: [
|
||
`ALTER TABLE CHATC2_CONVERSAS ADD CON_ETIQUETAS_DESC VARCHAR(500)`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 16: Tabela CHATC2_MENUS_EMPRESA (fluxo personalizado)
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 16,
|
||
descricao: 'Criar tabela CHATC2_MENUS_EMPRESA para fluxo de atendimento personalizado',
|
||
sql: [
|
||
`CREATE TABLE CHATC2_MENUS_EMPRESA (
|
||
MNE_CODIGO_ID INTEGER NOT NULL PRIMARY KEY,
|
||
MNE_EMPRESA_ID INTEGER,
|
||
MNE_EQUIPE_ID INTEGER,
|
||
MNE_MENU_PAI_ID INTEGER,
|
||
MNE_ORDEM INTEGER DEFAULT 0,
|
||
MNE_TITULO VARCHAR(100),
|
||
MNE_TIPO CHAR(1) DEFAULT 'M',
|
||
MNE_TEXTO BLOB SUB_TYPE TEXT,
|
||
MNE_ACAO_ROTA VARCHAR(100),
|
||
MNE_ACAO_METODO VARCHAR(10),
|
||
MNE_ACAO_PROMPT VARCHAR(300),
|
||
MNE_SITUACAO CHAR(1) DEFAULT 'A'
|
||
)`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 17: CON_USUARIO_NOME, CON_EQUIPE_NOME, CON_ETIQUETAS_DESC em CHATC2_CONVERSAS
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 17,
|
||
descricao: 'Adicionar CON_USUARIO_NOME, CON_EQUIPE_NOME, CON_ETIQUETAS_DESC em CHATC2_CONVERSAS',
|
||
sql: [
|
||
`ALTER TABLE CHATC2_CONVERSAS ADD CON_USUARIO_NOME VARCHAR(100)`,
|
||
`ALTER TABLE CHATC2_CONVERSAS ADD CON_EQUIPE_NOME VARCHAR(100)`,
|
||
`ALTER TABLE CHATC2_CONVERSAS ADD CON_ETIQUETAS_DESC VARCHAR(500)`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 18: Etiquetas nos menus de fluxo
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 18,
|
||
descricao: 'Adicionar MNE_ETIQUETA_IDS em CHATC2_MENUS_EMPRESA (etiquetas por etapa do fluxo)',
|
||
sql: [
|
||
`ALTER TABLE CHATC2_MENUS_EMPRESA ADD MNE_ETIQUETA_IDS VARCHAR(200)`,
|
||
],
|
||
},
|
||
|
||
// ----------------------------------------------------------
|
||
// MIGRAÇÃO 19: Transcrição de áudio em CHATC2_MENSAGENS_ATENDIMENTOS
|
||
// ----------------------------------------------------------
|
||
{
|
||
id: 19,
|
||
descricao: 'Adicionar MAT_TRANSCRICAO em CHATC2_MENSAGENS_ATENDIMENTOS (transcricao de audio)',
|
||
sql: [
|
||
`ALTER TABLE CHATC2_MENSAGENS_ATENDIMENTOS ADD MAT_TRANSCRICAO BLOB SUB_TYPE TEXT`,
|
||
],
|
||
},
|
||
|
||
// ============================================================
|
||
// >>> ADICIONE NOVAS MIGRAÇÕES AQUI <<<
|
||
// ============================================================
|
||
//
|
||
// Exemplo:
|
||
// {
|
||
// id: 19,
|
||
// descricao: 'Descrição clara do que esta migração faz',
|
||
// sql: [
|
||
// `ALTER TABLE EXEMPLO ADD NOVO_CAMPO VARCHAR(100)`,
|
||
// `CREATE TABLE NOVA_TABELA ( ... )`,
|
||
// ],
|
||
// },
|
||
//
|
||
];
|
||
|
||
// ============================================================
|
||
// EXECUTOR DE MIGRAÇÕES
|
||
// ============================================================
|
||
async function main() {
|
||
console.log(`\n=== MIGRAÇÕES DE BANCO DE DADOS ===`);
|
||
console.log(`Alias: ${alias}\n`);
|
||
|
||
// Blindagem: a DDL aqui é Firebird. Se o alias for Postgres (banco externo,
|
||
// gerenciado fora), não há o que aplicar — sai sem erro.
|
||
let driver;
|
||
try { driver = db.driverOf(alias); }
|
||
catch (e) { console.error('❌', e.message); process.exit(1); }
|
||
if (driver !== 'firebird') {
|
||
console.log(`⚠️ O alias "${alias}" usa o driver "${driver}". Este script aplica DDL Firebird.`);
|
||
console.log(' O schema do PostgreSQL é gerenciado no banco externo — nada a fazer aqui.');
|
||
console.log(' Para migrar um banco Firebird: node scripts/migracoes.js firebird_local\n');
|
||
process.exit(0);
|
||
}
|
||
|
||
await garantirControle();
|
||
|
||
var executadas = 0;
|
||
var pendentes = 0;
|
||
|
||
for (var mig of MIGRACOES) {
|
||
var jaExecutou = await migracaoJaExecutada(mig.id);
|
||
|
||
if (jaExecutou) {
|
||
console.log(`⏭️ [${mig.id}] ${mig.descricao} — já executada`);
|
||
continue;
|
||
}
|
||
|
||
pendentes++;
|
||
console.log(`▶️ [${mig.id}] ${mig.descricao}...`);
|
||
|
||
var erros = 0;
|
||
for (var cmd of mig.sql) {
|
||
try {
|
||
await db.execute(alias, cmd);
|
||
console.log(` ✅ ${cmd.substring(0, 80)}...`);
|
||
} catch(e) {
|
||
var msg = e.message;
|
||
// Firebird pode reportar "already exists" de várias formas
|
||
if (msg.includes('already exists') || msg.includes('Violation') || msg.includes('duplicate') || msg.includes('Unknow')) {
|
||
console.log(` ℹ️ Já existe: ${cmd.substring(0, 60)}...`);
|
||
} else {
|
||
console.log(` ❌ ${msg.substring(0, 120)}`);
|
||
erros++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (erros === 0) {
|
||
await registrarMigracao(mig.id, mig.descricao);
|
||
executadas++;
|
||
console.log(` ✅ Migração ${mig.id} concluída\n`);
|
||
} else {
|
||
console.log(` ⚠️ Migração ${mig.id} concluída com ${erros} erro(s)\n`);
|
||
}
|
||
}
|
||
|
||
console.log(`=== RESUMO ===`);
|
||
console.log(`Total de migrações: ${MIGRACOES.length}`);
|
||
console.log(`Executadas agora: ${executadas}`);
|
||
console.log(`Já executadas antes: ${MIGRACOES.length - pendentes}`);
|
||
console.log(`Pendentes (com erro): ${pendentes - executadas}`);
|
||
console.log(`\n✅ Finalizado!`);
|
||
process.exit(0);
|
||
}
|
||
|
||
main().catch(function(err) {
|
||
console.error('❌ Erro fatal:', err.message);
|
||
process.exit(1);
|
||
});
|