Eigene Flow-Operations in Directus mit dem Extension SDK bauen
Directus Flows decken viele Automatisierungsfälle bereits mit Standard-Operations ab. Daten lesen, Daten schreiben, Bedingungen prüfen, Webhooks aufrufen oder JavaScript ausführen – für viele Workflows reicht das vollkommen aus.
Irgendwann entsteht jedoch häufig ein wiederkehrender Spezialfall:
- eine interne API soll immer gleich angesprochen werden
- eine Datentransformation taucht in mehreren Flows auf
- ein komplexer Prüfprozess soll nicht ständig per Run Script kopiert werden
- eine eigene Operation soll im Flow Editor sauber konfigurierbar sein
Dann lohnt sich eine eigene Flow-Operation.
Mit dem Directus Extension SDK können Sie solche Operations als wiederverwendbare Erweiterung bauen, im Data Studio konfigurieren und bei Bedarf intern oder über den Marketplace verteilen.
Wenn Sie zunächst das Grundprinzip von Triggern, Operations und Data Chains verstehen möchten, empfehlen wir die Directus Flows Anleitung.
Wann eine eigene Operation nötig ist
Nicht jede individuelle Logik benötigt sofort eine eigene Extension.
Oft reicht eine bestehende Operation oder ein kleines Run Script.
Eine Custom Operation lohnt sich dann, wenn Logik wiederverwendbar, wartbar und klar konfigurierbar sein soll.
Wiederverwendung statt Run-Script-Copy-Paste
Die Run-Script-Operation ist praktisch.
Sie eignet sich für:
- kleine Berechnungen
- einfache Transformationen
- schnelle Prototypen
Sie wird problematisch, wenn derselbe Code in vielen Flows auftaucht.
Dann entstehen typische Wartungsprobleme:
- Änderungen müssen an mehreren Stellen erfolgen
- Fehler werden mehrfach kopiert
- Tests sind schwierig
- Verantwortlichkeiten verschwimmen
Eine eigene Operation kapselt diese Logik zentral.
Aufruf eigener Microservices ohne Generic Webhook
Natürlich kann Directus externe Systeme per Webhook Request URL aufrufen.
Für wiederkehrende interne APIs ist das aber oft zu generisch.
Eine eigene Operation kann:
- Authentifizierung kapseln
- Header automatisch setzen
- Fehler standardisieren
- Payloads validieren
- Response-Daten normalisieren
Dadurch wird der Flow Editor deutlich sauberer.
Spezielle Datentransformationen
Typische Beispiele:
- ERP-Artikelnummern normalisieren
- Preislisten transformieren
- Adressdaten validieren
- Kundensegmente berechnen
- KI-Antworten strukturieren
Wenn diese Logik fachlich relevant ist, sollte sie nicht als versteckter JavaScript-Block im Flow liegen.
Extension-SDK Grundlagen
Directus Extensions folgen einer klaren Struktur.
Für Flow-Operations sind vor allem zwei Dateien wichtig:
app.tsapi.ts
Diese Trennung ist eine der häufigsten Stolperfallen.
app.ts: Die Oberfläche im Data Studio
Die Datei app.ts beschreibt, wie die Operation im Directus Data Studio aussieht.
Dazu gehören:
- ID
- Name
- Icon
- Beschreibung
- Eingabefelder
- Validierungen
- Vorschau
Kurz gesagt:
app.ts ist die UI-Konfiguration.
api.ts: Die Server-Logik
Die Datei api.ts enthält die eigentliche Ausführung.
Hier passiert die Logik:
- Daten entgegennehmen
- Optionen auswerten
- externe API aufrufen
- Directus Services nutzen
- Ergebnis zurückgeben
Kurz gesagt:
api.ts ist die Runtime-Logik.
Lokale Entwicklung mit create-directus-extension
Der schnellste Einstieg erfolgt über das Directus-CLI-Tool.
Beispiel:
npx create-directus-extension
Danach wählen Sie:
Operation
und idealerweise:
TypeScript
Für produktive Projekte empfehlen wir TypeScript, weil Directus-Typen und Optionsstrukturen deutlich besser wartbar werden.
Projektstruktur
Eine einfache Operation sieht typischerweise so aus:
directus-extension-send-internal-api/ ├── src/ │ ├── app.ts │ └── api.ts ├── package.json ├── tsconfig.json └── README.md
Wichtig:
app.tsdefiniert die Darstellung im Flow Builderapi.tsdefiniert die Ausführung auf Serverseitepackage.jsonenthält Extension-Metadaten- Build-Ergebnis wird in Directus installiert
Sandboxing
Directus unterstützt sandboxed Extensions. Das ist besonders wichtig, wenn Erweiterungen veröffentlicht oder in sicherheitskritischen Umgebungen eingesetzt werden.
Sandboxing begrenzt, was eine Operation darf.
Beispielsweise:
- Netzwerkzugriffe
- Zugriff auf Umgebungsvariablen
- Zugriff auf Directus Services
Für Marketplace-Extensions sind deklarierte Sandbox-Permissions besonders wichtig.
Ohne korrekt deklarierte Permissions kann die Operation im Marketplace nicht sauber geprüft und angezeigt werden.
app.ts: UI-Konfiguration der Operation
Die UI-Datei beschreibt, wie Ihre Operation im Flow Editor erscheint.
Ein einfaches Beispiel:
export default {
id: 'send-internal-api',
name: 'Send to Internal API',
icon: 'send',
description: 'Sendet Daten an eine interne API.',
overview: ({ url, method }) => [
{
label: 'URL',
text: url,
},
{
label: 'Methode',
text: method,
},
],
options: [
{
field: 'url',
name: 'API URL',
type: 'string',
meta: {
width: 'full',
interface: 'input',
required: true,
},
},
{
field: 'method',
name: 'HTTP Method',
type: 'string',
schema: {
default_value: 'POST',
},
meta: {
width: 'half',
interface: 'select-dropdown',
options: {
choices: [
{ text: 'POST', value: 'POST' },
{ text: 'PUT', value: 'PUT' },
{ text: 'PATCH', value: 'PATCH' },
],
},
},
},
],
};
ID, Name und Icon
Die id sollte stabil bleiben. Sie ist die technische Referenz der Operation. Der name ist die sichtbare Bezeichnung im Flow Editor. Das icon hilft, die Operation visuell zu unterscheiden.
Options-Schema
Über options definieren Sie die Felder, die später im Data Studio konfigurierbar sind.
Typische Felder:
- URL
- API-Key
- Methode
- Mapping
- Timeout
- Retry-Verhalten
Dadurch wird die Operation für Nicht-Entwickler nutzbar.
Vorschau-Template
Mit overview können Sie die wichtigsten Einstellungen direkt im Flow Builder anzeigen.
Das ist besonders hilfreich bei komplexen Flows.
api.ts: Server-Logik der Operation
Die Runtime-Datei führt die Operation aus.
Ein einfaches Beispiel:
type Options = {
url: string;
method: 'POST' | 'PUT' | 'PATCH';
};
export default {
id: 'send-internal-api',
handler: async (options: Options, context: any) => {
const { url, method } = options;
const { data } = context;
const response = await fetch(url, {
method,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`Internal API failed with status ${response.status}`);
}
return await response.json();
},
};
Handler-Signatur
Der Handler erhält typischerweise:
- Optionen aus dem Data Studio
- Flow-Kontext
- Data Chain
- Directus Services
Die Operation sollte immer ein Ergebnis zurückgeben.
Dieses Ergebnis wird Teil der Data Chain und steht nachfolgenden Operations zur Verfügung.
Zugriff auf Directus Services
In Custom Operations können Directus Services genutzt werden, etwa um:
- Items zu lesen
- Items zu schreiben
- Rollen zu prüfen
- Benutzerinformationen zu laden
Das ist besonders nützlich, wenn die Operation nicht nur externe APIs anspricht, sondern direkt mit Directus-Daten arbeiten soll.
Fehlerbehandlung
Fehler sollten explizit geworfen werden.
Beispiel:
if (!response.ok) {
throw new Error(`API request failed: ${response.status}`);
}
Dadurch wird der Flow sauber als fehlgeschlagen markiert.
Für produktive Setups empfiehlt sich zusätzlich:
- Logging
- Retry-Strategie
- Fehler-Collection
- Monitoring
Beispiel: Operation “Send to Internal API”
Nehmen wir an, Sie möchten Kundendaten an einen internen Pricing-Service senden.
Der Flow soll:
- durch eine Kundenerstellung starten
- Kundendaten an die Custom Operation übergeben
- Pricing-Service aufrufen
- Ergebnis in der Data Chain zurückgeben
app.ts
export default {
id: 'send-pricing-service',
name: 'Send to Pricing Service',
icon: 'price_check',
description: 'Sendet Kundendaten an den internen Pricing-Service.',
options: [
{
field: 'endpoint',
name: 'Endpoint',
type: 'string',
meta: {
interface: 'input',
width: 'full',
required: true,
},
},
{
field: 'apiKey',
name: 'API Key',
type: 'string',
meta: {
interface: 'input',
width: 'full',
required: true,
},
},
],
};
api.ts
type Options = {
endpoint: string;
apiKey: string;
};
export default {
id: 'send-pricing-service',
handler: async (options: Options, context: any) => {
const { endpoint, apiKey } = options;
const payload = context.data;
const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey,
},
body: JSON.stringify(payload),
});
if (!response.ok) {
return {
success: false,
status: response.status,
message: await response.text(),
};
}
const result = await response.json();
return {
success: true,
pricing: result,
};
},
};
Test mit lokalem Flow
Zum Testen:
- Extension lokal bauen
- Directus neu starten
- Flow anlegen
- Custom Operation auswählen
- Testdaten übergeben
- Ausführung im Flow Log prüfen
Wichtig:
Testen Sie nicht nur den Erfolgsfall.
Prüfen Sie auch:
- Timeout
- falscher API-Key
- leere Payload
- ungültige Response
- Service nicht erreichbar
Build und Installation
Typischer Build:
npm run build
Danach wird das Build-Ergebnis in den Directus-Extensions-Ordner kopiert.
Beispiel:
/extensions/operations/send-pricing-service/
Nach einem Neustart steht die Operation im Flow Builder zur Verfügung.
Distribution
Eigene Operations können intern oder öffentlich verteilt werden.
NPM Publishing
Für interne Teams empfiehlt sich ein privates NPM-Paket.
Vorteile:
- Versionierung
- CI/CD-fähig
- einfache Installation
- Rollback möglich
Marketplace-Eintrag
Für öffentliche Extensions kann ein Marketplace-Eintrag erstellt werden.
Dafür wichtig:
- klare Beschreibung
- README
- Screenshots
- Lizenz
- Versionierung
- Sandbox-Permissions
Sandbox-Permissions deklarieren
Marketplace-Extensions benötigen saubere Permission-Angaben.
Beispiele:
{
"permissions": {
"network": ["https://api.example.com"],
"env": ["INTERNAL_API_KEY"]
}
}
Fehlende Permissions führen dazu, dass die Operation nicht korrekt ausgeführt oder nicht akzeptiert wird.
Best Practices
TypeScript verwenden
TypeScript reduziert Fehler und verbessert Wartbarkeit.
Gerade bei Optionen und Response-Strukturen lohnt sich der Mehraufwand.
Keine Secrets hart codieren
API-Keys gehören nicht in den Code.
Besser:
- Environment Variables
- Directus Settings
- Secret Manager
Kleine Operations bauen
Eine Operation sollte genau eine Aufgabe erfüllen.
Nicht: Validieren, transformieren, API aufrufen, E-Mail senden
Besser: Eine Operation je Verantwortlichkeit
Flow-Logs ernst nehmen
Custom Operations sollten gut nachvollziehbare Ergebnisse zurückgeben.
So bleibt Debugging möglich.
Custom Operation oder Custom Endpoint?
Eine häufige Frage lautet:
Wann baue ich eine Operation und wann einen Endpoint?
Custom Operation
Geeignet für:
- Flow-Schritte
- interne Automatisierung
- wiederverwendbare Prozesslogik
Custom Endpoint
Geeignet für:
- externe APIs
- eigene REST-Routen
- Frontend-spezifische Endpunkte
Faustregel:
Wenn die Logik innerhalb eines Flows genutzt wird, bauen Sie eine Operation.
Wenn externe Systeme die Logik direkt aufrufen sollen, bauen Sie einen Endpoint.
Fazit
Eigene Flow-Operations sind der richtige Weg, wenn Directus-Flows über Standardbausteine hinausgehen und wiederverwendbare Logik benötigen.
Sie verhindern Copy-Paste in Run-Script-Operations, kapseln API-Aufrufe und machen komplexe Prozesse für Fachanwender konfigurierbar.
Das wichtigste Architekturprinzip lautet:
app.tsdefiniert die Oberflächeapi.tsenthält die Logik- Sandbox-Permissions definieren, was erlaubt ist
Wer diese Trennung sauber einhält, kann Directus Flows gezielt erweitern und daraus eine robuste Automatisierungsplattform machen.
Der nächste sinnvolle Schritt: Prüfen Sie, wie KI-Agenten-Workflows eigene Operations nutzen können, um Daten kontrolliert zu lesen, zu transformieren und Aktionen auszulösen.
FAQ
Was unterscheidet eine Custom Operation von einer Custom Endpoint Extension?
Eine Custom Operation wird innerhalb von Directus Flows genutzt. Ein Custom Endpoint stellt eine eigene API-Route bereit, die von externen Systemen oder Frontends aufgerufen werden kann.
Kann ich Node-Module in einer sandboxed Operation nutzen?
Nur eingeschränkt. Sandboxed Extensions sind bewusst limitiert. Externe Abhängigkeiten und Berechtigungen müssen explizit erlaubt und sauber deklariert werden.
Wie deklariere ich Sandbox-Permissions?
Sandbox-Permissions werden in den Extension-Metadaten definiert. Dort legen Sie fest, auf welche Netzwerkziele, Umgebungsvariablen oder Ressourcen die Extension zugreifen darf.
Wie veröffentliche ich meine Operation im Marketplace?
Sie benötigen ein sauberes NPM-Paket, Dokumentation, Versionierung, Lizenzinformationen und deklarierte Sandbox-Permissions. Anschließend kann die Extension für den Marketplace eingereicht werden.
Sollte ich Custom Operations in TypeScript oder JavaScript schreiben?
Für produktive Projekte ist TypeScript empfehlenswert, weil Optionen, Responses und Directus-Kontexte besser typisiert werden können.