Exemplos JavaScript
Exemplos JavaScript e TypeScript para interagir com a API External do Efflux.
Configuração
Variáveis de Ambiente
Armazene sua API key em variáveis de ambiente:
EFFLUX_API_KEY=efflux_live_suaempresa_abc123...Classe Cliente da API
Crie um cliente de API reutilizável:
interface EffluxConfig { apiKey: string; baseUrl?: string;}
interface ContentItem { id: string; name: string; description?: string; type: string; mimeType: string; status: 'active' | 'inactive' | 'archived'; durationSeconds?: number; storageUrl: string; thumbnailUrl?: string; createdAt: string; updatedAt: string;}
interface Schedule { id: number; name: string; description?: string; status: 'active' | 'inactive'; orientation?: string; playerIds: string[]; contentIds: string[]; contentCount: number; createdAt: string; updatedAt: string;}
interface Player { id: string; name: string; status: string; platform: string; healthStatus: string; lastSeenAt: string;}
interface AnalyticsSummary { totalContent: number; activeContent: number; totalPlayers: number; totalPlays: number; totalDurationSeconds: number; lastPlayedAt: string;}
class EffluxApiError extends Error { constructor( public status: number, public code: string, message: string ) { super(message); this.name = 'EffluxApiError'; }}
class EffluxClient { private apiKey: string; private baseUrl: string;
constructor(config: EffluxConfig) { this.apiKey = config.apiKey; this.baseUrl = config.baseUrl || 'https://api.efflux.media/api/external'; }
private async request<T>(endpoint: string, params?: Record<string, string>): Promise<T> { const url = new URL(`${this.baseUrl}${endpoint}`);
if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined) url.searchParams.set(key, value); }); }
const response = await fetch(url.toString(), { headers: { 'X-API-Key': this.apiKey, 'Accept': 'application/json', }, });
if (!response.ok) { const error = await response.json(); throw new EffluxApiError(response.status, error.code, error.error); }
return response.json(); }
// Conteúdos async listContent(options?: { status?: string; limit?: number }): Promise<ContentItem[]> { return this.request('/content', { status: options?.status, limit: options?.limit?.toString(), }); }
async getContent(id: string): Promise<ContentItem> { return this.request(`/content/${id}`); }
// Programações async listSchedules(options?: { status?: string }): Promise<Schedule[]> { return this.request('/schedules', { status: options?.status }); }
// Players async listPlayers(): Promise<Player[]> { return this.request('/players'); }
// Analytics async getAnalyticsSummary(): Promise<AnalyticsSummary> { return this.request('/analytics/summary'); }}
export { EffluxClient, EffluxApiError };export type { ContentItem, Schedule, Player, AnalyticsSummary };Exemplos de Uso
Inicializar Cliente
import { EffluxClient } from './efflux-client';
const client = new EffluxClient({ apiKey: process.env.EFFLUX_API_KEY!,});Listar Conteúdos
// Listar todo o conteúdoconst todoConteudo = await client.listContent();console.log(`Total de conteúdos: ${todoConteudo.length}`);
// Listar apenas conteúdo ativoconst conteudoAtivo = await client.listContent({ status: 'active' });console.log(`Conteúdos ativos: ${conteudoAtivo.length}`);
// Listar com limiteconst conteudoRecente = await client.listContent({ limit: 10 });Obter Conteúdo Específico
try { const content = await client.getContent('550e8400-e29b-41d4-a716-446655440000'); console.log(`Nome: ${content.name}`); console.log(`Tipo: ${content.type}`); console.log(`Status: ${content.status}`);} catch (error) { if (error instanceof EffluxApiError && error.status === 404) { console.log('Conteúdo não encontrado'); } else { throw error; }}Monitorar Players
const players = await client.listPlayers();
const saudaveis = players.filter(p => p.healthStatus === 'healthy');const offline = players.filter(p => p.healthStatus === 'offline');
console.log(`Saudáveis: ${saudaveis.length}, Offline: ${offline.length}`);
// Encontrar players não vistos nos últimos 15 minutosconst quinzeMinutosAtras = new Date(Date.now() - 15 * 60 * 1000);const inativos = players.filter(p => new Date(p.lastSeenAt) < quinzeMinutosAtras);
if (inativos.length > 0) { console.warn(`Aviso: ${inativos.length} players não vistos recentemente`); inativos.forEach(p => console.warn(` - ${p.name}: último acesso ${p.lastSeenAt}`));}Obter Analytics
const summary = await client.getAnalyticsSummary();
console.log('=== Resumo de Analytics ===');console.log(`Conteúdo: ${summary.activeContent}/${summary.totalContent} ativos`);console.log(`Players: ${summary.totalPlayers}`);console.log(`Total de reproduções: ${summary.totalPlays.toLocaleString('pt-BR')}`);console.log(`Tempo total: ${Math.round(summary.totalDurationSeconds / 3600)} horas`);console.log(`Última atividade: ${summary.lastPlayedAt}`);Exemplo de Hook React
import { useState, useEffect } from 'react';import { EffluxClient, ContentItem, EffluxApiError } from './efflux-client';
const client = new EffluxClient({ apiKey: process.env.NEXT_PUBLIC_EFFLUX_API_KEY!,});
interface UseContentResult { content: ContentItem[]; loading: boolean; error: EffluxApiError | null; refetch: () => void;}
export function useContent(status?: string): UseContentResult { const [content, setContent] = useState<ContentItem[]>([]); const [loading, setLoading] = useState(true); const [error, setError] = useState<EffluxApiError | null>(null); const [refetchTrigger, setRefetchTrigger] = useState(0);
useEffect(() => { let cancelled = false;
async function fetchContent() { setLoading(true); setError(null);
try { const data = await client.listContent({ status }); if (!cancelled) { setContent(data); } } catch (err) { if (!cancelled && err instanceof EffluxApiError) { setError(err); } } finally { if (!cancelled) { setLoading(false); } } }
fetchContent();
return () => { cancelled = true; }; }, [status, refetchTrigger]);
const refetch = () => setRefetchTrigger(t => t + 1);
return { content, loading, error, refetch };}Usando o Hook
function ListaConteudo() { const { content, loading, error, refetch } = useContent('active');
if (loading) return <div>Carregando...</div>; if (error) return <div>Erro: {error.message}</div>;
return ( <div> <button onClick={refetch}>Atualizar</button> <ul> {content.map(item => ( <li key={item.id}> {item.name} - {item.type} </li> ))} </ul> </div> );}Exemplo Backend Node.js
import express from 'express';import { EffluxClient } from './efflux-client';
const app = express();const client = new EffluxClient({ apiKey: process.env.EFFLUX_API_KEY!,});
// Cache de conteúdo por 5 minutoslet contentCache: { data: any; expires: number } | null = null;
app.get('/api/content', async (req, res) => { try { if (contentCache && Date.now() < contentCache.expires) { return res.json(contentCache.data); }
const content = await client.listContent({ status: 'active' });
contentCache = { data: content, expires: Date.now() + 5 * 60 * 1000, };
res.json(content); } catch (error) { if (error instanceof EffluxApiError) { res.status(error.status).json({ error: error.message, code: error.code, }); } else { res.status(500).json({ error: 'Erro interno do servidor' }); } }});
app.get('/api/dashboard', async (req, res) => { try { const [content, players, analytics] = await Promise.all([ client.listContent(), client.listPlayers(), client.getAnalyticsSummary(), ]);
res.json({ conteudo: { total: content.length, ativos: content.filter(c => c.status === 'active').length, }, players: { total: players.length, saudaveis: players.filter(p => p.healthStatus === 'healthy').length, }, analytics, }); } catch (error) { res.status(500).json({ error: 'Falha ao buscar dados do dashboard' }); }});
app.listen(3000, () => { console.log('Servidor rodando na porta 3000');});Tratamento de Erros
import { EffluxApiError } from './efflux-client';
async function safeApiCall<T>(fn: () => Promise<T>): Promise<T | null> { try { return await fn(); } catch (error) { if (error instanceof EffluxApiError) { switch (error.status) { case 401: console.error('Autenticação falhou:', error.code); // Tratar erro de auth (ex: atualizar token, notificar admin) break; case 403: console.error('Permissão negada:', error.message); break; case 404: console.log('Recurso não encontrado'); break; case 429: console.warn('Rate limit - aguardando'); // Implementar lógica de retry break; default: console.error('Erro da API:', error.message); } } else { console.error('Erro inesperado:', error); } return null; }}
// Usoconst content = await safeApiCall(() => client.getContent(id));if (content) { console.log('Conteúdo obtido:', content.name);}