v1.0
Acessar api.vupi.us

Dependências Externas

Declare bibliotecas externas no composer.json do seu módulo. A IDE instala tudo automaticamente no deploy.

Como funciona

Cada módulo criado na IDE já vem com um composer.json próprio. Você declara as dependências que precisa — como PHPMailer, Guzzle, Stripe SDK — e ao clicar em Publicar, o sistema:

1

Verifica conflitos

Compara as versões requeridas com o composer.lock do projeto usando Composer\Semver. Se houver conflito, o deploy é bloqueado com erro claro antes de qualquer mudança.

2

Instala apenas o que falta

Pacotes já instalados e compatíveis são ignorados — zero efeito colateral. Apenas pacotes novos são instalados via composer require.

3

Registra o namespace

O namespace PSR-4 do módulo é adicionado ao composer.json do projeto e o autoloader é regenerado.

4

Recarrega o PHP-FPM

O OPcache é invalidado e o PHP-FPM recarregado graciosamente. As classes ficam disponíveis imediatamente na próxima requisição.

Exemplo: módulo com PHPMailer

Edite o composer.json do seu módulo na IDE e declare a dependência:

json
{
  "name": "meu-vendor/modulo-notificacao",
  "description": "Módulo de notificações por e-mail",
  "require": {
    "php": ">=8.1",
    "phpmailer/phpmailer": "^6.9"
  },
  "autoload": {
    "psr-4": {
      "Src\\Modules\\Notificacao\\": ""
    }
  },
  "extra": {
    "vupi.us": {
      "provides": ["email-sender"]
    }
  }
}

No seu Service, use normalmente:

php
<?php

namespace Src\Modules\Notificacao\Services;

use PHPMailer\PHPMailer\PHPMailer;

class NotificacaoService
{
    public function enviar(string $para, string $assunto, string $html): void
    {
        $mail = new PHPMailer(true);
        $mail->isSMTP();
        $mail->Host     = $_ENV['MAILER_HOST'];
        $mail->Username = $_ENV['MAILER_USERNAME'];
        $mail->Password = $_ENV['MAILER_PASSWORD'];
        $mail->Port     = (int) $_ENV['MAILER_PORT'];
        $mail->SMTPAuth = true;
        $mail->setFrom($_ENV['MAILER_FROM_EMAIL'], $_ENV['MAILER_FROM_NAME']);
        $mail->addAddress($para);
        $mail->isHTML(true);
        $mail->Subject = $assunto;
        $mail->Body    = $html;
        $mail->send();
    }
}
Prefira libs já presentes no projeto

O projeto já inclui phpmailer/phpmailer, firebase/php-jwt, ramsey/uuid e vlucas/phpdotenv. Reutilize-as sempre que possível para evitar conflitos de versão.

Dependency Health Report e botão de instalação

O painel lateral da IDE exibe automaticamente o status de saúde das dependências do módulo aberto. Quando há pacotes ausentes, aparece o botão "Instalar dependências" — sem precisar fazer deploy:

🟢 OK

Tudo instalado e compatível. Pode publicar.

🟡 Warning + botão

Pacote ausente. O botão "Instalar dependências" aparece. Clique para instalar sem precisar fazer deploy.

🔴 Critical

Conflito de versão. Deploy bloqueado. A IDE mostra versão instalada, requerida e sugestão de fix.

Como instalar dependências na IDE

1

Edite o composer.json

Abra composer.json na IDE e adicione o pacote na seção require. Salve com Ctrl+S.

2

Veja o status no painel

O painel lateral atualiza automaticamente. O pacote aparece com status 🟡 não instalado e o botão "Instalar dependências" aparece.

3

Clique em "Instalar dependências"

O sistema roda composer require em background. Ao terminar, o status muda para 🟢 e a lib fica disponível no terminal e no código.

4

Use no terminal para testar

Abra o terminal da IDE (Ctrl+`) e teste a lib diretamente: $mail = new PHPMailer\PHPMailer\PHPMailer();

O que acontece quando algo dá errado

SituaçãoO que a IDE mostraO que fazer
Pacote não existe no Packagist Modal com: "Pacote(s) não encontrado(s): vendor/pacote — verifique o nome em packagist.org" Corrija o nome no composer.json. Formato: vendor/pacote
Versão incompatível com o PHP do servidor Modal com: "Versão incompatível com o PHP atual do servidor" Use uma versão mais antiga do pacote que suporte seu PHP
Conflito com pacote já instalado Modal com lista de conflitos, versão instalada, requerida e sugestão Use constraint flexível: "^7.0 || ^6.5"
Sem conexão com a internet Modal com: "Sem conexão com o Packagist" Verifique a conexão do servidor
Módulo não publicado ainda Erro: "O módulo ainda não foi publicado. Clique em Publicar primeiro." Publique o módulo antes de instalar dependências separadamente

Resolvendo conflitos de versão

Quando o deploy é bloqueado por conflito, a IDE exibe um modal com os detalhes e a sugestão automática:

text
Conflito de dependências detectado 🚫

📦 guzzlehttp/guzzle
   Instalado:  7.8.1
   Requerido:  ^6.0
   💡 Sugestão: ^7.0 || ^6.0

Ajuste a constraint no composer.json do módulo:

json
"require": {
  "guzzlehttp/guzzle": "^7.0 || ^6.0"
}

Recursos do sistema disponíveis no seu módulo

Antes de adicionar dependências externas, verifique o que o kernel já oferece gratuitamente via injeção de dependência:

Interface / ClasseO que fazComo usar no construtor
EmailSenderInterface Envia e-mails via SMTP (PHPMailer já configurado) private ?EmailSenderInterface $email = null
UserRepositoryInterface Busca usuários por UUID, e-mail ou username private UserRepositoryInterface $usuarios
TokenBlacklistInterface Verifica se um JWT foi revogado private TokenBlacklistInterface $blacklist
PDO Conexão com o banco de dados (core ou modules) private PDO $pdo
AuditLogger Registra eventos de segurança no banco e stderr private AuditLogger $audit
ThreatScorer Acumula score de comportamento suspeito por IP private ThreatScorer $threat
IdempotencyLock Distributed lock para operações críticas (evita race condition) Uso estático: IdempotencyLock::acquire('chave', 30)
IpResolver Resolve IP real do cliente (respeita TRUST_PROXY) Uso estático: IpResolver::resolve()
Sanitizer Sanitiza inputs: string, email, uuid, url, search... Uso estático: Sanitizer::string($input)
OwnershipGuard Verifica se o usuário autenticado é dono do recurso (previne IDOR) Uso estático: OwnershipGuard::check($userId, $resourceOwnerId)
RelogioTimeZone Retorna DateTimeImmutable com timezone do APP_TIMEZONE Uso estático: RelogioTimeZone::agora()
ImageProcessor Redimensiona e salva imagens (JPEG, PNG, WebP) private ImageProcessor $images

Exemplo usando EmailSenderInterface e AuditLogger juntos:

php
<?php

namespace Src\Modules\Pedido\Services;

use Src\Kernel\Contracts\EmailSenderInterface;
use Src\Kernel\Support\AuditLogger;
use Src\Kernel\Http\Request\Request;

class PedidoService
{
    public function __construct(
        private readonly PedidoRepository $repository,
        private readonly ?EmailSenderInterface $email = null,  // opcional
        private readonly ?AuditLogger $audit = null            // opcional
    ) {}

    public function criar(array $data, Request $request): array
    {
        $pedido = $this->repository->create($data);

        // Envia e-mail de confirmação (se módulo de e-mail instalado)
        $this->email?->sendCustom(
            $data['email'],
            'Pedido confirmado',
            "<p>Pedido #{$pedido['id']} criado!</p>"
        );

        // Registra no audit log
        $this->audit?->registrar('pedido.criado', $data['user_id'], [
            'pedido_id' => $pedido['id'],
        ]);

        return $pedido;
    }
}

Boas práticas

RegraExemplo
✅ Use o que o kernel já ofereceEmailSenderInterface, AuditLogger, Sanitizer
✅ Constraints flexíveis"^7.0 || ^6.5"
⚠️ Evite novas dependências desnecessáriasImplemente funções simples diretamente
❌ Nunca fixe versões rígidas"guzzle": "7.8.1" → use "^7.0"
Testando no terminal da IDE

Após instalar uma dependência, abra o terminal (Ctrl+`) e teste diretamente. O sandbox carrega o vendor/autoload.php do projeto, então todas as libs instaladas ficam disponíveis imediatamente — sem precisar fazer deploy.