Pular para o conteúdo

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:

.env
EFFLUX_API_KEY=efflux_live_suaempresa_abc123...

Classe Cliente da API

Crie um cliente de API reutilizável:

efflux-client.ts
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údo
const todoConteudo = await client.listContent();
console.log(`Total de conteúdos: ${todoConteudo.length}`);
// Listar apenas conteúdo ativo
const conteudoAtivo = await client.listContent({ status: 'active' });
console.log(`Conteúdos ativos: ${conteudoAtivo.length}`);
// Listar com limite
const 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 minutos
const 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

useEfflux.ts
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

server.ts
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 minutos
let 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;
}
}
// Uso
const content = await safeApiCall(() => client.getContent(id));
if (content) {
console.log('Conteúdo obtido:', content.name);
}