@checkstack/integration-backend 0.1.30 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +188 -0
- package/package.json +11 -9
- package/src/connection-credentials-migration.test.ts +171 -0
- package/src/connection-credentials-migration.ts +182 -0
- package/src/connection-credentials.test.ts +180 -0
- package/src/connection-credentials.ts +165 -0
- package/src/connection-store.ts +119 -6
- package/src/index.ts +55 -181
- package/src/provider-registry.test.ts +56 -286
- package/src/provider-registry.ts +5 -20
- package/src/provider-types.ts +23 -149
- package/src/router.ts +87 -608
- package/src/schema.ts +13 -59
- package/src/test-connection-masking.test.ts +98 -0
- package/tsconfig.json +6 -0
- package/src/delivery-coordinator.ts +0 -391
- package/src/event-registry.test.ts +0 -396
- package/src/event-registry.ts +0 -99
- package/src/hook-subscriber.ts +0 -105
|
@@ -1,314 +1,84 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Provider registry behaviour tests — scoped to connection-management
|
|
3
|
+
* after the Automation Platform migration. Subscription / delivery
|
|
4
|
+
* concerns moved to the trigger / action registries on the automation
|
|
5
|
+
* side; the integration registry now only owns connection schemas.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, expect, it, beforeEach } from "bun:test";
|
|
2
8
|
import { z } from "zod";
|
|
9
|
+
import { Versioned, configString } from "@checkstack/backend-api";
|
|
3
10
|
import {
|
|
4
11
|
createIntegrationProviderRegistry,
|
|
5
12
|
type IntegrationProviderRegistry,
|
|
6
13
|
} from "./provider-registry";
|
|
7
14
|
import type { IntegrationProvider } from "./provider-types";
|
|
8
|
-
import { Versioned } from "@checkstack/backend-api";
|
|
9
15
|
|
|
10
|
-
|
|
11
|
-
* Unit tests for IntegrationProviderRegistry.
|
|
12
|
-
*
|
|
13
|
-
* Tests cover:
|
|
14
|
-
* - Provider registration with proper namespacing
|
|
15
|
-
* - Provider retrieval by qualified ID
|
|
16
|
-
* - Config schema JSON conversion
|
|
17
|
-
*/
|
|
16
|
+
const testPlugin = { pluginId: "test-plugin" } as const;
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
pluginId: "test-plugin",
|
|
22
|
-
displayName: "Test Plugin",
|
|
23
|
-
} as const;
|
|
24
|
-
|
|
25
|
-
// Test config schemas
|
|
26
|
-
const webhookConfigSchema = z.object({
|
|
27
|
-
url: z.string().url(),
|
|
28
|
-
method: z.enum(["GET", "POST"]),
|
|
29
|
-
timeout: z.number().default(5000),
|
|
18
|
+
const sampleConnectionSchema = z.object({
|
|
19
|
+
apiKey: configString({ "x-secret": true }).describe("API key"),
|
|
30
20
|
});
|
|
31
21
|
|
|
32
|
-
|
|
33
|
-
webhookUrl: z.string().url(),
|
|
34
|
-
channel: z.string(),
|
|
35
|
-
});
|
|
22
|
+
type SampleConnection = z.infer<typeof sampleConnectionSchema>;
|
|
36
23
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
config: new Versioned({
|
|
48
|
-
version: 1,
|
|
49
|
-
schema,
|
|
50
|
-
}),
|
|
51
|
-
deliver: async () => ({ success: true }),
|
|
52
|
-
};
|
|
53
|
-
}
|
|
24
|
+
const sampleProvider: IntegrationProvider<SampleConnection> = {
|
|
25
|
+
id: "sample",
|
|
26
|
+
displayName: "Sample",
|
|
27
|
+
description: "Sample provider for tests",
|
|
28
|
+
icon: "Webhook",
|
|
29
|
+
connectionSchema: new Versioned({
|
|
30
|
+
version: 1,
|
|
31
|
+
schema: sampleConnectionSchema,
|
|
32
|
+
}),
|
|
33
|
+
};
|
|
54
34
|
|
|
55
35
|
describe("IntegrationProviderRegistry", () => {
|
|
56
36
|
let registry: IntegrationProviderRegistry;
|
|
57
|
-
|
|
58
37
|
beforeEach(() => {
|
|
59
38
|
registry = createIntegrationProviderRegistry();
|
|
60
39
|
});
|
|
61
40
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const provider = createTestProvider("webhook", webhookConfigSchema);
|
|
69
|
-
|
|
70
|
-
registry.register(provider, testPluginMetadata);
|
|
71
|
-
|
|
72
|
-
expect(registry.hasProvider("test-plugin.webhook")).toBe(true);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("generates correct qualified ID", () => {
|
|
76
|
-
const provider = createTestProvider("webhook", webhookConfigSchema);
|
|
77
|
-
|
|
78
|
-
registry.register(provider, testPluginMetadata);
|
|
79
|
-
|
|
80
|
-
const registered = registry.getProvider("test-plugin.webhook");
|
|
81
|
-
expect(registered?.qualifiedId).toBe("test-plugin.webhook");
|
|
82
|
-
expect(registered?.ownerPluginId).toBe("test-plugin");
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("preserves provider metadata", () => {
|
|
86
|
-
const provider: IntegrationProvider<unknown> = {
|
|
87
|
-
id: "custom",
|
|
88
|
-
displayName: "Custom Provider",
|
|
89
|
-
description: "A custom provider for testing",
|
|
90
|
-
icon: "Cog",
|
|
91
|
-
config: new Versioned({ version: 1, schema: webhookConfigSchema }),
|
|
92
|
-
deliver: async () => ({ success: true }),
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
registry.register(provider, testPluginMetadata);
|
|
96
|
-
|
|
97
|
-
const registered = registry.getProvider("test-plugin.custom");
|
|
98
|
-
expect(registered?.displayName).toBe("Custom Provider");
|
|
99
|
-
expect(registered?.description).toBe("A custom provider for testing");
|
|
100
|
-
expect(registered?.icon).toBe("Cog");
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it("preserves deliver function", () => {
|
|
104
|
-
const deliverFn = async () => ({ success: true, externalId: "ext-123" });
|
|
105
|
-
const provider: IntegrationProvider<unknown> = {
|
|
106
|
-
id: "webhook",
|
|
107
|
-
displayName: "Webhook",
|
|
108
|
-
config: new Versioned({ version: 1, schema: webhookConfigSchema }),
|
|
109
|
-
deliver: deliverFn,
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
registry.register(provider, testPluginMetadata);
|
|
113
|
-
|
|
114
|
-
const registered = registry.getProvider("test-plugin.webhook");
|
|
115
|
-
expect(registered?.deliver).toBeDefined();
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
it("preserves testConnection function if provided", () => {
|
|
119
|
-
const provider: IntegrationProvider<unknown> = {
|
|
120
|
-
id: "webhook",
|
|
121
|
-
displayName: "Webhook",
|
|
122
|
-
config: new Versioned({ version: 1, schema: webhookConfigSchema }),
|
|
123
|
-
deliver: async () => ({ success: true }),
|
|
124
|
-
testConnection: async () => ({ success: true, message: "OK" }),
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
registry.register(provider, testPluginMetadata);
|
|
128
|
-
|
|
129
|
-
const registered = registry.getProvider("test-plugin.webhook");
|
|
130
|
-
expect(registered?.testConnection).toBeDefined();
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
135
|
-
// Provider Retrieval
|
|
136
|
-
// ─────────────────────────────────────────────────────────────────────────
|
|
137
|
-
|
|
138
|
-
describe("getProviders", () => {
|
|
139
|
-
it("returns empty array when no providers registered", () => {
|
|
140
|
-
expect(registry.getProviders()).toEqual([]);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("returns all registered providers", () => {
|
|
144
|
-
registry.register(
|
|
145
|
-
createTestProvider("webhook", webhookConfigSchema),
|
|
146
|
-
testPluginMetadata
|
|
147
|
-
);
|
|
148
|
-
registry.register(
|
|
149
|
-
createTestProvider("slack", slackConfigSchema),
|
|
150
|
-
testPluginMetadata
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
const providers = registry.getProviders();
|
|
154
|
-
expect(providers.length).toBe(2);
|
|
155
|
-
expect(providers.map((p) => p.id).sort()).toEqual(["slack", "webhook"]);
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
describe("getProvider", () => {
|
|
160
|
-
it("returns undefined for non-existent provider", () => {
|
|
161
|
-
expect(registry.getProvider("non-existent.provider")).toBeUndefined();
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it("returns provider by qualified ID", () => {
|
|
165
|
-
registry.register(
|
|
166
|
-
createTestProvider("webhook", webhookConfigSchema),
|
|
167
|
-
testPluginMetadata
|
|
168
|
-
);
|
|
169
|
-
|
|
170
|
-
const provider = registry.getProvider("test-plugin.webhook");
|
|
171
|
-
expect(provider?.displayName).toBe("Webhook Provider");
|
|
172
|
-
});
|
|
41
|
+
it("namespaces ids by plugin", () => {
|
|
42
|
+
registry.register(sampleProvider, testPlugin);
|
|
43
|
+
const registered = registry.getProvider("test-plugin.sample");
|
|
44
|
+
expect(registered).toBeDefined();
|
|
45
|
+
expect(registered?.qualifiedId).toBe("test-plugin.sample");
|
|
46
|
+
expect(registered?.ownerPluginId).toBe("test-plugin");
|
|
173
47
|
});
|
|
174
48
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
createTestProvider("webhook", webhookConfigSchema),
|
|
183
|
-
testPluginMetadata
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
expect(registry.hasProvider("test-plugin.webhook")).toBe(true);
|
|
187
|
-
});
|
|
49
|
+
it("returns all registered providers", () => {
|
|
50
|
+
registry.register(sampleProvider, testPlugin);
|
|
51
|
+
registry.register(
|
|
52
|
+
{ ...sampleProvider, id: "other" } as IntegrationProvider<SampleConnection>,
|
|
53
|
+
testPlugin,
|
|
54
|
+
);
|
|
55
|
+
expect(registry.getProviders()).toHaveLength(2);
|
|
188
56
|
});
|
|
189
57
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
describe("getProviderConfigSchema", () => {
|
|
195
|
-
it("returns undefined for non-existent provider", () => {
|
|
196
|
-
expect(
|
|
197
|
-
registry.getProviderConfigSchema("non-existent.provider")
|
|
198
|
-
).toBeUndefined();
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
it("returns JSON Schema for provider config", () => {
|
|
202
|
-
registry.register(
|
|
203
|
-
createTestProvider("webhook", webhookConfigSchema),
|
|
204
|
-
testPluginMetadata
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
const schema = registry.getProviderConfigSchema("test-plugin.webhook");
|
|
208
|
-
expect(schema).toBeDefined();
|
|
209
|
-
expect(typeof schema).toBe("object");
|
|
210
|
-
expect(schema?.type).toBe("object");
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it("JSON Schema includes property definitions", () => {
|
|
214
|
-
registry.register(
|
|
215
|
-
createTestProvider("webhook", webhookConfigSchema),
|
|
216
|
-
testPluginMetadata
|
|
217
|
-
);
|
|
218
|
-
|
|
219
|
-
const schema = registry.getProviderConfigSchema("test-plugin.webhook");
|
|
220
|
-
const properties = schema?.properties as Record<string, unknown>;
|
|
221
|
-
|
|
222
|
-
expect(properties).toBeDefined();
|
|
223
|
-
expect(properties.url).toBeDefined();
|
|
224
|
-
expect(properties.method).toBeDefined();
|
|
225
|
-
expect(properties.timeout).toBeDefined();
|
|
226
|
-
});
|
|
58
|
+
it("reports presence via hasProvider", () => {
|
|
59
|
+
registry.register(sampleProvider, testPlugin);
|
|
60
|
+
expect(registry.hasProvider("test-plugin.sample")).toBe(true);
|
|
61
|
+
expect(registry.hasProvider("test-plugin.missing")).toBe(false);
|
|
227
62
|
});
|
|
228
63
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
it("handles providers from multiple plugins", () => {
|
|
235
|
-
const plugin1 = { pluginId: "plugin-1" } as const;
|
|
236
|
-
const plugin2 = { pluginId: "plugin-2" } as const;
|
|
237
|
-
|
|
238
|
-
registry.register(
|
|
239
|
-
createTestProvider("webhook", webhookConfigSchema),
|
|
240
|
-
plugin1
|
|
241
|
-
);
|
|
242
|
-
registry.register(
|
|
243
|
-
createTestProvider("webhook", webhookConfigSchema),
|
|
244
|
-
plugin2
|
|
245
|
-
);
|
|
246
|
-
|
|
247
|
-
expect(registry.hasProvider("plugin-1.webhook")).toBe(true);
|
|
248
|
-
expect(registry.hasProvider("plugin-2.webhook")).toBe(true);
|
|
249
|
-
|
|
250
|
-
const providers = registry.getProviders();
|
|
251
|
-
expect(providers.length).toBe(2);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
it("correctly namespaces providers by plugin", () => {
|
|
255
|
-
const plugin1 = { pluginId: "integration-webhook" } as const;
|
|
256
|
-
const plugin2 = { pluginId: "integration-slack" } as const;
|
|
257
|
-
|
|
258
|
-
registry.register(
|
|
259
|
-
{
|
|
260
|
-
...createTestProvider("default", webhookConfigSchema),
|
|
261
|
-
displayName: "Webhook",
|
|
262
|
-
},
|
|
263
|
-
plugin1
|
|
264
|
-
);
|
|
265
|
-
registry.register(
|
|
266
|
-
{
|
|
267
|
-
...createTestProvider("default", slackConfigSchema),
|
|
268
|
-
displayName: "Slack",
|
|
269
|
-
},
|
|
270
|
-
plugin2
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
expect(
|
|
274
|
-
registry.getProvider("integration-webhook.default")?.displayName
|
|
275
|
-
).toBe("Webhook");
|
|
276
|
-
expect(
|
|
277
|
-
registry.getProvider("integration-slack.default")?.displayName
|
|
278
|
-
).toBe("Slack");
|
|
279
|
-
});
|
|
64
|
+
it("exposes the connection JSON schema when present", () => {
|
|
65
|
+
registry.register(sampleProvider, testPlugin);
|
|
66
|
+
const schema = registry.getProviderConnectionSchema("test-plugin.sample");
|
|
67
|
+
expect(schema).toBeDefined();
|
|
68
|
+
expect((schema as Record<string, unknown>).type).toBe("object");
|
|
280
69
|
});
|
|
281
70
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
registry.register(provider, testPluginMetadata);
|
|
297
|
-
|
|
298
|
-
const registered = registry.getProvider("test-plugin.limited");
|
|
299
|
-
expect(registered?.supportedEvents).toEqual([
|
|
300
|
-
"incident.created",
|
|
301
|
-
"incident.resolved",
|
|
302
|
-
]);
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
it("handles provider with no supportedEvents (accepts all)", () => {
|
|
306
|
-
const provider = createTestProvider("webhook", webhookConfigSchema);
|
|
307
|
-
|
|
308
|
-
registry.register(provider, testPluginMetadata);
|
|
309
|
-
|
|
310
|
-
const registered = registry.getProvider("test-plugin.webhook");
|
|
311
|
-
expect(registered?.supportedEvents).toBeUndefined();
|
|
312
|
-
});
|
|
71
|
+
it("returns undefined for providers without a connection schema", () => {
|
|
72
|
+
const minimal: IntegrationProvider<undefined> = {
|
|
73
|
+
id: "minimal",
|
|
74
|
+
displayName: "Minimal",
|
|
75
|
+
};
|
|
76
|
+
registry.register(
|
|
77
|
+
minimal as IntegrationProvider<unknown>,
|
|
78
|
+
testPlugin,
|
|
79
|
+
);
|
|
80
|
+
expect(
|
|
81
|
+
registry.getProviderConnectionSchema("test-plugin.minimal"),
|
|
82
|
+
).toBeUndefined();
|
|
313
83
|
});
|
|
314
84
|
});
|
package/src/provider-registry.ts
CHANGED
|
@@ -6,8 +6,11 @@ import type {
|
|
|
6
6
|
} from "./provider-types";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Registry for integration providers
|
|
10
|
-
*
|
|
9
|
+
* Registry for integration providers — now scoped to connection
|
|
10
|
+
* management only. Per-subscription `config` + `deliver` moved to the
|
|
11
|
+
* Automation platform's `ActionDefinition` (see
|
|
12
|
+
* `@checkstack/automation-backend`); the legacy subscription system is
|
|
13
|
+
* gone.
|
|
11
14
|
*/
|
|
12
15
|
export interface IntegrationProviderRegistry {
|
|
13
16
|
/**
|
|
@@ -30,11 +33,6 @@ export interface IntegrationProviderRegistry {
|
|
|
30
33
|
/** Check if a provider is registered */
|
|
31
34
|
hasProvider(qualifiedId: string): boolean;
|
|
32
35
|
|
|
33
|
-
/** Get the JSON Schema for a provider's config */
|
|
34
|
-
getProviderConfigSchema(
|
|
35
|
-
qualifiedId: string
|
|
36
|
-
): Record<string, unknown> | undefined;
|
|
37
|
-
|
|
38
36
|
/** Get the JSON Schema for a provider's connection config (if any) */
|
|
39
37
|
getProviderConnectionSchema(
|
|
40
38
|
qualifiedId: string
|
|
@@ -46,7 +44,6 @@ export interface IntegrationProviderRegistry {
|
|
|
46
44
|
*/
|
|
47
45
|
export function createIntegrationProviderRegistry(): IntegrationProviderRegistry {
|
|
48
46
|
const providers = new Map<string, RegisteredIntegrationProvider<unknown>>();
|
|
49
|
-
const configSchemas = new Map<string, Record<string, unknown>>();
|
|
50
47
|
const connectionSchemas = new Map<string, Record<string, unknown>>();
|
|
51
48
|
|
|
52
49
|
return {
|
|
@@ -64,12 +61,6 @@ export function createIntegrationProviderRegistry(): IntegrationProviderRegistry
|
|
|
64
61
|
|
|
65
62
|
providers.set(qualifiedId, registered);
|
|
66
63
|
|
|
67
|
-
// Convert the provider's config schema to JSON Schema for UI
|
|
68
|
-
// Uses the platform's toJsonSchema which handles secrets/colors
|
|
69
|
-
const jsonSchema = toJsonSchema(provider.config.schema);
|
|
70
|
-
configSchemas.set(qualifiedId, jsonSchema);
|
|
71
|
-
|
|
72
|
-
// Also convert connection schema if present
|
|
73
64
|
if (provider.connectionSchema) {
|
|
74
65
|
const connectionJsonSchema = toJsonSchema(
|
|
75
66
|
provider.connectionSchema.schema
|
|
@@ -92,12 +83,6 @@ export function createIntegrationProviderRegistry(): IntegrationProviderRegistry
|
|
|
92
83
|
return providers.has(qualifiedId);
|
|
93
84
|
},
|
|
94
85
|
|
|
95
|
-
getProviderConfigSchema(
|
|
96
|
-
qualifiedId: string
|
|
97
|
-
): Record<string, unknown> | undefined {
|
|
98
|
-
return configSchemas.get(qualifiedId);
|
|
99
|
-
},
|
|
100
|
-
|
|
101
86
|
getProviderConnectionSchema(
|
|
102
87
|
qualifiedId: string
|
|
103
88
|
): Record<string, unknown> | undefined {
|
package/src/provider-types.ts
CHANGED
|
@@ -1,95 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Integration Provider Types
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* All backend-only types live here - frontend uses Zod schemas from integration-common.
|
|
2
|
+
* Integration Provider Types — connection-only after the Automation
|
|
3
|
+
* Platform migration. Per-event delivery context types are gone; the
|
|
4
|
+
* Automation engine's `ActionExecutionContext` replaces them.
|
|
6
5
|
*/
|
|
7
|
-
import {
|
|
8
|
-
import type { Versioned, Logger, Hook } from "@checkstack/backend-api";
|
|
6
|
+
import type { Versioned, Logger } from "@checkstack/backend-api";
|
|
9
7
|
import type { LucideIconName } from "@checkstack/common";
|
|
10
8
|
|
|
11
|
-
// =============================================================================
|
|
12
|
-
// Integration Event Definition Types
|
|
13
|
-
// =============================================================================
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Metadata for registering a hook as an integration event.
|
|
17
|
-
* Plugins use this to expose their hooks for external webhook subscriptions.
|
|
18
|
-
*/
|
|
19
|
-
export interface IntegrationEventDefinition<T = unknown> {
|
|
20
|
-
/** The hook to expose (from the owning plugin) */
|
|
21
|
-
hook: Hook<T>;
|
|
22
|
-
|
|
23
|
-
/** Human-readable name for the UI */
|
|
24
|
-
displayName: string;
|
|
25
|
-
|
|
26
|
-
/** Description of when this event fires */
|
|
27
|
-
description?: string;
|
|
28
|
-
|
|
29
|
-
/** Category for UI grouping (e.g., "Health", "Incidents", "Maintenance") */
|
|
30
|
-
category?: string;
|
|
31
|
-
|
|
32
|
-
/** Zod schema for the payload (used for UI preview and validation) */
|
|
33
|
-
payloadSchema: z.ZodType<T>;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Optional: Transform hook payload before sending to webhooks.
|
|
37
|
-
* Use this to enrich the payload with additional context or
|
|
38
|
-
* redact sensitive fields.
|
|
39
|
-
*/
|
|
40
|
-
transformPayload?: (payload: T) => Record<string, unknown>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// =============================================================================
|
|
44
|
-
// Integration Provider Types
|
|
45
|
-
// =============================================================================
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Context passed to the provider's deliver() method.
|
|
49
|
-
*/
|
|
50
|
-
export interface IntegrationDeliveryContext<TConfig = unknown> {
|
|
51
|
-
event: {
|
|
52
|
-
/** Fully qualified event ID */
|
|
53
|
-
eventId: string;
|
|
54
|
-
/** Event payload (possibly transformed) */
|
|
55
|
-
payload: Record<string, unknown>;
|
|
56
|
-
/** ISO timestamp when the event was emitted */
|
|
57
|
-
timestamp: string;
|
|
58
|
-
/** Unique ID for this delivery attempt */
|
|
59
|
-
deliveryId: string;
|
|
60
|
-
};
|
|
61
|
-
subscription: {
|
|
62
|
-
/** Subscription ID */
|
|
63
|
-
id: string;
|
|
64
|
-
/** Subscription name */
|
|
65
|
-
name: string;
|
|
66
|
-
};
|
|
67
|
-
/** Provider-specific configuration */
|
|
68
|
-
providerConfig: TConfig;
|
|
69
|
-
/** Scoped logger for delivery tracing */
|
|
70
|
-
logger: Logger;
|
|
71
|
-
/**
|
|
72
|
-
* Get connection credentials by ID (for providers with connectionSchema).
|
|
73
|
-
* Only available when provider has a connectionSchema defined.
|
|
74
|
-
*/
|
|
75
|
-
getConnectionWithCredentials?: (
|
|
76
|
-
connectionId: string
|
|
77
|
-
) => Promise<{ config: Record<string, unknown> } | undefined>;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Result of a provider delivery attempt.
|
|
82
|
-
*/
|
|
83
|
-
export interface IntegrationDeliveryResult {
|
|
84
|
-
success: boolean;
|
|
85
|
-
/** External ID returned by the target system (e.g., Jira issue key) */
|
|
86
|
-
externalId?: string;
|
|
87
|
-
/** Error message if delivery failed */
|
|
88
|
-
error?: string;
|
|
89
|
-
/** Milliseconds to wait before retrying (if applicable) */
|
|
90
|
-
retryAfterMs?: number;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
9
|
/**
|
|
94
10
|
* Result of testing a provider connection.
|
|
95
11
|
*/
|
|
@@ -144,15 +60,19 @@ export interface GetConnectionOptionsParams {
|
|
|
144
60
|
|
|
145
61
|
/**
|
|
146
62
|
* Integration provider definition.
|
|
147
|
-
*
|
|
63
|
+
* Connection-provider definition. Plugins register one per external
|
|
64
|
+
* system to expose a connection schema, test endpoint, and dynamic
|
|
65
|
+
* dropdown resolvers used by the Automation editor's config forms.
|
|
148
66
|
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
67
|
+
* The legacy `config` (per-subscription) + `deliver` fields are gone:
|
|
68
|
+
* those responsibilities moved to the Automation platform's
|
|
69
|
+
* `ActionDefinition` (see `@checkstack/automation-backend`). Existing
|
|
70
|
+
* subscriptions are migrated to automations on boot — see
|
|
71
|
+
* `core/automation-backend/src/migration/`.
|
|
72
|
+
*
|
|
73
|
+
* @template TConnection - Site-wide connection configuration type
|
|
151
74
|
*/
|
|
152
|
-
export interface IntegrationProvider<
|
|
153
|
-
TConfig = unknown,
|
|
154
|
-
TConnection = undefined
|
|
155
|
-
> {
|
|
75
|
+
export interface IntegrationProvider<TConnection = undefined> {
|
|
156
76
|
/** Local identifier, namespaced on registration to {pluginId}.{id} */
|
|
157
77
|
id: string;
|
|
158
78
|
|
|
@@ -165,38 +85,21 @@ export interface IntegrationProvider<
|
|
|
165
85
|
/** Lucide icon name in PascalCase (e.g., 'Webhook') */
|
|
166
86
|
icon?: LucideIconName;
|
|
167
87
|
|
|
168
|
-
/** Per-subscription configuration schema */
|
|
169
|
-
config: Versioned<TConfig>;
|
|
170
|
-
|
|
171
88
|
/**
|
|
172
89
|
* Optional site-wide connection schema.
|
|
173
90
|
* When provided, the platform will:
|
|
174
91
|
* - Store connections centrally via ConfigService
|
|
175
92
|
* - Show a "Connections" management UI
|
|
176
|
-
* -
|
|
93
|
+
* - Make connections selectable in automation action config forms
|
|
177
94
|
*/
|
|
178
95
|
connectionSchema?: Versioned<TConnection>;
|
|
179
96
|
|
|
180
97
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* Event IDs are fully qualified: {pluginId}.{hookId}
|
|
184
|
-
*/
|
|
185
|
-
supportedEvents?: string[];
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Optional documentation to help users configure their endpoints.
|
|
189
|
-
* Displayed in the UI when creating/editing subscriptions.
|
|
98
|
+
* Optional documentation to help users configure connections.
|
|
99
|
+
* Displayed on the connections page.
|
|
190
100
|
*/
|
|
191
101
|
documentation?: ProviderDocumentation;
|
|
192
102
|
|
|
193
|
-
/**
|
|
194
|
-
* Transform and deliver the event to the external system.
|
|
195
|
-
*/
|
|
196
|
-
deliver(
|
|
197
|
-
context: IntegrationDeliveryContext<TConfig>
|
|
198
|
-
): Promise<IntegrationDeliveryResult>;
|
|
199
|
-
|
|
200
103
|
/**
|
|
201
104
|
* Optional: Test the connection configuration.
|
|
202
105
|
* Called when admin clicks "Test Connection" in the connections UI.
|
|
@@ -205,9 +108,9 @@ export interface IntegrationProvider<
|
|
|
205
108
|
testConnection?(config: TConnection): Promise<TestConnectionResult>;
|
|
206
109
|
|
|
207
110
|
/**
|
|
208
|
-
* Optional: Fetch dynamic options for cascading dropdowns
|
|
209
|
-
*
|
|
210
|
-
*
|
|
111
|
+
* Optional: Fetch dynamic options for cascading dropdowns inside
|
|
112
|
+
* automation action config forms. Resolver names are declared via
|
|
113
|
+
* `configString({ "x-options-resolver": "name" })` in action configs.
|
|
211
114
|
*/
|
|
212
115
|
getConnectionOptions?(
|
|
213
116
|
params: GetConnectionOptionsParams
|
|
@@ -217,10 +120,8 @@ export interface IntegrationProvider<
|
|
|
217
120
|
/**
|
|
218
121
|
* Registered provider with full namespace information.
|
|
219
122
|
*/
|
|
220
|
-
export interface RegisteredIntegrationProvider<
|
|
221
|
-
|
|
222
|
-
TConnection = unknown
|
|
223
|
-
> extends IntegrationProvider<TConfig, TConnection> {
|
|
123
|
+
export interface RegisteredIntegrationProvider<TConnection = unknown>
|
|
124
|
+
extends IntegrationProvider<TConnection> {
|
|
224
125
|
/** Fully qualified ID: {pluginId}.{id} */
|
|
225
126
|
qualifiedId: string;
|
|
226
127
|
|
|
@@ -228,30 +129,3 @@ export interface RegisteredIntegrationProvider<
|
|
|
228
129
|
ownerPluginId: string;
|
|
229
130
|
}
|
|
230
131
|
|
|
231
|
-
/**
|
|
232
|
-
* Registered integration event with full namespace information.
|
|
233
|
-
*/
|
|
234
|
-
export interface RegisteredIntegrationEvent<T = unknown> {
|
|
235
|
-
/** Fully qualified event ID: {pluginId}.{hookId} */
|
|
236
|
-
eventId: string;
|
|
237
|
-
|
|
238
|
-
/** Original hook reference */
|
|
239
|
-
hook: Hook<T>;
|
|
240
|
-
|
|
241
|
-
/** Plugin that registered this event */
|
|
242
|
-
ownerPluginId: string;
|
|
243
|
-
|
|
244
|
-
/** UI metadata */
|
|
245
|
-
displayName: string;
|
|
246
|
-
description?: string;
|
|
247
|
-
category?: string;
|
|
248
|
-
|
|
249
|
-
/** JSON Schema for payload (derived from Zod) */
|
|
250
|
-
payloadJsonSchema: Record<string, unknown>;
|
|
251
|
-
|
|
252
|
-
/** Original Zod schema */
|
|
253
|
-
payloadSchema: z.ZodType<T>;
|
|
254
|
-
|
|
255
|
-
/** Optional payload transformer */
|
|
256
|
-
transformPayload?: (payload: T) => Record<string, unknown>;
|
|
257
|
-
}
|