@slates/provider 1.0.0-rc.22 → 1.0.0-rc.24

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.
@@ -3,17 +3,11 @@ import type { SlateSpecification } from '../specification/specification';
3
3
  import {
4
4
  SlateAction,
5
5
  type SlateActionParameters,
6
- type SlatePollingOptions,
7
6
  type SlateTriggerMappingHandler,
8
- type SlateTriggerPollingHandler,
9
- type SlateTriggerWebhookAutoRegistrationHandler,
10
- type SlateTriggerWebhookAutoUnregistrationHandler,
11
- type SlateTriggerWebhookRequestHandler,
12
- type SlateWebhookHttpOptions
7
+ type SlateTriggerMatchesHandler
13
8
  } from './action';
14
9
  import { SlateActionBuilder } from './builder';
15
-
16
- export let SlateDefaultPollingIntervalSeconds = 60 * 10;
10
+ import type { SlateTriggerGroup } from './triggerGroup';
17
11
 
18
12
  export interface SlateTriggerParameters<
19
13
  ConfigType extends {},
@@ -24,14 +18,9 @@ export interface SlateTriggerParameters<
24
18
  }
25
19
  > extends SlateActionParameters {
26
20
  type: 'trigger';
27
- source: 'polling' | 'webhook';
28
- polling?: SlatePollingOptions;
29
- handleEvent: SlateTriggerMappingHandler<ConfigType, AuthType, InputType, OutputType>;
30
- handleRequest?: SlateTriggerWebhookRequestHandler<ConfigType, AuthType, InputType>;
31
- http?: SlateWebhookHttpOptions;
32
- pollEvents?: SlateTriggerPollingHandler<ConfigType, AuthType, InputType>;
33
- autoRegisterWebhook?: SlateTriggerWebhookAutoRegistrationHandler<ConfigType, AuthType>;
34
- autoUnregisterWebhook?: SlateTriggerWebhookAutoUnregistrationHandler<ConfigType, AuthType>;
21
+ triggerGroup: SlateTriggerGroup<ConfigType, AuthType>;
22
+ matches: SlateTriggerMatchesHandler;
23
+ map: SlateTriggerMappingHandler<ConfigType, AuthType, InputType, OutputType>;
35
24
  }
36
25
 
37
26
  export class SlateTrigger<
@@ -42,14 +31,9 @@ export class SlateTrigger<
42
31
  type: string;
43
32
  }
44
33
  > extends SlateAction<'trigger', ConfigType, AuthType, InputType, OutputType> {
45
- #source: 'polling' | 'webhook';
46
- #polling: SlatePollingOptions;
47
- #handleEvent: SlateTriggerMappingHandler<ConfigType, AuthType, InputType, OutputType>;
48
- #handleRequest?: SlateTriggerWebhookRequestHandler<ConfigType, AuthType, InputType>;
49
- #http?: SlateWebhookHttpOptions;
50
- #pollEvents?: SlateTriggerPollingHandler<ConfigType, AuthType, InputType>;
51
- #autoRegisterWebhook?: SlateTriggerWebhookAutoRegistrationHandler<ConfigType, AuthType>;
52
- #autoUnregisterWebhook?: SlateTriggerWebhookAutoUnregistrationHandler<ConfigType, AuthType>;
34
+ #triggerGroup: SlateTriggerGroup<ConfigType, AuthType>;
35
+ #matches: SlateTriggerMatchesHandler;
36
+ #map: SlateTriggerMappingHandler<ConfigType, AuthType, InputType, OutputType>;
53
37
 
54
38
  private constructor(
55
39
  spec: SlateSpecification<ConfigType, AuthType>,
@@ -59,16 +43,9 @@ export class SlateTrigger<
59
43
  ) {
60
44
  super('trigger', spec, inputSchema, outputSchema, params);
61
45
 
62
- this.#source = params.source;
63
- this.#polling = params.polling || {
64
- intervalInSeconds: SlateDefaultPollingIntervalSeconds
65
- };
66
- this.#handleEvent = params.handleEvent;
67
- this.#handleRequest = params.handleRequest;
68
- this.#http = params.http;
69
- this.#pollEvents = params.pollEvents;
70
- this.#autoRegisterWebhook = params.autoRegisterWebhook;
71
- this.#autoUnregisterWebhook = params.autoUnregisterWebhook;
46
+ this.#triggerGroup = params.triggerGroup;
47
+ this.#matches = params.matches;
48
+ this.#map = params.map;
72
49
  }
73
50
 
74
51
  static create<ConfigType extends {}, AuthType extends {}>(
@@ -81,36 +58,16 @@ export class SlateTrigger<
81
58
  });
82
59
  }
83
60
 
84
- get polling() {
85
- return this.#polling;
86
- }
87
-
88
- get source() {
89
- return this.#source;
90
- }
91
-
92
- get handleEvent() {
93
- return this.#handleEvent;
94
- }
95
-
96
- get handleRequest() {
97
- return this.#handleRequest;
98
- }
99
-
100
- get http() {
101
- return this.#http;
102
- }
103
-
104
- get pollEvents() {
105
- return this.#pollEvents;
61
+ get triggerGroup() {
62
+ return this.#triggerGroup;
106
63
  }
107
64
 
108
- get autoRegisterWebhook() {
109
- return this.#autoRegisterWebhook;
65
+ get matches() {
66
+ return this.#matches;
110
67
  }
111
68
 
112
- get autoUnregisterWebhook() {
113
- return this.#autoUnregisterWebhook;
69
+ get map() {
70
+ return this.#map;
114
71
  }
115
72
  }
116
73
 
@@ -0,0 +1,332 @@
1
+ import { z } from 'zod';
2
+ import type { SlateContext } from '../context';
3
+ import { SlateDeclarationError } from '../error';
4
+ import type { SlateSpecification } from '../specification/specification';
5
+ import type { SlateWebhookHttpResponseInit } from './action';
6
+
7
+ export let SlateDefaultPollingIntervalSeconds = 60 * 10;
8
+
9
+ export type SlateTriggerRoutingMatcher = Record<string, any>;
10
+
11
+ export type SlateWebhookTargetOwnership = 'single_user' | 'multi_user';
12
+
13
+ export interface SlateWebhookTarget {
14
+ webhookTargetIdentifier: string;
15
+ name: string;
16
+ description?: string;
17
+ metadata: Record<string, any>;
18
+ webhookTargetPayload: any;
19
+ targetOwnership: SlateWebhookTargetOwnership;
20
+ }
21
+
22
+ export type SlateTriggerGroupRoutingMatchersHandler<
23
+ ConfigType extends {},
24
+ AuthType extends {}
25
+ > = (context: SlateContext<ConfigType, AuthType, {}>) => Promise<SlateTriggerRoutingMatcher[]>;
26
+
27
+ export type SlateTriggerGroupPollHandler<ConfigType extends {}, AuthType extends {}> = (
28
+ context: SlateContext<ConfigType, AuthType, { state: any | null }>
29
+ ) => Promise<{
30
+ events: { payload: any; idempotencyKey?: string }[];
31
+ updatedState?: any;
32
+ }>;
33
+
34
+ export type SlateWebhookTargetListHandler<ConfigType extends {}, AuthType extends {}> = (
35
+ context: SlateContext<ConfigType, AuthType, { pageToken: any | null }>
36
+ ) => Promise<{
37
+ targets: SlateWebhookTarget[];
38
+ nextPageToken: any | null;
39
+ }>;
40
+
41
+ export type SlateWebhookRegisterHandler<ConfigType extends {}, AuthType extends {}> = (
42
+ context: SlateContext<
43
+ ConfigType,
44
+ AuthType,
45
+ {
46
+ webhookTargetIdentifier: string;
47
+ webhookTargetPayload: any;
48
+ webhookUrl: string;
49
+ }
50
+ >
51
+ ) => Promise<{
52
+ webhookRegistrationIdentifier: string;
53
+ webhookRegistrationPayload: any;
54
+ }>;
55
+
56
+ export type SlateWebhookUnregisterHandler<ConfigType extends {}, AuthType extends {}> = (
57
+ context: SlateContext<
58
+ ConfigType,
59
+ AuthType,
60
+ {
61
+ webhookRegistrationIdentifier: string;
62
+ webhookRegistrationPayload: any;
63
+ }
64
+ >
65
+ ) => Promise<unknown>;
66
+
67
+ export type SlateWebhookManualSetupHandler<
68
+ FullConfigSchema extends z.ZodType<any> = z.ZodType<any>
69
+ > = (context: SlateContext<{}, {}, { webhookUrl: string }>) => Promise<{
70
+ webhookSetupDocument: string;
71
+ partialWebhookRegistrationPayload: Partial<z.infer<FullConfigSchema>>;
72
+ }>;
73
+
74
+ export type SlateWebhookManualFinishHandler<
75
+ UserConfigSchema extends z.ZodType<any> = z.ZodType<any>,
76
+ FullConfigSchema extends z.ZodType<any> = z.ZodType<any>
77
+ > = (
78
+ context: SlateContext<
79
+ {},
80
+ {},
81
+ {
82
+ webhookUrl: string;
83
+ partialWebhookRegistrationPayload: Partial<z.infer<FullConfigSchema>>;
84
+ userWebhookRegistrationPayload: z.infer<UserConfigSchema>;
85
+ }
86
+ >
87
+ ) => Promise<{
88
+ webhookRegistrationPayload: z.infer<FullConfigSchema>;
89
+ }>;
90
+
91
+ export type SlateWebhookProcessHandler = (
92
+ context: SlateContext<
93
+ {},
94
+ {},
95
+ {
96
+ request: Request;
97
+ webhookRegistrationPayload: any;
98
+ }
99
+ >
100
+ ) => Promise<{
101
+ events: {
102
+ matchers: SlateTriggerRoutingMatcher[];
103
+ payload: any;
104
+ idempotencyKey?: string;
105
+ }[];
106
+ response?: Response | SlateWebhookHttpResponseInit;
107
+ }>;
108
+
109
+ export interface SlateTriggerGroupPollingParameters<
110
+ ConfigType extends {},
111
+ AuthType extends {}
112
+ > {
113
+ intervalSeconds: number;
114
+ pollEvents: SlateTriggerGroupPollHandler<ConfigType, AuthType>;
115
+ }
116
+
117
+ export interface SlateTriggerGroupWebhookAutoRegistrationParameters<
118
+ ConfigType extends {},
119
+ AuthType extends {}
120
+ > {
121
+ webhookTargetList: SlateWebhookTargetListHandler<ConfigType, AuthType>;
122
+ webhookRegister: SlateWebhookRegisterHandler<ConfigType, AuthType>;
123
+ webhookUnregister: SlateWebhookUnregisterHandler<ConfigType, AuthType>;
124
+ }
125
+
126
+ export interface SlateTriggerGroupWebhookManualRegistrationParameters<
127
+ UserConfigSchema extends z.ZodType<any> = z.ZodType<any>,
128
+ FullConfigSchema extends z.ZodType<any> = z.ZodType<any>
129
+ > {
130
+ userConfigSchema: UserConfigSchema;
131
+ fullConfigSchema: FullConfigSchema;
132
+ setup: SlateWebhookManualSetupHandler<FullConfigSchema>;
133
+ finish?: SlateWebhookManualFinishHandler<UserConfigSchema, FullConfigSchema>;
134
+ }
135
+
136
+ export interface SlateTriggerGroupWebhookParameters<
137
+ ConfigType extends {},
138
+ AuthType extends {}
139
+ > {
140
+ autoRegistration?: SlateTriggerGroupWebhookAutoRegistrationParameters<ConfigType, AuthType>;
141
+ manualRegistration?: SlateTriggerGroupWebhookManualRegistrationParameters<any, any>;
142
+ process: SlateWebhookProcessHandler;
143
+ }
144
+
145
+ export interface SlateTriggerGroupCreateParameters<
146
+ InputType extends {} = Record<string, unknown>
147
+ > {
148
+ key: string;
149
+ name: string;
150
+ description?: string;
151
+ metadata?: Record<string, any>;
152
+ eventSchema?: z.ZodType<InputType>;
153
+ }
154
+
155
+ export interface SlateTriggerGroupParameters<
156
+ ConfigType extends {},
157
+ AuthType extends {},
158
+ InputType extends {} = Record<string, unknown>
159
+ > extends SlateTriggerGroupCreateParameters<InputType> {
160
+ source: 'polling' | 'webhook';
161
+ polling?: SlateTriggerGroupPollingParameters<ConfigType, AuthType>;
162
+ webhook?: SlateTriggerGroupWebhookParameters<ConfigType, AuthType>;
163
+ routingMatchers: SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType>;
164
+ }
165
+
166
+ export class SlateTriggerGroup<
167
+ ConfigType extends {},
168
+ AuthType extends {},
169
+ InputType extends {} = Record<string, unknown>
170
+ > {
171
+ private constructor(
172
+ private readonly _spec: SlateSpecification<ConfigType, AuthType>,
173
+ private readonly _params: SlateTriggerGroupParameters<ConfigType, AuthType, InputType>
174
+ ) {}
175
+
176
+ static create<
177
+ ConfigType extends {},
178
+ AuthType extends {},
179
+ InputType extends {} = Record<string, unknown>
180
+ >(
181
+ spec: SlateSpecification<ConfigType, AuthType>,
182
+ params: SlateTriggerGroupCreateParameters<InputType>
183
+ ) {
184
+ return new SlateTriggerGroupBuilder(spec, params, p => new SlateTriggerGroup(spec, p));
185
+ }
186
+
187
+ get spec() {
188
+ return this._spec;
189
+ }
190
+
191
+ get key() {
192
+ return this._params.key;
193
+ }
194
+
195
+ get name() {
196
+ return this._params.name;
197
+ }
198
+
199
+ get description() {
200
+ return this._params.description;
201
+ }
202
+
203
+ get metadata() {
204
+ return this._params.metadata;
205
+ }
206
+
207
+ get eventSchema() {
208
+ return this._params.eventSchema ?? (z.object({}).passthrough() as z.ZodType<InputType>);
209
+ }
210
+
211
+ get source() {
212
+ return this._params.source;
213
+ }
214
+
215
+ get polling() {
216
+ return this._params.polling;
217
+ }
218
+
219
+ get webhook() {
220
+ return this._params.webhook;
221
+ }
222
+
223
+ get routingMatchers() {
224
+ return this._params.routingMatchers;
225
+ }
226
+ }
227
+
228
+ export class SlateTriggerGroupBuilder<
229
+ ConfigType extends {},
230
+ AuthType extends {},
231
+ InputType extends {} = Record<string, unknown>
232
+ > {
233
+ #source: 'polling' | 'webhook' | null = null;
234
+ #polling: SlateTriggerGroupPollingParameters<ConfigType, AuthType> | null = null;
235
+ #webhook: SlateTriggerGroupWebhookParameters<ConfigType, AuthType> | null = null;
236
+ #routingMatchers: SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType> | null =
237
+ null;
238
+
239
+ constructor(
240
+ private readonly spec: SlateSpecification<ConfigType, AuthType>,
241
+ private readonly params: SlateTriggerGroupCreateParameters<InputType>,
242
+ private readonly factory: (
243
+ params: SlateTriggerGroupParameters<ConfigType, AuthType, InputType>
244
+ ) => SlateTriggerGroup<ConfigType, AuthType, InputType>
245
+ ) {}
246
+
247
+ polling(props: {
248
+ intervalSeconds?: number;
249
+ pollEvents: SlateTriggerGroupPollHandler<ConfigType, AuthType>;
250
+ }): SlateTriggerGroupBuilder<ConfigType, AuthType, InputType> {
251
+ if (this.#source) {
252
+ throw new SlateDeclarationError('Trigger group invocation is already defined');
253
+ }
254
+
255
+ this.#source = 'polling';
256
+ this.#polling = {
257
+ intervalSeconds: props.intervalSeconds ?? SlateDefaultPollingIntervalSeconds,
258
+ pollEvents: props.pollEvents
259
+ };
260
+
261
+ return this;
262
+ }
263
+
264
+ webhook<
265
+ UserConfigSchema extends z.ZodType<any> = z.ZodType<any>,
266
+ FullConfigSchema extends z.ZodType<any> = z.ZodType<any>
267
+ >(props: {
268
+ autoRegistration?: SlateTriggerGroupWebhookAutoRegistrationParameters<
269
+ ConfigType,
270
+ AuthType
271
+ >;
272
+ manualRegistration?: SlateTriggerGroupWebhookManualRegistrationParameters<
273
+ UserConfigSchema,
274
+ FullConfigSchema
275
+ >;
276
+ process: SlateWebhookProcessHandler;
277
+ }): SlateTriggerGroupBuilder<ConfigType, AuthType, InputType> {
278
+ if (this.#source) {
279
+ throw new SlateDeclarationError('Trigger group invocation is already defined');
280
+ }
281
+
282
+ if (!!props.autoRegistration === !!props.manualRegistration) {
283
+ throw new SlateDeclarationError(
284
+ 'Webhook trigger groups require exactly one of autoRegistration or manualRegistration'
285
+ );
286
+ }
287
+
288
+ this.#source = 'webhook';
289
+ this.#webhook = {
290
+ autoRegistration: props.autoRegistration,
291
+ manualRegistration: props.manualRegistration,
292
+ process: props.process
293
+ };
294
+
295
+ return this;
296
+ }
297
+
298
+ routingMatchers(
299
+ handler: SlateTriggerGroupRoutingMatchersHandler<ConfigType, AuthType>
300
+ ): SlateTriggerGroupBuilder<ConfigType, AuthType, InputType> {
301
+ this.#routingMatchers = handler;
302
+ return this;
303
+ }
304
+
305
+ build(): SlateTriggerGroup<ConfigType, AuthType, InputType> {
306
+ if (!this.#source) {
307
+ throw new SlateDeclarationError(
308
+ 'Trigger group invocation (polling or webhook) is not defined'
309
+ );
310
+ }
311
+ if (!this.#routingMatchers) {
312
+ throw new SlateDeclarationError('Trigger group routing matchers handler is not defined');
313
+ }
314
+
315
+ return this.factory({
316
+ ...this.params,
317
+ source: this.#source,
318
+ polling: this.#polling ?? undefined,
319
+ webhook: this.#webhook ?? undefined,
320
+ routingMatchers: this.#routingMatchers
321
+ });
322
+ }
323
+ }
324
+
325
+ export let triggerGroup = <
326
+ ConfigType extends {},
327
+ AuthType extends {},
328
+ InputType extends {} = Record<string, unknown>
329
+ >(
330
+ spec: SlateSpecification<ConfigType, AuthType>,
331
+ params: SlateTriggerGroupCreateParameters<InputType>
332
+ ) => SlateTriggerGroup.create(spec, params);
@@ -1,6 +1,7 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
  import { z } from 'zod';
3
3
  import { SlateTool } from '../action/tool';
4
+ import { SlateTriggerGroup } from '../action/triggerGroup';
4
5
  import { SlateAuth } from '../auth';
5
6
  import { SlateConfig } from '../config';
6
7
  import { Slate } from '../specification/slate';
@@ -41,6 +42,16 @@ describe('SlateAdapterSpec', () => {
41
42
  }))
42
43
  .build();
43
44
 
45
+ let emailTriggerGroup = SlateTriggerGroup.create(spec, {
46
+ key: 'emails',
47
+ name: 'Emails'
48
+ })
49
+ .polling({
50
+ pollEvents: async () => ({ events: [] })
51
+ })
52
+ .routingMatchers(async () => [])
53
+ .build();
54
+
44
55
  let emailReceivedTrigger = gmailAdapterSpec
45
56
  .trigger(spec, {
46
57
  key: 'email_received',
@@ -48,13 +59,13 @@ describe('SlateAdapterSpec', () => {
48
59
  })
49
60
  .input(z.object({ messageId: z.string() }))
50
61
  .output(z.object({ type: z.literal('email.received') }))
51
- .polling({
52
- handleEvent: async ctx => ({
53
- type: 'email.received',
54
- id: ctx.input.messageId,
55
- output: { type: 'email.received' as const }
56
- })
57
- })
62
+ .triggerGroup(emailTriggerGroup)
63
+ .matches(() => true)
64
+ .map(async ctx => ({
65
+ type: 'email.received',
66
+ id: ctx.input.messageId,
67
+ output: { type: 'email.received' as const }
68
+ }))
58
69
  .build();
59
70
 
60
71
  expect(sendEmailTool.adapter).toBe('gmail');
@@ -218,6 +229,16 @@ describe('SlateAdapterSpec', () => {
218
229
  }))
219
230
  .build();
220
231
 
232
+ let sendEmailTriggerGroup = SlateTriggerGroup.create(spec, {
233
+ key: 'sent_emails',
234
+ name: 'Sent Emails'
235
+ })
236
+ .polling({
237
+ pollEvents: async () => ({ events: [] })
238
+ })
239
+ .routingMatchers(async () => [])
240
+ .build();
241
+
221
242
  let sendEmailTrigger = gmailAdapterSpec
222
243
  .trigger(spec, {
223
244
  key: 'send_email',
@@ -225,13 +246,13 @@ describe('SlateAdapterSpec', () => {
225
246
  })
226
247
  .input(z.object({}))
227
248
  .output(z.object({ type: z.string() }))
228
- .polling({
229
- handleEvent: async () => ({
230
- type: 'email.sent',
231
- id: '1',
232
- output: { type: 'email.sent' }
233
- })
234
- })
249
+ .triggerGroup(sendEmailTriggerGroup)
250
+ .matches(() => true)
251
+ .map(async () => ({
252
+ type: 'email.sent',
253
+ id: '1',
254
+ output: { type: 'email.sent' }
255
+ }))
235
256
  .build();
236
257
 
237
258
  expect(() =>
package/src/auth/types.ts CHANGED
@@ -22,6 +22,8 @@ export type SlateAuthWithOauth<
22
22
  scope: string;
23
23
  }[];
24
24
 
25
+ adapters?: string[];
26
+
25
27
  docs?: SlateAuthDocsReference[];
26
28
 
27
29
  inputSchema?: z.ZodType<InputType>;
@@ -92,6 +94,8 @@ export type SlateAuthWithToken<InputType extends {}, OutputType extends { token?
92
94
  name: string;
93
95
  key: string;
94
96
 
97
+ adapters?: string[];
98
+
95
99
  inputSchema?: z.ZodType<InputType>;
96
100
 
97
101
  docs?: SlateAuthDocsReference[];
@@ -124,6 +128,8 @@ export type SlateAuthWithServiceAccount<InputType extends {}, OutputType extends
124
128
  name: string;
125
129
  key: string;
126
130
 
131
+ adapters?: string[];
132
+
127
133
  inputSchema?: z.ZodType<InputType>;
128
134
 
129
135
  docs?: SlateAuthDocsReference[];
@@ -156,6 +162,8 @@ export type SlateAuthWithCustomData<InputType extends {}, OutputType extends {}>
156
162
  name: string;
157
163
  key: string;
158
164
 
165
+ adapters?: string[];
166
+
159
167
  inputSchema?: z.ZodType<InputType>;
160
168
 
161
169
  docs?: SlateAuthDocsReference[];
@@ -19,9 +19,9 @@ describe('resolveDefaultExport', () => {
19
19
  });
20
20
 
21
21
  it('unwraps nested default exports from double-bundling', () => {
22
- expect(
23
- resolveDefaultExport<typeof Example>({ default: { default: Example } })
24
- ).toBe(Example);
22
+ expect(resolveDefaultExport<typeof Example>({ default: { default: Example } })).toBe(
23
+ Example
24
+ );
25
25
  });
26
26
 
27
27
  it('throws when the export is not a constructor', () => {
@@ -0,0 +1,105 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { z } from 'zod';
3
+ import { SlateTrigger, SlateTriggerGroup } from '../action';
4
+ import { SlateAuth } from '../auth';
5
+ import { SlateConfig } from '../config';
6
+ import { Slate } from './slate';
7
+ import { SlateSpecification } from './specification';
8
+
9
+ let createTestSpec = () => {
10
+ let config = SlateConfig.create(z.object({}));
11
+ let auth = SlateAuth.create<{}>().output(z.object({}));
12
+
13
+ return SlateSpecification.create({
14
+ key: 'demo',
15
+ name: 'Demo',
16
+ config,
17
+ auth
18
+ });
19
+ };
20
+
21
+ let createManualWebhookTriggerGroup = (spec: ReturnType<typeof createTestSpec>, key: string) =>
22
+ SlateTriggerGroup.create(spec, {
23
+ key,
24
+ name: key
25
+ })
26
+ .webhook({
27
+ manualRegistration: {
28
+ userConfigSchema: z.object({}),
29
+ fullConfigSchema: z.object({}),
30
+ setup: async () => ({
31
+ webhookSetupDocument: '',
32
+ partialWebhookRegistrationPayload: {}
33
+ })
34
+ },
35
+ process: async () => ({ events: [] })
36
+ })
37
+ .routingMatchers(async () => [])
38
+ .build();
39
+
40
+ let createAutoWebhookTriggerGroup = (spec: ReturnType<typeof createTestSpec>, key: string) =>
41
+ SlateTriggerGroup.create(spec, {
42
+ key,
43
+ name: key
44
+ })
45
+ .webhook({
46
+ autoRegistration: {
47
+ webhookTargetList: async () => ({ targets: [], nextPageToken: null }),
48
+ webhookRegister: async () => ({
49
+ webhookRegistrationIdentifier: 'reg',
50
+ webhookRegistrationPayload: {}
51
+ }),
52
+ webhookUnregister: async () => {}
53
+ },
54
+ process: async () => ({ events: [] })
55
+ })
56
+ .routingMatchers(async () => [])
57
+ .build();
58
+
59
+ describe('Slate.create', () => {
60
+ it('rejects more than one manual webhook trigger group', () => {
61
+ let spec = createTestSpec();
62
+ let first = createManualWebhookTriggerGroup(spec, 'manual_one');
63
+ let second = createManualWebhookTriggerGroup(spec, 'manual_two');
64
+
65
+ expect(() =>
66
+ Slate.create({
67
+ spec,
68
+ tools: [],
69
+ triggers: [],
70
+ triggerGroups: [first, second]
71
+ })
72
+ ).toThrow(
73
+ 'Only one trigger group may use manual webhook registration, but found: manual_one, manual_two'
74
+ );
75
+ });
76
+
77
+ it('allows a single manual webhook trigger group alongside other trigger groups', () => {
78
+ let spec = createTestSpec();
79
+ let manual = createManualWebhookTriggerGroup(spec, 'manual_group');
80
+ let auto = createAutoWebhookTriggerGroup(spec, 'auto_group');
81
+
82
+ let manualTrigger = SlateTrigger.create(spec, {
83
+ key: 'manual_trigger',
84
+ name: 'Manual Trigger'
85
+ })
86
+ .input(z.object({}))
87
+ .output(z.object({ type: z.literal('demo') }))
88
+ .triggerGroup(manual)
89
+ .matches(() => true)
90
+ .map(async () => ({ type: 'demo', id: '1', output: { type: 'demo' as const } }))
91
+ .build();
92
+
93
+ let slate = Slate.create({
94
+ spec,
95
+ tools: [],
96
+ triggers: [manualTrigger],
97
+ triggerGroups: [manual, auto]
98
+ });
99
+
100
+ expect(slate.triggerGroups.map(group => group.key)).toEqual([
101
+ 'manual_group',
102
+ 'auto_group'
103
+ ]);
104
+ });
105
+ });