Écrire une intégration de canal
Ceci est une référence pour développeurs pour quiconque étend Structura avec un nouveau canal. Si vous cherchez comment utiliser les canaux existants, voir Comment fonctionnent les canaux à la place.
Ce guide parcourt l’ajout d’une nouvelle intégration au système de canaux. Nous utiliserons une intégration hypothétique « Mailchimp » comme exemple.
Étape 1 : Choisir les capacités
Décidez quelles interfaces de capacité votre intégration nécessite :
| Si votre intégration… | Implémentez |
|---|---|
| Envoie des notifications fire-and-forget | NotifiableIntegration |
| Réécrit le contenu via IA pour la plateforme | AdaptableIntegration |
| Publie du contenu vers l’API de la plateforme | PublishableIntegration |
| Utilise OAuth 2.0 pour l’authentification | OAuthIntegration |
| Est configurée en collant une URL | WebhookIntegration |
Les capacités sont composables. LinkedIn implémente OAuth + Adapt + Publish. Slack implémente Webhook + Notify. IndexNow implémente seulement Notify.
Étape 2 : Créer la classe Integration
Créez
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
}
}Règles clés :
- Acceptez
FetchLikevia le constructeur pour la testabilité. - Ne codez jamais en dur les appels HTTP — utilisez
toujours le
fetchinjecté. - Classifiez les erreurs HTTP de manière cohérente (voir le tableau de classification d’erreurs dans Contrats d’intégration de canal).
Étape 3 : Enregistrer l’intégration
Ajoutez votre classe à
functions/src/channels/registry/IntegrationRegistry.ts :
import { MailchimpIntegration } from "../integrations/MailchimpIntegration.js";
const CATALOG: Integration[] = [
// ... existing integrations
new MailchimpIntegration(),
];Étape 4 : Ajouter une entrée de catalogue
Ajoutez une entrée à
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",
}Étape 5 : Écrire les tests
Créez
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...
});Mettez à jour IntegrationRegistry.test.ts pour inclure
la nouvelle intégration dans les comptes attendus.
Étape 6 : Mettre à jour l’extension WordPress (si nécessaire)
Pour les intégrations basées sur identifiant ou webhook,
aucun changement d’extension n’est nécessaire — les
endpoints existants channelsSaveCredentialConnection et
channelsSaveWebhookConnection gèrent tous les types
d’authentification de manière générique.
Pour les intégrations OAuth, les endpoints existants
channelsOAuthInit et channelsOAuthCallback gèrent le
flux. Vous devrez peut-être ajouter de nouvelles entrées
defineSecret() pour le client ID/secret du fournisseur.
Étape 7 : Ajouter de la documentation
Créez docs/pages/channels/integrations/mailchimp.mdx
avec :
- Comment fonctionne l’intégration
- Tableau de métadonnées
- Forme du secret déchiffré
- Instructions de configuration de la connexion
- Tableau de gestion des erreurs
Mettez à jour
docs/pages/channels/integrations/_meta.json pour inclure
la nouvelle page.
Liste de vérification
- Classe Integration implémentant les bonnes interfaces de capacité
- Injection de dépendance
FetchLike - Classification des erreurs pour tous les codes de statut HTTP
- Messages localisés (si NotifiableIntegration)
- Implémentation du health check
- Enregistrée dans
IntegrationRegistry - Entrée de catalogue avec gating correct
- Tests unitaires (métadonnées, happy path, cas d’erreur, cas limites)
- Test du Registry mis à jour avec les nouveaux comptes attendus
- Page de documentation
- Secrets configurés (si OAuth ou clé API)