SDK
Полный пример
Пошаговое руководство по созданию полного коннектора с нуля — сервис погодных оповещений с аутентификацией SecretText, одним действием и одним webhook-триггером.
Полный пример: коннектор Weather Alerts
Это пошаговое руководство по созданию полного коннектора для вымышленного Weather Alerts API. Коннектор демонстрирует:
- Аутентификацию SecretText с валидацией
- Действие (Action) с несколькими типами свойств, включая Dropdown
- Webhook-триггер (Trigger) с полным жизненным циклом (onEnable, run, onDisable)
Структура проекта
packages/connectors/weather-alerts/
├── src/
│ ├── index.ts
│ ├── weather-alerts.connector.ts
│ ├── actions/
│ │ └── get-forecast.ts
│ └── triggers/
│ └── severe-alert.ts
└── package.jsonШаг 1: Аутентификация
Определите аутентификацию SecretText с вызовом валидации для проверки API-ключа:
// src/weather-alerts.connector.ts
import {
createConnector,
ConnectorAuth,
ConnectorError,
} from "@triggo/connector-sdk";
import { CONNECTOR_ERROR_CODES } from "@triggo/shared";
import { getForecast } from "./actions/get-forecast.ts";
import { severeAlert } from "./triggers/severe-alert.ts";
const auth = ConnectorAuth.SecretText({
displayName: "API Key",
description: "Your Weather Alerts API key from the developer dashboard.",
validate: async (authValue) => {
const response = await fetch("https://api.weather-alerts.example.com/v1/me", {
headers: { "X-Api-Key": authValue.secret },
});
if (response.status === 401) {
throw new ConnectorError(
CONNECTOR_ERROR_CODES.AUTH_EXPIRED,
"Invalid API key",
);
}
if (!response.ok) {
throw new ConnectorError(
CONNECTOR_ERROR_CODES.UPSTREAM_ERROR,
`Validation failed: ${response.status}`,
);
}
},
});
export const weatherAlertsConnector = createConnector({
name: "weather-alerts",
displayName: "Weather Alerts",
description: "Get weather forecasts and receive severe weather alerts.",
auth,
actions: [getForecast],
triggers: [severeAlert],
});Шаг 2: Действие — Get Forecast
Создайте действие, которое получает прогноз погоды для указанного города:
// src/actions/get-forecast.ts
import { createAction, Property, ConnectorError } from "@triggo/connector-sdk";
import { CONNECTOR_ERROR_CODES } from "@triggo/shared";
interface WeatherAuth {
readonly secret: string;
}
interface ForecastProps {
readonly city: string;
readonly units: string;
readonly days: number;
}
export const getForecast = createAction<WeatherAuth, ForecastProps>({
name: "get_forecast",
displayName: "Get Forecast",
description: "Retrieves a weather forecast for a city.",
props: {
city: Property.ShortText({
displayName: "City",
description: "City name (e.g., Moscow, Saint Petersburg).",
required: true,
}),
units: Property.Dropdown({
displayName: "Units",
description: "Temperature units.",
required: true,
defaultValue: "metric",
options: [
{ label: "Celsius", value: "metric" },
{ label: "Fahrenheit", value: "imperial" },
],
}),
days: Property.Number({
displayName: "Forecast Days",
description: "Number of days to forecast (1-7).",
required: false,
defaultValue: 3,
}),
},
errorHandlingOptions: {
retryOnFailure: { maxRetries: 2, baseIntervalMs: 1000 },
},
aiHints:
"Use this action to get a weather forecast for any city. " +
"Default is 3 days in Celsius. Supports up to 7 days.",
async run(context) {
const { city, units, days } = context.propsValue;
const apiKey = context.auth.secret;
const url = new URL("https://api.weather-alerts.example.com/v1/forecast");
url.searchParams.set("city", city);
url.searchParams.set("units", units);
url.searchParams.set("days", String(days));
const response = await fetch(url.toString(), {
headers: { "X-Api-Key": apiKey },
});
if (response.status === 404) {
throw new ConnectorError(
CONNECTOR_ERROR_CODES.NOT_FOUND,
`City not found: "${city}"`,
);
}
if (response.status === 429) {
throw new ConnectorError(
CONNECTOR_ERROR_CODES.RATE_LIMITED,
"Weather API rate limit exceeded",
);
}
if (!response.ok) {
throw new ConnectorError(
CONNECTOR_ERROR_CODES.UPSTREAM_ERROR,
`Weather API error: ${response.status}`,
);
}
return response.json();
},
});Шаг 3: Триггер — Severe Weather Alert
Создайте webhook-триггер, который срабатывает при выпуске предупреждения о суровой погоде:
// src/triggers/severe-alert.ts
import {
createTrigger,
TRIGGER_TYPES,
ConnectorError,
} from "@triggo/connector-sdk";
import { CONNECTOR_ERROR_CODES } from "@triggo/shared";
interface WeatherAuth {
readonly secret: string;
}
export const severeAlert = createTrigger<WeatherAuth, Record<string, never>>({
name: "severe_alert",
displayName: "Severe Weather Alert",
description: "Triggers when a severe weather alert is issued for any monitored region.",
props: {},
type: TRIGGER_TYPES.WEBHOOK,
outputSchema: {
type: "object",
properties: {
alertId: { type: "string" },
severity: { type: "string", enum: ["warning", "watch", "emergency"] },
region: { type: "string" },
headline: { type: "string" },
description: { type: "string" },
issuedAt: { type: "string", format: "date-time" },
},
required: ["alertId", "severity", "region", "headline", "issuedAt"],
},
sampleData: {
alertId: "ALERT-2026-001",
severity: "warning",
region: "Moscow Oblast",
headline: "Heavy Snowfall Warning",
description: "Expected 20-30cm of snow in the next 24 hours.",
issuedAt: "2026-02-27T08:00:00.000Z",
},
aiHints:
"Use this trigger to react to severe weather alerts. " +
"Fires automatically when the weather service detects dangerous conditions.",
async test() {
return [
{
alertId: "ALERT-TEST-001",
severity: "warning",
region: "Test Region",
headline: "Test Alert",
description: "This is a test alert.",
issuedAt: new Date().toISOString(),
},
];
},
async onEnable(context) {
const response = await fetch(
"https://api.weather-alerts.example.com/v1/webhooks",
{
method: "POST",
headers: {
"X-Api-Key": context.auth.secret,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: context.webhookUrl,
events: ["alert.severe"],
}),
},
);
if (!response.ok) {
throw new ConnectorError(
CONNECTOR_ERROR_CODES.UPSTREAM_ERROR,
`Failed to register webhook: ${response.status}`,
);
}
const body = (await response.json()) as { id: string };
await context.store.put("webhookId", body.id);
return { externalWebhookId: body.id };
},
async onDisable(context) {
const webhookId = (await context.store.get("webhookId")) as string | null;
if (webhookId) {
await fetch(
`https://api.weather-alerts.example.com/v1/webhooks/${webhookId}`,
{
method: "DELETE",
headers: { "X-Api-Key": context.auth.secret },
},
);
await context.store.delete("webhookId");
}
},
async run(context) {
const payload = context.payload as Record<string, unknown>;
return [
{
alertId: payload["id"],
severity: payload["severity"],
region: payload["region"],
headline: payload["headline"],
description: payload["description"],
issuedAt: payload["issued_at"],
},
];
},
});Шаг 4: Точка входа
Экспортируйте коннектор из точки входа пакета:
// src/index.ts
export { weatherAlertsConnector } from "./weather-alerts.connector.ts";Что SDK делает за вас
При вызове createConnector() SDK:
- Валидирует все имена (kebab-case для коннектора, snake_case для действий/триггеров)
- Генерирует JSON Schema из определений свойств (сохраняется в
definition.schema) - Строит карты поиска (
actionsMap,triggersMap) для доступа за O(1) движком выполнения - Глубоко замораживает всё определение для предотвращения случайных мутаций во время выполнения
Результирующий ConnectorDefinition готов к регистрации на платформе Triggo и обнаружению AI-генератором пайплайнов.