@automate.ax/catalog 0.55.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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/dist/catalog.d.ts +1106 -0
  4. package/dist/catalog.js +349 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.js +3 -0
  7. package/dist/triggers/airtable.d.ts +62 -0
  8. package/dist/triggers/airtable.js +36 -0
  9. package/dist/triggers/asana.d.ts +65 -0
  10. package/dist/triggers/asana.js +39 -0
  11. package/dist/triggers/brevo.d.ts +111 -0
  12. package/dist/triggers/brevo.js +65 -0
  13. package/dist/triggers/core.d.ts +50 -0
  14. package/dist/triggers/core.js +74 -0
  15. package/dist/triggers/github.d.ts +228 -0
  16. package/dist/triggers/github.js +136 -0
  17. package/dist/triggers/google.d.ts +126 -0
  18. package/dist/triggers/google.js +143 -0
  19. package/dist/triggers/index.d.ts +2598 -0
  20. package/dist/triggers/index.js +97 -0
  21. package/dist/triggers/linear.d.ts +110 -0
  22. package/dist/triggers/linear.js +59 -0
  23. package/dist/triggers/microsoft.d.ts +40 -0
  24. package/dist/triggers/microsoft.js +60 -0
  25. package/dist/triggers/resend.d.ts +110 -0
  26. package/dist/triggers/resend.js +59 -0
  27. package/dist/triggers/slack.d.ts +41 -0
  28. package/dist/triggers/slack.js +53 -0
  29. package/dist/triggers/trello.d.ts +56 -0
  30. package/dist/triggers/trello.js +35 -0
  31. package/dist/triggers/vercel.d.ts +279 -0
  32. package/dist/triggers/vercel.js +163 -0
  33. package/dist/triggers/whatsapp.d.ts +65 -0
  34. package/dist/triggers/whatsapp.js +39 -0
  35. package/dist/types.d.ts +134 -0
  36. package/dist/types.js +59 -0
  37. package/package.json +70 -0
  38. package/src/catalog.ts +403 -0
  39. package/src/index.ts +68 -0
  40. package/src/triggers/airtable.ts +39 -0
  41. package/src/triggers/asana.ts +42 -0
  42. package/src/triggers/brevo.ts +68 -0
  43. package/src/triggers/core.ts +93 -0
  44. package/src/triggers/github.ts +142 -0
  45. package/src/triggers/google.ts +149 -0
  46. package/src/triggers/index.ts +128 -0
  47. package/src/triggers/linear.ts +62 -0
  48. package/src/triggers/microsoft.ts +65 -0
  49. package/src/triggers/resend.ts +62 -0
  50. package/src/triggers/slack.ts +58 -0
  51. package/src/triggers/trello.ts +38 -0
  52. package/src/triggers/vercel.ts +170 -0
  53. package/src/triggers/whatsapp.ts +42 -0
  54. package/src/types.ts +219 -0
@@ -0,0 +1,134 @@
1
+ export interface IntegrationFormFieldBase {
2
+ description?: string;
3
+ label: string;
4
+ name: string;
5
+ required: boolean;
6
+ }
7
+ export type IntegrationFormField = (IntegrationFormFieldBase & {
8
+ default?: string;
9
+ input: "email" | "text" | "url";
10
+ placeholder?: string;
11
+ }) | (IntegrationFormFieldBase & {
12
+ input: "password";
13
+ placeholder?: string;
14
+ }) | (IntegrationFormFieldBase & {
15
+ default?: number;
16
+ input: "number";
17
+ placeholder?: string;
18
+ }) | (IntegrationFormFieldBase & {
19
+ default?: boolean;
20
+ input: "boolean";
21
+ });
22
+ interface IntegrationConnectionDefinitionBase {
23
+ description?: string;
24
+ id: string;
25
+ name: string;
26
+ }
27
+ export type IntegrationConnectionDefinition = (IntegrationConnectionDefinitionBase & {
28
+ type: "redirect";
29
+ }) | (IntegrationConnectionDefinitionBase & {
30
+ fields: readonly IntegrationFormField[];
31
+ type: "form";
32
+ });
33
+ export interface IntegrationServiceDefinition {
34
+ connectionMethods: readonly IntegrationConnectionDefinition[];
35
+ description?: string;
36
+ id: string;
37
+ /**
38
+ * Overrides the icon asset key inferred from `id`.
39
+ *
40
+ * Omit this unless the service intentionally reuses another icon asset.
41
+ */
42
+ icon?: string;
43
+ name: string;
44
+ preferredConnectionMethodId?: string;
45
+ }
46
+ export type IntegrationScopeRequirement = ScopeRequirementGroup | string;
47
+ /** A recursive group of integration authorization scope requirements. */
48
+ export interface ScopeRequirementGroup {
49
+ requirements: readonly IntegrationScopeRequirement[];
50
+ type: "and" | "or";
51
+ }
52
+ /** Combinators for declaring recursive integration scope requirements. */
53
+ export declare const scope: {
54
+ /**
55
+ * Requires every scope or nested group.
56
+ *
57
+ * @param requirements - Required scopes and nested groups.
58
+ */
59
+ and(...requirements: IntegrationScopeRequirement[]): ScopeRequirementGroup;
60
+ /**
61
+ * Requires any scope or nested group.
62
+ *
63
+ * Alternatives must be ordered from most permissive to least permissive.
64
+ *
65
+ * @param requirements - Alternative scopes and nested groups.
66
+ */
67
+ any(...requirements: IntegrationScopeRequirement[]): ScopeRequirementGroup;
68
+ };
69
+ /** One connection method accepted by an integration account requirement. */
70
+ export interface IntegrationAccountConnectionOption {
71
+ connectionId?: string;
72
+ requiredScopes: readonly IntegrationScopeRequirement[];
73
+ }
74
+ /** One normalized integration account requirement. */
75
+ export interface IntegrationAccountRequirement<TServiceId extends string = string> {
76
+ connectionOptions: readonly IntegrationAccountConnectionOption[];
77
+ serviceId: TServiceId;
78
+ }
79
+ /** Runtime-neutral metadata for one public trigger type. */
80
+ export interface TriggerDefinition<TType extends string = string, TServiceId extends string = string> {
81
+ account?: IntegrationAccountRequirement<TServiceId>;
82
+ description?: string;
83
+ /** Adds configuration-specific details to this trigger's presentation. */
84
+ getDetails?(context: TriggerPresentationContext): TriggerPresentationDetail[];
85
+ /**
86
+ * Overrides the connected service icon.
87
+ *
88
+ * Omit this from account-backed triggers to inherit their service icon.
89
+ */
90
+ icon?: string;
91
+ /**
92
+ * Overrides the display name inferred from `type`.
93
+ *
94
+ * Omit this unless custom copy adds value beyond the inferred name.
95
+ * `triggerCatalog` and `getTriggerDefinition` always expose a resolved name.
96
+ */
97
+ name?: string;
98
+ type: TType;
99
+ }
100
+ /** Runtime-neutral context used to describe one configured trigger. */
101
+ export interface TriggerPresentationContext {
102
+ appOrigin: string;
103
+ automationId: string;
104
+ config: unknown;
105
+ hookSlot: number;
106
+ projectId: string;
107
+ }
108
+ /** One user-facing property of a configured trigger. */
109
+ export interface TriggerPresentationDetail {
110
+ copyable?: boolean;
111
+ label: string;
112
+ value: string;
113
+ }
114
+ /** Client-safe presentation of one configured trigger. */
115
+ export interface TriggerPresentation {
116
+ details: TriggerPresentationDetail[];
117
+ name: string;
118
+ type: string;
119
+ }
120
+ /**
121
+ * Preserves the literal IDs and connection shapes in one shared definition.
122
+ *
123
+ * @param service - Complete runtime-neutral service definition.
124
+ * @throws When the service or a form connection is empty or IDs repeat.
125
+ */
126
+ export declare function defineIntegrationService<const TService extends IntegrationServiceDefinition>(service: TService): TService;
127
+ /**
128
+ * Validates and preserves one complete compile-time service catalog.
129
+ *
130
+ * @param services - Shared integration service definitions.
131
+ * @throws When multiple services use the same ID.
132
+ */
133
+ export declare function defineIntegrationCatalog<const TCatalog extends readonly IntegrationServiceDefinition[]>(services: TCatalog): TCatalog;
134
+ export {};
package/dist/types.js ADDED
@@ -0,0 +1,59 @@
1
+ /** Combinators for declaring recursive integration scope requirements. */
2
+ export const scope = {
3
+ /**
4
+ * Requires every scope or nested group.
5
+ *
6
+ * @param requirements - Required scopes and nested groups.
7
+ */
8
+ and(...requirements) {
9
+ return { requirements: [...new Set(requirements)], type: "and" };
10
+ },
11
+ /**
12
+ * Requires any scope or nested group.
13
+ *
14
+ * Alternatives must be ordered from most permissive to least permissive.
15
+ *
16
+ * @param requirements - Alternative scopes and nested groups.
17
+ */
18
+ any(...requirements) {
19
+ return { requirements: [...new Set(requirements)], type: "or" };
20
+ },
21
+ };
22
+ /**
23
+ * Preserves the literal IDs and connection shapes in one shared definition.
24
+ *
25
+ * @param service - Complete runtime-neutral service definition.
26
+ * @throws When the service or a form connection is empty or IDs repeat.
27
+ */
28
+ export function defineIntegrationService(service) {
29
+ if (service.connectionMethods.length === 0) {
30
+ throw new Error(`Integration service has no connection methods: ${service.id}`);
31
+ }
32
+ const emptyFormConnection = service.connectionMethods.find((connection) => connection.type === "form" && connection.fields.length === 0);
33
+ if (emptyFormConnection) {
34
+ throw new Error(`Integration service ${service.id} has no fields for form connection: ${emptyFormConnection.id}`);
35
+ }
36
+ const duplicateConnectionId = service.connectionMethods.find((connection, index) => service.connectionMethods.findIndex(({ id }) => id === connection.id) !==
37
+ index)?.id;
38
+ if (duplicateConnectionId) {
39
+ throw new Error(`Integration service ${service.id} has duplicate connection ID: ${duplicateConnectionId}`);
40
+ }
41
+ if (service.preferredConnectionMethodId &&
42
+ !service.connectionMethods.some(({ id }) => id === service.preferredConnectionMethodId)) {
43
+ throw new Error(`Integration service ${service.id} has an unknown preferred connection method: ${service.preferredConnectionMethodId}`);
44
+ }
45
+ return service;
46
+ }
47
+ /**
48
+ * Validates and preserves one complete compile-time service catalog.
49
+ *
50
+ * @param services - Shared integration service definitions.
51
+ * @throws When multiple services use the same ID.
52
+ */
53
+ export function defineIntegrationCatalog(services) {
54
+ const duplicateServiceId = services.find((service, index) => services.findIndex(({ id }) => id === service.id) !== index)?.id;
55
+ if (duplicateServiceId) {
56
+ throw new Error(`Duplicate integration service ID: ${duplicateServiceId}`);
57
+ }
58
+ return services;
59
+ }
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@automate.ax/catalog",
3
+ "version": "0.55.0",
4
+ "description": "Shared integration service and trigger definitions for Automate.ax.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/zachsents/automate.ax.git",
9
+ "directory": "packages/catalog"
10
+ },
11
+ "homepage": "https://automate.ax",
12
+ "bugs": {
13
+ "url": "https://github.com/zachsents/automate.ax/issues"
14
+ },
15
+ "type": "module",
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "zshy": {
20
+ "exports": {
21
+ ".": "./src/index.ts"
22
+ },
23
+ "cjs": false,
24
+ "conditions": {
25
+ "bun": "src"
26
+ }
27
+ },
28
+ "devDependencies": {
29
+ "@internal/config": "0.0.0",
30
+ "@types/bun": "latest",
31
+ "@typescript/native": "npm:typescript@^7.0.2",
32
+ "@zachsents/oxlint-config": "^0.4.1",
33
+ "concurrently": "^10.0.4",
34
+ "eslint": "^9.39.5",
35
+ "oxlint": "^1.76.0",
36
+ "oxlint-tsgolint": "^7.0.2001",
37
+ "zshy": "^0.7.2"
38
+ },
39
+ "scripts": {
40
+ "typecheck": "tsc --noEmit",
41
+ "lint": "concurrently --success all --kill-others-on-fail \"oxlint --type-aware\" \"bun --bun eslint .\"",
42
+ "lint:fix": "concurrently --success all --kill-others-on-fail \"oxlint --type-aware --fix --fix-suggestions\" \"bun --bun eslint . --fix\"",
43
+ "check": "bun run typecheck && bun run lint",
44
+ "test": "bun test",
45
+ "build": "zshy",
46
+ "prepublishOnly": "bun run check && bun run test && bun run build"
47
+ },
48
+ "files": [
49
+ "dist",
50
+ "src",
51
+ "README.md",
52
+ "LICENSE"
53
+ ],
54
+ "main": "./dist/index.js",
55
+ "module": "./dist/index.js",
56
+ "types": "./dist/index.d.ts",
57
+ "engines": {
58
+ "node": ">=24"
59
+ },
60
+ "exports": {
61
+ ".": {
62
+ "bun": "./src/index.ts",
63
+ "types": "./dist/index.d.ts",
64
+ "default": "./dist/index.js"
65
+ }
66
+ },
67
+ "dependencies": {
68
+ "zod": "^4.3.6"
69
+ }
70
+ }
package/src/catalog.ts ADDED
@@ -0,0 +1,403 @@
1
+ import { defineIntegrationCatalog, defineIntegrationService } from "./types"
2
+ import type { IntegrationServiceDefinition } from "./types"
3
+
4
+ const API_KEY_FIELD = {
5
+ input: "password",
6
+ label: "API key",
7
+ name: "apiKey",
8
+ required: true,
9
+ } as const
10
+
11
+ export const airtableService = defineIntegrationService({
12
+ connectionMethods: [{ id: "default", name: "OAuth", type: "redirect" }],
13
+ description: "Connect an Airtable account.",
14
+ id: "airtable",
15
+ name: "Airtable",
16
+ })
17
+
18
+ export const anthropicService = defineApiKeyService({
19
+ description: "Connect an Anthropic API key.",
20
+ id: "anthropic",
21
+ name: "Anthropic",
22
+ placeholder: "sk-ant-...",
23
+ })
24
+
25
+ export const apolloService = defineIntegrationService({
26
+ connectionMethods: [
27
+ { id: "oauth", name: "OAuth", type: "redirect" },
28
+ {
29
+ fields: [{ ...API_KEY_FIELD, placeholder: "Apollo API key" }],
30
+ id: "api-key",
31
+ name: "API key",
32
+ type: "form",
33
+ },
34
+ ],
35
+ description: "Connect an Apollo account with OAuth or an API key.",
36
+ id: "apollo",
37
+ name: "Apollo",
38
+ preferredConnectionMethodId: "oauth",
39
+ })
40
+
41
+ export const asanaService = defineIntegrationService({
42
+ connectionMethods: [{ id: "default", name: "OAuth", type: "redirect" }],
43
+ description: "Connect an Asana account.",
44
+ id: "asana",
45
+ name: "Asana",
46
+ })
47
+
48
+ export const brevoService = defineApiKeyService({
49
+ description: "Connect a Brevo API key.",
50
+ id: "brevo",
51
+ name: "Brevo",
52
+ placeholder: "xkeysib-...",
53
+ })
54
+
55
+ export const cerebrasService = defineApiKeyService({
56
+ description: "Connect a Cerebras API key.",
57
+ id: "cerebras",
58
+ name: "Cerebras",
59
+ })
60
+
61
+ export const cloudflareService = defineIntegrationService({
62
+ connectionMethods: [
63
+ { id: "oauth", name: "OAuth", type: "redirect" },
64
+ {
65
+ fields: [
66
+ {
67
+ input: "password",
68
+ label: "API token",
69
+ name: "apiKey",
70
+ placeholder: "Cloudflare API token",
71
+ required: true,
72
+ },
73
+ ],
74
+ id: "api-token",
75
+ name: "API token",
76
+ type: "form",
77
+ },
78
+ ],
79
+ description: "Connect a Cloudflare account with OAuth or an API token.",
80
+ id: "cloudflare",
81
+ name: "Cloudflare",
82
+ preferredConnectionMethodId: "oauth",
83
+ })
84
+
85
+ export const cohereService = defineApiKeyService({
86
+ description: "Connect a Cohere API key.",
87
+ id: "cohere",
88
+ name: "Cohere",
89
+ })
90
+
91
+ export const deepinfraService = defineApiKeyService({
92
+ description: "Connect a DeepInfra API key.",
93
+ id: "deepinfra",
94
+ name: "DeepInfra",
95
+ })
96
+
97
+ export const deepseekService = defineApiKeyService({
98
+ description: "Connect a DeepSeek API key.",
99
+ id: "deepseek",
100
+ name: "DeepSeek",
101
+ })
102
+
103
+ export const firecrawlService = defineApiKeyService({
104
+ description: "Connect a Firecrawl API key.",
105
+ id: "firecrawl",
106
+ name: "Firecrawl",
107
+ placeholder: "fc-...",
108
+ })
109
+
110
+ export const fireworksService = defineApiKeyService({
111
+ description: "Connect a Fireworks AI API key.",
112
+ id: "fireworks",
113
+ name: "Fireworks AI",
114
+ })
115
+
116
+ export const githubService = defineIntegrationService({
117
+ connectionMethods: [{ id: "default", name: "GitHub App", type: "redirect" }],
118
+ description: "Install Automate.ax on a GitHub account or organization.",
119
+ id: "github",
120
+ name: "GitHub",
121
+ })
122
+
123
+ export const googleService = defineIntegrationService({
124
+ connectionMethods: [{ id: "default", name: "OAuth", type: "redirect" }],
125
+ description: "Connect a Google account.",
126
+ id: "google",
127
+ name: "Google",
128
+ })
129
+
130
+ export const googleGenaiService = defineApiKeyService({
131
+ description: "Connect a Google AI Studio API key.",
132
+ id: "google-genai",
133
+ name: "Google Generative AI",
134
+ placeholder: "AIza...",
135
+ })
136
+
137
+ export const groqService = defineApiKeyService({
138
+ description: "Connect a Groq API key.",
139
+ id: "groq",
140
+ name: "Groq",
141
+ })
142
+
143
+ export const huggingfaceService = defineApiKeyService({
144
+ description: "Connect a Hugging Face access token.",
145
+ id: "huggingface",
146
+ name: "Hugging Face",
147
+ placeholder: "hf_...",
148
+ })
149
+
150
+ export const linearService = defineIntegrationService({
151
+ connectionMethods: [{ id: "default", name: "OAuth", type: "redirect" }],
152
+ description: "Connect a Linear workspace.",
153
+ id: "linear",
154
+ name: "Linear",
155
+ })
156
+
157
+ export const microsoftService = defineIntegrationService({
158
+ connectionMethods: [{ id: "default", name: "OAuth", type: "redirect" }],
159
+ description: "Connect a Microsoft account.",
160
+ id: "microsoft",
161
+ name: "Microsoft",
162
+ })
163
+
164
+ export const millionverifierService = defineApiKeyService({
165
+ description: "Connect a Million Verifier API key.",
166
+ id: "millionverifier",
167
+ name: "Million Verifier",
168
+ placeholder: "Million Verifier API key",
169
+ })
170
+
171
+ export const mistralService = defineApiKeyService({
172
+ description: "Connect a Mistral AI API key.",
173
+ id: "mistral",
174
+ name: "Mistral AI",
175
+ })
176
+
177
+ export const openaiService = defineApiKeyService({
178
+ description: "Connect an OpenAI API key.",
179
+ id: "openai",
180
+ name: "OpenAI",
181
+ placeholder: "sk-...",
182
+ })
183
+
184
+ export const openrouterService = defineApiKeyService({
185
+ description: "Connect an OpenRouter API key.",
186
+ id: "openrouter",
187
+ name: "OpenRouter",
188
+ placeholder: "sk-or-...",
189
+ })
190
+
191
+ export const perplexityService = defineApiKeyService({
192
+ description: "Connect a Perplexity API key.",
193
+ id: "perplexity",
194
+ name: "Perplexity",
195
+ })
196
+
197
+ export const postgresService = defineIntegrationService({
198
+ connectionMethods: [
199
+ {
200
+ fields: [
201
+ {
202
+ description: "A postgresql:// connection string.",
203
+ input: "password",
204
+ label: "Connection string",
205
+ name: "connectionString",
206
+ placeholder:
207
+ "postgresql://user:password@host:5432/database?sslmode=require",
208
+ required: true,
209
+ },
210
+ ],
211
+ id: "default",
212
+ name: "Credentials",
213
+ type: "form",
214
+ },
215
+ ],
216
+ description: "Connect a PostgreSQL database.",
217
+ id: "postgres",
218
+ name: "PostgreSQL",
219
+ })
220
+
221
+ export const resendService = defineIntegrationService({
222
+ connectionMethods: [
223
+ { id: "oauth", name: "OAuth", type: "redirect" },
224
+ {
225
+ fields: [{ ...API_KEY_FIELD, placeholder: "re_..." }],
226
+ id: "api-key",
227
+ name: "API key",
228
+ type: "form",
229
+ },
230
+ ],
231
+ description: "Connect a Resend account with OAuth or an API key.",
232
+ id: "resend",
233
+ name: "Resend",
234
+ preferredConnectionMethodId: "oauth",
235
+ })
236
+
237
+ export const scrapflyService = defineApiKeyService({
238
+ description: "Connect a Scrapfly API key.",
239
+ id: "scrapfly",
240
+ name: "Scrapfly",
241
+ placeholder: "scp-live-...",
242
+ })
243
+
244
+ export const slackService = defineIntegrationService({
245
+ connectionMethods: [{ id: "default", name: "OAuth", type: "redirect" }],
246
+ description: "Install the Automate.ax bot in a Slack workspace.",
247
+ id: "slack",
248
+ name: "Slack",
249
+ })
250
+
251
+ export const tidycalService = defineIntegrationService({
252
+ connectionMethods: [{ id: "default", name: "OAuth", type: "redirect" }],
253
+ description: "Connect a TidyCal account.",
254
+ id: "tidycal",
255
+ name: "TidyCal",
256
+ })
257
+
258
+ export const togetheraiService = defineApiKeyService({
259
+ description: "Connect a Together AI API key.",
260
+ id: "togetherai",
261
+ name: "Together AI",
262
+ })
263
+
264
+ export const trelloService = defineIntegrationService({
265
+ connectionMethods: [{ id: "default", name: "OAuth", type: "redirect" }],
266
+ description: "Connect a Trello account.",
267
+ id: "trello",
268
+ name: "Trello",
269
+ })
270
+
271
+ export const vercelAiGatewayService = defineApiKeyService({
272
+ description: "Connect a Vercel AI Gateway API key.",
273
+ icon: "vercel",
274
+ id: "vercel-ai-gateway",
275
+ name: "Vercel AI Gateway",
276
+ })
277
+
278
+ export const vercelService = defineIntegrationService({
279
+ connectionMethods: [
280
+ { id: "oauth", name: "OAuth", type: "redirect" },
281
+ {
282
+ fields: [
283
+ {
284
+ input: "password",
285
+ label: "Access token",
286
+ name: "apiKey",
287
+ placeholder: "Vercel access token",
288
+ required: true,
289
+ },
290
+ ],
291
+ id: "access-token",
292
+ name: "Access token",
293
+ type: "form",
294
+ },
295
+ ],
296
+ description: "Connect a Vercel account with OAuth or an access token.",
297
+ id: "vercel",
298
+ name: "Vercel",
299
+ preferredConnectionMethodId: "oauth",
300
+ })
301
+
302
+ export const whatsappService = defineIntegrationService({
303
+ connectionMethods: [
304
+ { id: "embedded-signup", name: "Embedded Signup", type: "redirect" },
305
+ ],
306
+ description: "Connect a WhatsApp Business Platform phone number.",
307
+ id: "whatsapp",
308
+ name: "WhatsApp",
309
+ })
310
+
311
+ export const xaiService = defineApiKeyService({
312
+ description: "Connect an xAI API key.",
313
+ id: "xai",
314
+ name: "xAI",
315
+ placeholder: "xai-...",
316
+ })
317
+
318
+ export const integrationCatalog = defineIntegrationCatalog([
319
+ airtableService,
320
+ anthropicService,
321
+ apolloService,
322
+ asanaService,
323
+ brevoService,
324
+ cerebrasService,
325
+ cloudflareService,
326
+ cohereService,
327
+ deepinfraService,
328
+ deepseekService,
329
+ firecrawlService,
330
+ fireworksService,
331
+ githubService,
332
+ googleService,
333
+ googleGenaiService,
334
+ groqService,
335
+ huggingfaceService,
336
+ linearService,
337
+ microsoftService,
338
+ millionverifierService,
339
+ mistralService,
340
+ openaiService,
341
+ openrouterService,
342
+ perplexityService,
343
+ postgresService,
344
+ resendService,
345
+ scrapflyService,
346
+ slackService,
347
+ tidycalService,
348
+ togetheraiService,
349
+ trelloService,
350
+ vercelAiGatewayService,
351
+ vercelService,
352
+ whatsappService,
353
+ xaiService,
354
+ ])
355
+
356
+ export type IntegrationServiceId = (typeof integrationCatalog)[number]["id"]
357
+
358
+ /**
359
+ * Looks up one known integration service by its stable ID.
360
+ *
361
+ * @param id - Stable integration service ID.
362
+ */
363
+ export function getIntegrationService(
364
+ id: string,
365
+ ): IntegrationServiceDefinition | undefined {
366
+ return integrationCatalog.find((service) => service.id === id)
367
+ }
368
+
369
+ interface ApiKeyServiceDefinition {
370
+ description: string
371
+ icon?: string
372
+ name: string
373
+ placeholder?: string
374
+ }
375
+
376
+ /**
377
+ * Defines one service backed by a conventional API-key credential form.
378
+ *
379
+ * @param service - API-key service identity and credential placeholder.
380
+ */
381
+ function defineApiKeyService<const TId extends string>(
382
+ service: ApiKeyServiceDefinition & { id: TId },
383
+ ) {
384
+ return defineIntegrationService({
385
+ connectionMethods: [
386
+ {
387
+ fields: [
388
+ {
389
+ ...API_KEY_FIELD,
390
+ placeholder: service.placeholder ?? "API key",
391
+ },
392
+ ],
393
+ id: "default",
394
+ name: "API key",
395
+ type: "form",
396
+ },
397
+ ],
398
+ description: service.description,
399
+ ...(service.icon ? { icon: service.icon } : {}),
400
+ id: service.id,
401
+ name: service.name,
402
+ })
403
+ }