core/setup-appwrite.js
Tiago Yamamoto e6d5bef07a feat: adiciona script de setup automático do Appwrite
- Cria setup-appwrite.js para automatizar criação de database e collections
- Adiciona node-appwrite e dotenv como dependências
- Cria SETUP_GUIDE.md com instruções detalhadas
- Script cria database DevOpsPlatform automaticamente
- Cria 4 collections com schemas corretos (servers, github_repos, audit_logs, cloud_accounts)
- Popula com dados de exemplo (4 servidores, 3 repos, 3 logs, 2 contas)
- Atualiza .env automaticamente com IDs gerados
- Novo comando: npm run setup:appwrite
2025-12-11 20:06:21 -03:00

406 lines
14 KiB
JavaScript

#!/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();