chore: initial setup with PostgreSQL, DragonflyDB, and Nginx routing configs

This commit is contained in:
Antigravity AI Agent
2026-05-13 05:12:32 +02:00
commit 19dbbae8b8
551 changed files with 308309 additions and 0 deletions
+111
View File
@@ -0,0 +1,111 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pluginRegistry = void 0;
const logger_1 = require("../config/logger");
/**
* Registry central dos plugins.
* Gerencia o lifecycle (activate/deactivate) e expõe metadados para a API admin.
*/
class PluginRegistry {
entries = new Map();
ctx;
/** Deve ser chamado uma vez no bootstrap com o contexto completo */
setContext(ctx) {
this.ctx = ctx;
}
/** Registra plugins carregados (sem ativar ainda) */
register(plugins) {
for (const { instance, manifest, dir } of plugins) {
this.entries.set(manifest.name, { instance, manifest, active: false, dir });
}
}
/** Ativa todos os plugins marcados como enabled no manifest.
* Plugins com dependências faltando são pulados com warning (não crasham o servidor). */
async activateAll() {
for (const [name, entry] of this.entries) {
if (!entry.manifest.enabled)
continue;
try {
await this.activate(name);
}
catch (err) {
logger_1.logger.warn({ name, err: err.message }, '[PluginRegistry] Plugin pulado na inicialização');
}
}
}
async activate(name) {
const entry = this.entries.get(name);
if (!entry)
throw new Error(`Plugin "${name}" não encontrado`);
if (entry.active)
return;
// Verifica dependências
for (const dep of entry.manifest.dependencies) {
const depEntry = this.entries.get(dep);
if (!depEntry?.active) {
throw new Error(`Dependência "${dep}" do plugin "${name}" não está ativa`);
}
}
try {
await entry.instance.activate(this.ctx);
entry.active = true;
entry.manifest.enabled = true;
logger_1.logger.info({ name }, '[PluginRegistry] Plugin ativado');
}
catch (err) {
logger_1.logger.error({ err, name }, '[PluginRegistry] Falha ao ativar plugin');
throw err;
}
}
async deactivate(name) {
const entry = this.entries.get(name);
if (!entry)
throw new Error(`Plugin "${name}" não encontrado`);
if (!entry.active)
return;
if (!entry.manifest.canDisable)
throw new Error(`Plugin "${name}" não pode ser desativado`);
// Verifica se algum plugin ativo depende deste
for (const [depName, depEntry] of this.entries) {
if (depEntry.active && depEntry.manifest.dependencies.includes(name)) {
throw new Error(`Plugin "${depName}" depende de "${name}". Desative-o primeiro.`);
}
}
try {
await entry.instance.deactivate(this.ctx);
entry.active = false;
entry.manifest.enabled = false;
logger_1.logger.info({ name }, '[PluginRegistry] Plugin desativado');
}
catch (err) {
logger_1.logger.error({ err, name }, '[PluginRegistry] Falha ao desativar plugin');
throw err;
}
}
/** Retorna lista de todos os plugins com status para a API admin */
list() {
return Array.from(this.entries.entries()).map(([name, entry]) => ({ name, ...entry }));
}
getEntry(name) {
return this.entries.get(name);
}
/**
* Força reativação de um plugin sem passar pelo deactivate.
* Útil quando canDisable=false mas a config foi atualizada e precisa ser relida.
*/
async reactivate(name) {
const entry = this.entries.get(name);
if (!entry)
throw new Error(`Plugin "${name}" não encontrado`);
entry.active = false;
await this.activate(name);
logger_1.logger.info({ name }, '[PluginRegistry] Plugin reativado com nova config');
}
/** Retorna menu items de todos os plugins ativos */
getActiveMenuItems() {
return Array.from(this.entries.values())
.filter((e) => e.active && e.manifest.frontend?.menuItems?.length)
.map((e) => ({ pluginName: e.manifest.name, items: e.manifest.frontend }));
}
}
exports.pluginRegistry = new PluginRegistry();