#!/usr/bin/env node /** * Appwrite Setup Script * * Automaticamente: * 1. Cria Database "DevOpsPlatform" * 2. Cria 4 Collections com schemas corretos * 3. Popula com dados de exemplo * 4. Atualiza .env com os IDs gerados * * Uso: node setup-appwrite.js */ import { Client, Databases, ID, Permission, Role } from 'node-appwrite'; import * as dotenv from 'dotenv'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import { readFileSync, writeFileSync } from 'fs'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); // Carregar .env dotenv.config(); // Validar variáveis necessárias const ENDPOINT = process.env.APPWRITE_ENDPOINT; const PROJECT_ID = process.env.APPWRITE_PROJECT_ID; const API_KEY = process.env.APPWRITE_API_KEY; if (!ENDPOINT || !PROJECT_ID || !API_KEY) { console.error('❌ Erro: Variáveis de ambiente faltando!'); console.error(''); console.error('Por favor, preencha no arquivo .env:'); if (!ENDPOINT) console.error(' - APPWRITE_ENDPOINT'); if (!PROJECT_ID) console.error(' - APPWRITE_PROJECT_ID'); if (!API_KEY) console.error(' - APPWRITE_API_KEY'); console.error(''); console.error('Para obter a API_KEY:'); console.error('1. Acesse https://cloud.appwrite.io'); console.error('2. Vá em Settings → API Keys'); console.error('3. Crie uma API Key com todos os scopes (Admin)'); process.exit(1); } // Inicializar cliente Appwrite const client = new Client() .setEndpoint(ENDPOINT) .setProject(PROJECT_ID) .setKey(API_KEY); const databases = new Databases(client); // IDs que serão gerados let databaseId = ''; const collectionIds = { servers: '', github_repos: '', audit_logs: '', cloud_accounts: '' }; console.log('🚀 Iniciando setup do Appwrite...\n'); console.log(`📍 Endpoint: ${ENDPOINT}`); console.log(`📁 Project ID: ${PROJECT_ID}\n`); /** * 1. Criar Database */ async function createDatabase() { try { console.log('📦 Criando Database "DevOpsPlatform"...'); const database = await databases.create( ID.unique(), 'DevOpsPlatform', true // enabled ); databaseId = database.$id; console.log(`✅ Database criado: ${databaseId}\n`); return database; } catch (error) { if (error.code === 409) { console.log('⚠️ Database já existe, buscando ID...'); const list = await databases.list(); const existing = list.databases.find(db => db.name === 'DevOpsPlatform'); if (existing) { databaseId = existing.$id; console.log(`✅ Usando database existente: ${databaseId}\n`); return existing; } } throw error; } } /** * 2. Criar Collection: servers */ async function createServersCollection() { try { console.log('📋 Criando collection "servers"...'); const collection = await databases.createCollection( databaseId, 'servers', 'Servers', [ Permission.read(Role.any()), Permission.create(Role.users()), Permission.update(Role.users()), Permission.delete(Role.users()) ] ); collectionIds.servers = collection.$id; // Criar atributos await databases.createStringAttribute(databaseId, collectionIds.servers, 'name', 255, true); await databases.createStringAttribute(databaseId, collectionIds.servers, 'ip', 45, true); await databases.createEnumAttribute(databaseId, collectionIds.servers, 'status', ['online', 'offline'], true, 'online'); await databases.createStringAttribute(databaseId, collectionIds.servers, 'region', 100, false); console.log(`✅ Collection "servers" criada: ${collectionIds.servers}`); // Aguardar atributos serem processados await new Promise(resolve => setTimeout(resolve, 2000)); } catch (error) { if (error.code === 409) { collectionIds.servers = 'servers'; console.log(`⚠️ Collection "servers" já existe`); } else { throw error; } } } /** * 3. Criar Collection: github_repos */ async function createGitHubReposCollection() { try { console.log('📋 Criando collection "github_repos"...'); const collection = await databases.createCollection( databaseId, 'github_repos', 'GitHub Repositories', [ Permission.read(Role.any()), Permission.create(Role.users()), Permission.update(Role.users()), Permission.delete(Role.users()) ] ); collectionIds.github_repos = collection.$id; // Criar atributos await databases.createStringAttribute(databaseId, collectionIds.github_repos, 'repo_name', 255, true); await databases.createUrlAttribute(databaseId, collectionIds.github_repos, 'url', true); await databases.createStringAttribute(databaseId, collectionIds.github_repos, 'last_commit', 255, false); await databases.createStringAttribute(databaseId, collectionIds.github_repos, 'status', 50, false, 'active'); console.log(`✅ Collection "github_repos" criada: ${collectionIds.github_repos}`); await new Promise(resolve => setTimeout(resolve, 2000)); } catch (error) { if (error.code === 409) { collectionIds.github_repos = 'github_repos'; console.log(`⚠️ Collection "github_repos" já existe`); } else { throw error; } } } /** * 4. Criar Collection: audit_logs */ async function createAuditLogsCollection() { try { console.log('📋 Criando collection "audit_logs"...'); const collection = await databases.createCollection( databaseId, 'audit_logs', 'Audit Logs', [ Permission.read(Role.any()), Permission.create(Role.users()), Permission.update(Role.users()), Permission.delete(Role.users()) ] ); collectionIds.audit_logs = collection.$id; // Criar atributos await databases.createStringAttribute(databaseId, collectionIds.audit_logs, 'event', 500, true); await databases.createStringAttribute(databaseId, collectionIds.audit_logs, 'user_id', 255, true); await databases.createDatetimeAttribute(databaseId, collectionIds.audit_logs, 'timestamp', true); console.log(`✅ Collection "audit_logs" criada: ${collectionIds.audit_logs}`); await new Promise(resolve => setTimeout(resolve, 2000)); } catch (error) { if (error.code === 409) { collectionIds.audit_logs = 'audit_logs'; console.log(`⚠️ Collection "audit_logs" já existe`); } else { throw error; } } } /** * 5. Criar Collection: cloud_accounts */ async function createCloudAccountsCollection() { try { console.log('📋 Criando collection "cloud_accounts"...'); const collection = await databases.createCollection( databaseId, 'cloud_accounts', 'Cloud Accounts', [ Permission.read(Role.any()), Permission.create(Role.users()), Permission.update(Role.users()), Permission.delete(Role.users()) ] ); collectionIds.cloud_accounts = collection.$id; // Criar atributos await databases.createStringAttribute(databaseId, collectionIds.cloud_accounts, 'provider', 100, true); await databases.createStringAttribute(databaseId, collectionIds.cloud_accounts, 'apiKey', 500, true); await databases.createStringAttribute(databaseId, collectionIds.cloud_accounts, 'label', 255, false); console.log(`✅ Collection "cloud_accounts" criada: ${collectionIds.cloud_accounts}`); await new Promise(resolve => setTimeout(resolve, 2000)); } catch (error) { if (error.code === 409) { collectionIds.cloud_accounts = 'cloud_accounts'; console.log(`⚠️ Collection "cloud_accounts" já existe`); } else { throw error; } } } /** * 6. Popular com dados de exemplo */ async function seedData() { console.log('\n🌱 Populando com dados de exemplo...\n'); // Servidores const servers = [ { name: 'web-01', ip: '192.168.1.10', status: 'online', region: 'us-east-1' }, { name: 'web-02', ip: '192.168.1.11', status: 'online', region: 'us-east-1' }, { name: 'db-01', ip: '192.168.1.20', status: 'online', region: 'us-west-2' }, { name: 'cache-01', ip: '192.168.1.30', status: 'offline', region: 'eu-west-1' }, ]; for (const server of servers) { try { await databases.createDocument(databaseId, collectionIds.servers, ID.unique(), server); console.log(` ✅ Servidor criado: ${server.name}`); } catch (error) { console.log(` ⚠️ Servidor ${server.name} já existe`); } } // Repositórios GitHub const repos = [ { repo_name: 'core-platform', url: 'https://github.com/rede5/core', last_commit: 'docs: adiciona setup completo', status: 'active' }, { repo_name: 'api-backend', url: 'https://github.com/rede5/api', last_commit: 'feat: add authentication', status: 'active' }, { repo_name: 'mobile-app', url: 'https://github.com/rede5/mobile', last_commit: 'fix: crash on startup', status: 'active' }, ]; for (const repo of repos) { try { await databases.createDocument(databaseId, collectionIds.github_repos, ID.unique(), repo); console.log(` ✅ Repositório criado: ${repo.repo_name}`); } catch (error) { console.log(` ⚠️ Repositório ${repo.repo_name} já existe`); } } // Audit Logs const logs = [ { event: 'User login', user_id: 'admin', timestamp: new Date().toISOString() }, { event: 'Server deployed', user_id: 'admin', timestamp: new Date().toISOString() }, { event: 'Configuration updated', user_id: 'admin', timestamp: new Date().toISOString() }, ]; for (const log of logs) { try { await databases.createDocument(databaseId, collectionIds.audit_logs, ID.unique(), log); console.log(` ✅ Log criado: ${log.event}`); } catch (error) { console.log(` ⚠️ Log já existe`); } } // Cloud Accounts const accounts = [ { provider: 'Cloudflare', apiKey: 'cf_example_key_123', label: 'Production Account' }, { provider: 'AWS', apiKey: 'aws_example_key_456', label: 'Staging Account' }, ]; for (const account of accounts) { try { await databases.createDocument(databaseId, collectionIds.cloud_accounts, ID.unique(), account); console.log(` ✅ Conta criada: ${account.provider}`); } catch (error) { console.log(` ⚠️ Conta ${account.provider} já existe`); } } } /** * 7. Atualizar arquivo .env */ function updateEnvFile() { console.log('\n📝 Atualizando arquivo .env...'); const envPath = join(__dirname, '.env'); let envContent = readFileSync(envPath, 'utf8'); // Atualizar IDs envContent = envContent.replace( /VITE_APPWRITE_PROJECT_ID=.*/, `VITE_APPWRITE_PROJECT_ID=${PROJECT_ID}` ); envContent = envContent.replace( /VITE_APPWRITE_DATABASE_ID=.*/, `VITE_APPWRITE_DATABASE_ID=${databaseId}` ); envContent = envContent.replace( /VITE_APPWRITE_COLLECTION_SERVERS_ID=.*/, `VITE_APPWRITE_COLLECTION_SERVERS_ID=${collectionIds.servers}` ); envContent = envContent.replace( /VITE_APPWRITE_COLLECTION_GITHUB_REPOS_ID=.*/, `VITE_APPWRITE_COLLECTION_GITHUB_REPOS_ID=${collectionIds.github_repos}` ); envContent = envContent.replace( /VITE_APPWRITE_COLLECTION_AUDIT_LOGS_ID=.*/, `VITE_APPWRITE_COLLECTION_AUDIT_LOGS_ID=${collectionIds.audit_logs}` ); envContent = envContent.replace( /VITE_APPWRITE_COLLECTION_CLOUDFLARE_ACCOUNTS_ID=.*/, `VITE_APPWRITE_COLLECTION_CLOUDFLARE_ACCOUNTS_ID=${collectionIds.cloud_accounts}` ); writeFileSync(envPath, envContent); console.log('✅ Arquivo .env atualizado!\n'); } /** * Main */ async function main() { try { await createDatabase(); await createServersCollection(); await createGitHubReposCollection(); await createAuditLogsCollection(); await createCloudAccountsCollection(); await seedData(); updateEnvFile(); console.log('\n🎉 Setup concluído com sucesso!\n'); console.log('📋 Resumo:'); console.log(` Database ID: ${databaseId}`); console.log(` servers: ${collectionIds.servers}`); console.log(` github_repos: ${collectionIds.github_repos}`); console.log(` audit_logs: ${collectionIds.audit_logs}`); console.log(` cloud_accounts: ${collectionIds.cloud_accounts}`); console.log('\n✅ Arquivo .env atualizado com os IDs'); console.log('\n🚀 Próximo passo: npm run dev:web\n'); } catch (error) { console.error('\n❌ Erro durante setup:'); console.error(error.message); if (error.response) { console.error('Detalhes:', error.response); } process.exit(1); } } main();