Skip to Content
ReferenceCrear una integración de canal

Crear una integración de canal

Esta es una referencia para desarrolladores para cualquiera que extienda Structura con un nuevo canal. Si buscas cómo usar los canales existentes, mira Cómo funcionan los canales en su lugar.

Esta guía recorre el añadido de una nueva integración al sistema de canales. Usaremos una integración hipotética de «Mailchimp» como ejemplo.

Paso 1: Elegir capacidades

Decide qué interfaces de capacidad necesita tu integración:

Si tu integración…Implementa
Envía notificaciones fire-and-forgetNotifiableIntegration
Reescribe contenido vía IA para la plataformaAdaptableIntegration
Publica contenido a la API de la plataformaPublishableIntegration
Usa OAuth 2.0 para autenticarseOAuthIntegration
Se configura pegando una URLWebhookIntegration

Las capacidades son combinables. LinkedIn implementa OAuth + Adapt + Publish. Slack implementa Webhook + Notify. IndexNow implementa solo Notify.

Paso 2: Crear la clase Integration

Crea functions/src/channels/integrations/MailchimpIntegration.ts:

import type { FetchLike } from "../contracts/Integration.js"; import type { Integration, IntegrationMetadata, HealthStatus, ConnectionRecord, } from "../contracts/Integration.js"; import type { NotifiableIntegration, NotifyContext, NotifyResult } from "../contracts/Integration.js"; export const MAILCHIMP_INTEGRATION_ID = "mailchimp"; export class MailchimpIntegration implements Integration, NotifiableIntegration { constructor(private readonly fetch: FetchLike = globalThis.fetch) {} readonly metadata: IntegrationMetadata = { id: MAILCHIMP_INTEGRATION_ID, name: "Mailchimp", category: "email", sku: "channels", // or "free" for free integrations capabilities: ["notify"], authType: "apikey", // or "oauth2", "webhook", "none" iconUrl: "/icons/mailchimp.svg", }; async healthCheck(connection: ConnectionRecord): Promise<HealthStatus> { if (connection.status === "connected") return { status: "healthy" }; return { status: "unhealthy", reason: connection.lastError?.message }; } async notify(ctx: NotifyContext): Promise<NotifyResult> { // Implementation here } }

Reglas clave:

  • Acepta FetchLike por el constructor para testabilidad.
  • Nunca codifiques llamadas HTTP — usa siempre el fetch inyectado.
  • Clasifica los errores HTTP de forma consistente (mira la tabla de clasificación de errores en Contratos de integración de canal).

Paso 3: Registrar la integración

Añade tu clase a functions/src/channels/registry/IntegrationRegistry.ts:

import { MailchimpIntegration } from "../integrations/MailchimpIntegration.js"; const CATALOG: Integration[] = [ // ... existing integrations new MailchimpIntegration(), ];

Añade una entrada a functions/src/channels/registry/catalog.ts:

{ id: "mailchimp", name: "Mailchimp", description: "Send email campaigns when posts are published", category: "email", capabilities: ["notify"], authType: "apikey", gating: { requiredPlan: "free", // Minimum plan requiredAddon: "channels", // null if free, "channels" if paid }, iconUrl: "/icons/mailchimp.svg", }

Paso 5: Escribir pruebas

Crea functions/src/channels/__tests__/MailchimpIntegration.test.ts:

import { describe, it, expect, vi } from "vitest"; import { MailchimpIntegration } from "../integrations/MailchimpIntegration.js"; describe("MailchimpIntegration", () => { it("has correct metadata", () => { const integration = new MailchimpIntegration(); expect(integration.metadata.id).toBe("mailchimp"); expect(integration.metadata.capabilities).toContain("notify"); }); it("sends notification on publish", async () => { const stubFetch = vi.fn().mockResolvedValue({ ok: true, status: 200, json: async () => ({}), }); const integration = new MailchimpIntegration(stubFetch); const result = await integration.notify(/* NotifyContext */); expect(result.status).toBe("ok"); expect(stubFetch).toHaveBeenCalledOnce(); }); // Test error classification for each HTTP status... });

Actualiza IntegrationRegistry.test.ts para incluir la nueva integración en los conteos esperados.

Paso 6: Actualizar el plugin de WordPress (si hace falta)

Para integraciones basadas en credenciales o webhook, no hacen falta cambios en el plugin — los endpoints existentes channelsSaveCredentialConnection y channelsSaveWebhookConnection manejan todos los tipos de auth de forma genérica.

Para integraciones OAuth, los endpoints existentes channelsOAuthInit y channelsOAuthCallback manejan el flujo. Puede que necesites añadir nuevas entradas defineSecret() para el client ID/secret del proveedor.

Paso 7: Añadir documentación

Crea docs/pages/channels/integrations/mailchimp.mdx con:

  • Cómo funciona la integración
  • Tabla de metadatos
  • Forma del secreto descifrado
  • Instrucciones de configuración de la conexión
  • Tabla de manejo de errores

Actualiza docs/pages/channels/integrations/_meta.json para incluir la nueva página.

Lista de comprobación

  • Clase Integration que implementa las interfaces de capacidad correctas
  • Inyección de dependencia FetchLike
  • Clasificación de errores para todos los códigos de estado HTTP
  • Mensajes con conciencia de idioma (si NotifiableIntegration)
  • Implementación de health check
  • Registrada en IntegrationRegistry
  • Entrada de catálogo con gating correcto
  • Pruebas unitarias (metadatos, happy path, casos de error, casos límite)
  • Prueba de Registry actualizada con los nuevos conteos esperados
  • Página de documentación
  • Secretos configurados (si OAuth o clave API)
Last updated on