ometra/apollo-sdk

Modular Laravel SDK for the Apollo suite APIs

Maintainers

Package info

github.com/Ometra-Apollo/mx.ometra.apollo.apollo-sdk

pkg:composer/ometra/apollo-sdk

Transparency log

Statistics

Installs: 450

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

4.1.0 2026-07-16 22:06 UTC

This package is auto-updated.

Last update: 2026-07-16 22:07:38 UTC


README

Cliente Laravel/PHP modular para consumir Proteus, Pulse, Flare e Ignis con autenticacion compartida de Caronte.

Instalacion

composer require ometra/apollo-sdk

Publica la configuracion si necesitas sobrescribir las URLs de modulos:

php artisan vendor:publish --tag=apollo-config

El archivo publicado es config/apollo.php.

Paginas de error

Apollo registra automaticamente paginas HTML para los errores HTTP comunes de Laravel (401, 403, 404, 419, 429, 500, 503). El SDK agrega sus vistas como fallback, por lo que cualquier archivo local en resources/views/errors mantiene prioridad.

Para deshabilitar este fallback:

APOLLO_ERROR_PAGES_ENABLED=false

Si necesitas personalizar las vistas dentro de la app host, publicalas con:

php artisan vendor:publish --tag=apollo-error-pages

Tambien puedes publicar configuracion y paginas de error juntas:

php artisan vendor:publish --tag=apollo

AppMenu compartido

El SDK incluye el menu compartido de la suite en resources/js/shared/AppMenu. Publicalo en una app host con:

php artisan vendor:publish --tag=apollo-app-menu

Tambien se publica con el tag agregado apollo.

DirectoryTree compartido

El SDK incluye el arbol de directorios en resources/js/shared/DirectoryTree. Publicalo en una app host con:

php artisan vendor:publish --tag=apollo-directory-tree

Tambien se publica con el tag agregado apollo.

Documentacion detallada de componentes UI:

  • docs/ui-components.md

Configuracion

Apollo solo configura URLs por modulo; la autenticacion sigue viviendo en el SDK de Caronte.

PROTEUS_BASE_URL=https://proteus.example.com/api
PULSE_BASE_URL=https://pulse.example.com/api
FLARE_BASE_URL=https://flare.example.com/api
IGNIS_BASE_URL=https://ignis.example.com/api

Las llamadas HTTP usan el transporte de Caronte 7.1, incluyendo uploads multipart y respuestas binarias sin parsing. Segun el tipo de request agregan:

  • X-Group-Token cuando existe una aplicacion grupal; en caso contrario, X-Application-Token
  • X-User-Token en llamadas de usuario
  • X-Tenant-Id desde TenantContext cuando existe

Uso modular

use Ometra\Apollo\Sdk\Facades\Apollo;

$directories = Apollo::proteus()->directories()->index();

$media = Apollo::proteus()->media()->upload([
    'type' => 'image',
    'directory_id' => $directoryId,
    'media' => [$request->file('image')],
    'metadata' => [
        'source' => 'apollo',
    ],
]);

Apollo::proteus()->media()->setMetadata($mediaId, [
    'metadata' => [
        'title' => 'Hero image',
    ],
]);

$metadata = Apollo::proteus()->metadata()->index($mediaId, [
    'search' => 'title',
]);

$images = Apollo::proteus()->media()->index(['type' => 'image']);

$lightPath = Apollo::proteus()->media()->lightPathUrl($mediaId, [
    'ext' => 'mp4',
    'url_ttl_seconds' => 3600,
]);

$stations = Apollo::flare()->stations()->index(['country' => 'mx']);

$campaigns = Apollo::ignis()->campaigns()->byGroup('group-1');
$campaign = Apollo::ignis()->campaigns()->show('group-1', 11);

Apollo::ignis()->contentHits()->report([
    ['content_id' => 'content-1', 'hits' => 10],
]);

$groups = Apollo::pulse()->groups()->index();

URLs LightPath para media

LightPath se integra desde el recurso de media de Proteus porque Proteus es la autoridad de permisos y formatos. El SDK solo solicita una URL temporal; no valida tokens ni habla con nodos LightPath.

$response = Apollo::proteus()->media()->lightPathUrl($mediaId, [
    'ext' => 'mp4',
    'url_ttl_seconds' => 3600,
]);

$url = $response['data']['url'];

La respuesta incluye id_lightpath_grant (UUID), url, format, url_expires_at, renewable_from y renewable_until.

Opciones:

  • ext: formato a entregar. Si se omite, Proteus usa el formato default.
  • url_ttl_seconds: vigencia de la URL. Proteus aplica su maximo configurado.

El owner puede extender o eliminar el grant. AppToken y GroupToken validos del mismo tenant tambien pueden administrarlo, aunque no pueden crear grants:

$grantId = $response['data']['id_lightpath_grant'];

Apollo::proteus()->lightPath()->extendGrant($grantId, 3600);
Apollo::proteus()->lightPath()->deleteGrant($grantId);

// En un proceso autenticado con AppToken:
Apollo::proteus()->asApplication()->lightPath()->extendGrant($grantId, 3600);

Miniaturas de media

Para solicitar la miniatura de un recurso de media, usa MediaResource::thumbnail().

$response = Apollo::proteus()->media()->thumbnail($mediaId);

Esta llamada aprovecha el mismo endpoint de descarga y solicita el formato thumb mediante ext=thumb.

La URL generada tiene forma https://lightpath.example.com/m/{token}. El token opaco es la unica credencial y quien tenga la URL puede consumirla hasta url_expires_at.

Uso en jobs y contextos sin usuario

Cuando necesites hacer llamadas desde un job, un comando o cualquier contexto donde no haya sesion de usuario activa, usa asApplication(). Esto fuerza a todas las operaciones del modulo a usar autenticacion de aplicacion (sin X-User-Token) en lugar de autenticacion de usuario:

// En un job — sin sesion HTTP, sin token de usuario
$proteus = Apollo::proteus()->asApplication();

$proteus->media()->index(['type' => 'audio']);
$proteus->directories()->show($directoryId);

Tambien puedes inyectar el entrypoint principal:

use Ometra\Apollo\Sdk\Apollo;

public function __invoke(Apollo $apollo): array
{
    return $apollo->proteus()->media()->index(['type' => 'image']);
}

Pulse expone groups()->index() sobre el endpoint ignis/groups.

Exposicion de grupos Ignis (inbound, opt-in)

Apollo es solo outbound por defecto. Cuando lo habilitas, el SDK registra una ruta inbound GET /{prefix}/groups en la app host para que clientes externos (incluido Pulse) puedan descubrir los grupos de la app. No agrega llamadas HTTP hacia Ignis.

Habilitar la ruta

La ruta esta deshabilitada por defecto. Habilitala con una variable de entorno:

APOLLO_IGNIS_GROUPS_ENABLED=true

O publica la configuracion y edita config/apollo.php:

'ignis_groups' => [
    'enabled' => true,
    'route_prefix' => 'api/ignis',
    'middleware' => ['caronte.application:tenant_required'],
],

Con enabled=false (por defecto) no se registra ninguna ruta y GET /api/ignis/groups devuelve 404.

Proveer la implementacion del contrato

Para exponer grupos reales, crea una clase que implemente Ometra\Apollo\Sdk\Contracts\IgnisGroupContract:

namespace App\Services;

use Ometra\Apollo\Sdk\Contracts\IgnisGroupContract;
use Ometra\Apollo\Sdk\DTO\ExternalGroupDTO;

final class HostGroupProvider implements IgnisGroupContract
{
    public function getGroups(): array
    {
        return [
            ExternalGroupDTO::fromArray([
                'name' => 'Mi grupo',
                'external_id' => 'grupo-1',
                'media_type' => ['video', 'audio'],
                'play_modifiers' => ['frequency' => 2],
            ]),
        ];
    }
}

Registra esa clase en un service provider de la app host:

use App\Services\HostGroupProvider;
use Ometra\Apollo\Sdk\Contracts\IgnisGroupContract;

$this->app->bind(IgnisGroupContract::class, HostGroupProvider::class);

Si APOLLO_IGNIS_GROUPS_ENABLED=true y la app host no registra el contrato, el SDK falla al arrancar para no exponer datos dummy por accidente.

Prefijo de ruta y middleware

El prefijo por defecto es api/ignis (la ruta queda en GET /api/ignis/groups). Cambialo con route_prefix:

'ignis_groups' => [
    'enabled' => true,
    'route_prefix' => 'api/custom/ignis', // GET /api/custom/ignis/groups
],

La ruta esta protegida por el middleware caronte.application:tenant_required. Las peticiones sin contexto de tenant valido son rechazadas por Caronte (401/403) antes de llegar al controlador. Puedes overridear la pila de middleware con la clave middleware.

API

El contrato completo esta en docs/api-contract.md.

Pruebas

composer test

La suite valida identidad Apollo, configuracion modular, autenticacion Caronte, rutas Proteus, ausencia de API flat y limpieza legacy.